This commit is contained in:
Guus Waals 2025-06-06 01:02:56 +08:00
parent a559f68de2
commit ab0c1473ec
77 changed files with 9913 additions and 162 deletions

3
.gitmodules vendored
View File

@ -10,3 +10,6 @@
[submodule "third_party/hooker"]
path = third_party/hooker
url = https://github.com/guusw/hooker.git
[submodule "third_party/magic_enum"]
path = third_party/magic_enum
url = https://github.com/Neargye/magic_enum.git

View File

@ -89,61 +89,86 @@ public class FindRelocations extends GhidraScript {
private void analyzeInstruction(Instruction instruction) {
String mnemonic = instruction.getMnemonicString().toLowerCase();
boolean trace = instruction.getAddress().getOffset() == 0x0049b154;
if (trace) {
println("DEBUG: " + mnemonic + " at " + instruction.getAddress());
}
// Check for instructions that commonly use absolute addresses
if (isRelocatableInstruction(mnemonic)) {
// Check references from this instruction
Reference[] refs = instruction.getReferencesFrom();
for (Reference ref : refs) {
Address toAddr = ref.getToAddress();
if (isInMainMemorySpace(toAddr)) {
// Check if the target address appears in the instruction bytes (absolute addressing)
int operandOffset = findAbsoluteAddressOffset(instruction, toAddr);
boolean isInMainMemorySpace = isInMainMemorySpace(toAddr);
if (trace) {
println(" isInMainMemorySpace: " + toAddr + " " + isInMainMemorySpace);
}
if (isInMainMemorySpace) {
// Check if the target address appears in the instruction bytes (absolute
// addressing)
int operandOffset = findAbsoluteAddressOffset(instruction, toAddr, trace);
if (operandOffset >= 0) {
recordRelocation(instruction.getAddress(), toAddr, mnemonic,
"absolute_" + ref.getReferenceType().getName(), operandOffset);
recordRelocation(instruction.getAddress(), toAddr, mnemonic,
"absolute_" + ref.getReferenceType().getName(), operandOffset);
} else {
if (trace) {
println(" operandOffset was not found: " + operandOffset);
}
}
}
}
}
}
private int findAbsoluteAddressOffset(Instruction instruction, Address targetAddr) {
private int findAbsoluteAddressOffset(Instruction instruction, Address targetAddr, boolean trace) {
try {
byte[] instructionBytes = instruction.getBytes();
long targetValue = targetAddr.getOffset();
// Convert target address to little-endian byte array (x86 32-bit)
byte[] targetBytes = new byte[4];
targetBytes[0] = (byte) (targetValue & 0xFF);
targetBytes[1] = (byte) ((targetValue >> 8) & 0xFF);
targetBytes[2] = (byte) ((targetValue >> 16) & 0xFF);
targetBytes[3] = (byte) ((targetValue >> 24) & 0xFF);
// Search for the target address bytes in the instruction and return offset
int offset = findSequenceOffset(instructionBytes, targetBytes);
int offset = findSequenceOffset(instructionBytes, targetBytes, trace);
return offset;
} catch (Exception e) {
if (trace) {
println("findAbsoluteAddressOffset exception: " + e.getMessage());
}
return -1;
}
}
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
if (i > 0) sb.append(" ");
if (i > 0)
sb.append(" ");
sb.append(String.format("%02x", bytes[i] & 0xFF));
}
return sb.toString();
}
private int findSequenceOffset(byte[] haystack, byte[] needle) {
private int findSequenceOffset(byte[] haystack, byte[] needle, boolean trace) {
if (trace) {
println("findSequenceOffset inspected bytes: " + bytesToHex(haystack) + " (length: " + haystack.length + ")");
}
if (needle.length > haystack.length) {
if (trace) {
println("findSequenceOffset needle.length > haystack.length");
}
return -1;
}
for (int i = 0; i <= haystack.length - needle.length; i++) {
boolean found = true;
for (int j = 0; j < needle.length; j++) {
@ -162,12 +187,12 @@ public class FindRelocations extends GhidraScript {
private boolean isRelocatableInstruction(String mnemonic) {
// Instructions that commonly use absolute addresses
return mnemonic.equals("mov") || mnemonic.equals("lea") ||
mnemonic.equals("call") || mnemonic.equals("jmp") ||
mnemonic.equals("push") || mnemonic.equals("cmp") ||
mnemonic.equals("test") || mnemonic.equals("add") ||
mnemonic.equals("sub") || mnemonic.equals("and") ||
mnemonic.equals("or") || mnemonic.equals("xor") ||
mnemonic.startsWith("j"); // All jumps, we'll filter by byte analysis
mnemonic.equals("call") || mnemonic.equals("jmp") ||
mnemonic.equals("push") || mnemonic.equals("cmp") ||
mnemonic.equals("test") || mnemonic.equals("add") ||
mnemonic.equals("sub") || mnemonic.equals("and") ||
mnemonic.equals("or") || mnemonic.equals("xor") ||
mnemonic.startsWith("j"); // All jumps, we'll filter by byte analysis
}
private void analyzeDataReferences(long instructionsProcessed, long totalWork) {
@ -175,18 +200,18 @@ public class FindRelocations extends GhidraScript {
MemoryBlock[] blocks = currentProgram.getMemory().getBlocks();
long processedBytes = 0;
int pointerSize = currentProgram.getDefaultPointerSize();
for (MemoryBlock block : blocks) {
// Skip executable blocks (code sections)
if (block.isExecute()) {
continue;
}
// Only scan initialized data blocks
if (!block.isInitialized()) {
continue;
}
if (monitor.isCancelled()) {
println("Operation cancelled by user");
return;
@ -195,9 +220,9 @@ public class FindRelocations extends GhidraScript {
if (block.getName().equals(".rsrc")) {
continue;
}
println("Scanning data block: " + block.getName() + " (" + block.getStart() + " - " + block.getEnd() + ")");
Address addr = block.getStart();
while (addr != null && addr.compareTo(block.getEnd()) <= 0) {
try {
@ -250,11 +275,11 @@ public class FindRelocations extends GhidraScript {
private void recordRelocation(Address fromAddr, Address toAddr, String instruction, String type, int operandOffset) {
String relocKey = fromAddr.toString() + " -> " + toAddr.toString();
if (foundRelocations.add(relocKey)) {
String instructionBytes = getInstructionBytesString(fromAddr);
Address operandPtr = fromAddr.add(operandOffset);
String line = String.format("REL(0x%s, 0x%s, 0x%s) // %s [%s] | %s",
fromAddr.toString(),
operandPtr.toString(),
@ -262,7 +287,7 @@ public class FindRelocations extends GhidraScript {
instruction,
type,
instructionBytes);
outputFile.println(line);
outputFile.flush();
}
@ -287,7 +312,8 @@ public class FindRelocations extends GhidraScript {
if (bytesRead > 0) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytesRead; i++) {
if (i > 0) sb.append(" ");
if (i > 0)
sb.append(" ");
sb.append(String.format("%02x", bytes[i] & 0xFF));
}
return sb.toString();
@ -308,15 +334,16 @@ public class FindRelocations extends GhidraScript {
if (instruction != null) {
return true;
}
// Check if this address is within any function's body
Function function = currentProgram.getFunctionManager().getFunctionContaining(addr);
if (function != null) {
// Additional check: make sure we're in the function body, not just data referenced by it
// Additional check: make sure we're in the function body, not just data
// referenced by it
AddressSetView functionBody = function.getBody();
return functionBody.contains(addr);
}
return false;
}
}

View File

@ -225,9 +225,9 @@ public class FunctionDumper {
String addrString = "0x" +
externalFunction.getEntryPoint().toString().replace("0x", "");
if (returnType.equals("void")) {
writer2.println(" " + stubFunction + "<" + addrString + ", void>(" + paramList.toString() + ");");
writer2.println(" " + stubFunction + "<(stub_t)" + addrString + ", void>(" + paramList.toString() + ");");
} else {
writer2.println(" return " + stubFunction + "<" + addrString + ", " + returnType + ">(" +
writer2.println(" return " + stubFunction + "<(stub_t)" + addrString + ", " + returnType + ">(" +
paramList.toString() + ");");
}

View File

@ -169,14 +169,14 @@ public class GlobalDumper {
DataType baseType = ((Pointer) dt).getDataType();
if (baseType == null) {
script.println("WARNING: Missing base type for pointer: " + name + " at " + addr);
dataType = "pointer";
dataType = "pointer&";
} else if (baseType instanceof FunctionDefinition) {
script.println("Value is a function type " + name + " at " + addr);
dataType = ((FunctionDefinition) baseType).getDisplayName();
} else {
dataType = baseType.getDisplayName() + "*";
dataType = baseType.getDisplayName() + "*&";
}
initBlk += "(" + dataType + ")&GH_MEM(0x" + addr + ")";
initBlk += "(" + dataType + ")GH_MEM(0x" + addr + ")";
fullyDefinedType = true;
}
String linkagePrefix = "extern ";

View File

@ -32,9 +32,11 @@ function(setup_target TARGET DBG_MODE)
target_compile_definitions(${TARGET} PRIVATE
_CRT_SECURE_NO_WARNINGS=1
_CRT_NONSTDC_NO_WARNINGS=1)
_CRT_NONSTDC_NO_WARNINGS=1
SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE
)
target_link_libraries(${TARGET} PRIVATE spdlog)
target_link_libraries(${TARGET} PRIVATE spdlog CLI11 magic_enum)
file(GLOB GH_AUTO_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_auto/*.cxx)
file(GLOB GH_FIX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gh_fix/*.cxx)

View File

@ -7,20 +7,28 @@
extern "C" {
undefined4 crt_createProgramHeap(undefined4 param_1) {
return gh_stub_impl_cdecl<0x00404902, undefined4>(param_1);
return gh_stub_impl_cdecl<(stub_t)0x00404902, undefined4>(param_1);
}
undefined4 ioinit(void) {
return gh_stub_impl_cdecl<(stub_t)0x004046bf, undefined4>();
}
void crt_initConsole(void) {
return gh_stub_impl_cdecl<(stub_t)0x00404503, void>();
}
LPSTR crt_setupEnv(void) {
return gh_stub_impl_cdecl<(stub_t)0x004043d1, LPSTR>();
}
undefined4 ioinit(void) { return gh_stub_impl_cdecl<0x004046bf, undefined4>(); }
void crt_initConsole(void) { return gh_stub_impl_cdecl<0x00404503, void>(); }
LPSTR crt_setupEnv(void) { return gh_stub_impl_cdecl<0x004043d1, LPSTR>(); }
undefined4 crt_main2(void) {
return gh_stub_impl_cdecl<0x00404184, undefined4>();
return gh_stub_impl_cdecl<(stub_t)0x00404184, undefined4>();
}
undefined4 crt_main1(void) {
return gh_stub_impl_cdecl<0x004040cb, undefined4>();
return gh_stub_impl_cdecl<(stub_t)0x004040cb, undefined4>();
}
void crt_static_init(void) {
return gh_stub_impl_cdecl<(stub_t)0x004027be, void>();
}
void crt_static_init(void) { return gh_stub_impl_cdecl<0x004027be, void>(); }
char *crt_0(void) { return gh_stub_impl_cdecl<0x00404073, char *>(); }
char *crt_0(void) { return gh_stub_impl_cdecl<(stub_t)0x00404073, char *>(); }
void gh_pre_main(void) {
DWORD DVar1;

View File

@ -7,10 +7,10 @@ extern "C" {
undefined FUN_00447130(void); // 00447130 // FUN_00447130 // cdecl
void doGraphics(byte param_1); // 00447460 // doGraphics // stdcall
bool UNKr3_renderViewport(byte viewportIdx); // 00447200 // ?r3_renderViewport // stdcall
undefined FUN_0046fec0(void); // 0046fec0 // FUN_0046fec0 // cdecl
int get_one(void); // 0046f2c0 // get_one // cdecl
undefined FUN_00451530(undefined4 param_1); // 00451530 // FUN_00451530 // cdecl
undefined FUN_0048a920(undefined4 param_1); // 0048a920 // FUN_0048a920 // cdecl
void r3_setRendererState(void); // 0046fec0 // r3_setRendererState // cdecl
undefined FUN_0045fc70(undefined4 param_1); // 0045fc70 // FUN_0045fc70 // cdecl
// 00446fc0
@ -46,13 +46,13 @@ void __cdecl r3_levelDisplayFn(byte param)
if (cVar3 != '\0') {
param = param + 1;
}
if (param == (uint32_t&)DAT_005d2b18) {
if (param == DAT_005d2b18) {
FUN_0045fc70(*(undefined4 *)(iVar1 + 4));
}
}
}
if (DAT_005d2b18 != 0) {
FUN_0046fec0(0,0,0,0);
r3_setRendererState();
}
}
/* WARNING: Could not inline here */

View File

@ -12,15 +12,15 @@ undefined r3_checkDisc(void); // 004464f0 // r3_checkDisc
undefined FUN_00503710(void); // 00503710 // FUN_00503710
undefined r3_initAllModules(void); // 00401000 // r3_initAllModules
undefined FUN_00472150(void); // 00472150 // FUN_00472150
undefined r3_wait_for_dvd(char *param_1, char *param_2,
undefined4 param_3); // 0043e540 // r3_wait_for_dvd
undefined r3_waitForDvd(char *param_1, char *param_2,
undefined4 param_3); // 0043e540 // r3_waitForDvd
undefined FUN_004725a0(void); // 004725a0 // FUN_004725a0
int r3_get_gli_width1(void); // 0047baf0 // r3_get_gli_width1
undefined gfx_init2(void); // 00470be0 // gfx_init2
void g_setInitVar0(void); // 00401310 // g_setInitVar0
int r3_get_gli_height1(void); // 0047bb00 // r3_get_gli_height1
undefined FUN_004010b0(void); // 004010b0 // FUN_004010b0
undefined FUN_00401320(void); // 00401320 // FUN_00401320
undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor
void r3_noop(void *p_cTxt1, void *p_cTxt2); // 00401100 // r3_noop
undefined FUN_005038e0(void); // 005038e0 // FUN_005038e0
undefined FUN_004fb300(void); // 004fb300 // FUN_004fb300
@ -608,7 +608,7 @@ LAB_004017ce:
return -1;
}
g_setInitVar0();
FUN_00401320();
r3_windowLockCursor();
spawnThread();
r3_noop(p_cTxt1, p_cTxt2);
gfx_init2();
@ -655,7 +655,7 @@ LAB_004017ce:
}
sprintf(UStack_830, s_Please_run_the__s_setup__005b63f4, s_windowTitle);
sprintf(acStack_528, s__s_not_initialized__005b63e0, s_windowTitle);
r3_wait_for_dvd(UStack_830, acStack_528, 0);
r3_waitForDvd(UStack_830, acStack_528, 0);
/* WARNING: Subroutine does not return */
exit(-1);
}

View File

@ -4,21 +4,21 @@
#include <gh_global.h>
extern "C" {
undefined FUN_0043e4f0(void); // 0043e4f0 // FUN_0043e4f0
void IPT_fn_vReadInput(void); // 00505fe0 // IPT_fn_vReadInput
undefined r3_gfxFrameUNK(void); // 0046fed0 // r3_gfxFrame?
undefined FUN_00441d70(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5); // 00441d70 // FUN_00441d70
undefined FUN_0046fe20(undefined4 param_1, undefined4 param_2, undefined4 param_3); // 0046fe20 // FUN_0046fe20
undefined r3_setRendererState1(undefined4 param_1, undefined4 param_2, undefined4 param_3); // 0046fe20 // r3_setRendererState1 // cdecl
undefined FUN_0043e4f0(void); // 0043e4f0 // FUN_0043e4f0 // cdecl
undefined r3_gfxFrameUNK(void); // 0046fed0 // r3_gfxFrame? // cdecl
undefined FUN_00441d70(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5); // 00441d70 // FUN_00441d70 // cdecl
void IPT_fn_vReadInput(void); // 00505fe0 // IPT_fn_vReadInput // stdcall
// 0043e540
int r3_wait_for_dvd(char *param_1,char *param_2,uint param_3)
int __cdecl r3_waitForDvd(char *param_1,char *param_2,uint param_3)
{
ushort uVar1;
int iVar2;
char local_64 [100];
FUN_0046fe20(1,1,0);
r3_setRendererState1(1,1,0);
iVar2 = FUN_00441d70((undefined4)param_1,0x42c80000,0x43480000,0,0xffffffff);
if (iVar2 == 0) {
iVar2 = MessageBoxA(g_gameHWND1,param_1,param_2,param_3 | 0x10000);

View File

@ -4,12 +4,10 @@
#include <gh_global.h>
extern "C" {
HWND getHWND(void); // 00401300 // getHWND // stdcall // Params: | Types: | Return: typedef HWND HWND__ *
HWND getHWND(void); // 00401300 // getHWND // stdcall
// 00401320 // r3_windowLockCursor(cdecl)
// Parameters: | Types: | Return: undefined
void unknown r3_windowLockCursor(void)
// 00401320
void __cdecl r3_windowLockCursor(void)
{
HWND pHVar1;
@ -30,7 +28,7 @@ void unknown r3_windowLockCursor(void)
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);
// ShowCursor(0);
}
return;
}

View File

@ -4,7 +4,7 @@
#include <gh_global.h>
extern "C" {
undefined FUN_00401320(void); // 00401320 // FUN_00401320 // cdecl
undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor // cdecl
undefined r3_windowUnlockCursor(void); // 004013a0 // r3_windowUnlockCursor // cdecl
// 004025e0
@ -16,7 +16,7 @@ long __stdcall r3_windowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
if (uMsg < WM_SETCURSOR + 1) {
if (uMsg == WM_SETCURSOR) {
if (((g_engineShouldRun != 0) && (g_engineRunning != 0)) && (g_runMaximized != 0)) {
FUN_00401320();
r3_windowLockCursor();
return 1;
}
}

View File

@ -64,8 +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);
FnProcessInput PTR_r3_processInput1_005bdb1c = (FnProcessInput)&GH_MEM(0x005bdb1c); // 005bdb1c
FnDisplay p_fn_vDisplayAll = (FnDisplay)&GH_MEM(0x005bdb24); // 005bdb24
FnProcessInput PTR_r3_processInput1_005bdb1c = (FnProcessInput)GH_MEM(0x005bdb1c); // 005bdb1c
FnDisplay p_fn_vDisplayAll = (FnDisplay)GH_MEM(0x005bdb24); // 005bdb24
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
@ -73,7 +73,7 @@ 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_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
pointer s_Yes = (pointer)&GH_MEM(0x005be304); // 005be304
pointer& s_Yes = (pointer&)GH_MEM(0x005be304); // 005be304
const char* s_SingleProcessor_005be308 = "SingleProcessor"; // 005be308
const char* lpDefault_005be318 = "No"; // 005be318
const char* s_StartDirectory_005be31c = "StartDirectory"; // 005be31c
@ -111,7 +111,7 @@ dword& DWORD_005cf974= (dword&) GH_MEM(0x005cf974);
dword& DWORD_005cf978= (dword&) GH_MEM(0x005cf978);
dword& DWORD_005cf97c= (dword&) GH_MEM(0x005cf97c);
dword& DWORD_005cf980= (dword&) GH_MEM(0x005cf980);
char* PTR_005cf9b4 = (char*)&GH_MEM(0x005cf9b4); // 005cf9b4
char*& PTR_005cf9b4 = (char*&)GH_MEM(0x005cf9b4); // 005cf9b4
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);
@ -135,7 +135,7 @@ HWND& g_gameHWND= (HWND&) GH_MEM(0x0077d4c4);
HANDLE& g_mainThreadHandle= (HANDLE&) GH_MEM(0x0077d4c8);
char(&g_appCmdLine)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d4e0));
char(&s_wndStrRestoring)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d5e0));
char* g_crt_cmdLine = (char*)&GH_MEM(0x0077ea84); // 0077ea84
char*& g_crt_cmdLine = (char*&)GH_MEM(0x0077ea84); // 0077ea84
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);

View File

@ -78,7 +78,7 @@ 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_DVD_s_no_v_lido_005be1ec; // 005be1ec
extern const char* s_Impossible_de_trouver_le_DVD_____005be238; // 005be238
extern pointer s_Yes; // 005be304
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
@ -116,7 +116,7 @@ extern dword& DWORD_005cf974; // 005cf974
extern dword& DWORD_005cf978; // 005cf978
extern dword& DWORD_005cf97c; // 005cf97c
extern dword& DWORD_005cf980; // 005cf980
extern char* PTR_005cf9b4; // 005cf9b4
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
@ -140,7 +140,7 @@ extern HWND& g_gameHWND; // 0077d4c4
extern HANDLE& g_mainThreadHandle; // 0077d4c8
extern char(&g_appCmdLine)[256]; // 0077d4e0
extern char(&s_wndStrRestoring)[256]; // 0077d5e0
extern char* g_crt_cmdLine; // 0077ea84
extern char*& g_crt_cmdLine; // 0077ea84
extern char(&s_quitting1)[64]; // 007825c0
extern char(&s_wndStrQuiting)[56]; // 00782600
extern GAM_EngineStructure& g_stEngineStructure; // 007d7dc0

View File

@ -9,5 +9,5 @@
// 0043e1d0
// Erm_fn_ucInitErrMsg
extern "C" byte Erm_fn_ucInitErrMsg(void) {
return gh_stub_impl_stdcall<0x0043e1d0, byte>();
return gh_stub_impl_stdcall<(stub_t)0x0043e1d0, byte>();
}

View File

@ -9,5 +9,5 @@
// 004010b0
// FUN_004010b0
extern "C" undefined FUN_004010b0(void) {
return gh_stub_impl_cdecl<0x004010b0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x004010b0, undefined>();
}

View File

@ -8,6 +8,6 @@
// 00402470
// FUN_00402470
extern "C" undefined FUN_00402470(undefined4 param_1) {
return gh_stub_impl_cdecl<0x00402470, undefined>(param_1);
extern "C" void FUN_00402470(HWND param_1) {
gh_stub_impl_cdecl<(stub_t)0x00402470, void>(param_1);
}

View File

@ -9,5 +9,5 @@
// 0043e4f0
// FUN_0043e4f0
extern "C" undefined FUN_0043e4f0(void) {
return gh_stub_impl_cdecl<0x0043e4f0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x0043e4f0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00441d70
// FUN_00441d70
extern "C" undefined FUN_00441d70(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5) {
return gh_stub_impl_cdecl<0x00441d70, undefined>(param_1, param_2, param_3, param_4, param_5);
return gh_stub_impl_cdecl<(stub_t)0x00441d70, undefined>(param_1, param_2, param_3, param_4, param_5);
}

View File

@ -9,5 +9,5 @@
// 00442c50
// FUN_00442c50
extern "C" undefined FUN_00442c50(void) {
return gh_stub_impl_cdecl<0x00442c50, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00442c50, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00442f70
// FUN_00442f70
extern "C" undefined FUN_00442f70(undefined4 param_1) {
return gh_stub_impl_cdecl<0x00442f70, undefined>(param_1);
return gh_stub_impl_cdecl<(stub_t)0x00442f70, undefined>(param_1);
}

View File

@ -9,5 +9,5 @@
// 00443120
// FUN_00443120
extern "C" undefined FUN_00443120(undefined4 param_1) {
return gh_stub_impl_cdecl<0x00443120, undefined>(param_1);
return gh_stub_impl_cdecl<(stub_t)0x00443120, undefined>(param_1);
}

View File

@ -9,5 +9,5 @@
// 00445440
// FUN_00445440
extern "C" undefined FUN_00445440(void) {
return gh_stub_impl_cdecl<0x00445440, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00445440, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00445460
// FUN_00445460
extern "C" undefined FUN_00445460(void) {
return gh_stub_impl_cdecl<0x00445460, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00445460, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00447130
// FUN_00447130
extern "C" undefined FUN_00447130(void) {
return gh_stub_impl_cdecl<0x00447130, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00447130, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00451530
// FUN_00451530
extern "C" undefined FUN_00451530(undefined4 param_1) {
return gh_stub_impl_cdecl<0x00451530, undefined>(param_1);
return gh_stub_impl_cdecl<(stub_t)0x00451530, undefined>(param_1);
}

View File

@ -9,5 +9,5 @@
// 0045fc70
// FUN_0045fc70
extern "C" undefined FUN_0045fc70(undefined4 param_1) {
return gh_stub_impl_cdecl<0x0045fc70, undefined>(param_1);
return gh_stub_impl_cdecl<(stub_t)0x0045fc70, undefined>(param_1);
}

View File

@ -9,5 +9,5 @@
// 00470350
// FUN_00470350
extern "C" undefined FUN_00470350(void) {
return gh_stub_impl_cdecl<0x00470350, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00470350, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00470410
// FUN_00470410
extern "C" undefined FUN_00470410(void) {
return gh_stub_impl_cdecl<0x00470410, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00470410, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00470db0
// FUN_00470db0
extern "C" undefined FUN_00470db0(void) {
return gh_stub_impl_cdecl<0x00470db0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00470db0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00472150
// FUN_00472150
extern "C" undefined FUN_00472150(void) {
return gh_stub_impl_cdecl<0x00472150, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00472150, undefined>();
}

View File

@ -9,5 +9,5 @@
// 004725a0
// FUN_004725a0
extern "C" undefined FUN_004725a0(void) {
return gh_stub_impl_cdecl<0x004725a0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x004725a0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 0047bae0
// FUN_0047bae0
extern "C" undefined FUN_0047bae0(void) {
return gh_stub_impl_cdecl<0x0047bae0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x0047bae0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 0048a920
// FUN_0048a920
extern "C" undefined FUN_0048a920(undefined4 param_1) {
return gh_stub_impl_cdecl<0x0048a920, undefined>(param_1);
return gh_stub_impl_cdecl<(stub_t)0x0048a920, undefined>(param_1);
}

View File

@ -9,5 +9,5 @@
// 004fa650
// FUN_004fa650
extern "C" undefined FUN_004fa650(void) {
return gh_stub_impl_cdecl<0x004fa650, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x004fa650, undefined>();
}

View File

@ -9,5 +9,5 @@
// 004fb300
// FUN_004fb300
extern "C" undefined FUN_004fb300(void) {
return gh_stub_impl_cdecl<0x004fb300, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x004fb300, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00503710
// FUN_00503710
extern "C" undefined FUN_00503710(void) {
return gh_stub_impl_cdecl<0x00503710, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00503710, undefined>();
}

View File

@ -9,5 +9,5 @@
// 005038e0
// FUN_005038e0
extern "C" undefined FUN_005038e0(void) {
return gh_stub_impl_cdecl<0x005038e0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x005038e0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 0051a7a0
// FUN_0051a7a0
extern "C" undefined FUN_0051a7a0(short hGLDDevice, undefined4 param_2) {
return gh_stub_impl_cdecl<0x0051a7a0, undefined>(hGLDDevice, param_2);
return gh_stub_impl_cdecl<(stub_t)0x0051a7a0, undefined>(hGLDDevice, param_2);
}

View File

@ -9,5 +9,5 @@
// 0051a900
// FUN_0051a900
extern "C" undefined FUN_0051a900(short hGLDDevice) {
return gh_stub_impl_cdecl<0x0051a900, undefined>(hGLDDevice);
return gh_stub_impl_cdecl<(stub_t)0x0051a900, undefined>(hGLDDevice);
}

View File

@ -9,5 +9,5 @@
// 00505490
// IPT_fn_vActivateAllEntryElements
extern "C" undefined IPT_fn_vActivateAllEntryElements(void) {
return gh_stub_impl_cdecl<0x00505490, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00505490, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00505fe0
// IPT_fn_vReadInput
extern "C" void IPT_fn_vReadInput(void) {
gh_stub_impl_stdcall<0x00505fe0, void>();
gh_stub_impl_stdcall<(stub_t)0x00505fe0, void>();
}

View File

@ -9,5 +9,5 @@
// 0043f830
// Mmg_fn_vFirstInitMmgModule
extern "C" undefined Mmg_fn_vFirstInitMmgModule(undefined1 ucMaxNbChannel) {
return gh_stub_impl_stdcall<0x0043f830, undefined>(ucMaxNbChannel);
return gh_stub_impl_stdcall<(stub_t)0x0043f830, undefined>(ucMaxNbChannel);
}

View File

@ -9,5 +9,5 @@
// 0040a1e0
// SND_fn_vResumeSound
extern "C" undefined SND_fn_vResumeSound(void) {
return gh_stub_impl_cdecl<0x0040a1e0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x0040a1e0, undefined>();
}

View File

@ -8,6 +8,6 @@
// 00447200
// ?r3_renderViewport
extern "C" undefined UNKr3_renderViewport(undefined4 viewportIdx) {
return gh_stub_impl_cdecl<0x00447200, undefined>(viewportIdx);
extern "C" bool UNKr3_renderViewport(byte viewportIdx) {
return gh_stub_impl_stdcall<(stub_t)0x00447200, bool>(viewportIdx);
}

View File

@ -9,5 +9,5 @@
// 00447460
// doGraphics
extern "C" void doGraphics(byte param_1) {
gh_stub_impl_stdcall<0x00447460, void>(param_1);
gh_stub_impl_stdcall<(stub_t)0x00447460, void>(param_1);
}

View File

@ -9,5 +9,5 @@
// 004022f0
// fn_bCreateMainDisplayScreen
extern "C" undefined fn_bCreateMainDisplayScreen(void) {
return gh_stub_impl_cdecl<0x004022f0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x004022f0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00401310
// g_setInitVar0
extern "C" void g_setInitVar0(void) {
gh_stub_impl_stdcall<0x00401310, void>();
gh_stub_impl_stdcall<(stub_t)0x00401310, void>();
}

View File

@ -9,5 +9,5 @@
// 00401300
// getHWND
extern "C" HWND getHWND(void) {
return gh_stub_impl_stdcall<0x00401300, HWND>();
return gh_stub_impl_stdcall<(stub_t)0x00401300, HWND>();
}

View File

@ -9,5 +9,5 @@
// 0046f2c0
// get_one
extern "C" int get_one(void) {
return gh_stub_impl_cdecl<0x0046f2c0, int>();
return gh_stub_impl_cdecl<(stub_t)0x0046f2c0, int>();
}

View File

@ -9,5 +9,5 @@
// 00470be0
// gfx_init2
extern "C" undefined gfx_init2(void) {
return gh_stub_impl_cdecl<0x00470be0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00470be0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00402450
// loadSplashBitmap
extern "C" void loadSplashBitmap(HWND unused) {
gh_stub_impl_stdcall<0x00402450, void>(unused);
gh_stub_impl_stdcall<(stub_t)0x00402450, void>(unused);
}

View File

@ -9,5 +9,5 @@
// 004711d0
// r3_closeConcatTextureFile
extern "C" undefined r3_closeConcatTextureFile(void) {
return gh_stub_impl_cdecl<0x004711d0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x004711d0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 004704e0
// r3_config_setGLIMode
extern "C" undefined r3_config_setGLIMode(char * param_1) {
return gh_stub_impl_cdecl<0x004704e0, undefined>(param_1);
return gh_stub_impl_cdecl<(stub_t)0x004704e0, undefined>(param_1);
}

View File

@ -9,5 +9,5 @@
// 00470570
// r3_config_setIdentifier
extern "C" undefined r3_config_setIdentifier(char * param_1) {
return gh_stub_impl_cdecl<0x00470570, undefined>(param_1);
return gh_stub_impl_cdecl<(stub_t)0x00470570, undefined>(param_1);
}

View File

@ -9,5 +9,5 @@
// 00470f30
// r3_config_setTexturesMem
extern "C" void r3_config_setTexturesMem(char * param_1) {
gh_stub_impl_cdecl<0x00470f30, void>(param_1);
gh_stub_impl_cdecl<(stub_t)0x00470f30, void>(param_1);
}

View File

@ -9,5 +9,5 @@
// 00401220
// r3_engineLoop
extern "C" undefined r3_engineLoop(void) {
return gh_stub_impl_cdecl<0x00401220, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00401220, undefined>();
}

View File

@ -9,5 +9,5 @@
// 0047bb00
// r3_get_gli_height1
extern "C" int r3_get_gli_height1(void) {
return gh_stub_impl_stdcall<0x0047bb00, int>();
return gh_stub_impl_stdcall<(stub_t)0x0047bb00, int>();
}

View File

@ -9,5 +9,5 @@
// 0047baf0
// r3_get_gli_width1
extern "C" int r3_get_gli_width1(void) {
return gh_stub_impl_stdcall<0x0047baf0, int>();
return gh_stub_impl_stdcall<(stub_t)0x0047baf0, int>();
}

View File

@ -9,5 +9,5 @@
// 0046fed0
// r3_gfxFrame?
extern "C" undefined r3_gfxFrameUNK(void) {
return gh_stub_impl_cdecl<0x0046fed0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x0046fed0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00471760
// r3_load_textures_2
extern "C" undefined r3_load_textures_2(void) {
return gh_stub_impl_cdecl<0x00471760, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00471760, undefined>();
}

View File

@ -9,5 +9,5 @@
// 0043e630
// r3_module1_init
extern "C" undefined r3_module1_init(void) {
return gh_stub_impl_cdecl<0x0043e630, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x0043e630, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00443f10
// r3_module_big_init
extern "C" undefined r3_module_big_init(void) {
return gh_stub_impl_cdecl<0x00443f10, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00443f10, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00401100
// r3_noop
extern "C" void r3_noop(void * p_cTxt1, void * p_cTxt2) {
gh_stub_impl_stdcall<0x00401100, void>(p_cTxt1, p_cTxt2);
gh_stub_impl_cdecl<(stub_t)0x00401100, void>(p_cTxt1, p_cTxt2);
}

View File

@ -9,5 +9,5 @@
// 00446f10
// r3_processInput1
extern "C" undefined r3_processInput1(void) {
return gh_stub_impl_cdecl<0x00446f10, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00446f10, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00445fc0
// r3_read_game_config_modem_quality
extern "C" undefined r3_read_game_config_modem_quality(void) {
return gh_stub_impl_cdecl<0x00445fc0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00445fc0, undefined>();
}

View File

@ -9,5 +9,5 @@
// 00446040
// r3_read_game_config_udp_port
extern "C" undefined r3_read_game_config_udp_port(void) {
return gh_stub_impl_cdecl<0x00446040, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x00446040, undefined>();
}

View File

@ -7,7 +7,7 @@
#include <gh_global.h>
// 0046fec0
// FUN_0046fec0
extern "C" undefined FUN_0046fec0(void) {
return gh_stub_impl_cdecl<0x0046fec0, undefined>();
// r3_setRendererState
extern "C" void r3_setRendererState(void) {
gh_stub_impl_cdecl<(stub_t)0x0046fec0, void>();
}

View File

@ -7,7 +7,7 @@
#include <gh_global.h>
// 0046fe20
// FUN_0046fe20
extern "C" undefined FUN_0046fe20(undefined4 param_1, undefined4 param_2, undefined4 param_3) {
return gh_stub_impl_cdecl<0x0046fe20, undefined>(param_1, param_2, param_3);
// r3_setRendererState1
extern "C" undefined r3_setRendererState1(undefined4 param_1, undefined4 param_2, undefined4 param_3) {
return gh_stub_impl_cdecl<(stub_t)0x0046fe20, undefined>(param_1, param_2, param_3);
}

View File

@ -9,5 +9,5 @@
// 0055a8d0
// r3_set_GameDataPath
extern "C" void r3_set_GameDataPath(char * param_1) {
gh_stub_impl_cdecl<0x0055a8d0, void>(param_1);
gh_stub_impl_cdecl<(stub_t)0x0055a8d0, void>(param_1);
}

View File

@ -9,5 +9,5 @@
// 0043e620
// setGameHWND3
extern "C" void setGameHWND3(HWND wnd) {
gh_stub_impl_stdcall<0x0043e620, void>(wnd);
gh_stub_impl_stdcall<(stub_t)0x0043e620, void>(wnd);
}

View File

@ -9,5 +9,5 @@
// 004477d0
// spawnThread
extern "C" undefined spawnThread(void) {
return gh_stub_impl_cdecl<0x004477d0, undefined>();
return gh_stub_impl_cdecl<(stub_t)0x004477d0, undefined>();
}

View File

@ -212,7 +212,8 @@ uint8_t *gh_map_dbg_mem(size_t addr) {
}
void *gh_stub_impl_ptr(void *ptr) {
R3Bin::get();
SPDLOG_DEBUG("Forwarding implementation at {}", ptr);
return (void *)R3Bin::get().translateAddress((void *)ptr);
void* r = (void *)R3Bin::get().translateAddress((void *)ptr);
SPDLOG_DEBUG("Forwarding implementation at {} => {}", ptr, r);
return r;
}
void gh_init_dbg_loader() { R3Bin::get(); }

View File

@ -9,31 +9,33 @@ struct GHStubException : public std::exception {
void *gh_stub_impl_ptr(void *ptr);
template <uintptr_t addr, typename T, typename... Args>
typedef uintptr_t stub_t;
template <stub_t addr, typename T, typename... Args> struct TStubFunctionImpl {
typedef T (*TFn)(Args...);
static inline TFn ptr = (TFn)gh_stub_impl_ptr((void *)addr);
};
template <stub_t addr, typename T, typename... Args>
struct TStubFunctionImplStdCall {
typedef T (*__stdcall TFn)(Args...);
static inline TFn ptr = (TFn)gh_stub_impl_ptr((void *)addr);
};
template <stub_t addr, typename T, typename... Args>
T gh_stub_impl_cdecl(Args... args) {
#if RE_DBG_INJECTED
#if MSVC
static T (*__cdecl ptr)(Args...) = (T(*)(Args...))gh_stub_impl_ptr((void*)addr);
#else
using TFn = __cdecl T (*)(Args...);
static TFn ptr = (TFn)gh_stub_impl_ptr((void*)addr);
#endif
auto ptr = TStubFunctionImpl<addr, T, Args...>::ptr;
return ptr(args...);
#else
throw GHStubException("Function not implemented");
#endif
}
template <uintptr_t addr, typename T, typename... Args>
template <stub_t addr, typename T, typename... Args>
T gh_stub_impl_stdcall(Args... args) {
#if RE_DBG_INJECTED
#if MSVC
static T (*__stdcall ptr)(Args...) =
(T(*__stdcall)(Args...))gh_stub_impl_ptr((void*)addr);
#else
using TFn = __stdcall T (*)(Args...);
static TFn ptr = (TFn)gh_stub_impl_ptr((void*)addr);
#endif
auto ptr = TStubFunctionImplStdCall<addr, T, Args...>::ptr;
return ptr(args...);
#else
throw GHStubException("Function not implemented");

View File

@ -15,10 +15,28 @@ void gh_pre_main(void);
#include <r3/binders/static_mem.h>
#endif
#include <CLI11.hpp>
#include <magic_enum/magic_enum.hpp>
extern "C" int r3_main(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR *cmdline, int showCmd);
int main(int argc, char **argv) {
CLI::App app("Reman 3: The hooded ones");
std::string log_level = "info";
app.add_option("-l,--log-level", log_level, "Log level");
CLI11_PARSE(app, argc, argv);
auto log_level_enum = magic_enum::enum_cast<spdlog::level::level_enum>(log_level);
if (log_level_enum.has_value()) {
spdlog::set_level(log_level_enum.value());
} else {
SPDLOG_ERROR("Invalid log level: {}", log_level);
return 1;
}
try {
#if RE_DBG_INJECTED
gh_init_dbg_loader();

9686
third_party/CLI11/CLI11.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -40,4 +40,9 @@ if(WIN32)
add_library(dinput8 INTERFACE)
target_include_directories(dinput8 INTERFACE ${SDK_INCLUDE})
target_link_libraries(dinput8 INTERFACE dinput8_import)
endif()
endif()
add_library(CLI11 INTERFACE)
target_include_directories(CLI11 INTERFACE ${CMAKE_CURRENT_LIST_DIR}/CLI11)
add_subdirectory(magic_enum)

1
third_party/magic_enum vendored Submodule

@ -0,0 +1 @@
Subproject commit a413fcc9c46a020a746907136a384c227f3cd095