Compare commits

...

2 Commits

Author SHA1 Message Date
Guus Waals 7a7c907abb Tool verify 2025-06-01 21:59:37 +08:00
Guus Waals 6bce41bd2d WIP 2025-06-01 21:13:47 +08:00
27 changed files with 693 additions and 286 deletions

View File

@ -51,7 +51,10 @@ void gh_pre_main(void) {
// pvStack_14 = ExceptionList; // pvStack_14 = ExceptionList;
// local_1c = &stack0xffffff88; // local_1c = &stack0xffffff88;
// ExceptionList = &pvStack_14; // ExceptionList = &pvStack_14;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
DVar1 = GetVersion(); DVar1 = GetVersion();
#pragma clang diagnostic pop
DWORD_005cf980 = DVar1 >> 8 & 0xff; DWORD_005cf980 = DVar1 >> 8 & 0xff;
DWORD_005cf97c = DVar1 & 0xff; DWORD_005cf97c = DVar1 & 0xff;
DWORD_005cf978 = DWORD_005cf97c * 0x100 + DWORD_005cf980; DWORD_005cf978 = DWORD_005cf97c * 0x100 + DWORD_005cf980;

View File

@ -69,8 +69,7 @@ int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR *cmdline,
CHAR pathToUbi_ini[228]; CHAR pathToUbi_ini[228];
char acStack_528[16]; char acStack_528[16];
char acStack_518[244]; char acStack_518[244];
char acStack_424[16]; char acStack_424[0x104];
CHAR aCStack_414[244];
char acStack_320[16]; char acStack_320[16];
char acStack_310[240]; char acStack_310[240];
char acStack_220[256]; char acStack_220[256];
@ -544,9 +543,9 @@ LAB_004017ce:
return -1; return -1;
} }
p_cTxt2 = (void *)0x401e5a; p_cTxt2 = (void *)0x401e5a;
GetWindowsDirectoryA(aCStack_414, 0x104);
iVar13 = -1;
#if RE_AUTHENTIC == 0 #if RE_AUTHENTIC == 0
GetWindowsDirectoryA(acStack_424, 0x104);
iVar13 = -1;
/* Append ubi.ini */ /* Append ubi.ini */
pcVar4 = acStack_424; pcVar4 = acStack_424;
do { do {
@ -566,6 +565,7 @@ LAB_004017ce:
#else #else
strcpy(acStack_424, config.gameRootDir.c_str()); strcpy(acStack_424, config.gameRootDir.c_str());
strcat(acStack_424, "/ubi.ini"); strcat(acStack_424, "/ubi.ini");
instance = hInstance;
#endif #endif
/* Read graphics settings */ /* Read graphics settings */
GetPrivateProfileStringA(lpAppName_005b68f0, s_Adapter_005b68e4, GetPrivateProfileStringA(lpAppName_005b68f0, s_Adapter_005b68e4,
@ -596,13 +596,6 @@ LAB_004017ce:
DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
&duplicatedHandle, DVar7, BVar18, dwOptions); &duplicatedHandle, DVar7, BVar18, dwOptions);
/* Copy cmdline */ /* Copy cmdline */
ppCVar8 = puStack_14;
g_mainThreadHandle = duplicatedHandle;
// do {
// uVar14 = *ppCVar8;
// *(char *)(((int)g_appCmdLine - (int)puStack_14) + (int)ppCVar8) =
// (char)uVar14; ppCVar8 = (uint *)((int)ppCVar8 + 1);
// } while ((char)uVar14 != '\0');
LPSTR cmdline = GetCommandLineA(); LPSTR cmdline = GetCommandLineA();
strncpy(g_appCmdLine, cmdline, std::size(g_appCmdLine)); strncpy(g_appCmdLine, cmdline, std::size(g_appCmdLine));
/* SEM_FAILCRITICALERRORS */ /* SEM_FAILCRITICALERRORS */
@ -610,7 +603,7 @@ LAB_004017ce:
pcVar4 = strstr(cmdline, s_dashCC); pcVar4 = strstr(cmdline, s_dashCC);
if (pcVar4 == (char *)0x0) { if (pcVar4 == (char *)0x0) {
r3_initAllModules(); r3_initAllModules();
iVar13 = setupWindow(instance, uStack_10, g_runMaximized); iVar13 = setupWindow(instance, 0, g_runMaximized);
if (iVar13 == 0) { if (iVar13 == 0) {
return -1; return -1;
} }
@ -628,17 +621,19 @@ LAB_004017ce:
iVar10 = r3_get_gli_width1(); iVar10 = r3_get_gli_width1();
iVar10 = iVar10 + 0xc; iVar10 = iVar10 + 0xc;
iVar11 = r3_get_gli_height1(); iVar11 = r3_get_gli_height1();
iVar11 = (int)(rect.top - iVar11) / 2; iVar11 = (int)(rect.bottom - iVar11) / 2;
iVar12 = r3_get_gli_width1(); iVar12 = r3_get_gli_width1();
MoveWindow(g_gameHWND, (int)(rect.right - iVar12) / 2, iVar11, iVar10, MoveWindow(g_gameHWND, 0, 0, iVar10,
iVar13, BVar18); iVar13, BVar18);
FUN_004010b0(); FUN_004010b0();
#if RE_AUTHENTIC == 0
DWORD screensaveActive; DWORD screensaveActive;
SystemParametersInfoA(SPI_GETSCREENSAVEACTIVE, 0, &screensaveActive, 0); SystemParametersInfoA(SPI_GETSCREENSAVEACTIVE, 0, &screensaveActive, 0);
SystemParametersInfoA(SPI_SETSCREENSAVEACTIVE, 0, (PVOID)0x0, 0); SystemParametersInfoA(SPI_SETSCREENSAVEACTIVE, 0, (PVOID)0x0, 0);
ShowCursor(0); ShowCursor(0);
uStack_85c = 0; uStack_85c = 0;
SystemParametersInfoA(0x61, 1, &uStack_85c, 0); SystemParametersInfoA(0x61, 1, &uStack_85c, 0);
#endif
g_engineRunning = 1; g_engineRunning = 1;
r3_engineLoop(); r3_engineLoop();
/* cleanup starts here */ /* cleanup starts here */
@ -648,11 +643,13 @@ LAB_004017ce:
FUN_004fb300(); FUN_004fb300();
FUN_00472150(); FUN_00472150();
FUN_00470db0(); FUN_00470db0();
#if RE_AUTHENTIC == 0
uStack_85c = 0; uStack_85c = 0;
SystemParametersInfoA(0x61, 0, &uStack_85c, 0); SystemParametersInfoA(0x61, 0, &uStack_85c, 0);
ShowCursor(1); ShowCursor(1);
SystemParametersInfoA(0x11, uiParam, (PVOID)0x0, 0); SystemParametersInfoA(0x11, uiParam, (PVOID)0x0, 0);
CloseHandle(lpBuffer); #endif
CloseHandle(duplicatedHandle);
} }
return 0; return 0;
} }

View File

