WIP setup CRT
This commit is contained in:
parent
acb9d47e0e
commit
2c104648cd
|
@ -64,11 +64,29 @@ function(setup_target TARGET DBG_MODE)
|
|||
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/r3/binders/auto_pch.cxx>"
|
||||
)
|
||||
|
||||
# Potentially might want 1/1 translation for code
|
||||
# For now it has the following values:
|
||||
# 0 = 100% original (as possible)
|
||||
# 1 = Runtime QOL (no cd checks, windowed mode, etc.)
|
||||
target_compile_definitions(${TARGET} PRIVATE
|
||||
RE_AUTHENTIC=1
|
||||
)
|
||||
|
||||
if(DBG_MODE)
|
||||
target_sources(${TARGET} PRIVATE
|
||||
r3/binders/dbg_mem.cxx
|
||||
)
|
||||
target_compile_definitions(game_dbg PRIVATE RE_DBG_INJECTED=1)
|
||||
|
||||
# We load the original binary at it's original location, so offset the base address
|
||||
target_link_options(${TARGET} PRIVATE
|
||||
-Wl,/BASE:0x20000000
|
||||
-Wl,/DYNAMICBASE:NO
|
||||
)
|
||||
target_link_libraries(${TARGET} PRIVATE
|
||||
DbgHelp
|
||||
)
|
||||
|
||||
else()
|
||||
target_sources(${TARGET} PRIVATE
|
||||
r3/binders/static_mem.cxx
|
||||
|
|
BIN
game_re/gh_datasegment.bin (Stored with Git LFS)
BIN
game_re/gh_datasegment.bin (Stored with Git LFS)
Binary file not shown.
|
@ -3,9 +3,9 @@
|
|||
#pragma once
|
||||
#include <cstddef>
|
||||
|
||||
#define GH_DATA_START 0x00597000
|
||||
#define GH_DATA_START 0x00400000
|
||||
#define GH_DATA_END 0x00843fff
|
||||
#define GH_DATA_SIZE (GH_DATA_END - GH_DATA_START)
|
||||
constexpr size_t gh_data_start = 0x00597000;
|
||||
constexpr size_t gh_data_start = 0x00400000;
|
||||
constexpr size_t gh_data_end = 0x00843fff;
|
||||
constexpr size_t gh_data_size = gh_data_end - gh_data_start;
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!!
|
||||
|
||||
#include <r3/binders/auto.h>
|
||||
#include <r3/binders/stub.h>
|
||||
#include <gh_global.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
extern "C" {
|
||||
undefined4 crt_createProgramHeap(undefined4 param_1) {
|
||||
return gh_stub_impl_cdecl<undefined4>((void *)0x00404902, param_1);
|
||||
}
|
||||
undefined4 ioinit(void) {
|
||||
return gh_stub_impl_cdecl<undefined4>((void *)0x004046bf);
|
||||
}
|
||||
void crt_initConsole(void) {
|
||||
return gh_stub_impl_cdecl<void>((void *)0x00404503);
|
||||
}
|
||||
LPSTR crt_setupEnv(void) {
|
||||
return gh_stub_impl_cdecl<LPSTR>((void *)0x004043d1);
|
||||
}
|
||||
undefined4 crt_main2(void) {
|
||||
return gh_stub_impl_cdecl<undefined4>((void *)0x00404184);
|
||||
}
|
||||
undefined4 crt_main1(void) {
|
||||
return gh_stub_impl_cdecl<undefined4>((void *)0x004040cb);
|
||||
}
|
||||
void c_static_init(void) {
|
||||
return gh_stub_impl_cdecl<void>((void *)0x004027be);
|
||||
}
|
||||
|
||||
char* crt_0(void) {
|
||||
return gh_stub_impl_cdecl<char*>((void *)0x00404073);
|
||||
}
|
||||
|
||||
void gh_pre_main(void) {
|
||||
DWORD DVar1;
|
||||
int iVar2;
|
||||
LPSTR *cmdline;
|
||||
uint showCmd;
|
||||
HMODULE hInstance;
|
||||
HINSTANCE hPrevInstance;
|
||||
_STARTUPINFOA local_60;
|
||||
undefined1 *local_1c;
|
||||
void *pvStack_14;
|
||||
undefined1 *puStack_10;
|
||||
undefined *puStack_c;
|
||||
undefined4 local_8;
|
||||
|
||||
local_8 = 0xffffffff;
|
||||
// This sets up the unhandled exception handler i think?
|
||||
// puStack_c = &DAT_00597ca0;
|
||||
// puStack_10 = &LAB_00404a58;
|
||||
// pvStack_14 = ExceptionList;
|
||||
// local_1c = &stack0xffffff88;
|
||||
// ExceptionList = &pvStack_14;
|
||||
DVar1 = GetVersion();
|
||||
DWORD_005cf980 = DVar1 >> 8 & 0xff;
|
||||
DWORD_005cf97c = DVar1 & 0xff;
|
||||
DWORD_005cf978 = DWORD_005cf97c * 0x100 + DWORD_005cf980;
|
||||
DWORD_005cf974 = DVar1 >> 0x10;
|
||||
iVar2 = crt_createProgramHeap(1);
|
||||
if (iVar2 == 0) {
|
||||
SPDLOG_ERROR("crt_createProgramHeap failed");
|
||||
exit(0);
|
||||
}
|
||||
iVar2 = ioinit();
|
||||
if (iVar2 == 0) {
|
||||
SPDLOG_ERROR("_ioinit failed");
|
||||
exit(0);
|
||||
}
|
||||
local_8 = 0;
|
||||
crt_initConsole();
|
||||
g_crt_cmdLine = GetCommandLineA();
|
||||
PTR_005cf9b4 = crt_setupEnv();
|
||||
crt_main2();
|
||||
crt_main1();
|
||||
c_static_init();
|
||||
local_60.dwFlags = 0;
|
||||
GetStartupInfoA(&local_60);
|
||||
cmdline = (LPSTR *)crt_0();
|
||||
if ((local_60.dwFlags & 1) == 0) {
|
||||
showCmd = 10;
|
||||
} else {
|
||||
showCmd = (uint)local_60.wShowWindow;
|
||||
}
|
||||
hPrevInstance = (HINSTANCE)0x0;
|
||||
hInstance = GetModuleHandleA((LPCSTR)0x0);
|
||||
}
|
||||
}
|
|
@ -82,7 +82,8 @@ int r3_main(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR *cmdline,int showC
|
|||
LPRECT lpRect;
|
||||
LPHANDLE lpTargetHandle;
|
||||
undefined4 uVar22;
|
||||
|
||||
|
||||
#if RE_AUTHENTIC == 0
|
||||
lpBuffer = pathToUbi_ini;
|
||||
uiParam = 0x104;
|
||||
/* Append windows dir / ubi.ini */
|
||||
|
@ -111,17 +112,17 @@ int r3_main(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR *cmdline,int showC
|
|||
pcVar4[(int)(tStack_820 + iVar13)] = cVar1;
|
||||
pcVar4 = pcVar4 + 1;
|
||||
} while (cVar1 != '\0');
|
||||
pcVar4 = strrchr(tStack_820,0x5c);
|
||||
pcVar4 = strrchr(tStack_820,0x5c); // Get the exe path
|
||||
if (pcVar4 == (char *)0x0) {
|
||||
/* Read from ubi.ini */
|
||||
GetPrivateProfileStringA
|
||||
(lpAppName_005b68f0,s_Directory_005b68f8,s_None,tStack_820,0xff,acStack_61c);
|
||||
iVar13 = strcmpi(tStack_820,s_None);
|
||||
}
|
||||
else {
|
||||
else { // We have the .exe path
|
||||
pcVar4 = strrchr(tStack_820,0x5c);
|
||||
*pcVar4 = '\0';
|
||||
iVar13 = chdir(tStack_820);
|
||||
*pcVar4 = '\0'; // Split into the binary path (strip .exe)
|
||||
iVar13 = chdir(tStack_820); // Change into the binary path
|
||||
if (iVar13 != -1) goto LAB_00401765;
|
||||
/* Read from ubi.ini */
|
||||
GetPrivateProfileStringA
|
||||
|
@ -244,7 +245,7 @@ LAB_004017ce:
|
|||
/* Setup localized quiting/restoring strings */
|
||||
iVar13 = strcmpi(aCStack_71c,s_French_005b6828);
|
||||
if (iVar13 == 0) {
|
||||
sprintf(s_windowTitleRestoring,s_Restauration_fmt,s_windowTitle);
|
||||
sprintf(g_windowTitleRestoring,s_Restauration_fmt,s_windowTitle);
|
||||
chars = s_QUITTER + Field<4, 4>();
|
||||
pcVar4 = s_ou_appuyez_sur_Echap_pour_quitte_005b67d0;
|
||||
pcVar17 = s_quitting1;
|
||||
|
@ -279,7 +280,7 @@ LAB_004017ce:
|
|||
else {
|
||||
iVar13 = strcmpi(aCStack_71c,s_Spanish_005b67a0);
|
||||
if (iVar13 == 0) {
|
||||
sprintf(s_windowTitleRestoring,s__s___Restablecer_datos____005b6784,s_windowTitle);
|
||||
sprintf(g_windowTitleRestoring,s__s___Restablecer_datos____005b6784,s_windowTitle);
|
||||
uVar2 = s_SALIR_005b675c + Field<4, 2>();
|
||||
pcVar4 = s_Pulsa_ESC_para_salir_Rayman_3__005b6764;
|
||||
pcVar17 = s_quitting1;
|
||||
|
@ -319,7 +320,7 @@ LAB_004017ce:
|
|||
else {
|
||||
iVar13 = strcmpi(aCStack_71c,s_Italian_005b6730);
|
||||
if (iVar13 == 0) {
|
||||
sprintf(s_windowTitleRestoring,s__s___Ripristino_dati____005b6718,s_windowTitle);
|
||||
sprintf(g_windowTitleRestoring,s__s___Ripristino_dati____005b6718,s_windowTitle);
|
||||
uVar2 = s_USCIRE_005b66ec + Field<4, 2>();
|
||||
pcVar4 = s_Premi_ESC_per_uscire_da_Rayman_3_005b66f4;
|
||||
pcVar17 = s_quitting1;
|
||||
|
@ -360,7 +361,7 @@ LAB_004017ce:
|
|||
else {
|
||||
iVar13 = strcmpi(aCStack_71c,s_German_005b66c4);
|
||||
if (iVar13 == 0) {
|
||||
sprintf(s_windowTitleRestoring,s__s___Daten_Reparatur____005b66ac,s_windowTitle);
|
||||
sprintf(g_windowTitleRestoring,s__s___Daten_Reparatur____005b66ac,s_windowTitle);
|
||||
chars = s_BEENDIGEN_005b6678 + Field<0, 4>();
|
||||
pcVar4 = &CHAR_E_005b6684;
|
||||
pcVar17 = s_quitting1;
|
||||
|
@ -420,7 +421,7 @@ LAB_004017ce:
|
|||
s_wndStrRestoring[0x12] = s_Daten_Reparatur____005b6664[0x12];
|
||||
}
|
||||
else {
|
||||
sprintf(s_windowTitleRestoring,s__s___Restoring_data____005b664c,s_windowTitle);
|
||||
sprintf(g_windowTitleRestoring,s__s___Restoring_data____005b664c,s_windowTitle);
|
||||
chars = s_QUIT + Field<0, 4>();
|
||||
pcVar4 = s_or_press_ESC_to_quit_Rayman_3__005b662c;
|
||||
pcVar17 = s_quitting1;
|
||||
|
@ -462,6 +463,13 @@ LAB_004017ce:
|
|||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
strcpy(g_windowTitle, "Reman3");
|
||||
strcpy(g_windowTitle1, "Reman3 - Paused");
|
||||
strcpy(g_windowTitleRestoring, "Restoring data");
|
||||
|
||||
|
||||
#endif
|
||||
/* Create draw semaphore
|
||||
Initial count = 1
|
||||
Maximum count = 1 */
|
||||
|
|
|
@ -1,5 +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);
|
||||
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));
|
||||
|
@ -58,6 +60,11 @@ const char* s_Directory_005b68f8 = "Directory"; // 005b68f8
|
|||
const char* s_None = "None"; // 005b6904
|
||||
const char* s_UbiSoft_Ubi_ini = "/UbiSoft/Ubi.ini"; // 005b690c
|
||||
long& lpDefault_005cf96c= (long&) GH_MEM(0x005cf96c);
|
||||
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);
|
||||
r3_main_data& r3_main_data_005d28b6= (r3_main_data&) GH_MEM(0x005d28b6);
|
||||
int& g_runMaximized= (int&) GH_MEM(0x0077d0a8);
|
||||
undefined4& g_engineRunning= (undefined4&) GH_MEM(0x0077d0b4);
|
||||
|
@ -65,12 +72,13 @@ HANDLE& g_drawSemaphore= (HANDLE&) GH_MEM(0x0077d0bc);
|
|||
char(&g_mutexName_Rayman3)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d0c0));
|
||||
char(&g_windowTitle)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d1c0));
|
||||
char(&g_windowTitle1)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d2c0));
|
||||
char(&s_windowTitleRestoring)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d3c0));
|
||||
char(&g_windowTitleRestoring)[256] = reinterpret_cast<char(&)[256]>(GH_MEM(0x0077d3c0));
|
||||
HINSTANCE& g_hinstance= (HINSTANCE&) GH_MEM(0x0077d4c0);
|
||||
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);
|
||||
char(&s_quitting1)[64] = reinterpret_cast<char(&)[64]>(GH_MEM(0x007825c0));
|
||||
char(&s_wndStrQuiting)[56] = reinterpret_cast<char(&)[56]>(GH_MEM(0x00782600));
|
||||
uint& DAT_007d9cc4= (uint&) GH_MEM(0x007d9cc4);
|
||||
undefined4& DAT_007d9cc4= (undefined4&) GH_MEM(0x007d9cc4);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <r3/binders/global.h>
|
||||
|
||||
|
||||
extern undefined4& crt_unhandled_exception_handler; // 00404a58
|
||||
extern undefined4& DAT_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
|
||||
|
@ -63,6 +65,11 @@ extern const char* s_Directory_005b68f8; // 005b68f8
|
|||
extern const char* s_None; // 005b6904
|
||||
extern const char* s_UbiSoft_Ubi_ini; // 005b690c
|
||||
extern long& lpDefault_005cf96c; // 005cf96c
|
||||
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 r3_main_data& r3_main_data_005d28b6; // 005d28b6
|
||||
extern int& g_runMaximized; // 0077d0a8
|
||||
extern undefined4& g_engineRunning; // 0077d0b4
|
||||
|
@ -70,13 +77,14 @@ extern HANDLE& g_drawSemaphore; // 0077d0bc
|
|||
extern char(&g_mutexName_Rayman3)[256]; // 0077d0c0
|
||||
extern char(&g_windowTitle)[256]; // 0077d1c0
|
||||
extern char(&g_windowTitle1)[256]; // 0077d2c0
|
||||
extern char(&s_windowTitleRestoring)[256]; // 0077d3c0
|
||||
extern char(&g_windowTitleRestoring)[256]; // 0077d3c0
|
||||
extern HINSTANCE& g_hinstance; // 0077d4c0
|
||||
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(&s_quitting1)[64]; // 007825c0
|
||||
extern char(&s_wndStrQuiting)[56]; // 00782600
|
||||
extern uint& DAT_007d9cc4; // 007d9cc4
|
||||
extern undefined4& DAT_007d9cc4; // 007d9cc4
|
||||
#endif // GH_GENERATED_GLOBALS_H
|
||||
|
|
|
@ -1,10 +1,134 @@
|
|||
#include "r3/config/static.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <windows.h>
|
||||
#include <DbgHelp.h>
|
||||
|
||||
#define GH_BASE_ADDR 0x00400000
|
||||
|
||||
static uintptr_t g_gh_translationOffset{};
|
||||
|
||||
struct R3Bin {
|
||||
R3Bin() { SPDLOG_DEBUG("R3Bin constructor"); }
|
||||
R3Bin() { loadOriginal(); }
|
||||
|
||||
static R3Bin& get() {
|
||||
void loadOriginal() {
|
||||
SPDLOG_DEBUG("Loading original binary");
|
||||
|
||||
auto &config = getDefaultConfig();
|
||||
std::string path = config.gameRootDir + "/Rayman3.exe";
|
||||
module = LoadLibraryA(path.c_str());
|
||||
if (!module)
|
||||
throw std::runtime_error("Failed to load original binary");
|
||||
|
||||
fixupImports(module);
|
||||
|
||||
g_gh_translationOffset = translationOffset =
|
||||
uintptr_t(module) - GH_BASE_ADDR;
|
||||
}
|
||||
|
||||
// Translate address relative from the original image base address
|
||||
void *translateAddress(void *original) {
|
||||
uint8_t *runtime_addr =
|
||||
reinterpret_cast<uint8_t *>(original) + translationOffset;
|
||||
return reinterpret_cast<void *>(runtime_addr);
|
||||
}
|
||||
|
||||
void fixupImports(HINSTANCE h) {
|
||||
// Find the IAT size
|
||||
DWORD ulsize = 0;
|
||||
PIMAGE_IMPORT_DESCRIPTOR pImportDesc =
|
||||
(PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
|
||||
h, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulsize);
|
||||
if (!pImportDesc)
|
||||
return;
|
||||
|
||||
// Loop names
|
||||
for (; pImportDesc->Name; pImportDesc++) {
|
||||
PSTR pszModName = (PSTR)((PBYTE)h + pImportDesc->Name);
|
||||
if (!pszModName)
|
||||
break;
|
||||
|
||||
HINSTANCE hImportDLL = LoadLibraryA(pszModName);
|
||||
if (!hImportDLL) {
|
||||
// ... (error)
|
||||
}
|
||||
|
||||
// Get caller's import address table (IAT) for the callee's functions
|
||||
PIMAGE_THUNK_DATA pThunk =
|
||||
(PIMAGE_THUNK_DATA)((PBYTE)h + pImportDesc->FirstThunk);
|
||||
|
||||
// Replace current function address with new function address
|
||||
for (; pThunk->u1.Function; pThunk++) {
|
||||
FARPROC pfnNew = 0;
|
||||
size_t rva = 0;
|
||||
#ifdef _WIN64
|
||||
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
|
||||
#else
|
||||
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
|
||||
#endif
|
||||
{
|
||||
// Ordinal
|
||||
#ifdef _WIN64
|
||||
size_t ord = IMAGE_ORDINAL64(pThunk->u1.Ordinal);
|
||||
#else
|
||||
size_t ord = IMAGE_ORDINAL32(pThunk->u1.Ordinal);
|
||||
#endif
|
||||
|
||||
PROC *ppfn = (PROC *)&pThunk->u1.Function;
|
||||
if (!ppfn) {
|
||||
// ... (error)
|
||||
}
|
||||
rva = (size_t)pThunk;
|
||||
|
||||
char fe[100] = {0};
|
||||
sprintf_s(fe, 100, "#%u", ord);
|
||||
pfnNew = GetProcAddress(hImportDLL, (LPCSTR)ord);
|
||||
if (!pfnNew) {
|
||||
// ... (error)
|
||||
}
|
||||
} else {
|
||||
// Get the address of the function address
|
||||
PROC *ppfn = (PROC *)&pThunk->u1.Function;
|
||||
if (!ppfn) {
|
||||
// ... (error)
|
||||
}
|
||||
rva = (size_t)pThunk;
|
||||
PSTR fName = (PSTR)h;
|
||||
fName += pThunk->u1.Function;
|
||||
fName += 2;
|
||||
if (!fName)
|
||||
break;
|
||||
pfnNew = GetProcAddress(hImportDLL, fName);
|
||||
if (!pfnNew) {
|
||||
// ... (error)
|
||||
}
|
||||
}
|
||||
|
||||
// Patch it now...
|
||||
auto hp = GetCurrentProcess();
|
||||
if (!WriteProcessMemory(hp, (LPVOID *)rva, &pfnNew, sizeof(pfnNew),
|
||||
NULL) &&
|
||||
(ERROR_NOACCESS == GetLastError())) {
|
||||
DWORD dwOldProtect;
|
||||
if (VirtualProtect((LPVOID)rva, sizeof(pfnNew), PAGE_WRITECOPY,
|
||||
&dwOldProtect)) {
|
||||
if (!WriteProcessMemory(GetCurrentProcess(), (LPVOID *)rva, &pfnNew,
|
||||
sizeof(pfnNew), NULL)) {
|
||||
// ... (error)
|
||||
}
|
||||
if (!VirtualProtect((LPVOID)rva, sizeof(pfnNew), dwOldProtect,
|
||||
&dwOldProtect)) {
|
||||
// ... (error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HINSTANCE module;
|
||||
uintptr_t translationOffset;
|
||||
|
||||
static R3Bin &get() {
|
||||
static R3Bin instance;
|
||||
return instance;
|
||||
}
|
||||
|
@ -13,13 +137,11 @@ struct R3Bin {
|
|||
uint8_t *gh_map_dbg_mem(size_t addr) {
|
||||
R3Bin::get();
|
||||
SPDLOG_DEBUG("Mapping debug memory at {}", addr);
|
||||
return nullptr;
|
||||
return (uint8_t *)R3Bin::get().translateAddress((void *)addr);
|
||||
}
|
||||
void *gh_stub_impl_ptr(void *ptr) {
|
||||
R3Bin::get();
|
||||
SPDLOG_DEBUG("Forwarding implementation at {}", ptr);
|
||||
return nullptr;
|
||||
return (void *)R3Bin::get().translateAddress((void *)ptr);
|
||||
}
|
||||
void gh_init_dbg_loader() {
|
||||
SPDLOG_DEBUG("Initializing debug loader");
|
||||
}
|
||||
void gh_init_dbg_loader() { R3Bin::get(); }
|
|
@ -11,7 +11,7 @@ void *gh_stub_impl_ptr(void *ptr);
|
|||
|
||||
template <typename T, typename... Args>
|
||||
T gh_stub_impl_cdecl(void *ptr_, Args... args) {
|
||||
#if RE_DBG_INJECTED
|
||||
#if RE_DBG_INJECTED
|
||||
using Callable = __cdecl T (*)(Args...);
|
||||
static Callable fn = (Callable)gh_stub_impl_ptr(ptr_);
|
||||
return fn(args...);
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
|
||||
#if RE_DBG_INJECTED
|
||||
#include <r3/binders/dbg_mem.h>
|
||||
extern "C" {
|
||||
// This is the part of Rayman3.exe main CRT setup that runs before main, but
|
||||
// doesn't call it
|
||||
void gh_pre_main(void);
|
||||
}
|
||||
#else
|
||||
#include <r3/binders/static_mem.h>
|
||||
#endif
|
||||
|
@ -17,6 +22,7 @@ int main(int argc, char **argv) {
|
|||
try {
|
||||
#if RE_DBG_INJECTED
|
||||
gh_init_dbg_loader();
|
||||
gh_pre_main();
|
||||
#else
|
||||
gh_init_data_segment();
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// Script to refresh all custom globals & types from Ghidra
|
||||
// @category _Reman3
|
||||
// @menupath Reman3.Redump Globals and Types
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import re3lib.GlobalDumper;
|
||||
import re3lib.RemanConfig;
|
||||
import re3lib.TypeDumper;
|
||||
import re3lib.FunctionDatabase;
|
||||
|
||||
public class DumpGlobals extends GhidraScript {
|
||||
@Override
|
||||
protected void run() throws Exception {
|
||||
RemanConfig.INSTANCE = new RemanConfig(this);
|
||||
RemanConfig.INSTANCE.createDirectories();
|
||||
|
||||
try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {
|
||||
GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase);
|
||||
globalDumper.loadGlobalManifest();
|
||||
|
||||
globalDumper.dumpGlobals();
|
||||
globalDumper.saveGlobalManifest();
|
||||
|
||||
TypeDumper dumper = new TypeDumper(this);
|
||||
dumper.run();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// Exports binary read only and data segments to a binary + header file
|
||||
// @category _Reman3
|
||||
// @menupath Tools.Reman3.Export Data
|
||||
// @menupath Reman3.Export Data Segment
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
|
|
@ -625,7 +625,7 @@ public class FunctionDatabase implements AutoCloseable {
|
|||
public void addGlobal(Address address, String name, String dataType) throws Exception {
|
||||
ensureConnection();
|
||||
|
||||
String filepath = "globals.h"; // Default filepath for globals
|
||||
String filepath = RemanConfig.GLOBAL_H_FILE; // Default filepath for globals
|
||||
String addressStr = address.toString();
|
||||
|
||||
try {
|
||||
|
|
|
@ -58,7 +58,7 @@ public class GlobalDumper {
|
|||
public void removeGlobalManifest() {
|
||||
// Remove globals from database instead of file
|
||||
try {
|
||||
functionDatabase.removeGlobalsByFilepath("globals.h");
|
||||
functionDatabase.removeGlobalsByFilepath(RemanConfig.INSTANCE.GLOBAL_H_FILE);
|
||||
globalAddrs.clear();
|
||||
} catch (Exception e) {
|
||||
script.println("Error removing global manifest: " + e.getMessage());
|
||||
|
@ -91,7 +91,13 @@ public class GlobalDumper {
|
|||
|
||||
if (type == null) {
|
||||
script.println("WARNING: Could not reconstruct type for global: " + entry.name + " at " + entry.address);
|
||||
continue;
|
||||
type = dtp.parse("undefined4");
|
||||
}
|
||||
|
||||
// Retrieve the name again
|
||||
Symbol sym = script.getSymbolAt(entry.address);
|
||||
if (sym != null) {
|
||||
entry.name = sym.getName();
|
||||
}
|
||||
|
||||
globalAddrs.put(entry.address, new GlobalRec(entry.address, entry.name, type));
|
||||
|
@ -130,14 +136,14 @@ public class GlobalDumper {
|
|||
}
|
||||
|
||||
public void dumpGlobals() throws Exception {
|
||||
File globalSymbolsListH = new File(RemanConfig.INSTANCE.outputDir, "gh_global.h");
|
||||
File globalSymbolsListH = new File(RemanConfig.INSTANCE.outputDir, RemanConfig.GLOBAL_H_FILE);
|
||||
PrintWriter hwriter = new PrintWriter(globalSymbolsListH, "UTF-8");
|
||||
hwriter.println("// AUTO-GENERATED FILE ");
|
||||
Utils.headerGuardPre(hwriter, "GLOBALS");
|
||||
hwriter.println("#include <r3/binders/global.h>");
|
||||
hwriter.println();
|
||||
|
||||
File globalSymbolsListC = new File(RemanConfig.INSTANCE.outputDir, "gh_global.cxx");
|
||||
File globalSymbolsListC = new File(RemanConfig.INSTANCE.outputDir, RemanConfig.GLOBAL_CXX_FILE);
|
||||
PrintWriter cwriter = new PrintWriter(globalSymbolsListC, "UTF-8");
|
||||
cwriter.println("// AUTO-GENERATED FILE ");
|
||||
cwriter.println("#include <r3/binders/global.h>");
|
||||
|
@ -216,7 +222,7 @@ public class GlobalDumper {
|
|||
script.println("Saving globals to database");
|
||||
|
||||
// Clear existing globals for the default filepath
|
||||
functionDatabase.removeGlobalsByFilepath("globals.h");
|
||||
functionDatabase.removeGlobalsByFilepath(RemanConfig.GLOBAL_H_FILE);
|
||||
|
||||
// Add all current globals to database
|
||||
for (GlobalRec global : globalAddrs.values()) {
|
||||
|
@ -226,6 +232,10 @@ public class GlobalDumper {
|
|||
}
|
||||
|
||||
public void addGlobal(Address addr, HighSymbol sym) throws Exception {
|
||||
if (sym.getName().equals("ExceptionList")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr.compareTo(RemanConfig.INSTANCE.staticMemoryBlockStart) < 0
|
||||
|| addr.compareTo(RemanConfig.INSTANCE.staticMemoryBlockEnd) > 0) {
|
||||
throw new Exception("Global address out of range: " + addr);
|
||||
|
|
|
@ -55,8 +55,11 @@ public class RemanConfig {
|
|||
|
||||
public static RemanConfig INSTANCE;
|
||||
|
||||
public static final String GLOBAL_H_FILE = "gh_global.h"; // Default filepath for globals
|
||||
public static final String GLOBAL_CXX_FILE = "gh_global.cxx"; // Default filepath for globals
|
||||
|
||||
public RemanConfig(GhidraScript script) {
|
||||
staticMemoryBlockStart = script.getCurrentProgram().getAddressFactory().getAddress("00597000");
|
||||
staticMemoryBlockStart = script.getCurrentProgram().getAddressFactory().getAddress("00400000");
|
||||
staticMemoryBlockEnd = script.getCurrentProgram().getAddressFactory().getAddress("00843fff");
|
||||
|
||||
this.script = script;
|
||||
|
|
Loading…
Reference in New Issue