diff --git a/.gitignore b/.gitignore index 4062d0be..54ec4f1b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ windows_libs_other/ *.rep .vscode .clangd +headers ACP_Ray2/ build/ diff --git a/game_re/.gitignore b/game_re/.gitignore index f0e12bb3..d8604757 100644 --- a/game_re/.gitignore +++ b/game_re/.gitignore @@ -1 +1,3 @@ gh_auto/* +gh_ref/* +*.bak \ No newline at end of file diff --git a/game_re/binders/gh_base.h b/game_re/binders/gh_base.h index 598a0a3f..3951b66a 100644 --- a/game_re/binders/gh_base.h +++ b/game_re/binders/gh_base.h @@ -10,31 +10,31 @@ #include #include -// Fallback to int if type is not annotated -struct undefined { - size_t _0; - undefined(int i) { - *this = i; - } - undefined(uint32_t i) { - *this = i; - } - undefined(void* i) { - reinterpret_cast(_0) = i; - } - undefined(uint64_t i) { - *this = i; - } - undefined() = default; - template operator T&() { - static_assert(sizeof(T) <= sizeof(_0), "Invalid assignment"); - return reinterpret_cast(_0); - } - template T& operator=(const T &other) { - static_assert(sizeof(T) <= sizeof(_0), "Invalid assignment"); - return reinterpret_cast(_0) = other; - } -}; +// struct undefined { +// size_t _0; +// undefined(int i) { +// *this = i; +// } +// undefined(uint32_t i) { +// *this = i; +// } +// undefined(void* i) { +// reinterpret_cast(_0) = i; +// } +// undefined(uint64_t i) { +// *this = i; +// } +// undefined() = default; +// template operator T&() { +// static_assert(sizeof(T) <= sizeof(_0), "Invalid assignment"); +// return reinterpret_cast(_0); +// } +// template T& operator=(const T &other) { +// static_assert(sizeof(T) <= sizeof(_0), "Invalid assignment"); +// return reinterpret_cast(_0) = other; +// } +// }; +typedef uint8_t undefined; typedef uint32_t undefined4; typedef uint16_t undefined2; struct undefined3 { diff --git a/game_re/gh_global.cxx b/game_re/gh_global.cxx index 8fff4255..0c89aa78 100644 --- a/game_re/gh_global.cxx +++ b/game_re/gh_global.cxx @@ -57,7 +57,24 @@ const char* lpAppName_005b68f0 = "Rayman3"; // 005b68f0 const char* s_Directory_005b68f8 = "Directory"; // 005b68f8 const char* s_None = "None"; // 005b6904 const char* s_UbiSoft_Ubi_ini = "/UbiSoft/Ubi.ini"; // 005b690c +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 +const char* s_Die__s_DVDROM_kann_nicht_gelesen_005be130 = "Die %s DVDROM kann nicht gelesen werden"; // 005be130 +const char* s_Impossibile_trovare_il_DVD____s_005be198 = "Impossibile trovare il DVD : %s"; // 005be198 +undefined DAT_005be1ec= (undefined&) GH_MEM(0x005be1ec); +const char* s_Impossible_de_trouver_le_DVD_____005be238 = "Impossible de trouver le DVD : %s"; // 005be238 +const char* s_Please_insert_the_DVD_in_the_DVD_005be400 = "Please insert the DVD in the DVD-Rom drive."; // 005be400 +const char* s_Bitte_legen_Sie_DVD_von_Rayman_3_005be438 = "Bitte legen Sie DVD von Rayman 3 in Ihr DVD-ROM Laufwerk ein."; // 005be438 +const char* s_Inserisci_il_DVD_di_Rayman_3_nel_005be484 = "Inserisci il DVD di Rayman 3 nel lettore DVD-ROM."; // 005be484 +const char* s_Introduce_el_DVD_de_Rayman_3_en_l_005be4c0 = "Introduce el DVD de Rayman 3 en la unidad de DVD-ROM."; // 005be4c0 +undefined DAT_005be500= (undefined&) GH_MEM(0x005be500); +const char* s__c__s_005be540 = "%c:%s"; // 005be540 +const char* s__program_files_Ubi_Soft_Rayman3_005be548 = "\\program files\\Ubi Soft\\Rayman3"; // 005be548 +undefined* PTR_DAT_005be568 = (undefined*)&GH_MEM(0x005be568); // 005be568 long lpDefault_005cf96c= (long&) GH_MEM(0x005cf96c); +undefined1 DAT_005d26a8= (undefined1&) GH_MEM(0x005d26a8); +undefined lpVolumeNameBuffer_005d27b0= (undefined&) GH_MEM(0x005d27b0); r3_main_data r3_main_data_005d28b6= (r3_main_data&) GH_MEM(0x005d28b6); uint hasGLIMode= (uint&) GH_MEM(0x0077d0a8); undefined4 g_engineRunning= (undefined4&) GH_MEM(0x0077d0b4); @@ -74,3 +91,5 @@ char(&s_wndStrRestoring)[256] = *reinterpret_cast(GH_MEM(0x0077d5e undefined2 DAT_007825c0= (undefined2&) GH_MEM(0x007825c0); char(&s_wndStrQuiting)[56] = *reinterpret_cast(GH_MEM(0x00782600)); uint DAT_007d9cc4= (uint&) GH_MEM(0x007d9cc4); +undefined lpRootPathName_007d9e70= (undefined&) GH_MEM(0x007d9e70); +undefined3 UNK_007d9e71= (undefined3&) GH_MEM(0x007d9e71); diff --git a/game_re/gh_global.h b/game_re/gh_global.h index 38cbabb4..298a0958 100644 --- a/game_re/gh_global.h +++ b/game_re/gh_global.h @@ -62,7 +62,24 @@ extern const char* lpAppName_005b68f0; // 005b68f0 extern const char* s_Directory_005b68f8; // 005b68f8 extern const char* s_None; // 005b6904 extern const char* s_UbiSoft_Ubi_ini; // 005b690c +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 +extern const char* s_Die__s_DVDROM_kann_nicht_gelesen_005be130; // 005be130 +extern const char* s_Impossibile_trovare_il_DVD____s_005be198; // 005be198 +extern undefined& DAT_005be1ec; // 005be1ec +extern const char* s_Impossible_de_trouver_le_DVD_____005be238; // 005be238 +extern const char* s_Please_insert_the_DVD_in_the_DVD_005be400; // 005be400 +extern const char* s_Bitte_legen_Sie_DVD_von_Rayman_3_005be438; // 005be438 +extern const char* s_Inserisci_il_DVD_di_Rayman_3_nel_005be484; // 005be484 +extern const char* s_Introduce_el_DVD_de_Rayman_3_en_l_005be4c0; // 005be4c0 +extern undefined& DAT_005be500; // 005be500 +extern const char* s__c__s_005be540; // 005be540 +extern const char* s__program_files_Ubi_Soft_Rayman3_005be548; // 005be548 +extern undefined* PTR_DAT_005be568; // 005be568 extern long& lpDefault_005cf96c; // 005cf96c +extern undefined1& DAT_005d26a8; // 005d26a8 +extern undefined& lpVolumeNameBuffer_005d27b0; // 005d27b0 extern r3_main_data& r3_main_data_005d28b6; // 005d28b6 extern uint& hasGLIMode; // 0077d0a8 extern undefined4& g_engineRunning; // 0077d0b4 @@ -79,4 +96,6 @@ extern char(&s_wndStrRestoring)[256]; // 0077d5e0 extern undefined2& DAT_007825c0; // 007825c0 extern char(&s_wndStrQuiting)[56]; // 00782600 extern uint& DAT_007d9cc4; // 007d9cc4 +extern undefined& lpRootPathName_007d9e70; // 007d9e70 +extern undefined3& UNK_007d9e71; // 007d9e71 #endif // GH_GENERATED_GLOBALS_H diff --git a/game_re/globals.txt b/game_re/globals.txt new file mode 100644 index 00000000..da722da7 --- /dev/null +++ b/game_re/globals.txt @@ -0,0 +1,93 @@ +005b63e0 || s__s_not_initialized__005b63e0 || / || string +005b63f4 || s_Please_run_the__s_setup__005b63f4 || / || string +005b6410 || s_dashCC || / || char[4] +005b6414 || s_Gli_Mode_005b6414 || / || string +005b6420 || s_Identifier_005b6420 || / || string +005b6430 || s_Check_your_version_of_DirectX__V_005b6430 || / || string +005b6478 || lpText_005b6478 || / || TerminatedCString +005b64f0 || lpText_005b64f0 || / || TerminatedCString +005b6540 || lpText_005b6540 || / || TerminatedCString +005b6588 || s_Rayman_3_005b6588 || / || string +005b6598 || lpText_005b6598 || / || TerminatedCString +005b65e4 || s_Erreur_Rayman_3_005b65e4 || / || string +005b65f8 || s_dpnhpast_dll_005b65f8 || / || string +005b6608 || s_DRAWSEM_005b6608 || / || string +005b6610 || s_Restoring_data_____005b6610 || / || string +005b6624 || s_QUIT || / || char[8] +005b662c || s_or_press_ESC_to_quit_Rayman_3__005b662c || / || string +005b664c || s__s___Restoring_data____005b664c || / || string +005b6664 || s_Daten_Reparatur____005b6664 || / || string +005b6678 || s_BEENDIGEN_005b6678 || / || undefined +005b6684 || DAT_005b6684 || / || undefined2 +005b66ac || s__s___Daten_Reparatur____005b66ac || / || string +005b66c4 || s_German_005b66c4 || / || string +005b66cc || s_Ripristino_dati____005b66cc || / || string +005b66e0 || s__s___Pausa_005b66e0 || / || string +005b66ec || s_USCIRE_005b66ec || / || undefined +005b66f4 || s_Premi_ESC_per_uscire_da_Rayman_3_005b66f4 || / || string +005b6718 || s__s___Ripristino_dati____005b6718 || / || string +005b6730 || s_Italian_005b6730 || / || string +005b6738 || s_Restablecer_datos____005b6738 || / || string +005b6750 || s__s___Rotura_005b6750 || / || string +005b675c || s_SALIR_005b675c || / || undefined +005b6764 || s_Pulsa_ESC_para_salir_Rayman_3__005b6764 || / || string +005b6784 || s__s___Restablecer_datos____005b6784 || / || string +005b67a0 || s_Spanish_005b67a0 || / || string +005b67a8 || s_Restauration || / || TerminatedCString +005b67c4 || s__s___Pause_005b67c4 || / || string +005b67d0 || s_ou_appuyez_sur_Echap_pour_quitte_005b67d0 || / || string +005b67fc || s_QUITTER || / || char[8] +005b6804 || s_Restauration_fmt || / || TerminatedCString +005b6828 || s_French_005b6828 || / || string +005b6830 || s_windowTitle || / || char[12] +005b683c || s_percents || / || char[4] +005b6840 || s_Language_005b6840 || / || string +005b684c || s_English_005b684c || / || string +005b6854 || s_CompleteInstall_005b6854 || / || string +005b6864 || s_SOFTWARE_UBI_SOFT_RAYMAN_3_005b6864 || / || string +005b6880 || s_Unable_to_find_R3_Setup_DX8_exe__005b6880 || / || string +005b68bc || s_Rayman_3_Error_005b68bc || / || string +005b68cc || fopen_mode_r_binary || / || TerminatedCString +005b68d0 || s__R3_Setup_DX8_exe_005b68d0 || / || string +005b68e4 || s_Adapter_005b68e4 || / || string +005b68ec || fopen_mode_r_text || / || TerminatedCString +005b68f0 || lpAppName_005b68f0 || / || TerminatedCString +005b68f8 || s_Directory_005b68f8 || / || string +005b6904 || s_None || / || TerminatedCString +005b690c || s_UbiSoft_Ubi_ini || / || TerminatedCString +005bdfd8 || s_R3_DVD_005bdfd8 || / || string +005be0ec || s_R3_DVD_005be0ec || / || string +005be0f4 || s_%s_DVD_missing_005be0f4 || / || string +005be130 || s_Die_%s_DVDROM_kann_nicht_gelesen_005be130 || / || string +005be198 || s_Impossibile_trovare_il_DVD_:_%s_005be198 || / || string +005be1ec || DAT_005be1ec || / || undefined +005be238 || s_Impossible_de_trouver_le_DVD_:_%_005be238 || / || string +005be400 || s_Please_insert_the_DVD_in_the_DVD_005be400 || / || string +005be438 || s_Bitte_legen_Sie_DVD_von_Rayman_3_005be438 || / || string +005be484 || s_Inserisci_il_DVD_di_Rayman_3_nel_005be484 || / || string +005be4c0 || s_Introduce_el_DVD_de_Rayman_3_en_l_005be4c0 || / || string +005be500 || DAT_005be500 || / || undefined +005be540 || s_%c:%s_005be540 || / || string +005be548 || s_\program_files\Ubi_Soft\Rayman3_005be548 || / || string +005be568 || PTR_DAT_005be568 || / || undefined * +005cf96c || lpDefault_005cf96c || / || long +005d26a8 || DAT_005d26a8 || / || undefined1 +005d27b0 || lpVolumeNameBuffer_005d27b0 || / || undefined +005d28b6 || r3_main_data_005d28b6 || / || r3_main_data +0077d0a8 || hasGLIMode || / || uint +0077d0b4 || g_engineRunning || / || undefined4 +0077d0bc || g_drawSemaphore || /winnt.h || HANDLE +0077d0c0 || g_mutexName_Rayman3 || / || char[256] +0077d1c0 || g_windowTitle || / || char[256] +0077d2c0 || lpString_0077d2c0 || / || char[256] +0077d3c0 || s_windowTitleRestoring || / || char[256] +0077d4c0 || g_hinstance || /windef.h || HINSTANCE +0077d4c4 || g_gameHWND || /windef.h || HWND +0077d4c8 || g_mainThreadHandle || /winnt.h || HANDLE +0077d4e0 || g_appCmdLine || / || char[256] +0077d5e0 || s_wndStrRestoring || / || char[256] +007825c0 || DAT_007825c0 || / || undefined2 +00782600 || s_wndStrQuiting || / || char[56] +007d9cc4 || DAT_007d9cc4 || / || uint +007d9e70 || lpRootPathName_007d9e70 || / || undefined +007d9e71 || UNK_007d9e71 || / || undefined3 diff --git a/scripts/DumpCurrentFunction.java b/scripts/DumpCurrentFunction.java index 8aa6a6b8..0e0b83c4 100644 --- a/scripts/DumpCurrentFunction.java +++ b/scripts/DumpCurrentFunction.java @@ -13,20 +13,16 @@ public class DumpCurrentFunction extends GhidraScript { public void run() throws Exception { RecompileConfig.INSTANCE = new RecompileConfig(this); RecompileConfig.INSTANCE.createDirectories(); - + GlobalDumper globalDumper = new GlobalDumper(this); - try { - globalDumper.loadGlobalManifest(); - } catch (Exception e) { - println("No global manifest found"); - } + globalDumper.loadGlobalManifest(); FunctionDumper functionDumper = new FunctionDumper(this, globalDumper); - + Function currentFunction = getFunctionContaining(currentAddress); if (currentFunction != null) { - functionDumper.dump(currentFunction); + functionDumper.dump(currentFunction); } else { - println("No function found at the current address."); + println("No function found at the current address."); } globalDumper.dumpGlobals(); diff --git a/scripts/re3lib/GlobalDumper.java b/scripts/re3lib/GlobalDumper.java index 64a2deda..02c71798 100644 --- a/scripts/re3lib/GlobalDumper.java +++ b/scripts/re3lib/GlobalDumper.java @@ -13,13 +13,22 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import javax.xml.datatype.DatatypeFactory; + import ghidra.app.script.GhidraScript; +import ghidra.app.services.DataTypeManagerService; import ghidra.program.model.address.Address; import ghidra.program.model.data.AbstractStringDataType; import ghidra.program.model.data.Array; import ghidra.program.model.data.DataType; +import ghidra.program.model.data.DataTypeManager; +import ghidra.program.model.data.DataTypePath; import ghidra.program.model.data.PointerDataType; +import ghidra.program.model.data.Undefined; +import ghidra.program.model.listing.Data; import ghidra.program.model.pcode.HighSymbol; +import ghidra.util.data.DataTypeParser; +import ghidra.util.data.DataTypeParser.AllowedDataTypes; public class GlobalDumper { @@ -44,26 +53,58 @@ public class GlobalDumper { manifestFile = new File(RecompileConfig.INSTANCE.outputDir, "globals.txt"); } - public void loadGlobalManifest() throws Exception { + public boolean loadGlobalManifest() throws Exception { // Globals are stored in the format of //
|| || + + if (!manifestFile.exists()) { + script.println("Global manifest file not found: " + manifestFile); + return false; + } + + // Get the dataTypeManagerService + DataTypeManagerService dataTypeManagerService = (DataTypeManagerService) script.getState().getTool() + .getService(DataTypeManagerService.class); + DataTypeManager dtm = script.getCurrentProgram().getDataTypeManager(); + DataTypeParser dtp = new DataTypeParser(dataTypeManagerService, AllowedDataTypes.ALL); try (BufferedReader reader = new BufferedReader(new FileReader(manifestFile))) { String line; while ((line = reader.readLine()) != null) { - String[] parts = line.split(" || "); - if (parts.length == 3) { - String address = parts[0]; - String name = parts[1]; - String typeName = parts[2]; - DataType type = script.getCurrentProgram().getDataTypeManager().getDataType(typeName); - globalAddrs.put(script.parseAddress(address), new GlobalRec(script.parseAddress(address), name, type)); + String[] parts = line.split("\\|\\|"); + if (parts.length == 4) { + Address address = script.parseAddress(parts[0].trim()); + String name = parts[1].trim(); + String categoryPath = parts[2].trim(); + String dataTypePath = parts[3].trim(); + DataTypePath typePath = new DataTypePath(categoryPath, dataTypePath); + DataType type = null; + type = dtm.getDataType(typePath); + if (type == null) { + // script.println("Parsing type: " + dataTypePath); + type = dtp.parse(dataTypePath); + } + if (type == null) { + script.println("WARNING: Failed to find type: " + dataTypePath + " for global: " + name + " at " + address); + continue; + } + globalAddrs.put(address, new GlobalRec(address, name, type)); + } else { + script.println("Invalid global manifest line: " + line); } } } + + script.println("Loaded " + globalAddrs.size() + " globals from " + manifestFile); + return true; } public void addGlobal(Address addr, HighSymbol sym) { - globalAddrs.put(addr, new GlobalRec(addr, sym.getName(), sym.getDataType())); + DataType dt = sym.getDataType(); + if (dt == null) { + script.println("WARNING: Missing type for global: " + sym.getName() + " at " + addr); + return; + } + globalAddrs.put(addr, new GlobalRec(addr, sym.getName(), dt)); } String escapeCString(String str) { @@ -172,12 +213,23 @@ public class GlobalDumper { } public void saveGlobalManifest() throws Exception { + File backupFile = new File(manifestFile.getParentFile(), manifestFile.getName() + ".bak"); + if (backupFile.exists()) { + if (!backupFile.delete()) { + throw new Exception("Failed to delete backup file: " + backupFile + ", globals will not be saved!"); + } + } + if (!manifestFile.renameTo(backupFile)) + throw new Exception("Failed to rename manifest file: " + manifestFile + ", globals will not be saved!"); + try (PrintWriter writer = new PrintWriter(manifestFile)) { script.println("Saving global manifest to " + manifestFile); GlobalRec[] globals = globalAddrs.values().toArray(new GlobalRec[0]); Arrays.sort(globals, (a, b) -> a.address.compareTo(b.address)); for (GlobalRec global : globals) { - writer.println(global.address.toString() + " || " + global.name + " || " + global.type.getDisplayName()); + DataTypePath path = global.type.getDataTypePath(); + writer.println(global.address.toString() + " || " + global.name + " || " + path.getCategoryPath() + " || " + + path.getDataTypeName()); } } }