@ -0,0 +1,106 @@
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
#include <r3/binders/auto.h>
#include <gh_global.h>
#include <r3/config/static.hpp>
extern "C" {
undefined
r3_config_setIdentifier(char *param_1); // 00470570 // r3_config_setIdentifier
void r3_set_GameDataPath(char *param_1); // 0055a8d0 // r3_set_GameDataPath
void r3_config_setTexturesMem(
char *param_1); // 00470f30 // r3_config_setTexturesMem
void r3_noop(void *p_cTxt1, void *p_cTxt2); // 00401100 // r3_noop
undefined
r3_read_game_config_udp_port(void); // 00446040 // r3_read_game_config_udp_port
undefined
r3_config_setGLIMode(char *param_1); // 004704e0 // r3_config_setGLIMode
undefined r3_read_game_config_modem_quality(
void); // 00445fc0 // r3_read_game_config_modem_quality
// 004460c0
/* WARNING: Inlined function: r3_config_set_adapter */
/* WARNING: Inlined function: r3_config_setTexturesCompressed */
/* WARNING: Inlined function: r3_config_setTnl */
/* WARNING: Inlined function: r3_config_setTrilinearFiltering */
void r3_read_gli_config(void)
{
UINT tempOutVal;
void *pcVar2;
void *pcVar3;
HANDLE hProcess;
int iVar4;
char *pcVar1;
char *pcVar4;
void *in_stack_fffffce0;
char *ptr0;
char *ptr1;
char local_218[20];
char local_204[168];
char local_15c[32];
char stringBuffer[256];
char cVar1;
DWORD_PTR dwProcessAffinityMask;
const char *iniPath = getIniPath();
GetPrivateProfileStringA(lpAppName_005b68f0, s_GLI_Mode_005be3e0,
g_default_display_mode, stringBuffer, 0xff, iniPath);
r3_config_setGLIMode(stringBuffer);
g_GLI_adapter =
GetPrivateProfileIntA(lpAppName_005b68f0, s_Adapter_005b68e4, 0, iniPath);
/* set adapter */
GetPrivateProfileStringA(lpAppName_005b68f0, s_Identifier_005b6420,
(LPCSTR)&lpDefault_005cf96c, stringBuffer, 0xff,
iniPath);
r3_config_setIdentifier(stringBuffer);
tempOutVal = GetPrivateProfileIntA(lpAppName_005b68f0,
s_TexturesCompressed_005be3cc, 0, iniPath);
g_config_tex_compressed = (undefined1)tempOutVal;
tempOutVal =
GetPrivateProfileIntA(lpAppName_005b68f0, (LPCSTR)&s_Tnl, 0, iniPath);
g_GLI_tnl = (undefined1)tempOutVal;
tempOutVal = GetPrivateProfileIntA(lpAppName_005b68f0, s_TriLinear_005be3bc,
0, iniPath);
g_GLI_trilinear = (undefined1)tempOutVal;
pcVar2 = (void *)GetPrivateProfileIntA(lpAppName_005b68f0,
s_DynamicShadows_005be3ac, 0, iniPath);
pcVar3 = (void *)GetPrivateProfileIntA(lpAppName_005b68f0,
s_StaticShadows_005be39c, 0, iniPath);
//r3_noop(pcVar2, pcVar3);
pcVar2 = (void *)GetPrivateProfileIntA(lpAppName_005b68f0, s_Outline_005be394,
0, iniPath);
//r3_noop(pcVar2, in_stack_fffffce0);
GetPrivateProfileStringA(lpAppName_005b68f0, s_TexturesMem_005be384,
(LPCSTR)&s_Agp, stringBuffer, 0xff, iniPath);
r3_config_setTexturesMem(stringBuffer);
GetPrivateProfileStringA(lpAppName_005b68f0, s_SoundOnHD_005be374, "0",
stringBuffer, 0x104, iniPath);
sscanf(stringBuffer, s_percent_d, &g_soundOnHD);
GetPrivateProfileStringA(lpAppName_005b68f0, s_Complete_005be364, "1",
stringBuffer, 0x104, iniPath);
sscanf(stringBuffer, s_percent_d, &g_complete);
g_config_unused0 = 0;
g_config_camera_hor_axis = GetPrivateProfileIntA(
lpAppName_005b68f0, s_Camera_HorizontalAxis_005be34c, 2, iniPath);
g_config_camera_ver_axis = GetPrivateProfileIntA(
lpAppName_005b68f0, s_Camera_VerticalAxis_005be338, 5, iniPath);
GetPrivateProfileStringA(lpAppName_005b68f0, s_StartDirectory_005be31c,
s_Gamedata_005be32c, stringBuffer, 0x104, iniPath);
r3_set_GameDataPath(stringBuffer);
GetPrivateProfileStringA(lpAppName_005b68f0, s_SingleProcessor_005be308, "No",
stringBuffer, 0x104, iniPath);
/* Set single processor mode */
iVar4 = strcmpi(stringBuffer, (char *)&s_Yes);
if (iVar4 == 0) {
dwProcessAffinityMask = 1;
hProcess = GetCurrentProcess();
SetProcessAffinityMask(hProcess, dwProcessAffinityMask);
}
r3_read_game_config_modem_quality();
r3_read_game_config_udp_port();
return;
}
}

View File

@ -0,0 +1,63 @@
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
#include <r3/binders/auto.h>
#include <gh_global.h>
extern "C" {
undefined r3_windowUnlockCursor(void); // 004013a0 // r3_windowUnlockCursor
undefined FUN_00401320(void); // 00401320 // FUN_00401320
// 004025e0
long CALLBACK r3_windowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
long lVar1;
if (uMsg < WM_SETCURSOR + 1) {
if (uMsg == WM_SETCURSOR) {
if (((g_engineShouldRun != 0) && (g_engineRunning != 0)) && (g_runMaximized != 0)) {
FUN_00401320();
return 1;
}
}
else {
if (uMsg == WM_CLOSE) {
r3_windowUnlockCursor();
g_windowCloseRequested = 1;
if (g_drawSemaphore != (HANDLE)0x0) {
CloseHandle(g_drawSemaphore);
}
g_drawSemaphore = (HANDLE)0x0;
PostQuitMessage(0);
return 0;
}
if (uMsg == WM_ACTIVATEAPP) {
g_engineShouldRun = wParam;
}
}
}
else {
if (uMsg != WM_NCHITTEST) {
if (uMsg != WM_SYSCOMMAND) goto LAB_004026ab;
/* handle SYSCOMMAND */
if (wParam < SC_MAXIMIZE + 1) {
if ((wParam != SC_MAXIMIZE) && ((wParam != SC_SIZE && (wParam != SC_MOVE))))
goto LAB_004026ab;
}
else if ((wParam != SC_KEYMENU) && (wParam != SC_MONITORPOWER)) goto LAB_004026ab;
}
/* WM_NCHITTEST
*/
if (g_runMaximized != 0) {
return 1;
}
}
LAB_004026ab:
/* WARNING: Could not recover jumptable at 0x004026b3. Too many branches */
/* WARNING: Treating indirect jump as call */
lVar1 = DefWindowProcA(hwnd,uMsg,wParam,lParam);
return lVar1;
}
}

View File

