SA-MP/saco/main.cpp
2024-10-21 22:46:54 +08:00

672 lines
14 KiB
C++

#include "main.h"
#include "game/util.h"
int iGtaVersion=0;
GAME_SETTINGS tSettings;
CHAR szArtworkProxy[MAX_PATH+1];
CHAR szConfigFile[MAX_PATH+1];
CHAR byte_1026E710[256]; // unused
CHAR szChatLogFile[MAX_PATH+1];
CHAR szSAMPDir[MAX_PATH+1];
CHAR szCacheDir[MAX_PATH+1];
CConfig *pConfig=0;
CChatWindow *pChatWindow=0;
CCmdWindow *pCmdWindow=0;
CDeathWindow *pDeathWindow=0;
CAudioStream *pAudioStream=0;
CSpawnScreen *pSpawnScreen=0;
CNetGame *pNetGame=0;
//DWORD dword_1026EB98=0;
CFontRender *pDefaultFont=0;
CUnkClass13 *pUnkClass13=0;
CUnkClass14 *pUnkClass14=0;
CUnkClass15 *pUnkClass15=0;
BOOL bGameInited=FALSE;
BOOL bQuitGame=FALSE;
DWORD dwStartQuitTick=0;
WORD wVehicleComponentDebug=0;
IDirect3D9 *pD3D;
IDirect3DDevice9 *pD3DDevice = NULL;
HANDLE hInstance=0;
CNewPlayerTags *pNewPlayerTags=NULL;
CScoreBoard *pScoreBoard=NULL;
CUnkClass3 *pUnkClass3=NULL;
CUnkClass4 *pUnkClass4=NULL;
CUnkClass5 *pUnkClass5=NULL;
CLabel *pLabel=NULL;
CUnkClass10 *pUnkClass10=NULL;
CUnkClass11 *pUnkClass11=NULL;
CUnkClass12 *pUnkClass12=NULL;
CNetStats *pNetStats=NULL;
CSvrNetStats *pSvrNetStats=NULL;
CHelpDialog *pHelpDialog=NULL;
CUnkClass8 *pUnkClass8=NULL;
bool bShowDebugLabels = false;
CGame *pGame=0;
DWORD dwGraphicsLoop=0;
CFileSystem *pFileSystem=NULL;
// forwards
BOOL SubclassGameWindow();
void SetupCommands();
void TheGraphicsLoop();
LONG WINAPI exc_handler(_EXCEPTION_POINTERS* exc_inf);
void FUNC_1009DD50();
DWORD dwOrgRwSetState=0;
DWORD dwSetStateCaller=0;
DWORD dwSetStateOption=0;
DWORD dwSetStateParam=0;
char dbgstr[256];
// polls the game until it's able to run.
void LaunchMonitor(PVOID v)
{
if(pGame)
pGame->InitGame();
while(1) {
if(*(PDWORD)ADDR_ENTRY == 7) {
FUNC_1009DD50();
pGame->StartGame();
break;
}
else {
Sleep(5);
}
}
ExitThread(0);
}
//----------------------------------------------------
#define ARCHIVE_FILE "samp.saa"
BOOL WINAPI DllMain_2(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if(DLL_PROCESS_ATTACH==fdwReason)
{
hInstance = hinstDLL;
InitSettings();
if(tSettings.bDebug || tSettings.bPlayOnline)
{
SetUnhandledExceptionFilter(exc_handler);
dwGraphicsLoop = (DWORD)TheGraphicsLoop;
CHAR szArchiveFile[MAX_PATH];
GetModuleFileNameA((HMODULE)hInstance, szArchiveFile, MAX_PATH);
DWORD dwFileNameLen = strlen(szArchiveFile);
while(szArchiveFile[dwFileNameLen] != '\\')
dwFileNameLen--;
strcpy(szArchiveFile+dwFileNameLen+1, ARCHIVE_FILE);
pFileSystem = new CArchiveFS();
if(!pFileSystem->Load(ARCHIVE_FILE)) _asm int 3
AddFontResourceA("gtaweap3.ttf");
AddFontResourceA("sampaux3.ttf");
InstallFileSystemHooks();
InstallShowCursorHook();
pGame = new CGame();
_beginthread(LaunchMonitor,0,NULL);
}
}
else if(DLL_PROCESS_DETACH==fdwReason)
{
if(tSettings.bDebug || tSettings.bPlayOnline) {
UninstallFileSystemHooks();
}
}
return TRUE;
}
//----------------------------------------------------
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
_asm jmp DllMain_2
}
//----------------------------------------------------
PCHAR GetSAMPPath()
{
return szSAMPDir;
}
//----------------------------------------------------
PCHAR GetCachePath()
{
return szCacheDir;
}
//----------------------------------------------------
void SetupCacheDirectories()
{
ZeroMemory(szCacheDir, sizeof(szCacheDir));
CHAR szPath[MAX_PATH+1];
DWORD cbData = MAX_PATH;
HKEY hKey;
DWORD dwType;
ZeroMemory(szPath, sizeof(szPath));
sprintf(szCacheDir, "%s\\cache", szSAMPDir);
if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\SAMP", 0, KEY_READ, &hKey) == ERROR_SUCCESS &&
RegQueryValueEx(hKey, "model_cache", NULL, &dwType, (LPBYTE) szPath, &cbData) == ERROR_SUCCESS)
{
strncpy(szCacheDir, szPath, MAX_PATH+1);
}
if(!IsFileOrDirectoryExists(szCacheDir))
CreateDirectoryA(szCacheDir, NULL);
CHAR szLocalDir[MAX_PATH+1];
sprintf(szLocalDir, "%s\\local", szCacheDir);
if(!IsFileOrDirectoryExists(szLocalDir))
CreateDirectoryA(szLocalDir, NULL);
}
//----------------------------------------------------
PCHAR GetArtworkProxy()
{
ZeroMemory(szArtworkProxy, sizeof(szArtworkProxy));
DWORD cbData = MAX_PATH;
HKEY hKey;
DWORD dwType;
if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\SAMP", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
if(RegQueryValueEx(hKey, "artwork_proxy", NULL, &dwType, (LPBYTE) szArtworkProxy, &cbData) == ERROR_SUCCESS) {
return szArtworkProxy;
} else {
return NULL;
}
} else {
return NULL;
}
}
//----------------------------------------------------
void SetupDirectories()
{
ZeroMemory(szSAMPDir, sizeof(szSAMPDir));
if(strlen((char*)0xC92368) == 0) {
GetCurrentDirectory(MAX_PATH+1, szSAMPDir);
} else {
sprintf(szSAMPDir, "%s\\SAMP", (char*)0xC92368);
if(!IsFileOrDirectoryExists(szSAMPDir))
CreateDirectoryA(szSAMPDir, NULL);
CHAR szScreensDir[MAX_PATH+1];
sprintf(szScreensDir, "%s\\screens", szSAMPDir);
if(!IsFileOrDirectoryExists(szScreensDir))
CreateDirectoryA(szScreensDir, NULL);
SetupCacheDirectories();
}
}
//----------------------------------------------------
DWORD dwFogEnabled = 0;
DWORD dwFogColor = 0x00FF00FF;
BOOL gDisableAllFog = FALSE;
void SetupD3DFog(BOOL bEnable)
{
float fFogStart = 500.0f;
float fFogEnd = 700.0f;
if(gDisableAllFog) bEnable = FALSE;
if(pD3DDevice) {
pD3DDevice->SetRenderState(D3DRS_FOGENABLE, bEnable);
//pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, dwFogColor);
pD3DDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
pD3DDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
//pD3DDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD*)(&fFogStart));
//pD3DDevice->SetRenderState(D3DRS_FOGEND, *(DWORD*)(&fFogEnd));
}
}
//----------------------------------------------------
void _declspec(naked) RwRenderStateSetHook()
{
_asm mov eax, [esp]
_asm mov dwSetStateCaller, eax
_asm mov eax, [esp+4]
_asm mov dwSetStateOption, eax
_asm mov eax, [esp+8]
_asm mov dwSetStateParam, eax
if(dwSetStateOption == 14) {
if(dwSetStateParam) {
SetupD3DFog(TRUE);
dwFogEnabled = 1;
} else {
SetupD3DFog(FALSE);
dwFogEnabled = 0;
}
_asm mov [esp+8], 0 ; no fog
}
_asm mov eax, dwOrgRwSetState
_asm jmp eax
}
//----------------------------------------------------
void HookRwRenderStateSet()
{
DWORD dwNewRwSetState = (DWORD)RwRenderStateSetHook;
_asm mov ebx, 0xC97B24
_asm mov eax, [ebx]
_asm mov edx, [eax+32]
_asm mov dwOrgRwSetState, edx
_asm mov edx, dwNewRwSetState
_asm mov [eax+32], edx
#ifdef _DEBUG
sprintf(dbgstr,"HookRwRenderStateSet(0x%X)",dwOrgRwSetState);
OutputDebugString(dbgstr);
#endif
}
//----------------------------------------------------
void CallRwRenderStateSet(int state, int option)
{
_asm push option
_asm push state
_asm mov ebx, 0xC97B24
_asm mov eax, [ebx]
_asm call dword ptr [eax+32]
_asm add esp, 8
}
//----------------------------------------------------
void CallRwRenderStateGet(int state, int *option)
{
_asm push option
_asm push state
_asm mov ebx, 0xC97B24
_asm mov eax, [ebx]
_asm call dword ptr [eax+36]
_asm add esp, 8
}
//----------------------------------------------------
void DoInitStuff()
{
// GAME INIT
if(!bGameInited)
{
SetupDirectories();
sprintf(szConfigFile, "%s\\sa-mp.cfg", szSAMPDir);
sprintf(szChatLogFile, "%s\\chatlog.txt", szSAMPDir);
pConfig = new CConfig(szConfigFile);
timeBeginPeriod(1); // increases the accuracy of Sleep()
FUNC_1009DD50();
SubclassGameWindow();
// Grab the real IDirect3D9 * from the game.
pD3D = (IDirect3D9 *)pGame->GetD3D();
// Grab the real IDirect3DDevice9 * from the game.
pD3DDevice = (IDirect3DDevice9 *)pGame->GetD3DDevice();
*(IDirect3DDevice9Hook**)ADDR_ID3D9DEVICE = new IDirect3DDevice9Hook();
pD3DDevice->ShowCursor(FALSE);
// Create instances of the chat and input classes.
pDefaultFont = new CFontRender(pD3DDevice);
pChatWindow = new CChatWindow(pD3DDevice,pDefaultFont,szChatLogFile);
pCmdWindow = new CCmdWindow(pD3DDevice);
if(tSettings.bPlayOnline) {
pDeathWindow = new CDeathWindow(pD3DDevice);
pSpawnScreen = new CSpawnScreen(pD3DDevice);
pNewPlayerTags = new CNewPlayerTags(pD3DDevice);
pScoreBoard = new CScoreBoard(pD3DDevice);
pUnkClass3 = new CUnkClass3(pD3DDevice);
pUnkClass4 = new CUnkClass4(pD3DDevice);
pUnkClass5 = new CUnkClass5(pD3DDevice);
pNetStats = new CNetStats(pD3DDevice);
pSvrNetStats = new CSvrNetStats(pD3DDevice);
pHelpDialog = new CHelpDialog(pD3DDevice);
pUnkClass8 = new CUnkClass8();
}
pLabel = new CLabel(pD3DDevice);
pUnkClass10 = new CUnkClass10(pD3DDevice);
pUnkClass11 = new CUnkClass11();
pUnkClass12 = new CUnkClass12();
pUnkClass13 = new CUnkClass13(pD3DDevice);
pUnkClass14 = new CUnkClass14(pD3DDevice);
pUnkClass15 = new CUnkClass15();
// Setting up the commands.
OutputDebugString("Setting up commands..");
SetupCommands();
OutputDebugString("Hooking RwSetState..");
HookRwRenderStateSet();
pGame->SetMaxStats();
if(tSettings.bDebug) {
}
// TODO: DoInitStuff
bGameInited = TRUE;
return;
}
}
//----------------------------------------------------
void DoProcessStuff()
{
DoInitStuff();
SetupD3DFog(TRUE);
// Process the netgame if it's active.
if(pNetGame) {
//Sleep(0); // This hands the context over to raknet
pNetGame->Process();
}
if(pAudioStream) {
pAudioStream->Process();
}
}
//----------------------------------------------------
void TheGraphicsLoop()
{
_asm pushad // because we're called from a hook
DoProcessStuff();
_asm popad
}
//----------------------------------------------------
void QuitGame()
{
if(pNetGame && pNetGame->GetGameState() == GAMESTATE_CONNECTED) {
pNetGame->GetRakClient()->Disconnect(500);
}
bQuitGame = TRUE;
dwStartQuitTick = GetTickCount();
}
//----------------------------------------------------
void InitSettings()
{
PCHAR szCmdLine = GetCommandLineA();
memset(&tSettings,0,sizeof(GAME_SETTINGS));
while(*szCmdLine) {
if(*szCmdLine == '-' || *szCmdLine == '/') {
szCmdLine++;
switch(*szCmdLine) {
case 'd':
tSettings.bDebug = TRUE;
tSettings.bPlayOnline = FALSE;
break;
case 'c':
tSettings.bPlayOnline = TRUE;
tSettings.bDebug = FALSE;
break;
case 'z':
szCmdLine++;
SetStringFromCommandLine(szCmdLine,tSettings.szConnectPass);
break;
/*
// We'll do this using ALT+ENTER
case 'w':
tSettings.bWindowedMode = TRUE;
break;
*/
case 'h':
szCmdLine++;
SetStringFromCommandLine(szCmdLine,tSettings.szConnectHost);
break;
case 'p':
szCmdLine++;
SetStringFromCommandLine(szCmdLine,tSettings.szConnectPort);
break;
case 'n':
szCmdLine++;
SetStringFromCommandLine(szCmdLine,tSettings.szNickName);
break;
case 'l':
szCmdLine++;
SetStringFromQuotedCommandLine(szCmdLine,tSettings.szDebugScript);
break;
}
}
szCmdLine++;
}
}
//----------------------------------------------------
void SetStringFromCommandLine(char *szCmdLine, char *szString)
{
while(*szCmdLine == ' ') szCmdLine++;
while(*szCmdLine &&
*szCmdLine != ' ' &&
*szCmdLine != '-' &&
*szCmdLine != '/')
{
*szString = *szCmdLine;
szString++; szCmdLine++;
}
*szString = '\0';
}
//----------------------------------------------------
void SetStringFromQuotedCommandLine(char *szCmdLine, char *szString)
{
while(*szCmdLine != '"') szCmdLine++;
szCmdLine++;
while(*szCmdLine &&
*szCmdLine != '"')
{
*szString = *szCmdLine;
szString++; szCmdLine++;
}
*szString = '\0';
}
//----------------------------------------------------
float GetElapsedTime()
{
static BOOL bTimerInit = false;
static BOOL bUsingOPF = false;
static LONGLONG nTicksPerSec = 0;
if (!bTimerInit)
{
bTimerInit = true;
LARGE_INTEGER qwTicksPerSec;
bUsingOPF = QueryPerformanceFrequency(&qwTicksPerSec);
if (bUsingOPF) nTicksPerSec = qwTicksPerSec.QuadPart;
}
if (bUsingOPF)
{
LARGE_INTEGER qwTime;
QueryPerformanceCounter(&qwTime);
static LONGLONG llLastTime = qwTime.QuadPart;
double fElapsedTime = (double)(qwTime.QuadPart - llLastTime) / (double) nTicksPerSec;
llLastTime = qwTime.QuadPart;
return (float)fElapsedTime;
} else {
double fTime = timeGetTime() * 0.001;
static double fLastTime = fTime;
double fElapsedTime = (double)(fTime - fLastTime);
fLastTime = fTime;
return (float)fElapsedTime;
}
}
//----------------------------------------------------
void DisableMouseProcess();
void DIResetMouse();
void UpdatePads();
DWORD GLOBAL_1026EBD0;
DWORD __stdcall FUNC_100C4530(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
{
if(pNetGame && pGame) {
UnFuck(0x541DF5,5);
memset((PVOID)0x541DF5,0x90,5);
DisableMouseProcess();
DIResetMouse();
UpdatePads();
UnFuck(0x6194A0,1);
*(BYTE*)0x6194A0 = 0xC3;
GLOBAL_1026EBD0++;
}
return 69;
}
//----------------------------------------------------
DWORD GLOBAL_10117478 = 69;
DWORD GLOBAL_1026EBE8;
DWORD GLOBAL_1026EBEC;
DWORD GLOBAL_1026EBF0;
DWORD GLOBAL_1014FD98;
int FUNC_100C46B0(bool a1)
{
if(GLOBAL_10117478 == 69)
{
GLOBAL_1026EBEC = GLOBAL_1014FD98;
GLOBAL_1026EBE8 = GLOBAL_1014FD98;
GLOBAL_10117478 = 70;
}
else
{
if(a1)
{
if(GLOBAL_1014FD98 <= GLOBAL_1026EBEC && FUNC_100C4530(59, 1, 6, 12, 17, 2, 50) != 69)
exit(0);
if(GLOBAL_1026EBE8 >= GLOBAL_1014FD98 && FUNC_100C4530(60, 1, 6, 12, 17, 2, 50) != 69)
exit(0);
GLOBAL_1026EBE8 = GLOBAL_1014FD98;
}
if(GLOBAL_1026EBD0 > 5 && FUNC_100C4530(65, 1, 6, 12, 17, 2, 50) != 69)
exit(0);
}
GLOBAL_1026EBF0++;
return GLOBAL_1026EBF0;
}
//----------------------------------------------------
int GetFontSize()
{
int size;
if (pGame->GetScreenWidth() < 1024)
size = 14;
else if (pGame->GetScreenWidth() < 1400)
size = 16;
else if (pGame->GetScreenWidth() < 1600)
size = 18;
else
size = 20;
return size + 2 * pConfig->GetIntVariable("fontsize");
}
int GetDeathWindowFontSize()
{
int size = 14;
if (pGame->GetScreenWidth() < 1024)
size = 12;
int fontsize = size + 2 * pConfig->GetIntVariable("fontsize");
if(fontsize < size)
fontsize = size;
return fontsize;
}
int GetUIFontSize()
{
return 2 * pConfig->GetIntVariable("fontsize") + 20;
}
int GetFontWeight()
{
int fontweight = pConfig->GetIntVariable("fontweight");
if(fontweight == 0) return FW_BOLD;
return fontweight != 1 ? FW_BOLD : FW_NORMAL;
}
char *GetFontFace()
{
if(pConfig && pConfig->GetStringVariable("fontface"))
{
return pConfig->GetStringVariable("fontface");
}
return "Arial";
}