SA-MP/saco/main.cpp

599 lines
13 KiB
C++
Raw Normal View History

2023-10-20 06:46:57 +08:00
#include "main.h"
2023-12-01 18:31:52 +08:00
#include "game/util.h"
2023-10-20 06:46:57 +08:00
2023-11-15 18:46:57 +08:00
int iGtaVersion=0;
GAME_SETTINGS tSettings;
2023-12-01 18:31:52 +08:00
CHAR szArtworkProxy[MAX_PATH+1];
CHAR szConfigFile[MAX_PATH+1];
CHAR byte_1026E710[256]; // unused
CHAR szChatLogFile[MAX_PATH+1];
2023-12-01 18:31:52 +08:00
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;
WORD wVehicleComponentDebug=0;
IDirect3D9 *pD3D;
IDirect3DDevice9 *pD3DDevice = NULL;
2023-10-20 06:46:57 +08:00
HANDLE hInstance=0;
CNewPlayerTags *pNewPlayerTags=NULL;
CScoreBoard *pScoreBoard=NULL;
CUnkClass3 *pUnkClass3=NULL;
CUnkClass4 *pUnkClass4=NULL;
CUnkClass5 *pUnkClass5=NULL;
2024-04-21 20:49:59 +08:00
CLabel *pLabel=NULL;
CUnkClass10 *pUnkClass10=NULL;
CUnkClass11 *pUnkClass11=NULL;
CUnkClass12 *pUnkClass12=NULL;
2024-04-21 21:19:10 +08:00
CNetStats *pNetStats=NULL;
2024-03-27 23:27:18 +08:00
CSvrNetStats *pSvrNetStats=NULL;
CHelpDialog *pHelpDialog=NULL;
CUnkClass8 *pUnkClass8=NULL;
2023-10-19 08:02:18 +08:00
2024-02-16 22:23:35 +08:00
bool bShowDebugLabels = false;
2023-11-23 23:41:28 +08:00
CGame *pGame=0;
DWORD dwGraphicsLoop=0;
2023-10-23 23:04:28 +08:00
2023-11-08 20:29:53 +08:00
CFileSystem *pFileSystem=NULL;
// forwards
BOOL SubclassGameWindow();
2024-04-07 22:42:34 +08:00
void SetupCommands();
2023-11-24 23:30:07 +08:00
void TheGraphicsLoop();
LONG WINAPI exc_handler(_EXCEPTION_POINTERS* exc_inf);
void sub_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) {
2024-07-24 17:01:39 +08:00
FUNC_1009DD50();
pGame->StartGame();
break;
}
else {
Sleep(5);
}
}
ExitThread(0);
}
2023-11-22 23:40:22 +08:00
//----------------------------------------------------
#define ARCHIVE_FILE "samp.saa"
2024-03-14 23:56:03 +08:00
BOOL WINAPI DllMain_2(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
2023-10-19 08:02:18 +08:00
{
2023-10-20 06:46:57 +08:00
if(DLL_PROCESS_ATTACH==fdwReason)
{
hInstance = hinstDLL;
InitSettings();
if(tSettings.bDebug || tSettings.bPlayOnline)
{
SetUnhandledExceptionFilter(exc_handler);
2023-11-24 23:30:07 +08:00
dwGraphicsLoop = (DWORD)TheGraphicsLoop;
2023-11-08 20:29:53 +08:00
CHAR szArchiveFile[MAX_PATH];
GetModuleFileNameA((HMODULE)hInstance, szArchiveFile, MAX_PATH);
DWORD dwFileNameLen = strlen(szArchiveFile);
while(szArchiveFile[dwFileNameLen] != '\\')
dwFileNameLen--;
strcpy(szArchiveFile+dwFileNameLen+1, ARCHIVE_FILE);
2023-11-08 20:29:53 +08:00
pFileSystem = new CArchiveFS();
if(!pFileSystem->Load(ARCHIVE_FILE)) _asm int 3
2023-10-23 22:58:28 +08:00
2023-10-20 06:46:57 +08:00
AddFontResourceA("gtaweap3.ttf");
AddFontResourceA("sampaux3.ttf");
2023-10-23 22:58:28 +08:00
InstallFileSystemHooks();
InstallShowCursorHook();
2023-10-23 23:04:28 +08:00
pGame = new CGame();
_beginthread(LaunchMonitor,0,NULL);
2023-10-20 06:46:57 +08:00
}
}
else if(DLL_PROCESS_DETACH==fdwReason)
{
if(tSettings.bDebug || tSettings.bPlayOnline) {
UninstallFileSystemHooks();
2023-10-20 06:46:57 +08:00
}
}
2023-10-19 08:02:18 +08:00
return TRUE;
}
2023-10-20 06:46:57 +08:00
//----------------------------------------------------
2024-03-14 23:56:03 +08:00
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
_asm jmp DllMain_2
}
//----------------------------------------------------
2023-12-01 18:31:52 +08:00
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;
2024-08-21 22:49:16 +08:00
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 {
2023-12-01 18:31:52 +08:00
return NULL;
2024-08-21 22:49:16 +08:00
}
2023-12-01 18:31:52 +08:00
}
//----------------------------------------------------
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();
}
}
//----------------------------------------------------
2024-02-19 21:16:42 +08:00
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()
2024-07-24 17:01:39 +08:00
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();
2024-02-26 22:57:09 +08:00
*(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);
2024-03-20 23:43:00 +08:00
pCmdWindow = new CCmdWindow(pD3DDevice);
2024-02-26 22:57:09 +08:00
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);
2024-04-21 21:19:10 +08:00
pNetStats = new CNetStats(pD3DDevice);
2024-03-27 23:27:18 +08:00
pSvrNetStats = new CSvrNetStats(pD3DDevice);
pHelpDialog = new CHelpDialog(pD3DDevice);
pUnkClass8 = new CUnkClass8();
}
2024-02-26 22:57:09 +08:00
2024-04-21 20:49:59 +08:00
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();
2024-04-07 22:42:34 +08:00
// 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();
}
}
//----------------------------------------------------
2023-11-24 23:30:07 +08:00
void TheGraphicsLoop()
{
_asm pushad // because we're called from a hook
DoProcessStuff();
_asm popad
2023-11-24 23:30:07 +08:00
}
//----------------------------------------------------
2023-10-20 06:46:57 +08:00
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;
}
}
//----------------------------------------------------
2024-07-17 22:23:48 +08:00
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;
}
2024-07-17 22:25:04 +08:00
char *GetFontFace()
{
if(pConfig && pConfig->GetStringVariable("fontface"))
{
return pConfig->GetStringVariable("fontface");
}
return "Arial";
}