@ -0,0 +1,105 @@
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
#include <r3/binders/auto.h>
#include <gh_global.h>
extern "C" {
long CALLBACK r3_windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // 004025e0 // r3_windowProc
undefined fn_bCreateMainDisplayScreen(void); // 004022f0 // fn_bCreateMainDisplayScreen
void loadSplashBitmap(HWND unused); // 00402450 // loadSplashBitmap
void setGameHWND3(HWND wnd); // 0043e620 // setGameHWND3
// 00402140
int setupWindow(HINSTANCE instance,undefined4 param_2,int windowedParam)
{
ATOM AVar1;
int windowHeight;
int yCaption;
HWND hWnd;
HWND pHVar2;
int r0;
BOOL success;
bool windowed;
GLD_DeviceAttributes *windowParams;
DWORD dwStyle;
WNDCLASSA wndClass;
int showWindow;
int windowWidth;
g_windowInitialized = 1;
/* WindowClassA (overlaps usage below) */
wndClass.style = 0x3003;
wndClass.lpfnWndProc = r3_windowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = instance;
wndClass.hIcon = LoadIconA(instance,(LPCSTR)0x65);
wndClass.hCursor = LoadCursorA((HINSTANCE)0x0,(LPCSTR)0x7f00);
wndClass.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME;
wndClass.lpszMenuName = (LPCSTR)0x0;
wndClass.lpszClassName = g_windowTitle;
AVar1 = RegisterClassA(&wndClass);
if (AVar1 != 0) {
windowed = windowedParam == 0;
if (windowed) {
/* SM_CXSIZEFRAME */
windowWidth = GetSystemMetrics(32);
/* x*2 + 320 */
windowWidth = windowWidth * 2 + 320;
/* SM_CYSIZEFRAME, retrieves the size of the vertical resizing border */
windowHeight = GetSystemMetrics(33);
/* SM_CYCAPTION, The height of a caption area, in pixels */
yCaption = GetSystemMetrics(4);
/* ebp still 0 at this point */
windowHeight = yCaption + 240 + windowHeight * 2;
dwStyle = 0x90cf0000;
}
else {
windowHeight = 0xf0;
windowWidth = 0x140;
dwStyle = 0x91000000;
}
hWnd = CreateWindowExA(0,g_windowTitle,g_windowTitle,dwStyle,(uint)windowed,(uint)windowed,
windowWidth,windowHeight,(HWND)0x0,(HMENU)0x0,instance,(LPVOID)0x0);
g_gameHWND1 = hWnd;
if (hWnd != (HWND)0x0) {
g_gameHWND = hWnd;
SetWindowTextA(hWnd,s_windowTitle);
if (windowedParam == 0) {
/* SW_NORMAL */
showWindow = 1;
}
else {
/* SW_MAXIMIZE */
showWindow = 3;
}
ShowWindow(hWnd,showWindow);
SetWindowPos(hWnd,(HWND)0x0,0,0,0,0,0x43);
EnableWindow(hWnd,1);
SetFocus(hWnd);
UpdateWindow(hWnd);
SetForegroundWindow(hWnd);
pHVar2 = GetFocus();
while (pHVar2 != hWnd) {
SetWindowPos(hWnd,(HWND)0x0,0,0,0,0,0x43);
EnableWindow(hWnd,1);
SetFocus(hWnd);
UpdateWindow(hWnd);
SetForegroundWindow(hWnd);
pHVar2 = GetFocus();
}
setGameHWND3(hWnd);
loadSplashBitmap(hWnd);
/* unused? */
g_windowInitialized = 1;
r0 = fn_bCreateMainDisplayScreen();
return r0;
}
}
/* Failed */
return 0;
}
}

View File

