Fix persistent global mapping

This commit is contained in:
Guus Waals 2024-09-23 23:14:47 +08:00
parent 80c072e757
commit 3d9181f654
8 changed files with 226 additions and 44 deletions

1
.gitignore vendored
View File

@ -15,6 +15,7 @@ windows_libs_other/
*.rep
.vscode
.clangd
headers
ACP_Ray2/
build/

2
game_re/.gitignore vendored
View File

@ -1 +1,3 @@
gh_auto/*
gh_ref/*
*.bak

View File

@ -10,31 +10,31 @@
#include <stdio.h>
#include <string.h>
// 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<void*&>(_0) = i;
}
undefined(uint64_t i) {
*this = i;
}
undefined() = default;
template <typename T> operator T&() {
static_assert(sizeof(T) <= sizeof(_0), "Invalid assignment");
return reinterpret_cast<T&>(_0);
}
template <typename T> T& operator=(const T &other) {
static_assert(sizeof(T) <= sizeof(_0), "Invalid assignment");
return reinterpret_cast<T&>(_0) = other;
}
};
// struct undefined {
// size_t _0;
// undefined(int i) {
// *this = i;
// }
// undefined(uint32_t i) {
// *this = i;
// }
// undefined(void* i) {
// reinterpret_cast<void*&>(_0) = i;
// }
// undefined(uint64_t i) {
// *this = i;
// }
// undefined() = default;
// template <typename T> operator T&() {
// static_assert(sizeof(T) <= sizeof(_0), "Invalid assignment");
// return reinterpret_cast<T&>(_0);
// }
// template <typename T> T& operator=(const T &other) {
// static_assert(sizeof(T) <= sizeof(_0), "Invalid assignment");
// return reinterpret_cast<T&>(_0) = other;
// }
// };
typedef uint8_t undefined;
typedef uint32_t undefined4;
typedef uint16_t undefined2;
struct undefined3 {

View File

@ -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<char(*)[256]>(GH_MEM(0x0077d5e
undefined2 DAT_007825c0= (undefined2&) GH_MEM(0x007825c0);
char(&s_wndStrQuiting)[56] = *reinterpret_cast<char(*)[56]>(GH_MEM(0x00782600));
uint DAT_007d9cc4= (uint&) GH_MEM(0x007d9cc4);
undefined lpRootPathName_007d9e70= (undefined&) GH_MEM(0x007d9e70);
undefined3 UNK_007d9e71= (undefined3&) GH_MEM(0x007d9e71);

View File

@ -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

93
game_re/globals.txt Normal file
View File

@ -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

View File

@ -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();

View File

@ -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
// <address> || <name> || <type>
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());
}
}
}