Compare commits
10 Commits
f2606cd72f
...
ac9879a4aa
Author | SHA1 | Date |
---|---|---|
|
ac9879a4aa | |
|
2423d68e0a | |
|
66565671b5 | |
|
bd98761921 | |
|
cfb41094d5 | |
|
743d5aa015 | |
|
947165067c | |
|
cde5c7c313 | |
|
f6d2ec6efb | |
|
ac92d40671 |
|
@ -0,0 +1,118 @@
|
|||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||
|
||||
#include <r3/binders/auto.h>
|
||||
#include <gh_global.h>
|
||||
|
||||
extern "C" {
|
||||
undefined FUN_00470350(void); // 00470350 // FUN_00470350 // cdecl
|
||||
undefined r3_load_textures_2(void); // 00471760 // r3_load_textures_2 // cdecl
|
||||
void level_displayFn(byte param); // 00446fc0 // level_displayFn // cdecl
|
||||
void r3_noop(void * p_cTxt1, void * p_cTxt2); // 00401100 // r3_noop // stdcall
|
||||
undefined r3_closeConcatTextureFile(void); // 004711d0 // r3_closeConcatTextureFile // cdecl
|
||||
undefined FUN_00470db0(void); // 00470db0 // FUN_00470db0 // cdecl
|
||||
undefined FUN_00503710(void); // 00503710 // FUN_00503710 // cdecl
|
||||
undefined FUN_00443120(undefined4 param_1); // 00443120 // FUN_00443120 // cdecl
|
||||
undefined FUN_00442c50(void); // 00442c50 // FUN_00442c50 // cdecl
|
||||
undefined FUN_00470410(void); // 00470410 // FUN_00470410 // cdecl
|
||||
undefined FUN_00472150(void); // 00472150 // FUN_00472150 // cdecl
|
||||
undefined FUN_00445460(void); // 00445460 // FUN_00445460 // cdecl
|
||||
undefined FUN_00442f70(undefined4 param_1); // 00442f70 // FUN_00442f70 // cdecl
|
||||
undefined FUN_00445440(void); // 00445440 // FUN_00445440 // cdecl
|
||||
undefined SND_fn_vResumeSound(void); // 0040a1e0 // SND_fn_vResumeSound // cdecl
|
||||
undefined IPT_fn_vActivateAllEntryElements(void); // 00505490 // IPT_fn_vActivateAllEntryElements // cdecl
|
||||
undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor // cdecl
|
||||
undefined FUN_00402470(undefined4 param_1); // 00402470 // FUN_00402470 // cdecl
|
||||
undefined gfx_init2(void); // 00470be0 // gfx_init2 // cdecl
|
||||
undefined FUN_004725a0(void); // 004725a0 // FUN_004725a0 // cdecl
|
||||
undefined FUN_0051a900(short hGLDDevice); // 0051a900 // FUN_0051a900 // cdecl
|
||||
undefined FUN_005038e0(void); // 005038e0 // FUN_005038e0 // cdecl
|
||||
undefined FUN_004fb300(void); // 004fb300 // FUN_004fb300 // cdecl
|
||||
undefined FUN_004fa650(void); // 004fa650 // FUN_004fa650 // cdecl
|
||||
undefined r3_processInput1(void); // 00446f10 // r3_processInput1 // cdecl
|
||||
undefined FUN_0047bae0(void); // 0047bae0 // FUN_0047bae0 // cdecl
|
||||
undefined FUN_0051a7a0(short hGLDDevice, undefined4 param_2); // 0051a7a0 // FUN_0051a7a0 // cdecl
|
||||
|
||||
// 00401490
|
||||
/* WARNING: Inlined function: r3_get_engine_mode */
|
||||
|
||||
undefined4 __stdcall r3_restore(undefined4 param_1)
|
||||
|
||||
{
|
||||
HWND hWnd;
|
||||
int iVar1;
|
||||
DWORD DVar2;
|
||||
|
||||
hWnd = g_gameHWND;
|
||||
if (g_engineRunning != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (g_gameHWND == (HWND)0x0) {
|
||||
return 0;
|
||||
}
|
||||
SetWindowTextA(g_gameHWND,g_windowTitleRestoring);
|
||||
UpdateWindow(hWnd);
|
||||
SetForegroundWindow(hWnd);
|
||||
if (p_fn_vDisplayAll == r3_noop) {
|
||||
/* Set window callback? */
|
||||
p_fn_vDisplayAll = level_displayFn;
|
||||
}
|
||||
if ((code *)PTR_r3_processInput1_005bdb1c == r3_noop) {
|
||||
PTR_r3_processInput1_005bdb1c = r3_processInput1;
|
||||
IPT_fn_vActivateAllEntryElements();
|
||||
}
|
||||
iVar1 = FUN_0047bae0();
|
||||
if (iVar1 == 0) goto LAB_004015f7;
|
||||
DVar2 = WaitForSingleObject(g_drawSemaphore,500);
|
||||
if (DVar2 == 0x102) {
|
||||
return 0;
|
||||
}
|
||||
FUN_004725a0();
|
||||
if (g_currentBinkMovie + Field<32, 4>() == 0) {
|
||||
FUN_00470410();
|
||||
}
|
||||
FUN_0051a900(g_stEngineStructure.hGLDDevice);
|
||||
FUN_005038e0();
|
||||
FUN_00503710();
|
||||
FUN_004fb300();
|
||||
FUN_00472150();
|
||||
FUN_00470db0();
|
||||
FUN_00445440();
|
||||
gfx_init2();
|
||||
FUN_00445460();
|
||||
FUN_00402470(hWnd);
|
||||
FUN_0051a7a0(g_stEngineStructure.hGLDDevice,0);
|
||||
if (g_currentBinkMovie + Field<32, 4>() == 0) {
|
||||
FUN_00442f70(0);
|
||||
FUN_00443120(0);
|
||||
FUN_00442f70(1);
|
||||
FUN_00443120(1);
|
||||
FUN_00470350();
|
||||
if (g_currentBinkMovie + Field<32, 4>() != 0) goto LAB_004015bc;
|
||||
}
|
||||
else {
|
||||
LAB_004015bc:
|
||||
FUN_00445440();
|
||||
}
|
||||
r3_load_textures_2();
|
||||
if (((g_stEngineStructure.eEngineMode == E_EM_ModeStartingProgram) ||
|
||||
(g_stEngineStructure.eEngineMode == E_EM_ModeEnterGame)) ||
|
||||
(g_stEngineStructure.eEngineMode == E_EM_ModeEnterLevel)) {
|
||||
FUN_004fa650();
|
||||
}
|
||||
r3_closeConcatTextureFile();
|
||||
ReleaseSemaphore(g_drawSemaphore,1,(LPLONG)0x0);
|
||||
LAB_004015f7:
|
||||
g_stEngineStructure + Field<91, 1>() = 0;
|
||||
SetWindowTextA(hWnd,g_windowTitle);
|
||||
UpdateWindow(hWnd);
|
||||
SetForegroundWindow(hWnd);
|
||||
FUN_00442c50();
|
||||
SND_fn_vResumeSound();
|
||||
r3_windowLockCursor();
|
||||
/* Keep suspended
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||
|
||||
#include <r3/binders/auto.h>
|
||||
#include <gh_global.h>
|
||||
|
||||
extern "C" {
|
||||
HWND getHWND(void); // 00401300 // getHWND // stdcall // Params: | Types: | Return: typedef HWND HWND__ *
|
||||
|
||||
// 00401320 // r3_windowLockCursor(cdecl)
|
||||
// Parameters: | Types: | Return: undefined
|
||||
|
||||
void unknown r3_windowLockCursor(void)
|
||||
|
||||
{
|
||||
HWND pHVar1;
|
||||
tagRECT *ptVar2;
|
||||
RECT RStack_30;
|
||||
tagRECT local_20;
|
||||
tagRECT tStack_10;
|
||||
|
||||
if (g_initVar0 != '\0') {
|
||||
ptVar2 = &local_20;
|
||||
pHVar1 = getHWND();
|
||||
GetWindowRect(pHVar1,ptVar2);
|
||||
ptVar2 = &tStack_10;
|
||||
pHVar1 = getHWND();
|
||||
GetClientRect(pHVar1,ptVar2);
|
||||
RStack_30.left = local_20.left + 5;
|
||||
RStack_30.top = local_20.bottom - tStack_10.bottom;
|
||||
RStack_30.right = tStack_10.right + -5 + RStack_30.left;
|
||||
RStack_30.bottom = RStack_30.top + -5 + tStack_10.bottom;
|
||||
ClipCursor(&RStack_30);
|
||||
ShowCursor(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,11 +4,11 @@
|
|||
#include <gh_global.h>
|
||||
|
||||
extern "C" {
|
||||
undefined r3_windowUnlockCursor(void); // 004013a0 // r3_windowUnlockCursor
|
||||
undefined FUN_00401320(void); // 00401320 // FUN_00401320
|
||||
undefined FUN_00401320(void); // 00401320 // FUN_00401320 // cdecl
|
||||
undefined r3_windowUnlockCursor(void); // 004013a0 // r3_windowUnlockCursor // cdecl
|
||||
|
||||
// 004025e0
|
||||
long CALLBACK r3_windowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
long __stdcall r3_windowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
|
||||
{
|
||||
long lVar1;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||
|
||||
#include <r3/binders/auto.h>
|
||||
#include <gh_global.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// 004013a0
|
||||
void r3_windowUnlockCursor(void)
|
||||
|
||||
{
|
||||
HCURSOR hCursor;
|
||||
|
||||
/* IDC_ARROW */
|
||||
hCursor = LoadCursorA((HINSTANCE)0x0,(LPCSTR)0x7f00);
|
||||
SetCursor(hCursor);
|
||||
ClipCursor((RECT *)0x0);
|
||||
ShowCursor(1);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// AUTO-GENERATED FILE
|
||||
#include <r3/binders/global.h>
|
||||
undefined4& crt_unhandled_exception_handler= (undefined4&) GH_MEM(0x00404a58);
|
||||
undefined4& DAT_00597ca0= (undefined4&) GH_MEM(0x00597ca0);
|
||||
dword& DWORD_00597ca0= (dword&) GH_MEM(0x00597ca0);
|
||||
char(&s__s_not_initialized__005b63e0)[20] = reinterpret_cast<char(&)[20]>(GH_MEM(0x005b63e0));
|
||||
char(&s_Please_run_the__s_setup__005b63f4)[28] = reinterpret_cast<char(&)[28]>(GH_MEM(0x005b63f4));
|
||||
char(&s_dashCC)[4] = reinterpret_cast<char(&)[4]>(GH_MEM(0x005b6410));
|
||||
|
@ -64,6 +64,8 @@ undefined1& g_errModDInput= (undefined1&) GH_MEM(0x005bd29c);
|
|||
undefined4& DAT_005bd454= (undefined4&) GH_MEM(0x005bd454);
|
||||
const char* s__jc_z_d__s_005bd460 = "\\jc\\z%d:%s"; // 005bd460
|
||||
undefined1& g_errModMmg= (undefined1&) GH_MEM(0x005bd58c);
|
||||
pointer& PTR_r3_processInput1_005bdb1c= (pointer&) GH_MEM(0x005bdb1c);
|
||||
level_displayFn *& p_fn_vDisplayAll= (level_displayFn *&) GH_MEM(0x005bdb24);
|
||||
const char* s_R3_DVD_005bdfd8 = "R3_DVD"; // 005bdfd8
|
||||
const char* s_R3_DVD_005be0ec = "R3_DVD"; // 005be0ec
|
||||
const char* s__s_DVD_missing_005be0f4 = "%s DVD missing "; // 005be0f4
|
||||
|
@ -83,12 +85,12 @@ 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_Agp = "Agp"; // 005be390
|
||||
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_Tnl = "TnL"; // 005be3c8
|
||||
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
|
||||
|
@ -102,6 +104,7 @@ const char* s_r3_program_files = "\\program files\\Ubi Soft\\Rayman3"; // 005be5
|
|||
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);
|
||||
undefined1& g_initVar0= (undefined1&) GH_MEM(0x005cf960);
|
||||
HWND& g_gameHWND1= (HWND&) GH_MEM(0x005cf964);
|
||||
long& lpDefault_005cf96c= (long&) GH_MEM(0x005cf96c);
|
||||
dword& DWORD_005cf974= (dword&) GH_MEM(0x005cf974);
|
||||
|
@ -112,8 +115,8 @@ char *& PTR_005cf9b4= (char *&) GH_MEM(0x005cf9b4);
|
|||
GameStructure& g_currentBinkMovie= (GameStructure&) GH_MEM(0x005d2660);
|
||||
char(&s_volumeNameBuffer)[128] = reinterpret_cast<char(&)[128]>(GH_MEM(0x005d27b0));
|
||||
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);
|
||||
dword& g_soundOnHD= (dword&) GH_MEM(0x005d29bc);
|
||||
dword& g_complete= (dword&) GH_MEM(0x005d29c0);
|
||||
int& g_windowInitialized= (int&) GH_MEM(0x0077d0a4);
|
||||
int& g_runMaximized= (int&) GH_MEM(0x0077d0a8);
|
||||
undefined4& g_engineShouldRun= (undefined4&) GH_MEM(0x0077d0b0);
|
||||
|
@ -132,8 +135,9 @@ char(&s_wndStrRestoring)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d5e0
|
|||
char *& g_crt_cmdLine= (char *&) GH_MEM(0x0077ea84);
|
||||
char(&s_quitting1)[64] = reinterpret_cast<char(&)[64]>(GH_MEM(0x007825c0));
|
||||
char(&s_wndStrQuiting)[56] = reinterpret_cast<char(&)[56]>(GH_MEM(0x00782600));
|
||||
GAM_EngineStructure& g_stEngineStructure= (GAM_EngineStructure&) GH_MEM(0x007d7dc0);
|
||||
undefined4& DAT_007d9cc4= (undefined4&) GH_MEM(0x007d9cc4);
|
||||
undefined4& g_config_unused0= (undefined4&) GH_MEM(0x007d9df0);
|
||||
byte& g_config_unused0= (byte&) GH_MEM(0x007d9df0);
|
||||
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);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
extern undefined4& crt_unhandled_exception_handler; // 00404a58
|
||||
extern undefined4& DAT_00597ca0; // 00597ca0
|
||||
extern dword& DWORD_00597ca0; // 00597ca0
|
||||
extern char(&s__s_not_initialized__005b63e0)[20]; // 005b63e0
|
||||
extern char(&s_Please_run_the__s_setup__005b63f4)[28]; // 005b63f4
|
||||
extern char(&s_dashCC)[4]; // 005b6410
|
||||
|
@ -69,6 +69,8 @@ extern undefined1& g_errModDInput; // 005bd29c
|
|||
extern undefined4& DAT_005bd454; // 005bd454
|
||||
extern const char* s__jc_z_d__s_005bd460; // 005bd460
|
||||
extern undefined1& g_errModMmg; // 005bd58c
|
||||
extern pointer& PTR_r3_processInput1_005bdb1c; // 005bdb1c
|
||||
extern level_displayFn *& p_fn_vDisplayAll; // 005bdb24
|
||||
extern const char* s_R3_DVD_005bdfd8; // 005bdfd8
|
||||
extern const char* s_R3_DVD_005be0ec; // 005be0ec
|
||||
extern const char* s__s_DVD_missing_005be0f4; // 005be0f4
|
||||
|
@ -88,12 +90,12 @@ 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_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_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
|
||||
|
@ -107,6 +109,7 @@ extern const char* s_r3_program_files; // 005be548
|
|||
extern const char* s_driveLetterTemplate; // 005be568
|
||||
extern undefined4& g_config_camera_hor_axis; // 005c67c8
|
||||
extern undefined4& g_config_camera_ver_axis; // 005c67cc
|
||||
extern undefined1& g_initVar0; // 005cf960
|
||||
extern HWND& g_gameHWND1; // 005cf964
|
||||
extern long& lpDefault_005cf96c; // 005cf96c
|
||||
extern dword& DWORD_005cf974; // 005cf974
|
||||
|
@ -117,8 +120,8 @@ extern char *& PTR_005cf9b4; // 005cf9b4
|
|||
extern GameStructure& g_currentBinkMovie; // 005d2660
|
||||
extern char(&s_volumeNameBuffer)[128]; // 005d27b0
|
||||
extern r3_main_data& r3_main_data_005d28b6; // 005d28b6
|
||||
extern undefined4& g_soundOnHD; // 005d29bc
|
||||
extern undefined4& g_complete; // 005d29c0
|
||||
extern dword& g_soundOnHD; // 005d29bc
|
||||
extern dword& g_complete; // 005d29c0
|
||||
extern int& g_windowInitialized; // 0077d0a4
|
||||
extern int& g_runMaximized; // 0077d0a8
|
||||
extern undefined4& g_engineShouldRun; // 0077d0b0
|
||||
|
@ -137,8 +140,9 @@ extern char(&s_wndStrRestoring)[256]; // 0077d5e0
|
|||
extern char *& g_crt_cmdLine; // 0077ea84
|
||||
extern char(&s_quitting1)[64]; // 007825c0
|
||||
extern char(&s_wndStrQuiting)[56]; // 00782600
|
||||
extern GAM_EngineStructure& g_stEngineStructure; // 007d7dc0
|
||||
extern undefined4& DAT_007d9cc4; // 007d9cc4
|
||||
extern undefined4& g_config_unused0; // 007d9df0
|
||||
extern byte& g_config_unused0; // 007d9df0
|
||||
extern char(&g_driveLetter)[4]; // 007d9e70
|
||||
extern undefined4& g_GLI_adapter; // 007edd60
|
||||
extern undefined1& g_GLI_tnl; // 007edd64
|
||||
|
|
|
@ -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>
|
||||
|
||||
// 00402470
|
||||
// FUN_00402470
|
||||
extern "C" undefined FUN_00402470(undefined4 param_1) {
|
||||
return gh_stub_impl_cdecl<0x00402470, undefined>(param_1);
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
#include <r3/binders/stub.h>
|
||||
#include <gh_global.h>
|
||||
|
||||
// 00401320
|
||||
// FUN_00401320
|
||||
extern "C" undefined FUN_00401320(void) {
|
||||
return gh_stub_impl_cdecl<0x00401320, undefined>();
|
||||
// 00442c50
|
||||
// FUN_00442c50
|
||||
extern "C" undefined FUN_00442c50(void) {
|
||||
return gh_stub_impl_cdecl<0x00442c50, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00442f70
|
||||
// FUN_00442f70
|
||||
extern "C" undefined FUN_00442f70(undefined4 param_1) {
|
||||
return gh_stub_impl_cdecl<0x00442f70, undefined>(param_1);
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00443120
|
||||
// FUN_00443120
|
||||
extern "C" undefined FUN_00443120(undefined4 param_1) {
|
||||
return gh_stub_impl_cdecl<0x00443120, undefined>(param_1);
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
#include <r3/binders/stub.h>
|
||||
#include <gh_global.h>
|
||||
|
||||
// 004013a0
|
||||
// r3_windowUnlockCursor
|
||||
extern "C" undefined r3_windowUnlockCursor(void) {
|
||||
return gh_stub_impl_cdecl<0x004013a0, undefined>();
|
||||
// 00445440
|
||||
// FUN_00445440
|
||||
extern "C" undefined FUN_00445440(void) {
|
||||
return gh_stub_impl_cdecl<0x00445440, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00445460
|
||||
// FUN_00445460
|
||||
extern "C" undefined FUN_00445460(void) {
|
||||
return gh_stub_impl_cdecl<0x00445460, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00470350
|
||||
// FUN_00470350
|
||||
extern "C" undefined FUN_00470350(void) {
|
||||
return gh_stub_impl_cdecl<0x00470350, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00470410
|
||||
// FUN_00470410
|
||||
extern "C" undefined FUN_00470410(void) {
|
||||
return gh_stub_impl_cdecl<0x00470410, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 0047bae0
|
||||
// FUN_0047bae0
|
||||
extern "C" undefined FUN_0047bae0(void) {
|
||||
return gh_stub_impl_cdecl<0x0047bae0, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 004fa650
|
||||
// FUN_004fa650
|
||||
extern "C" undefined FUN_004fa650(void) {
|
||||
return gh_stub_impl_cdecl<0x004fa650, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 0051a7a0
|
||||
// FUN_0051a7a0
|
||||
extern "C" undefined FUN_0051a7a0(short hGLDDevice, undefined4 param_2) {
|
||||
return gh_stub_impl_cdecl<0x0051a7a0, undefined>(hGLDDevice, param_2);
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 0051a900
|
||||
// FUN_0051a900
|
||||
extern "C" undefined FUN_0051a900(short hGLDDevice) {
|
||||
return gh_stub_impl_cdecl<0x0051a900, undefined>(hGLDDevice);
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00505490
|
||||
// IPT_fn_vActivateAllEntryElements
|
||||
extern "C" undefined IPT_fn_vActivateAllEntryElements(void) {
|
||||
return gh_stub_impl_cdecl<0x00505490, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 0040a1e0
|
||||
// SND_fn_vResumeSound
|
||||
extern "C" undefined SND_fn_vResumeSound(void) {
|
||||
return gh_stub_impl_cdecl<0x0040a1e0, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00401300
|
||||
// getHWND
|
||||
extern "C" HWND getHWND(void) {
|
||||
return gh_stub_impl_stdcall<0x00401300, HWND>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00446fc0
|
||||
// level_displayFn
|
||||
extern "C" void level_displayFn(byte param) {
|
||||
gh_stub_impl_cdecl<0x00446fc0, void>(param);
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 004711d0
|
||||
// r3_closeConcatTextureFile
|
||||
extern "C" undefined r3_closeConcatTextureFile(void) {
|
||||
return gh_stub_impl_cdecl<0x004711d0, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00471760
|
||||
// r3_load_textures_2
|
||||
extern "C" undefined r3_load_textures_2(void) {
|
||||
return gh_stub_impl_cdecl<0x00471760, undefined>();
|
||||
}
|
|
@ -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>
|
||||
|
||||
// 00446f10
|
||||
// r3_processInput1
|
||||
extern "C" undefined r3_processInput1(void) {
|
||||
return gh_stub_impl_cdecl<0x00446f10, undefined>();
|
||||
}
|
|
@ -11,8 +11,18 @@ static uintptr_t g_gh_translationOffset{};
|
|||
|
||||
extern "C" {
|
||||
#define HOOK(addr, name) void name(void *);
|
||||
#define HOOK_S0(addr, name) void __stdcall name();
|
||||
#define HOOK_S1(addr, name) void __stdcall name(int);
|
||||
#define HOOK_S2(addr, name) void __stdcall name(int, int);
|
||||
#define HOOK_S3(addr, name) void __stdcall name(int, int, int);
|
||||
#define HOOK_S4(addr, name) void __stdcall name(int, int, int, int);
|
||||
#include "hooks.def"
|
||||
#undef HOOK
|
||||
#undef HOOK_S0
|
||||
#undef HOOK_S1
|
||||
#undef HOOK_S2
|
||||
#undef HOOK_S3
|
||||
#undef HOOK_S4
|
||||
}
|
||||
|
||||
struct R3Bin {
|
||||
|
@ -33,19 +43,20 @@ struct R3Bin {
|
|||
g_gh_translationOffset = translationOffset =
|
||||
uintptr_t(module) - GH_BASE_ADDR;
|
||||
|
||||
std::string msg = fmt::format("Rayman3.exe Base address: 0x{:x}\n", uintptr_t(module));
|
||||
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);
|
||||
|
||||
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
|
||||
relocateModule();
|
||||
patchFunctions();
|
||||
}
|
||||
|
||||
inline void relocate(void *instr, void *from,
|
||||
void *originalPointee) {
|
||||
inline void relocate(void *instr, void *from, void *originalPointee) {
|
||||
void *relocated_addr = (void *)(uintptr_t(from) + translationOffset);
|
||||
void *relocated_to =
|
||||
(void *)(uintptr_t(originalPointee) + translationOffset);
|
||||
|
@ -175,7 +186,13 @@ struct R3Bin {
|
|||
"Failed to patch function {} at {} (RVA: {})", name, resolved, at));
|
||||
}
|
||||
void patchFunctions() {
|
||||
#define HOOK(addr, name) patchFunction((void*)addr, &name, #name);
|
||||
#define HOOK(addr, name) patchFunction((void *)addr, &name, #name);
|
||||
#define HOOK_S0(addr, name) HOOK(addr, name)
|
||||
#define HOOK_S1(addr, name) HOOK(addr, name)
|
||||
#define HOOK_S2(addr, name) HOOK(addr, name)
|
||||
#define HOOK_S3(addr, name) HOOK(addr, name)
|
||||
#define HOOK_S4(addr, name) HOOK(addr, name)
|
||||
|
||||
#include "hooks.def"
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,11 @@ public class Test extends GhidraScript {
|
|||
try (FunctionDatabase db = new FunctionDatabase(this)) {
|
||||
List<FunctionDatabase.FunctionEntry> entries = db.loadAllEntries();
|
||||
for (FunctionDatabase.FunctionEntry entry : entries) {
|
||||
println("entry.name: " + entry.name + " entry.address: " + entry.address + " entry.type: " + entry.type);
|
||||
println("entry.name: " + entry.name + " entry.address: " + entry.address + " entry.type: " + entry.type
|
||||
+ " calling_convention: " + entry.callingConvention + " return_type: " + entry.returnType);
|
||||
if (!entry.parameterNames.isEmpty()) {
|
||||
println(" parameters: " + entry.parameterNames + " | types: " + entry.parameterTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,6 @@ public class DataTypeWriter {
|
|||
blocks.put(funcName, new Block(funcType, code.toString(), dependencies));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Step 3: Topological sort and write
|
||||
List<Block> sortedBlocks = topologicalSort(blocks);
|
||||
|
@ -171,7 +170,7 @@ public class DataTypeWriter {
|
|||
StringBuilder code = new StringBuilder();
|
||||
|
||||
// if (dt.getDisplayName().contains("HIE_tduLinkedObject")) {
|
||||
// System.out.println("DEBUG " + dt.getDisplayName());
|
||||
// System.out.println("DEBUG " + dt.getDisplayName());
|
||||
// }
|
||||
|
||||
if (dt.equals(DataType.DEFAULT)) {
|
||||
|
@ -189,7 +188,7 @@ public class DataTypeWriter {
|
|||
} else if (dt instanceof Union) {
|
||||
writeUnionBlock((Union) dt, code, dependencies);
|
||||
} else if (dt instanceof Enum) {
|
||||
if(dt.getDisplayName().contains(".conflict"))
|
||||
if (dt.getDisplayName().contains(".conflict"))
|
||||
return null;
|
||||
writeEnumBlock((Enum) dt, code, dependencies);
|
||||
} else if (dt instanceof TypeDef) {
|
||||
|
@ -265,7 +264,7 @@ public class DataTypeWriter {
|
|||
DataType depType = getImmediateDependencyType(componentDataType);
|
||||
if (depType != null) {
|
||||
dependencies.add(depType.getDisplayName());
|
||||
if(depType instanceof FunctionDefinition) {
|
||||
if (depType instanceof FunctionDefinition) {
|
||||
requiredFunctionTypes.add(depType.getDisplayName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,30 +46,121 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
}
|
||||
}
|
||||
|
||||
public static enum CallingConvention {
|
||||
Cdecl(0),
|
||||
Stdcall(1),
|
||||
Fastcall(2);
|
||||
|
||||
private final int value;
|
||||
|
||||
CallingConvention(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static CallingConvention fromValue(int value) {
|
||||
for (CallingConvention conv : CallingConvention.values()) {
|
||||
if (conv.value == value) {
|
||||
return conv;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown calling convention value: " + value);
|
||||
}
|
||||
|
||||
public static CallingConvention fromString(String convStr) {
|
||||
if (convStr == null) {
|
||||
return Cdecl; // Default
|
||||
}
|
||||
|
||||
String lower = convStr.toLowerCase();
|
||||
if (lower.contains("fastcall")) {
|
||||
return Fastcall;
|
||||
} else if (lower.contains("stdcall")) {
|
||||
return Stdcall;
|
||||
} else {
|
||||
return Cdecl; // Default
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case Fastcall:
|
||||
return "fastcall";
|
||||
case Stdcall:
|
||||
return "stdcall";
|
||||
case Cdecl:
|
||||
default:
|
||||
return "cdecl";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FunctionEntry {
|
||||
public Address address;
|
||||
public String name;
|
||||
public File file;
|
||||
public Type type;
|
||||
public CallingConvention callingConvention;
|
||||
public String parameterNames; // Semicolon-separated parameter names
|
||||
public String parameterTypes; // Semicolon-separated parameter types
|
||||
public String returnType; // Function return type
|
||||
|
||||
public FunctionEntry(Address address, String name, File file, Type type) {
|
||||
public FunctionEntry(Address address, String name, File file, Type type, CallingConvention callingConvention,
|
||||
String parameterNames, String parameterTypes, String returnType) {
|
||||
this.address = address;
|
||||
this.name = name;
|
||||
this.file = file;
|
||||
this.type = type;
|
||||
this.callingConvention = callingConvention;
|
||||
this.parameterNames = parameterNames != null ? parameterNames : "";
|
||||
this.parameterTypes = parameterTypes != null ? parameterTypes : "";
|
||||
this.returnType = returnType != null ? returnType : "void";
|
||||
}
|
||||
|
||||
// Helper methods to work with semicolon-separated parameter lists
|
||||
public String[] getParameterNamesArray() {
|
||||
if (parameterNames == null || parameterNames.trim().isEmpty()) {
|
||||
return new String[0];
|
||||
}
|
||||
return parameterNames.split(";");
|
||||
}
|
||||
|
||||
public String[] getParameterTypesArray() {
|
||||
if (parameterTypes == null || parameterTypes.trim().isEmpty()) {
|
||||
return new String[0];
|
||||
}
|
||||
return parameterTypes.split(";");
|
||||
}
|
||||
|
||||
public void setParameterNamesArray(String[] names) {
|
||||
if (names == null || names.length == 0) {
|
||||
this.parameterNames = "";
|
||||
} else {
|
||||
this.parameterNames = String.join(";", names);
|
||||
}
|
||||
}
|
||||
|
||||
public void setParameterTypesArray(String[] types) {
|
||||
if (types == null || types.length == 0) {
|
||||
this.parameterTypes = "";
|
||||
} else {
|
||||
this.parameterTypes = String.join(";", types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class GlobalEntry {
|
||||
public Address address;
|
||||
public String name;
|
||||
public String dataType;
|
||||
public File file;
|
||||
|
||||
public GlobalEntry(Address address, String name, String dataType, File file) {
|
||||
public GlobalEntry(Address address, String name, File file) {
|
||||
this.address = address;
|
||||
this.name = name;
|
||||
this.dataType = dataType;
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +175,7 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
private PreparedStatement findByAddressFunctions;
|
||||
private PreparedStatement findByAddressImports;
|
||||
private PreparedStatement insertOrReplaceFunctions;
|
||||
private PreparedStatement insertOrReplaceImports;
|
||||
private PreparedStatement deleteByFilepathFunctions;
|
||||
private PreparedStatement deleteByFilepathImports;
|
||||
private PreparedStatement loadAllFunctions;
|
||||
|
@ -124,7 +216,8 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
script.println("Connected to database: " + dbFile);
|
||||
} catch (SQLException e) {
|
||||
script.println("Error connecting to database: " + e.getMessage());
|
||||
throw new Exception("Failed to connect to database", e);
|
||||
// throw new Exception("Failed to connect to database", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,19 +244,21 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
private void prepareCachedStatements() throws SQLException {
|
||||
// Find by name
|
||||
findByNameFunctions = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Functions WHERE name = ?");
|
||||
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Functions WHERE name = ?");
|
||||
findByNameImports = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Imports WHERE name = ?");
|
||||
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Imports WHERE name = ?");
|
||||
|
||||
// Find by address
|
||||
findByAddressFunctions = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Functions WHERE address = ?");
|
||||
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Functions WHERE address = ?");
|
||||
findByAddressImports = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Imports WHERE address = ?");
|
||||
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Imports WHERE address = ?");
|
||||
|
||||
// Insert or replace
|
||||
insertOrReplaceFunctions = connection.prepareStatement(
|
||||
"INSERT OR REPLACE INTO Functions (filepath, name, address, type) VALUES (?, ?, ?, ?)");
|
||||
"INSERT OR REPLACE INTO Functions (filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
insertOrReplaceImports = connection.prepareStatement(
|
||||
"INSERT OR REPLACE INTO Imports (filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
|
||||
// Delete by filepath
|
||||
deleteByFilepathFunctions = connection.prepareStatement(
|
||||
|
@ -173,21 +268,21 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
|
||||
// Load all entries
|
||||
loadAllFunctions = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Functions");
|
||||
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Functions");
|
||||
loadAllImports = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Imports");
|
||||
"SELECT filepath, name, address, type, calling_convention, parameter_names, parameter_types, return_type FROM Imports");
|
||||
|
||||
// Global statements
|
||||
findByNameGlobals = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Globals WHERE name = ?");
|
||||
"SELECT filepath, name, address FROM Globals WHERE name = ?");
|
||||
findByAddressGlobals = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Globals WHERE address = ?");
|
||||
"SELECT filepath, name, address FROM Globals WHERE address = ?");
|
||||
insertOrReplaceGlobals = connection.prepareStatement(
|
||||
"INSERT OR REPLACE INTO Globals (filepath, name, address, type) VALUES (?, ?, ?, ?)");
|
||||
"INSERT OR REPLACE INTO Globals (filepath, name, address) VALUES (?, ?, ?)");
|
||||
deleteByFilepathGlobals = connection.prepareStatement(
|
||||
"DELETE FROM Globals WHERE filepath = ?");
|
||||
loadAllGlobals = connection.prepareStatement(
|
||||
"SELECT filepath, name, address, type FROM Globals");
|
||||
"SELECT filepath, name, address FROM Globals");
|
||||
}
|
||||
|
||||
private void closePreparedStatements() throws SQLException {
|
||||
|
@ -201,6 +296,8 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
findByAddressImports.close();
|
||||
if (insertOrReplaceFunctions != null)
|
||||
insertOrReplaceFunctions.close();
|
||||
if (insertOrReplaceImports != null)
|
||||
insertOrReplaceImports.close();
|
||||
if (deleteByFilepathFunctions != null)
|
||||
deleteByFilepathFunctions.close();
|
||||
if (deleteByFilepathImports != null)
|
||||
|
@ -250,13 +347,19 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
String name = rs.getString("name");
|
||||
String addressStr = rs.getString("address");
|
||||
int typeValue = rs.getInt("type");
|
||||
int callingConventionValue = rs.getInt("calling_convention");
|
||||
String parameterNames = rs.getString("parameter_names");
|
||||
String parameterTypes = rs.getString("parameter_types");
|
||||
String returnType = rs.getString("return_type");
|
||||
|
||||
if (addressStr != null && !addressStr.isEmpty()) {
|
||||
Address address = script.getCurrentProgram().getAddressFactory().getAddress(addressStr);
|
||||
File file = new File(RemanConfig.INSTANCE.outputDir, filepath);
|
||||
Type type = Type.fromValue(typeValue);
|
||||
CallingConvention callingConvention = CallingConvention.fromValue(callingConventionValue);
|
||||
|
||||
return new FunctionEntry(address, name, file, type);
|
||||
return new FunctionEntry(address, name, file, type, callingConvention,
|
||||
parameterNames, parameterTypes, returnType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -267,7 +370,11 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
filepath TEXT,
|
||||
name TEXT,
|
||||
address TEXT,
|
||||
type INTEGER,
|
||||
type INTEGER DEFAULT 0,
|
||||
calling_convention INTEGER DEFAULT 0,
|
||||
parameter_names TEXT DEFAULT '',
|
||||
parameter_types TEXT DEFAULT '',
|
||||
return_type TEXT DEFAULT '',
|
||||
PRIMARY KEY (name, filepath)
|
||||
)""";
|
||||
|
||||
|
@ -276,7 +383,11 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
filepath TEXT,
|
||||
name TEXT,
|
||||
address TEXT,
|
||||
type INTEGER,
|
||||
type INTEGER DEFAULT 0,
|
||||
calling_convention INTEGER DEFAULT 0,
|
||||
parameter_names TEXT DEFAULT '',
|
||||
parameter_types TEXT DEFAULT '',
|
||||
return_type TEXT DEFAULT '',
|
||||
PRIMARY KEY (name, filepath)
|
||||
)""";
|
||||
|
||||
|
@ -285,7 +396,6 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
filepath TEXT,
|
||||
name TEXT,
|
||||
address TEXT,
|
||||
type TEXT,
|
||||
PRIMARY KEY (name, filepath)
|
||||
)""";
|
||||
|
||||
|
@ -377,15 +487,46 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
insertOrReplaceFunctions.setString(2, entry.name);
|
||||
insertOrReplaceFunctions.setString(3, entry.address.toString());
|
||||
insertOrReplaceFunctions.setInt(4, entry.type.getValue());
|
||||
insertOrReplaceFunctions.setInt(5, entry.callingConvention.getValue());
|
||||
insertOrReplaceFunctions.setString(6, entry.parameterNames);
|
||||
insertOrReplaceFunctions.setString(7, entry.parameterTypes);
|
||||
insertOrReplaceFunctions.setString(8, entry.returnType);
|
||||
insertOrReplaceFunctions.executeUpdate();
|
||||
|
||||
script.println("Added/updated entry: " + entry.name + " at " + entry.address + " in " + relativePath);
|
||||
script.println("Added/updated entry: " + entry.name + " at " + entry.address + " in " + relativePath
|
||||
+ " (calling convention: " + entry.callingConvention + ", return type: " + entry.returnType + ")");
|
||||
} catch (SQLException e) {
|
||||
script.println("Error adding entry: " + e.getMessage());
|
||||
throw new Exception("Failed to add entry", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to add import entry
|
||||
public void addImportEntry(FunctionEntry entry) throws Exception {
|
||||
ensureConnection();
|
||||
|
||||
String relativePath = new File(RemanConfig.INSTANCE.outputDir).toPath()
|
||||
.relativize(entry.file.toPath()).toString().replace('\\', '/');
|
||||
|
||||
try {
|
||||
insertOrReplaceImports.setString(1, relativePath);
|
||||
insertOrReplaceImports.setString(2, entry.name);
|
||||
insertOrReplaceImports.setString(3, entry.address.toString());
|
||||
insertOrReplaceImports.setInt(4, entry.type.getValue());
|
||||
insertOrReplaceImports.setInt(5, entry.callingConvention.getValue());
|
||||
insertOrReplaceImports.setString(6, entry.parameterNames);
|
||||
insertOrReplaceImports.setString(7, entry.parameterTypes);
|
||||
insertOrReplaceImports.setString(8, entry.returnType);
|
||||
insertOrReplaceImports.executeUpdate();
|
||||
|
||||
script.println("Added/updated import entry: " + entry.name + " at " + entry.address + " in " + relativePath
|
||||
+ " (calling convention: " + entry.callingConvention + ", return type: " + entry.returnType + ")");
|
||||
} catch (SQLException e) {
|
||||
script.println("Error adding import entry: " + e.getMessage());
|
||||
throw new Exception("Failed to add import entry", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to remove entry by file path
|
||||
public void removeEntryAt(String filePath) throws Exception {
|
||||
ensureConnection();
|
||||
|
@ -566,13 +707,12 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
String filepath = rs.getString("filepath");
|
||||
String name = rs.getString("name");
|
||||
String addressStr = rs.getString("address");
|
||||
String typeStr = rs.getString("type");
|
||||
|
||||
if (addressStr != null && !addressStr.isEmpty()) {
|
||||
Address address = script.getCurrentProgram().getAddressFactory().getAddress(addressStr);
|
||||
File file = new File(RemanConfig.INSTANCE.outputDir, filepath);
|
||||
|
||||
return new GlobalEntry(address, name, typeStr, file);
|
||||
return new GlobalEntry(address, name, file);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -622,7 +762,7 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
}
|
||||
}
|
||||
|
||||
public void addGlobal(Address address, String name, String dataType) throws Exception {
|
||||
public void addGlobal(Address address, String name) throws Exception {
|
||||
ensureConnection();
|
||||
|
||||
String filepath = RemanConfig.GLOBAL_H_FILE; // Default filepath for globals
|
||||
|
@ -632,10 +772,9 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
insertOrReplaceGlobals.setString(1, filepath);
|
||||
insertOrReplaceGlobals.setString(2, name);
|
||||
insertOrReplaceGlobals.setString(3, addressStr);
|
||||
insertOrReplaceGlobals.setString(4, dataType);
|
||||
insertOrReplaceGlobals.executeUpdate();
|
||||
|
||||
script.println("Added/updated global: " + name + " at " + address + " with type " + dataType);
|
||||
script.println("Added/updated global: " + name + " at " + address);
|
||||
} catch (SQLException e) {
|
||||
script.println("Error adding global: " + e.getMessage());
|
||||
throw new Exception("Failed to add global", e);
|
||||
|
|
|
@ -47,6 +47,44 @@ public class FunctionDumper {
|
|||
initFunctionBlacklist();
|
||||
}
|
||||
|
||||
// Helper method to extract parameter names from Ghidra function
|
||||
private String extractParameterNames(Function function) {
|
||||
var parameters = function.getParameters();
|
||||
if (parameters.length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder names = new StringBuilder();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (i > 0) names.append(";");
|
||||
String paramName = parameters[i].getName();
|
||||
names.append(paramName != null ? paramName : "param" + i);
|
||||
}
|
||||
return names.toString();
|
||||
}
|
||||
|
||||
// Helper method to extract parameter types from Ghidra function
|
||||
private String extractParameterTypes(Function function) {
|
||||
var parameters = function.getParameters();
|
||||
if (parameters.length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder types = new StringBuilder();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (i > 0) types.append(";");
|
||||
String paramType = parameters[i].getDataType().toString();
|
||||
types.append(paramType != null ? paramType : "void*");
|
||||
}
|
||||
return types.toString();
|
||||
}
|
||||
|
||||
// Helper method to extract return type from Ghidra function
|
||||
private String extractReturnType(Function function) {
|
||||
var returnType = function.getReturnType();
|
||||
return returnType != null ? returnType.getDisplayName() : "void";
|
||||
}
|
||||
|
||||
boolean isValidFunction(Function function) {
|
||||
if (functionAddrBlackList.contains(function.getEntryPoint()))
|
||||
return false;
|
||||
|
@ -131,6 +169,17 @@ public class FunctionDumper {
|
|||
File f4 = new File(RemanConfig.INSTANCE.dirDecompStub, fileName);
|
||||
script.println("Generating function stub for " + externalFunction.getName() + " => " + f4.toString());
|
||||
|
||||
// Extract calling convention from Ghidra function
|
||||
String callingConventionName = externalFunction.getCallingConventionName();
|
||||
FunctionDatabase.CallingConvention callingConvention = FunctionDatabase.CallingConvention
|
||||
.fromString(callingConventionName);
|
||||
script.println("Detected calling convention: " + callingConventionName + " -> " + callingConvention);
|
||||
|
||||
// Extract parameter information and return type
|
||||
String parameterNames = extractParameterNames(externalFunction);
|
||||
String parameterTypes = extractParameterTypes(externalFunction);
|
||||
String returnType = extractReturnType(externalFunction);
|
||||
|
||||
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");
|
||||
|
@ -148,16 +197,16 @@ public class FunctionDumper {
|
|||
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")) {
|
||||
if (callingConvention == FunctionDatabase.CallingConvention.Stdcall) {
|
||||
stubFunction = "gh_stub_impl_stdcall";
|
||||
} else if (callingConvention == FunctionDatabase.CallingConvention.Fastcall) {
|
||||
stubFunction = "gh_stub_impl_fastcall";
|
||||
} else {
|
||||
// Default to cdecl for most cases
|
||||
stubFunction = "gh_stub_impl_cdecl";
|
||||
|
@ -189,9 +238,10 @@ public class FunctionDumper {
|
|||
createdFile = true;
|
||||
}
|
||||
|
||||
// Add stub function to database
|
||||
// Add stub function to database with calling convention and parameter information
|
||||
FunctionDatabase.FunctionEntry newEntry = new FunctionDatabase.FunctionEntry(externalFunction.getEntryPoint(),
|
||||
externalFunction.getName(), f4, FunctionDatabase.Type.Stub);
|
||||
externalFunction.getName(), f4, FunctionDatabase.Type.Stub, callingConvention,
|
||||
parameterNames, parameterTypes, returnType);
|
||||
functionDatabase.addEntryAt(newEntry);
|
||||
}
|
||||
|
||||
|
@ -204,6 +254,19 @@ public class FunctionDumper {
|
|||
List<FunctionDatabase.FunctionEntry> entries = functionDatabase.findEntriesByAddress(entrypoint);
|
||||
FunctionDatabase.Type targetType = FunctionDatabase.Type.Auto;
|
||||
|
||||
// Extract calling convention from Ghidra function
|
||||
String callingConventionName = function.getCallingConventionName();
|
||||
FunctionDatabase.CallingConvention callingConvention = FunctionDatabase.CallingConvention
|
||||
.fromString(callingConventionName);
|
||||
script.println("Detected calling convention: " + callingConventionName + " -> " + callingConvention);
|
||||
|
||||
// Extract parameter information and return type
|
||||
String parameterNames = extractParameterNames(function);
|
||||
String parameterTypes = extractParameterTypes(function);
|
||||
String returnType = extractReturnType(function);
|
||||
|
||||
script.println("Parameters: " + parameterNames + " | Types: " + parameterTypes + " | Return: " + returnType);
|
||||
|
||||
// Handle forceFixType flag
|
||||
if (forceFixType) {
|
||||
targetType = FunctionDatabase.Type.Fix;
|
||||
|
@ -271,14 +334,25 @@ public class FunctionDumper {
|
|||
File f0 = targetFilename;
|
||||
script.println("Processing " + function.getName() + " => " + f0.toString());
|
||||
|
||||
// Update database
|
||||
// Update database with calling convention and parameter information
|
||||
FunctionDatabase.FunctionEntry newEntry = new FunctionDatabase.FunctionEntry(entrypoint, function.getName(), f0,
|
||||
targetType);
|
||||
targetType, callingConvention, parameterNames, parameterTypes, returnType);
|
||||
functionDatabase.addEntryAt(newEntry);
|
||||
|
||||
List<Function> externalFunctionCalls = new ArrayList<>();
|
||||
HashMap<String, String> replacementMap = new HashMap<>();
|
||||
|
||||
String newFunctionName = sanitizedFunctionName;
|
||||
if (callingConvention == FunctionDatabase.CallingConvention.Stdcall ||
|
||||
callingConvention == FunctionDatabase.CallingConvention.Fastcall) {
|
||||
newFunctionName = "__" + callingConvention.toString() + " " + newFunctionName;
|
||||
}
|
||||
|
||||
String originalFunctionName = function.getName();
|
||||
if (newFunctionName != originalFunctionName) {
|
||||
replacementMap.put(originalFunctionName, newFunctionName);
|
||||
}
|
||||
|
||||
DecompileResults decompRes = RemanConfig.INSTANCE.decompCache.getOrInsert(function);
|
||||
try (PrintWriter writer2 = new PrintWriter(f0, "UTF-8")) {
|
||||
writer2.println("// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!! ");
|
||||
|
@ -305,11 +379,6 @@ public class FunctionDumper {
|
|||
// Parse preliminary line tokens
|
||||
for (int i = 0; i < line.getNumTokens(); i++) {
|
||||
ClangToken token = line.getToken(i);
|
||||
if (token.getText().equals("__cdecl") || token.getText().equals("__thiscall")
|
||||
|| token.getText().equals("__stdcall")) {
|
||||
// Remove function declaration
|
||||
continue;
|
||||
}
|
||||
if (!token.getText().isEmpty())
|
||||
tokens.add(token);
|
||||
}
|
||||
|
@ -410,9 +479,14 @@ public class FunctionDumper {
|
|||
String proto = externalFunction.getSignature().getPrototypeString(false);
|
||||
String name = externalFunction.getName();
|
||||
proto = proto.replace(name, Utils.sanitizeIdentifier(name));
|
||||
|
||||
// Add calling convention information to the comment
|
||||
String callingConv = externalFunction.getCallingConventionName();
|
||||
FunctionDatabase.CallingConvention conv = FunctionDatabase.CallingConvention.fromString(callingConv);
|
||||
|
||||
headers.add("" + proto
|
||||
+ "; // " + externalFunction.getEntryPoint() + " // "
|
||||
+ name);
|
||||
+ name + " // " + conv);
|
||||
}
|
||||
|
||||
for (String header : headers) {
|
||||
|
|
|
@ -226,8 +226,7 @@ public class GlobalDumper {
|
|||
|
||||
// Add all current globals to database
|
||||
for (GlobalRec global : globalAddrs.values()) {
|
||||
String dataTypeName = global.type.getDisplayName();
|
||||
functionDatabase.addGlobal(global.address, global.name, dataTypeName);
|
||||
functionDatabase.addGlobal(global.address, global.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.CategoryPath;
|
||||
import ghidra.program.model.data.Composite;
|
||||
import ghidra.program.model.data.DataType;
|
||||
|
@ -20,7 +21,9 @@ import ghidra.program.model.data.TypeDef;
|
|||
import ghidra.program.model.data.TypedefDataType;
|
||||
import ghidra.program.model.data.Union;
|
||||
import ghidra.program.model.data.UnionDataType;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import re3lib.FunctionDatabase.GlobalEntry;
|
||||
|
||||
public class TypeDumper {
|
||||
Program currentProgram;
|
||||
|
@ -35,6 +38,25 @@ public class TypeDumper {
|
|||
public void run() throws Exception {
|
||||
ProgramBasedDataTypeManager dtm = currentProgram.getDataTypeManager();
|
||||
|
||||
HashSet<String> requiredFunctionTypes = new HashSet<>();
|
||||
FunctionDatabase fd = new FunctionDatabase(script);
|
||||
List<GlobalEntry> globals = fd.loadAllGlobals();
|
||||
for (GlobalEntry globalEntry : globals) {
|
||||
// Fetch type of global from ghidra
|
||||
Address addr = globalEntry.address;
|
||||
if (globalEntry.name == "p_fn_vDisplayAll")
|
||||
script.println("EEEEE");
|
||||
|
||||
Data data = script.getDataAt(addr);
|
||||
if (data != null) {
|
||||
DataType type = data.getDataType();
|
||||
if (type instanceof FunctionDefinition) {
|
||||
requiredFunctionTypes.add(type.getDisplayName());
|
||||
script.println("Adding required global function type: " + type.getDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<String> typeBlacklist = Utils.loadSimpleBlacklist(RemanConfig.INSTANCE.typeBlacklistPath);
|
||||
HashSet<String> categoryPathBlacklist = Utils
|
||||
.loadSimpleBlacklist(RemanConfig.INSTANCE.categoryPathBlacklistPath);
|
||||
|
@ -89,7 +111,7 @@ public class TypeDumper {
|
|||
if (dt instanceof Structure || dt instanceof TypeDef || dt instanceof EnumDataType
|
||||
|| dt instanceof Union || dt instanceof Enum || dt instanceof FunctionDefinition) {
|
||||
|
||||
if (dt.getDisplayName().contains("NormalizeFn") || dt.getDisplayName().contains("_M_IX86"))
|
||||
if (dt.getDisplayName().contains("level_displayFn") || dt.getDisplayName().contains("_M_IX86"))
|
||||
script.println("DEBUG " + dt.getDisplayName() + " - " + dt.getClass().getSimpleName());
|
||||
|
||||
// if (dt.getDisplayName().contains("tdstObjectTypeElement_") ||
|
||||
|
@ -113,6 +135,7 @@ public class TypeDumper {
|
|||
writer.println("#include <r3/binders/type.h>");
|
||||
|
||||
DataTypeWriter dtw = new DataTypeWriter(dtm, writer);
|
||||
dtw.requiredFunctionTypes = requiredFunctionTypes;
|
||||
dtw.write(filteredTypes, script.getMonitor());
|
||||
|
||||
Utils.headerGuardPost(writer, "STRUCTS");
|
||||
|
|
|
@ -11,7 +11,8 @@ bool generateHooksFile(const std::string &output_filepath) {
|
|||
try {
|
||||
DatabaseManager db(options.db_path);
|
||||
|
||||
std::vector<FunctionInfo> fix_functions = db.getFunctionsByType(FileType::Fix);
|
||||
std::vector<FunctionInfo> fix_functions =
|
||||
db.getFunctionsByType(FileType::Fix);
|
||||
|
||||
std::ofstream output_stream(output_filepath);
|
||||
if (!output_stream.is_open()) {
|
||||
|
@ -23,17 +24,40 @@ bool generateHooksFile(const std::string &output_filepath) {
|
|||
|
||||
for (const auto &func : fix_functions) {
|
||||
// Extract just the filename from the full path
|
||||
std::string filename = std::filesystem::path(func.filepath).filename().string();
|
||||
std::string filename =
|
||||
std::filesystem::path(func.filepath).filename().string();
|
||||
std::string conv_str = callingConventionToString(func.calling_convention);
|
||||
size_t numParams = 0;
|
||||
if (!func.parameter_types.empty()) {
|
||||
std::string params = func.parameter_types;
|
||||
std::stringstream ss(params);
|
||||
std::string param;
|
||||
while (std::getline(ss, param, ';')) {
|
||||
if (!param.empty()) {
|
||||
numParams++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output_stream << "HOOK(0x" << func.address << ", " << func.name << ", " << conv_str << ") // " << filename << std::endl;
|
||||
if (func.parameter_types == "void")
|
||||
numParams = 0;
|
||||
|
||||
spdlog::debug("Added hook: {} {} {} from {}", func.address, func.name, conv_str, filename);
|
||||
if (conv_str == "stdcall") {
|
||||
output_stream << "HOOK_S" << numParams << "(0x" << func.address << ", "
|
||||
<< func.name << ") // " << filename << std::endl;
|
||||
} else {
|
||||
output_stream << "HOOK(0x" << func.address << ", " << func.name
|
||||
<< ") // " << filename << std::endl;
|
||||
}
|
||||
|
||||
spdlog::debug("Added hook: {} {} {} from {}", func.address, func.name,
|
||||
conv_str, filename);
|
||||
}
|
||||
|
||||
output_stream.close();
|
||||
|
||||
spdlog::info("Generated {} hooks in {}", fix_functions.size(), output_filepath);
|
||||
spdlog::info("Generated {} hooks in {}", fix_functions.size(),
|
||||
output_filepath);
|
||||
return true;
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
|
@ -43,7 +67,8 @@ bool generateHooksFile(const std::string &output_filepath) {
|
|||
}
|
||||
|
||||
void register_cmd_hooks(CLI::App &app) {
|
||||
auto cmd = app.add_subcommand("hooks", "Generate hooks file for Fix-type functions");
|
||||
auto cmd =
|
||||
app.add_subcommand("hooks", "Generate hooks file for Fix-type functions");
|
||||
cmd->add_option("-o,--output", output_file, "Output file for hooks")
|
||||
->default_val("hooks.def");
|
||||
cmd->final_callback([]() {
|
||||
|
|
|
@ -27,11 +27,11 @@ public:
|
|||
&delete_imports_stmt,
|
||||
"Failed to prepare delete imports statement");
|
||||
prepareStatement("INSERT OR REPLACE INTO Functions (filepath, name, "
|
||||
"address, type, calling_convention) VALUES (?, ?, ?, ?, ?)",
|
||||
"address, type, calling_convention, parameter_names, parameter_types, return_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
&insert_functions_stmt,
|
||||
"Failed to prepare insert functions statement");
|
||||
prepareStatement("INSERT OR REPLACE INTO Imports (filepath, name, address, "
|
||||
"type, calling_convention) VALUES (?, ?, ?, ?, ?)",
|
||||
"type, calling_convention, parameter_names, parameter_types, return_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
&insert_imports_stmt,
|
||||
"Failed to prepare insert imports statement");
|
||||
prepareStatement("DELETE FROM Globals WHERE filepath = ?",
|
||||
|
@ -80,8 +80,8 @@ DatabaseManager::DatabaseManager(const std::string &db_path) : db(nullptr) {
|
|||
}
|
||||
|
||||
const char *create_tables = R"(
|
||||
CREATE TABLE IF NOT EXISTS Functions (filepath TEXT, name TEXT, address TEXT, type INTEGER DEFAULT 0, calling_convention INTEGER DEFAULT 0, PRIMARY KEY (name, filepath));
|
||||
CREATE TABLE IF NOT EXISTS Imports (filepath TEXT, name TEXT, address TEXT, type INTEGER DEFAULT 0, calling_convention INTEGER DEFAULT 0, PRIMARY KEY (name, filepath));
|
||||
CREATE TABLE IF NOT EXISTS Functions (filepath TEXT, name TEXT, address TEXT, type INTEGER DEFAULT 0, calling_convention INTEGER DEFAULT 0, parameter_names TEXT DEFAULT '', parameter_types TEXT DEFAULT '', return_type TEXT DEFAULT '', PRIMARY KEY (name, filepath));
|
||||
CREATE TABLE IF NOT EXISTS Imports (filepath TEXT, name TEXT, address TEXT, type INTEGER DEFAULT 0, calling_convention INTEGER DEFAULT 0, parameter_names TEXT DEFAULT '', parameter_types TEXT DEFAULT '', return_type TEXT DEFAULT '', PRIMARY KEY (name, filepath));
|
||||
CREATE TABLE IF NOT EXISTS Globals (filepath TEXT, name TEXT, address TEXT);
|
||||
)";
|
||||
|
||||
|
@ -119,6 +119,9 @@ void DatabaseManager::insertFunction(const FunctionInfo &func) {
|
|||
sqlite3_bind_text(stmt, 3, func.address.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_int(stmt, 4, static_cast<int>(func.type));
|
||||
sqlite3_bind_int(stmt, 5, static_cast<int>(func.calling_convention));
|
||||
sqlite3_bind_text(stmt, 6, func.parameter_names.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 7, func.parameter_types.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 8, func.return_type.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_step(stmt);
|
||||
}
|
||||
|
||||
|
@ -241,7 +244,7 @@ std::vector<FunctionInfo> DatabaseManager::getFunctionsByType(FileType type) {
|
|||
std::vector<FunctionInfo> functions;
|
||||
|
||||
const char *sql = R"(
|
||||
SELECT name, address, filepath, calling_convention
|
||||
SELECT name, address, filepath, calling_convention, parameter_names, parameter_types, return_type
|
||||
FROM Functions
|
||||
WHERE type = ? AND address != ''
|
||||
ORDER BY address;
|
||||
|
@ -261,6 +264,9 @@ std::vector<FunctionInfo> DatabaseManager::getFunctionsByType(FileType type) {
|
|||
func.address = (const char *)sqlite3_column_text(stmt, 1);
|
||||
func.filepath = (const char *)sqlite3_column_text(stmt, 2);
|
||||
func.calling_convention = static_cast<CallingConvention>(sqlite3_column_int(stmt, 3));
|
||||
func.parameter_names = (const char *)sqlite3_column_text(stmt, 4);
|
||||
func.parameter_types = (const char *)sqlite3_column_text(stmt, 5);
|
||||
func.return_type = (const char *)sqlite3_column_text(stmt, 6);
|
||||
func.type = type;
|
||||
func.is_import = false; // Functions table contains non-imports
|
||||
|
||||
|
|
|
@ -281,15 +281,24 @@ void findFunctions(TSNode node, const char *source_code, uint32_t source_length,
|
|||
// Detect calling convention
|
||||
CallingConvention calling_conv = getCallingConvention(node, source_code);
|
||||
|
||||
FunctionInfo func{func_name, address, "",
|
||||
strcmp(type, "function_definition") == 0
|
||||
? !hasFunctionBody(node)
|
||||
: true,
|
||||
file_type}; // Add file_type parameter
|
||||
func.calling_convention = calling_conv; // Set the calling convention
|
||||
// Extract parameter information and return type
|
||||
std::string parameter_names = getParameterNames(node, source_code);
|
||||
std::string parameter_types = getParameterTypes(node, source_code);
|
||||
std::string return_type = getReturnType(node, source_code);
|
||||
|
||||
spdlog::debug("Found function: {} at {} with calling convention: {}",
|
||||
func_name, address, callingConventionToString(calling_conv));
|
||||
FunctionInfo func;
|
||||
func.name = func_name;
|
||||
func.address = address;
|
||||
func.filepath = "";
|
||||
func.parameter_names = parameter_names;
|
||||
func.parameter_types = parameter_types;
|
||||
func.return_type = return_type;
|
||||
func.is_import = strcmp(type, "function_definition") == 0 ? !hasFunctionBody(node) : true;
|
||||
func.type = file_type;
|
||||
func.calling_convention = calling_conv;
|
||||
|
||||
spdlog::debug("Found function: {} at {} with calling convention: {}, return type: {}, param names: {}, param types: {}",
|
||||
func_name, address, callingConventionToString(calling_conv), return_type, parameter_names, parameter_types);
|
||||
|
||||
functions.push_back(func);
|
||||
}
|
||||
|
@ -354,3 +363,139 @@ void findGlobals(TSNode node, const char *source_code, uint32_t source_length,
|
|||
findGlobals(ts_node_child(node, i), source_code, source_length, globals);
|
||||
}
|
||||
}
|
||||
|
||||
// Add helper functions to extract parameter information and return type
|
||||
std::string getParameterNames(TSNode node, const char *source_code) {
|
||||
std::vector<std::string> names;
|
||||
uint32_t child_count = ts_node_child_count(node);
|
||||
|
||||
for (uint32_t i = 0; i < child_count; i++) {
|
||||
TSNode child = ts_node_child(node, i);
|
||||
const char *type = ts_node_type(child);
|
||||
|
||||
if (strcmp(type, "function_declarator") == 0) {
|
||||
// Look for parameter_list within function_declarator
|
||||
uint32_t func_child_count = ts_node_child_count(child);
|
||||
for (uint32_t j = 0; j < func_child_count; j++) {
|
||||
TSNode func_child = ts_node_child(child, j);
|
||||
if (strcmp(ts_node_type(func_child), "parameter_list") == 0) {
|
||||
// Extract each parameter_declaration
|
||||
uint32_t param_list_count = ts_node_child_count(func_child);
|
||||
for (uint32_t k = 0; k < param_list_count; k++) {
|
||||
TSNode param_node = ts_node_child(func_child, k);
|
||||
if (strcmp(ts_node_type(param_node), "parameter_declaration") == 0) {
|
||||
// Find the identifier (parameter name) in this parameter
|
||||
std::string param_name = findIdentifierInDeclarator(param_node, source_code);
|
||||
if (!param_name.empty()) {
|
||||
names.push_back(param_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Join names with semicolon
|
||||
std::string result;
|
||||
for (size_t i = 0; i < names.size(); i++) {
|
||||
if (i > 0) result += ";";
|
||||
result += names[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string getParameterTypes(TSNode node, const char *source_code) {
|
||||
std::vector<std::string> types;
|
||||
uint32_t child_count = ts_node_child_count(node);
|
||||
|
||||
for (uint32_t i = 0; i < child_count; i++) {
|
||||
TSNode child = ts_node_child(node, i);
|
||||
const char *type = ts_node_type(child);
|
||||
|
||||
if (strcmp(type, "function_declarator") == 0) {
|
||||
// Look for parameter_list within function_declarator
|
||||
uint32_t func_child_count = ts_node_child_count(child);
|
||||
for (uint32_t j = 0; j < func_child_count; j++) {
|
||||
TSNode func_child = ts_node_child(child, j);
|
||||
if (strcmp(ts_node_type(func_child), "parameter_list") == 0) {
|
||||
// Extract each parameter_declaration
|
||||
uint32_t param_list_count = ts_node_child_count(func_child);
|
||||
for (uint32_t k = 0; k < param_list_count; k++) {
|
||||
TSNode param_node = ts_node_child(func_child, k);
|
||||
if (strcmp(ts_node_type(param_node), "parameter_declaration") == 0) {
|
||||
// Extract type part by getting everything except the identifier
|
||||
std::string full_param = extractNodeText(param_node, source_code);
|
||||
std::string param_name = findIdentifierInDeclarator(param_node, source_code);
|
||||
|
||||
// Remove the parameter name from the full parameter text to get just the type
|
||||
std::string param_type = full_param;
|
||||
if (!param_name.empty()) {
|
||||
size_t name_pos = param_type.rfind(param_name);
|
||||
if (name_pos != std::string::npos) {
|
||||
param_type = param_type.substr(0, name_pos);
|
||||
// Clean up trailing whitespace and pointer/reference symbols after the type
|
||||
param_type.erase(param_type.find_last_not_of(" \t\n\r*&") + 1);
|
||||
|
||||
// Add back any pointer/reference symbols that were part of the type
|
||||
size_t type_end = name_pos;
|
||||
while (type_end < full_param.length() &&
|
||||
(full_param[type_end] == ' ' || full_param[type_end] == '\t')) {
|
||||
type_end++;
|
||||
}
|
||||
if (type_end > name_pos + param_name.length()) {
|
||||
param_type += full_param.substr(name_pos + param_name.length(),
|
||||
type_end - (name_pos + param_name.length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up any extra whitespace
|
||||
param_type.erase(0, param_type.find_first_not_of(" \t\n\r"));
|
||||
param_type.erase(param_type.find_last_not_of(" \t\n\r") + 1);
|
||||
|
||||
if (!param_type.empty()) {
|
||||
types.push_back(param_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Join types with semicolon
|
||||
std::string result;
|
||||
for (size_t i = 0; i < types.size(); i++) {
|
||||
if (i > 0) result += ";";
|
||||
result += types[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string getReturnType(TSNode node, const char *source_code) {
|
||||
uint32_t child_count = ts_node_child_count(node);
|
||||
|
||||
for (uint32_t i = 0; i < child_count; i++) {
|
||||
TSNode child = ts_node_child(node, i);
|
||||
const char *type = ts_node_type(child);
|
||||
|
||||
// Look for type specifiers (return type comes before function declarator)
|
||||
if (strcmp(type, "type_identifier") == 0 ||
|
||||
strcmp(type, "primitive_type") == 0 ||
|
||||
strcmp(type, "sized_type_specifier") == 0) {
|
||||
return extractNodeText(child, source_code);
|
||||
}
|
||||
// Handle more complex types
|
||||
else if (strcmp(type, "qualified_identifier") == 0 ||
|
||||
strcmp(type, "template_type") == 0) {
|
||||
return extractNodeText(child, source_code);
|
||||
}
|
||||
}
|
||||
|
||||
return "void"; // Default return type
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ struct FunctionInfo {
|
|||
std::string name;
|
||||
std::string address;
|
||||
std::string filepath;
|
||||
std::string parameter_names; // Semicolon-separated parameter names
|
||||
std::string parameter_types; // Semicolon-separated parameter types
|
||||
std::string return_type; // Function return type
|
||||
bool is_import;
|
||||
FileType type;
|
||||
CallingConvention calling_convention = CallingConvention::Cdecl; // Default to cdecl
|
||||
|
@ -50,6 +53,9 @@ std::string findIdentifierInDeclarator(TSNode node, const char *source_code);
|
|||
std::string getFunctionName(TSNode node, const char *source_code);
|
||||
std::string getGlobalName(TSNode node, const char *source_code);
|
||||
std::string getComment(TSNode node, const char *source_code, uint32_t source_length, bool search_before);
|
||||
std::string getParameterNames(TSNode node, const char *source_code);
|
||||
std::string getParameterTypes(TSNode node, const char *source_code);
|
||||
std::string getReturnType(TSNode node, const char *source_code);
|
||||
bool hasFunctionBody(TSNode node);
|
||||
void findFunctions(TSNode node, const char *source_code, uint32_t source_length,
|
||||
std::vector<FunctionInfo> &functions, FileType file_type);
|
||||
|
|
Loading…
Reference in New Issue