@ -59,6 +59,7 @@ char(&lpAppName_005b68f0)[8] = reinterpret_cast<char(&)[8]>(GH_MEM(0x005b68f0));
const char* s_Directory_005b68f8 = "Directory"; // 005b68f8 const char* s_Directory_005b68f8 = "Directory"; // 005b68f8
const char* s_None = "None"; // 005b6904 const char* s_None = "None"; // 005b6904
const char* s_UbiSoft_Ubi_ini = "/UbiSoft/Ubi.ini"; // 005b690c const char* s_UbiSoft_Ubi_ini = "/UbiSoft/Ubi.ini"; // 005b690c
const char* s_percent_d = "%d"; // 005bad58
undefined1& g_errModDInput= (undefined1&) GH_MEM(0x005bd29c); undefined1& g_errModDInput= (undefined1&) GH_MEM(0x005bd29c);
undefined4& DAT_005bd454= (undefined4&) GH_MEM(0x005bd454); undefined4& DAT_005bd454= (undefined4&) GH_MEM(0x005bd454);
const char* s__jc_z_d__s_005bd460 = "\\jc\\z%d:%s"; // 005bd460 const char* s__jc_z_d__s_005bd460 = "\\jc\\z%d:%s"; // 005bd460
@ -70,6 +71,27 @@ const char* s_Die__s_DVDROM_kann_nicht_gelesen_005be130 = "Die %s DVDROM kann ni
const char* s_Impossibile_trovare_il_DVD____s_005be198 = "Impossibile trovare il DVD : %s"; // 005be198 const char* s_Impossibile_trovare_il_DVD____s_005be198 = "Impossibile trovare il DVD : %s"; // 005be198
const char* s_DVD_s_no_v_lido_005be1ec = "DVD %s no v£lido "; // 005be1ec const char* s_DVD_s_no_v_lido_005be1ec = "DVD %s no v£lido "; // 005be1ec
const char* s_Impossible_de_trouver_le_DVD_____005be238 = "Impossible de trouver le DVD : %s"; // 005be238 const char* s_Impossible_de_trouver_le_DVD_____005be238 = "Impossible de trouver le DVD : %s"; // 005be238
pointer& s_Yes= (pointer&) GH_MEM(0x005be304);
const char* s_SingleProcessor_005be308 = "SingleProcessor"; // 005be308
const char* lpDefault_005be318 = "No"; // 005be318
const char* s_StartDirectory_005be31c = "StartDirectory"; // 005be31c
const char* s_Gamedata_005be32c = "Gamedata"; // 005be32c
const char* s_Camera_VerticalAxis_005be338 = "Camera_VerticalAxis"; // 005be338
const char* s_Camera_HorizontalAxis_005be34c = "Camera_HorizontalAxis"; // 005be34c
const char* s_Complete_005be364 = "Complete"; // 005be364
const char* lpDefault_005be370 = "1"; // 005be370
const char* s_SoundOnHD_005be374 = "SoundOnHD"; // 005be374
const char* lpDefault_005be380 = "0"; // 005be380
const char* s_TexturesMem_005be384 = "TexturesMem"; // 005be384
pointer& s_Agp= (pointer&) GH_MEM(0x005be390);
const char* s_Outline_005be394 = "Outline"; // 005be394
const char* s_StaticShadows_005be39c = "StaticShadows"; // 005be39c
const char* s_DynamicShadows_005be3ac = "DynamicShadows"; // 005be3ac
const char* s_TriLinear_005be3bc = "TriLinear"; // 005be3bc
pointer& s_Tnl= (pointer&) GH_MEM(0x005be3c8);
const char* s_TexturesCompressed_005be3cc = "TexturesCompressed"; // 005be3cc
const char* s_GLI_Mode_005be3e0 = "GLI_Mode"; // 005be3e0
const char* g_default_display_mode = "1 - 640 x 480 x 16"; // 005be3ec
const char* s_Please_insert_the_DVD_in_the_DVD_005be400 = "Please insert the DVD in the DVD-Rom drive."; // 005be400 const char* s_Please_insert_the_DVD_in_the_DVD_005be400 = "Please insert the DVD in the DVD-Rom drive."; // 005be400
const char* s_Bitte_legen_Sie_DVD_von_Rayman_3_005be438 = "Bitte legen Sie DVD von Rayman 3 in Ihr DVD-ROM Laufwerk ein."; // 005be438 const char* s_Bitte_legen_Sie_DVD_von_Rayman_3_005be438 = "Bitte legen Sie DVD von Rayman 3 in Ihr DVD-ROM Laufwerk ein."; // 005be438
const char* s_Inserisci_il_DVD_di_Rayman_3_nel_005be484 = "Inserisci il DVD di Rayman 3 nel lettore DVD-ROM."; // 005be484 const char* s_Inserisci_il_DVD_di_Rayman_3_nel_005be484 = "Inserisci il DVD di Rayman 3 nel lettore DVD-ROM."; // 005be484
@ -78,6 +100,8 @@ const char* s_Veuillez_ins_rer_le_DVD_dans_vot_005be500 = "Veuillez ins←rer le
const char* s_fmt_c_colon_s = "%c:%s"; // 005be540 const char* s_fmt_c_colon_s = "%c:%s"; // 005be540
const char* s_r3_program_files = "\\program files\\Ubi Soft\\Rayman3"; // 005be548 const char* s_r3_program_files = "\\program files\\Ubi Soft\\Rayman3"; // 005be548
const char* s_driveLetterTemplate = "A:\\"; // 005be568 const char* s_driveLetterTemplate = "A:\\"; // 005be568
undefined4& g_config_camera_hor_axis= (undefined4&) GH_MEM(0x005c67c8);
undefined4& g_config_camera_ver_axis= (undefined4&) GH_MEM(0x005c67cc);
HWND& g_gameHWND1= (HWND&) GH_MEM(0x005cf964); HWND& g_gameHWND1= (HWND&) GH_MEM(0x005cf964);
long& lpDefault_005cf96c= (long&) GH_MEM(0x005cf96c); long& lpDefault_005cf96c= (long&) GH_MEM(0x005cf96c);
dword& DWORD_005cf974= (dword&) GH_MEM(0x005cf974); dword& DWORD_005cf974= (dword&) GH_MEM(0x005cf974);
@ -88,8 +112,13 @@ char *& PTR_005cf9b4= (char *&) GH_MEM(0x005cf9b4);
GameStructure& g_currentBinkMovie= (GameStructure&) GH_MEM(0x005d2660); GameStructure& g_currentBinkMovie= (GameStructure&) GH_MEM(0x005d2660);
char(&s_volumeNameBuffer)[128] = reinterpret_cast<char(&)[128]>(GH_MEM(0x005d27b0)); char(&s_volumeNameBuffer)[128] = reinterpret_cast<char(&)[128]>(GH_MEM(0x005d27b0));
r3_main_data& r3_main_data_005d28b6= (r3_main_data&) GH_MEM(0x005d28b6); r3_main_data& r3_main_data_005d28b6= (r3_main_data&) GH_MEM(0x005d28b6);
undefined4& g_soundOnHD= (undefined4&) GH_MEM(0x005d29bc);
undefined4& g_complete= (undefined4&) GH_MEM(0x005d29c0);
int& g_windowInitialized= (int&) GH_MEM(0x0077d0a4);
int& g_runMaximized= (int&) GH_MEM(0x0077d0a8); int& g_runMaximized= (int&) GH_MEM(0x0077d0a8);
undefined4& g_engineShouldRun= (undefined4&) GH_MEM(0x0077d0b0);
undefined4& g_engineRunning= (undefined4&) GH_MEM(0x0077d0b4); undefined4& g_engineRunning= (undefined4&) GH_MEM(0x0077d0b4);
undefined4& g_windowCloseRequested= (undefined4&) GH_MEM(0x0077d0b8);
HANDLE& g_drawSemaphore= (HANDLE&) GH_MEM(0x0077d0bc); HANDLE& g_drawSemaphore= (HANDLE&) GH_MEM(0x0077d0bc);
char(&g_mutexName_Rayman3)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d0c0)); char(&g_mutexName_Rayman3)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d0c0));
char(&g_windowTitle)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d1c0)); char(&g_windowTitle)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d1c0));
@ -104,4 +133,9 @@ char *& g_crt_cmdLine= (char *&) GH_MEM(0x0077ea84);
char(&s_quitting1)[64] = reinterpret_cast<char(&)[64]>(GH_MEM(0x007825c0)); char(&s_quitting1)[64] = reinterpret_cast<char(&)[64]>(GH_MEM(0x007825c0));
char(&s_wndStrQuiting)[56] = reinterpret_cast<char(&)[56]>(GH_MEM(0x00782600)); char(&s_wndStrQuiting)[56] = reinterpret_cast<char(&)[56]>(GH_MEM(0x00782600));
undefined4& DAT_007d9cc4= (undefined4&) GH_MEM(0x007d9cc4); undefined4& DAT_007d9cc4= (undefined4&) GH_MEM(0x007d9cc4);
undefined4& g_config_unused0= (undefined4&) GH_MEM(0x007d9df0);
char(&g_driveLetter)[4] = reinterpret_cast<char(&)[4]>(GH_MEM(0x007d9e70)); char(&g_driveLetter)[4] = reinterpret_cast<char(&)[4]>(GH_MEM(0x007d9e70));
undefined4& g_GLI_adapter= (undefined4&) GH_MEM(0x007edd60);
undefined1& g_GLI_tnl= (undefined1&) GH_MEM(0x007edd64);
undefined1& g_config_tex_compressed= (undefined1&) GH_MEM(0x007edd65);
undefined1& g_GLI_trilinear= (undefined1&) GH_MEM(0x007edd66);

View File

@ -64,6 +64,7 @@ extern char(&lpAppName_005b68f0)[8]; // 005b68f0
extern const char* s_Directory_005b68f8; // 005b68f8 extern const char* s_Directory_005b68f8; // 005b68f8
extern const char* s_None; // 005b6904 extern const char* s_None; // 005b6904
extern const char* s_UbiSoft_Ubi_ini; // 005b690c extern const char* s_UbiSoft_Ubi_ini; // 005b690c
extern const char* s_percent_d; // 005bad58
extern undefined1& g_errModDInput; // 005bd29c extern undefined1& g_errModDInput; // 005bd29c
extern undefined4& DAT_005bd454; // 005bd454 extern undefined4& DAT_005bd454; // 005bd454
extern const char* s__jc_z_d__s_005bd460; // 005bd460 extern const char* s__jc_z_d__s_005bd460; // 005bd460
@ -75,6 +76,27 @@ extern const char* s_Die__s_DVDROM_kann_nicht_gelesen_005be130; // 005be130
extern const char* s_Impossibile_trovare_il_DVD____s_005be198; // 005be198 extern const char* s_Impossibile_trovare_il_DVD____s_005be198; // 005be198
extern const char* s_DVD_s_no_v_lido_005be1ec; // 005be1ec extern const char* s_DVD_s_no_v_lido_005be1ec; // 005be1ec
extern const char* s_Impossible_de_trouver_le_DVD_____005be238; // 005be238 extern const char* s_Impossible_de_trouver_le_DVD_____005be238; // 005be238
extern pointer& s_Yes; // 005be304
extern const char* s_SingleProcessor_005be308; // 005be308
extern const char* lpDefault_005be318; // 005be318
extern const char* s_StartDirectory_005be31c; // 005be31c
extern const char* s_Gamedata_005be32c; // 005be32c
extern const char* s_Camera_VerticalAxis_005be338; // 005be338
extern const char* s_Camera_HorizontalAxis_005be34c; // 005be34c
extern const char* s_Complete_005be364; // 005be364
extern const char* lpDefault_005be370; // 005be370
extern const char* s_SoundOnHD_005be374; // 005be374
extern const char* lpDefault_005be380; // 005be380
extern const char* s_TexturesMem_005be384; // 005be384
extern pointer& s_Agp; // 005be390
extern const char* s_Outline_005be394; // 005be394
extern const char* s_StaticShadows_005be39c; // 005be39c
extern const char* s_DynamicShadows_005be3ac; // 005be3ac
extern const char* s_TriLinear_005be3bc; // 005be3bc
extern pointer& s_Tnl; // 005be3c8
extern const char* s_TexturesCompressed_005be3cc; // 005be3cc
extern const char* s_GLI_Mode_005be3e0; // 005be3e0
extern const char* g_default_display_mode; // 005be3ec
extern const char* s_Please_insert_the_DVD_in_the_DVD_005be400; // 005be400 extern const char* s_Please_insert_the_DVD_in_the_DVD_005be400; // 005be400
extern const char* s_Bitte_legen_Sie_DVD_von_Rayman_3_005be438; // 005be438 extern const char* s_Bitte_legen_Sie_DVD_von_Rayman_3_005be438; // 005be438
extern const char* s_Inserisci_il_DVD_di_Rayman_3_nel_005be484; // 005be484 extern const char* s_Inserisci_il_DVD_di_Rayman_3_nel_005be484; // 005be484
@ -83,6 +105,8 @@ extern const char* s_Veuillez_ins_rer_le_DVD_dans_vot_005be500; // 005be500
extern const char* s_fmt_c_colon_s; // 005be540 extern const char* s_fmt_c_colon_s; // 005be540
extern const char* s_r3_program_files; // 005be548 extern const char* s_r3_program_files; // 005be548
extern const char* s_driveLetterTemplate; // 005be568 extern const char* s_driveLetterTemplate; // 005be568
extern undefined4& g_config_camera_hor_axis; // 005c67c8
extern undefined4& g_config_camera_ver_axis; // 005c67cc
extern HWND& g_gameHWND1; // 005cf964 extern HWND& g_gameHWND1; // 005cf964
extern long& lpDefault_005cf96c; // 005cf96c extern long& lpDefault_005cf96c; // 005cf96c
extern dword& DWORD_005cf974; // 005cf974 extern dword& DWORD_005cf974; // 005cf974
@ -93,8 +117,13 @@ extern char *& PTR_005cf9b4; // 005cf9b4
extern GameStructure& g_currentBinkMovie; // 005d2660 extern GameStructure& g_currentBinkMovie; // 005d2660
extern char(&s_volumeNameBuffer)[128]; // 005d27b0 extern char(&s_volumeNameBuffer)[128]; // 005d27b0
extern r3_main_data& r3_main_data_005d28b6; // 005d28b6 extern r3_main_data& r3_main_data_005d28b6; // 005d28b6
extern undefined4& g_soundOnHD; // 005d29bc
extern undefined4& g_complete; // 005d29c0
extern int& g_windowInitialized; // 0077d0a4
extern int& g_runMaximized; // 0077d0a8 extern int& g_runMaximized; // 0077d0a8
extern undefined4& g_engineShouldRun; // 0077d0b0
extern undefined4& g_engineRunning; // 0077d0b4 extern undefined4& g_engineRunning; // 0077d0b4
extern undefined4& g_windowCloseRequested; // 0077d0b8
extern HANDLE& g_drawSemaphore; // 0077d0bc extern HANDLE& g_drawSemaphore; // 0077d0bc
extern char(&g_mutexName_Rayman3)[256]; // 0077d0c0 extern char(&g_mutexName_Rayman3)[256]; // 0077d0c0
extern char(&g_windowTitle)[256]; // 0077d1c0 extern char(&g_windowTitle)[256]; // 0077d1c0
@ -109,5 +138,10 @@ extern char *& g_crt_cmdLine; // 0077ea84
extern char(&s_quitting1)[64]; // 007825c0 extern char(&s_quitting1)[64]; // 007825c0
extern char(&s_wndStrQuiting)[56]; // 00782600 extern char(&s_wndStrQuiting)[56]; // 00782600
extern undefined4& DAT_007d9cc4; // 007d9cc4 extern undefined4& DAT_007d9cc4; // 007d9cc4
extern undefined4& g_config_unused0; // 007d9df0
extern char(&g_driveLetter)[4]; // 007d9e70 extern char(&g_driveLetter)[4]; // 007d9e70
extern undefined4& g_GLI_adapter; // 007edd60
extern undefined1& g_GLI_tnl; // 007edd64
extern undefined1& g_config_tex_compressed; // 007edd65
extern undefined1& g_GLI_trilinear; // 007edd66
#endif // GH_GENERATED_GLOBALS_H #endif // GH_GENERATED_GLOBALS_H

View File

@ -6,8 +6,8 @@
#include <r3/binders/stub.h> #include <r3/binders/stub.h>
#include <gh_global.h> #include <gh_global.h>
// 00402140 // 004022f0
// setupWindow // fn_bCreateMainDisplayScreen
extern "C" int setupWindow(HINSTANCE instance, undefined4 param_2, int windowedParam) { extern "C" undefined fn_bCreateMainDisplayScreen(void) {
return gh_stub_impl_stdcall<int>((void*)0x00402140, instance, param_2, windowedParam); return gh_stub_impl_cdecl<undefined>((void*)0x004022f0);
} }

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 00402450
// loadSplashBitmap
extern "C" void loadSplashBitmap(HWND unused) {
gh_stub_impl_stdcall<void>((void*)0x00402450, unused);
}

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 004704e0
// r3_config_setGLIMode
extern "C" undefined r3_config_setGLIMode(char * param_1) {
return gh_stub_impl_cdecl<undefined>((void*)0x004704e0, param_1);
}

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 00470570
// r3_config_setIdentifier
extern "C" undefined r3_config_setIdentifier(char * param_1) {
return gh_stub_impl_cdecl<undefined>((void*)0x00470570, param_1);
}

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 00470f30
// r3_config_setTexturesMem
extern "C" void r3_config_setTexturesMem(char * param_1) {
gh_stub_impl_cdecl<void>((void*)0x00470f30, param_1);
}

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 00445fc0
// r3_read_game_config_modem_quality
extern "C" undefined r3_read_game_config_modem_quality(void) {
return gh_stub_impl_cdecl<undefined>((void*)0x00445fc0);
}

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 00446040
// r3_read_game_config_udp_port
extern "C" undefined r3_read_game_config_udp_port(void) {
return gh_stub_impl_cdecl<undefined>((void*)0x00446040);
}

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 0055a8d0
// r3_set_GameDataPath
extern "C" void r3_set_GameDataPath(char * param_1) {
gh_stub_impl_cdecl<void>((void*)0x0055a8d0, param_1);
}

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 004013a0
// r3_windowUnlockCursor
extern "C" undefined r3_windowUnlockCursor(void) {
return gh_stub_impl_cdecl<undefined>((void*)0x004013a0);
}

View File

@ -0,0 +1,13 @@
// AUTO-GENERATED FILE!!!!
// This function has yet to be decompiled using 'Dump Current Function' in ghidra
// with possible manualy fixes
#include <r3/binders/auto.h>
#include <r3/binders/stub.h>
#include <gh_global.h>
// 0043e620
// setGameHWND3
extern "C" void setGameHWND3(HWND wnd) {
gh_stub_impl_stdcall<void>((void*)0x0043e620, wnd);
}

View File

@ -33,6 +33,12 @@ struct R3Bin {
g_gh_translationOffset = translationOffset = g_gh_translationOffset = translationOffset =
uintptr_t(module) - GH_BASE_ADDR; uintptr_t(module) - GH_BASE_ADDR;
std::string msg = fmt::format("Rayman3.exe Base address: 0x{:x}\n", uintptr_t(module));
OutputDebugStringA(msg.c_str());
msg = fmt::format("Rayman3.exe Translation offset: 0x{:x}\n", translationOffset);
OutputDebugStringA(msg.c_str());
// Now we have to relocate the module to the new base address // Now we have to relocate the module to the new base address
relocateModule(); relocateModule();
patchFunctions(); patchFunctions();

View File

@ -33,6 +33,7 @@ struct R3Config {
int cameraHorizontalAxis = 2; int cameraHorizontalAxis = 2;
int cameraVerticalAxis = 5; int cameraVerticalAxis = 5;
std::string gameDataBinPath; std::string gameDataBinPath;
std::string iniPath;
}; };
inline R3Config createDefaultConfig() { inline R3Config createDefaultConfig() {
@ -51,6 +52,7 @@ inline R3Config createDefaultConfig() {
config.gfxTnl = true; config.gfxTnl = true;
config.gfxTexturesCompressed = false; config.gfxTexturesCompressed = false;
config.gameDataBinPath = "Gamedatabin"; config.gameDataBinPath = "Gamedatabin";
config.iniPath = config.gameRootDir + "\\" + "ubi.ini";
return config; return config;
} }
@ -59,4 +61,8 @@ inline R3Config &getDefaultConfig() {
return config; return config;
} }
inline const char *getIniPath() {
return getDefaultConfig().iniPath.c_str();
}
#endif /* D9171C14_8ED0_407B_A289_4C75D30D9DCC */ #endif /* D9171C14_8ED0_407B_A289_4C75D30D9DCC */

View File

@ -1,8 +1,8 @@
#!/bin/bash #!/bin/bash
script_dir=$(readlink -f $(dirname "$0")) script_dir=$(readlink -f $(dirname "$0"))
tool=$script_dir/../tooling/bin/r3_gh_tool tool=$script_dir/../tooling/bin/gh_tool
set -e set -ex
shopt -s nullglob shopt -s nullglob
pushd $script_dir pushd $script_dir
@ -19,12 +19,12 @@ for type in "${types[@]}"; do
any_files=true any_files=true
done done
if [ "$any_files" = true ]; then if [ "$any_files" = true ]; then
$tool "@$file_list" -v --type=$type --log-file=logs/log-functions-${type}.txt $tool -v --log-file=logs/log-functions-${type}.txt functions "@$file_list" --type=$type
fi fi
fi fi
done done
$tool gh_global.h -mglobals -v --log-file=logs/log-globals.txt $tool -v --log-file=logs/log-globals.txt globals gh_global.h
$tool -mduplicates -v --log-file=logs/log-duplicates.txt $tool -v --log-file=logs/log-verify.txt verify
popd popd

View File

@ -1,184 +0,0 @@
// Script to export decompiled C code from Ghidra
// @category _Reman3
// @menupath Reman3.Decompile All
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Arrays;
import java.util.Dictionary;
import ghidra.app.decompiler.ClangFieldToken;
import ghidra.app.decompiler.ClangLine;
import ghidra.app.decompiler.ClangSyntaxToken;
import ghidra.app.decompiler.ClangToken;
import ghidra.app.decompiler.DecompileResults;
import ghidra.app.decompiler.PrettyPrinter;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.AbstractStringDataType;
import ghidra.program.model.data.Array;
import ghidra.program.model.data.ArrayDataType;
import ghidra.program.model.data.BitFieldDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeComponent;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.EnumDataType;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.ProgramBasedDataTypeManager;
import ghidra.program.model.data.Structure;
import ghidra.program.model.data.TypedefDataType;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.VariableStorage;
import ghidra.program.model.pcode.HighFunction;
import ghidra.program.model.pcode.HighSymbol;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.Symbol;
import ghidra.util.task.TaskMonitor;
import re3lib.*;
public class Decompile extends GhidraScript {
// void headerGuardPre(PrintWriter writer, String tag) {
// writer.println("#ifndef GH_GENERATED_" + tag + "_H");
// writer.println("#define GH_GENERATED_" + tag + "_H");
// writer.println();
// }
// void headerGuardPost(PrintWriter writer, String tag) {
// writer.println("#endif // GH_GENERATED_" + tag + "_H");
// }
// void dumpGlobals(Hashtable<String, GlobalRec> globalSymbols) throws Exception {
// File globalSymbolsListH = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.h");
// PrintWriter hwriter = new PrintWriter(globalSymbolsListH, "UTF-8");
// hwriter.println("// AUTO-GENERATED FILE ");
// headerGuardPre(hwriter, "GLOBALS");
// hwriter.println("#include <r3/binder/global.h>");
// hwriter.println();
// File globalSymbolsListC = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.cxx");
// PrintWriter cwriter = new PrintWriter(globalSymbolsListC, "UTF-8");
// cwriter.println("// AUTO-GENERATED FILE ");
// cwriter.println("#include <r3/binder/global.h>");
// hwriter.println();
// for (GlobalRec sym : globalSymbols.values()) {
// HighSymbol highSym = sym.highSymbol;
// DataType dt = highSym.getDataType();
// String dataType = dt.getDisplayName();
// String sanitizedName = sanitizeFunctionName(highSym.getName());
// String name = highSym.getName();
// if (!sanitizedName.equals(name)) {
// println("Invalid global symbol name: " + name);
// name = sanitizedName;
// }
// Address addr = sym.address;
// // println("Symbol: " + symbol + " Addr: " + addr + " Size:" + symSize + " " +
// // storage.getSerializationString());
// try {
// String initBlk = " = ";
// boolean fullyDefinedType = false;
// if (dt instanceof AbstractStringDataType) {
// AbstractStringDataType sdt = (AbstractStringDataType) dt;
// dataType = "const char*";
// // String type
// initBlk += "\"" + escapeCString(readCString(addr, 2048)) + "\"";
// fullyDefinedType = true;
// } else if (dt instanceof PointerDataType) {
// PointerDataType pdt = (PointerDataType) dt;
// DataType baseType = pdt.getDataType();
// dataType = baseType.getDisplayName() + "*";
// initBlk += "(" + dataType + ")&GH_MEM(0x" + addr + ")";
// fullyDefinedType = true;
// }
// if (fullyDefinedType) {
// hwriter.println("extern " + dataType + " " + name + "; // " + addr);
// cwriter.println(dataType + " " + name + initBlk + "; // " + addr);
// } else {
// if (dt instanceof Array) {
// // println("Array: " + dt.getDisplayName() + " - " + addr + " - " +
// // dt.getClass().getSimpleName());
// Array adt = (Array) dt;
// DataType baseType = adt.getDataType();
// hwriter.println(
// "extern " + baseType.getDisplayName() + "(&" + name + ")[" + adt.getNumElements() + "]; // " + addr);
// cwriter.println(
// baseType.getDisplayName() + "(&" + name + ")[" + adt.getNumElements() + "] = *reinterpret_cast<"
// + baseType.getDisplayName() + "(*)[" + adt.getNumElements() + "]>(GH_MEM(0x" + addr + "));");
// } else {
// String refTypeStr = dt.getDisplayName() + "&";
// hwriter.println("extern " + refTypeStr + " " + name + "; // " + addr);
// cwriter.println(dataType + " " + name + "= (" + refTypeStr + ") GH_MEM(0x" + addr + ");");
// }
// }
// } catch (Exception e) {
// println("Error processing global symbol: " + e);
// println("Symbol: " + highSym.getName() + " - " + addr + " - "
// + highSym.getHighFunction().getFunction().getName());
// }
// }
// headerGuardPost(hwriter, "GLOBALS");
// hwriter.close();
// cwriter.close();
// }
void decompileAll(List<Function> functions) throws Exception {
// Hashtable<String, GlobalRec> globalSymbols = new Hashtable<>();
// for (Function function : functions) {
// decompileFunction(globalSymbols, function);
// }
// dumpStructureTypes();
// dumpGlobals(globalSymbols);
}
@Override
public void run() throws Exception {
if (currentProgram == null) {
return;
}
RemanConfig.INSTANCE = new RemanConfig(this);
if (!new File(RemanConfig.INSTANCE.outputDir).exists()) {
throw new Exception("Output directory does not exist: " + RemanConfig.INSTANCE.outputDir);
}
// Make sure to create output folders
RemanConfig.INSTANCE.dirDecompFix.mkdirs();
RemanConfig.INSTANCE.dirDecompAuto.mkdirs();
RemanConfig.INSTANCE.dirDecompRef.mkdirs();
// buildFunctionBlacklist();
List<Function> functions = new ArrayList<>();
Iterator<Function> functionsIt = currentProgram.getFunctionManager().getFunctions(true).iterator();
while (functionsIt.hasNext()) {
Function function = functionsIt.next();
// if (!shouldDecompileFunction(function)) {
// continue;
// }
functions.add(function);
}
decompileAll(functions);
}
String sanitizeFunctionName(String name) {
return name.replaceAll("[^a-zA-Z0-9_]", "_");
}
}

View File

@ -0,0 +1,37 @@
// Script to regenerate all dumped stub functions
// @category _Reman3
// @menupath Reman3.Redump Stub Functions
import java.util.List;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.Function;
import re3lib.GlobalDumper;
import re3lib.RemanConfig;
import re3lib.TypeDumper;
import re3lib.FunctionDatabase;
import re3lib.FunctionDumper;
public class RedumpStubFunctions extends GhidraScript {
@Override
protected void run() throws Exception {
RemanConfig.INSTANCE = new RemanConfig(this);
RemanConfig.INSTANCE.createDirectories();
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
List<FunctionDatabase.FunctionEntry> entries = functionDatabase.loadAllEntries();
FunctionDumper dumper = new FunctionDumper(this, functionDatabase, null);
for (FunctionDatabase.FunctionEntry entry : entries) {
if (entry.type == FunctionDatabase.Type.Stub) {
Function function = getFunctionAt(entry.address);
if (function == null) {
printerr("Function not found at address: " + entry.address);
continue;
}
println("Dumping stub function: " + function.getName());
dumper.dumpStubFunction(function);
}
}
}
}
}

View File

@ -108,6 +108,91 @@ public class FunctionDumper {
} }
} }
public void dumpStubFunction(Function externalFunction) throws Exception {
String sanitizedExtFunctionName = Utils.sanitizeIdentifier(externalFunction.getName());
List<FunctionDatabase.FunctionEntry> entries1 = functionDatabase
.findEntriesByAddress(externalFunction.getEntryPoint());
boolean needStub = true;
for (FunctionDatabase.FunctionEntry entry : entries1) {
if (entry.type == FunctionDatabase.Type.Auto || entry.type == FunctionDatabase.Type.Fix) {
needStub = false;
break;
}
}
if (!needStub)
return;
String fileName = sanitizedExtFunctionName + ".cxx";
File f4 = new File(RemanConfig.INSTANCE.dirDecompStub, fileName);
script.println("Generating function stub for " + externalFunction.getName() + " => " + f4.toString());
try (PrintWriter writer2 = new PrintWriter(f4, "UTF-8")) {
writer2.println("// AUTO-GENERATED FILE!!!!");
writer2.println("// This function has yet to be decompiled using 'Dump Current Function' in ghidra");
writer2.println("// with possible manualy fixes");
writer2.println();
writer2.println("#include <r3/binders/auto.h>");
writer2.println("#include <r3/binders/stub.h>");
writer2.println("#include <gh_global.h>");
writer2.println();
writer2.println("// " + externalFunction.getEntryPoint());
writer2.println("// " + externalFunction.getName());
// Parse function signature to extract calling convention, return type, and
// parameters
String signature = externalFunction.getSignature().getPrototypeString(false);
signature = signature.replace(externalFunction.getName(), sanitizedExtFunctionName);
script.println("Santized Signature: " + signature);
String callingConvention = externalFunction.getCallingConventionName();
String returnType = externalFunction.getReturnType().toString();
// Generate function stub using appropriate forwarding function
writer2.println("extern \"C\" " + signature + " {");
// Determine which stub function to use based on calling convention
String stubFunction;
if (callingConvention != null && callingConvention.equals("__stdcall")) {
stubFunction = "gh_stub_impl_stdcall";
} else {
// Default to cdecl for most cases
stubFunction = "gh_stub_impl_cdecl";
}
// Generate parameter list for the call
StringBuilder paramList = new StringBuilder();
var params = externalFunction.getParameters();
for (int i = 0; i < params.length; i++) {
if (i > 0)
paramList.append(", ");
paramList.append(params[i].getName());
}
// Generate the stub call
String addrString = "0x" +
externalFunction.getEntryPoint().toString().replace("0x", "");
if (returnType.equals("void")) {
writer2.println(" " + stubFunction + "<" + addrString + ", void>(" +
(paramList.length() > 0 ? ", " + paramList.toString() : "") + ");");
} else {
writer2.println(" return " + stubFunction + "<" + addrString + ", " + returnType + ">(" +
externalFunction.getEntryPoint().toString().replace("0x", "") +
(paramList.length() > 0 ? ", " + paramList.toString() : "") + ");");
}
writer2.println("}");
}
if (!f4.exists()) {
createdFile = true;
}
// Add stub function to database
FunctionDatabase.FunctionEntry newEntry = new FunctionDatabase.FunctionEntry(externalFunction.getEntryPoint(),
externalFunction.getName(), f4, FunctionDatabase.Type.Stub);
functionDatabase.addEntryAt(newEntry);
}
public void dump(Function function) public void dump(Function function)
throws Exception { throws Exception {
String sanitizedFunctionName = Utils.sanitizeIdentifier(function.getName()); String sanitizedFunctionName = Utils.sanitizeIdentifier(function.getName());
@ -346,82 +431,7 @@ public class FunctionDumper {
// Possibly generate stubs for external functions // Possibly generate stubs for external functions
for (Function externalFunction : externalFunctionCalls) { for (Function externalFunction : externalFunctionCalls) {
String sanitizedExtFunctionName = Utils.sanitizeIdentifier(externalFunction.getName()); dumpStubFunction(externalFunction);
List<FunctionDatabase.FunctionEntry> entries1 = functionDatabase
.findEntriesByAddress(externalFunction.getEntryPoint());
boolean needStub = true;
for (FunctionDatabase.FunctionEntry entry : entries1) {
if (entry.type == FunctionDatabase.Type.Auto || entry.type == FunctionDatabase.Type.Fix) {
needStub = false;
break;
}
}
if (!needStub)
continue;
fileName = sanitizedExtFunctionName + ".cxx";
File f4 = new File(RemanConfig.INSTANCE.dirDecompStub, fileName);
script.println("Generating function stub for " + externalFunction.getName() + " => " + f4.toString());
try (PrintWriter writer2 = new PrintWriter(f4, "UTF-8")) {
writer2.println("// AUTO-GENERATED FILE!!!!");
writer2.println("// This function has yet to be decompiled using 'Dump Current Function' in ghidra");
writer2.println("// with possible manualy fixes");
writer2.println();
writer2.println("#include <r3/binders/auto.h>");
writer2.println("#include <r3/binders/stub.h>");
writer2.println("#include <gh_global.h>");
writer2.println();
writer2.println("// " + externalFunction.getEntryPoint());
writer2.println("// " + externalFunction.getName());
// Parse function signature to extract calling convention, return type, and
// parameters
String signature = externalFunction.getSignature().getPrototypeString(false);
signature = signature.replace(externalFunction.getName(), sanitizedExtFunctionName);
script.println("Santiziaed Signature: " + signature);
String callingConvention = externalFunction.getCallingConventionName();
String returnType = externalFunction.getReturnType().toString();
// Generate function stub using appropriate forwarding function
writer2.println("extern \"C\" " + signature + " {");
// Determine which stub function to use based on calling convention
String stubFunction;
if (callingConvention != null && callingConvention.equals("__stdcall")) {
stubFunction = "gh_stub_impl_stdcall";
} else {
// Default to cdecl for most cases
stubFunction = "gh_stub_impl_cdecl";
}
// Generate parameter list for the call
StringBuilder paramList = new StringBuilder();
var params = externalFunction.getParameters();
for (int i = 0; i < params.length; i++) {
if (i > 0)
paramList.append(", ");
paramList.append(params[i].getName());
}
// Generate the stub call
if (returnType.equals("void")) {
writer2.println(" " + stubFunction + "<void>((void*)0x" +
externalFunction.getEntryPoint().toString().replace("0x", "") +
(paramList.length() > 0 ? ", " + paramList.toString() : "") + ");");
} else {
writer2.println(" return " + stubFunction + "<" + returnType + ">((void*)0x" +
externalFunction.getEntryPoint().toString().replace("0x", "") +
(paramList.length() > 0 ? ", " + paramList.toString() : "") + ");");
}
writer2.println("}");
}
if (!f4.exists()) {
createdFile = true;
}
} }
} }
} }

View File

@ -2,6 +2,15 @@
#include <CLI11.hpp> #include <CLI11.hpp>
bool processDuplicates(DatabaseManager &db) { bool processDuplicates(DatabaseManager &db) {
// Scan all files in the database, and for non-existing files, remove them from the database
auto files = db.getAllFiles();
for (auto &file : files) {
if (!std::filesystem::exists(file)) {
spdlog::warn("File not found, removing from database: {}", file);
db.removeFile(file);
}
}
spdlog::info("=== Checking for duplicate addresses ==="); spdlog::info("=== Checking for duplicate addresses ===");
bool found_address_duplicates = db.checkDuplicateAddresses(); bool found_address_duplicates = db.checkDuplicateAddresses();
if (found_address_duplicates) { if (found_address_duplicates) {

View File

@ -12,6 +12,9 @@ public:
sqlite3_stmt *insert_imports_stmt; sqlite3_stmt *insert_imports_stmt;
sqlite3_stmt *delete_globals_stmt; sqlite3_stmt *delete_globals_stmt;
sqlite3_stmt *insert_globals_stmt; sqlite3_stmt *insert_globals_stmt;
sqlite3_stmt *delete_file_functions_stmt;
sqlite3_stmt *delete_file_imports_stmt;
sqlite3_stmt *delete_file_globals_stmt;
void prepareStatement(const char *sql, sqlite3_stmt **stmt, void prepareStatement(const char *sql, sqlite3_stmt **stmt,
const std::string &error_msg); const std::string &error_msg);
@ -38,6 +41,15 @@ public:
"VALUES (?, ?, ?)", "VALUES (?, ?, ?)",
&insert_globals_stmt, &insert_globals_stmt,
"Failed to prepare insert globals statement"); "Failed to prepare insert globals statement");
prepareStatement("DELETE FROM Functions WHERE filepath = ?",
&delete_file_functions_stmt,
"Failed to prepare delete file functions statement");
prepareStatement("DELETE FROM Imports WHERE filepath = ?",
&delete_file_imports_stmt,
"Failed to prepare delete file imports statement");
prepareStatement("DELETE FROM Globals WHERE filepath = ?",
&delete_file_globals_stmt,
"Failed to prepare delete file globals statement");
} }
~PreparedStatements() { ~PreparedStatements() {
@ -47,6 +59,9 @@ public:
sqlite3_finalize(insert_imports_stmt); sqlite3_finalize(insert_imports_stmt);
sqlite3_finalize(delete_globals_stmt); sqlite3_finalize(delete_globals_stmt);
sqlite3_finalize(insert_globals_stmt); sqlite3_finalize(insert_globals_stmt);
sqlite3_finalize(delete_file_functions_stmt);
sqlite3_finalize(delete_file_imports_stmt);
sqlite3_finalize(delete_file_globals_stmt);
} }
}; };
@ -253,3 +268,50 @@ std::vector<FunctionInfo> DatabaseManager::getFunctionsByType(FileType type) {
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return functions; return functions;
} }
std::vector<std::string> DatabaseManager::getAllFiles() {
std::vector<std::string> files;
const char *sql = R"(
SELECT DISTINCT filepath FROM (
SELECT filepath FROM Functions
UNION
SELECT filepath FROM Imports
UNION
SELECT filepath FROM Globals
) ORDER BY filepath;
)";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
spdlog::error("Failed to prepare getAllFiles query: {}", sqlite3_errmsg(db));
return files;
}
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char *filepath = (const char *)sqlite3_column_text(stmt, 0);
if (filepath) {
files.push_back(std::string(filepath));
}
}
sqlite3_finalize(stmt);
return files;
}
void DatabaseManager::removeFile(const std::string &filepath) {
// Use prepared statements for efficient deletion
sqlite3_stmt *stmts[] = {
prepared_stmts->delete_file_functions_stmt,
prepared_stmts->delete_file_imports_stmt,
prepared_stmts->delete_file_globals_stmt
};
for (auto stmt : stmts) {
sqlite3_reset(stmt);
sqlite3_bind_text(stmt, 1, filepath.c_str(), -1, SQLITE_STATIC);
sqlite3_step(stmt);
}
spdlog::debug("Removed all entries for file: {}", filepath);
}

View File

@ -31,9 +31,9 @@ int main(int argc, char *argv[]) {
} }
}); });
app.add_flag("--log-file", options.log_file, "Enable logging to file") app.add_flag("--log-file", options.log_file, "Enable logging to file")
->each([&](std::string) { ->each([&](const std::string& arg) {
auto log_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>( auto log_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(
options.log_file, true); arg, true);
console->sinks().push_back(log_sink); console->sinks().push_back(log_sink);
}); });
app.require_subcommand(); app.require_subcommand();

View File

@ -69,6 +69,8 @@ public:
bool checkDuplicateAddresses(); bool checkDuplicateAddresses();
bool checkDuplicateNames(); bool checkDuplicateNames();
std::vector<FunctionInfo> getFunctionsByType(FileType type); std::vector<FunctionInfo> getFunctionsByType(FileType type);
std::vector<std::string> getAllFiles();
void removeFile(const std::string &filepath);
}; };
// File processing functions // File processing functions