diff --git a/decompile/objdiff.json b/decompile/objdiff.json index 4c6af55..4b711b0 100644 --- a/decompile/objdiff.json +++ b/decompile/objdiff.json @@ -14,10 +14,10 @@ "source_path": "src/JSRF/Jet2.cpp" }, "symbol_mappings": { - "?main_funcinfo@@3UFuncInfo@@A": "$T747", - "?main_handler@@YAXPAUEHExceptionRecord@@PAKPAXPAU_xDISPATCHER_CONTEXT@@@Z": "$L751", - "?main_handler_unwind1@@YAXXZ": "$L743", - "?main_unwindmap@@3PAUUnwindMapEntry@@A": "$T753", + "?main_funcinfo@@3UFuncInfo@@A": "$T745", + "?main_handler@@YAXPAUEHExceptionRecord@@PAKPAXPAU_xDISPATCHER_CONTEXT@@@Z": "$L749", + "?main_handler_unwind1@@YAXXZ": "$L741", + "?main_unwindmap@@3PAUUnwindMapEntry@@A": "$T751", "[.rdata-0]": "[.xdata$x-0]" } }, @@ -42,15 +42,6 @@ "?finalizeGameData@@YAXXZ": "_$E2", "?initGameData@@YAXXZ": "_$E1" } - }, - { - "name": "XDK/Xapi/xapi0", - "target_path": "target/XDK/Xapi/xapi0.obj", - "base_path": "src/XDK/Xapi/xapi0.obj", - "metadata": { - "complete": false, - "source_path": "src/XDK/Xapi/xapi0.c" - } } ] } \ No newline at end of file diff --git a/decompile/src/XDK/CRT/crt0.c b/decompile/src/XDK/CRT/crt0.c new file mode 100644 index 0000000..4432fdc --- /dev/null +++ b/decompile/src/XDK/CRT/crt0.c @@ -0,0 +1,33 @@ +/* JSRF Decompilation: XDK/CRT0.c +C runtime initialization. +Like other CRT code, there's some magic here with symbols that get special +treatment from the compiler and linker. +*/ + +#include "../Win32.h" + + +// Every program is supposed to have a main(), so we can just assume its +// existence with a declaration here +int main(void); + + +void __cdecl mainCRTStartup (void); +DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter); + + +// Address: 0x00148023 +// Status: unimplemented +void __cdecl mainCRTStartup(void) { +/* The true entrypoint of the game, spawning a thread for the rest to run in +The linker automatically sets this function to the entrypoint. +*/ +} + +// Address: 0x00147FB4 +// Status: unimplemented +DWORD __stdcall mainXapiStartup(LPVOID const lpThreadParameter) { +/* Runs some initialization and then calls main() */ + main(); + return 0; +} diff --git a/decompile/src/XDK/Win32.h b/decompile/src/XDK/Win32.h index d6192d7..8bb6546 100644 --- a/decompile/src/XDK/Win32.h +++ b/decompile/src/XDK/Win32.h @@ -25,7 +25,7 @@ typedef __int64 LONGLONG; typedef unsigned char BYTE; typedef unsigned short WORD; -typedef unsigned long DWORD, * PDWORD; +typedef unsigned long DWORD; typedef void VOID; typedef void * LPVOID; @@ -45,8 +45,6 @@ union LARGE_INTEGER { LONGLONG QuadPart; }; -typedef void * HANDLE; - // Return codes typedef long HRESULT; diff --git a/decompile/src/XDK/Xapi/xapi0.c b/decompile/src/XDK/Xapi/xapi0.c deleted file mode 100644 index ee9c93b..0000000 --- a/decompile/src/XDK/Xapi/xapi0.c +++ /dev/null @@ -1,83 +0,0 @@ -/* JSRF Decompilation: XDK/Xapi/xapi0.c -Entrypoint for Xbox programs. -Awkwardly, the placement in the .xbe suggests this is not part of the C runtime -(which is normally what provides mainCRTStartup()), but rather part of Xapi. -It's been named xapi0 in analogy to crt0 in a C runtime. -*/ - -#include "../CRT/stddef.h" -#include "../Win32.h" - - -// Things that should get declared in a header somewhere -#define XLD_LAUNCH_DASHBOARD_ERROR 1 -#define XLD_ERROR_INVALID_XBE 1 - -extern struct IMAGE_TLS_DIRECTORY { - DWORD StartAddressOfRawData; - DWORD EndAddressOfRawData; - DWORD * AddressOfIndex; - void * AddressOfCallbacks; - DWORD SizeOfZeroFill; - DWORD Characteristics; -} _tls_used; - -extern int XapiTlsSize; - -DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter); -BOOL __stdcall CloseHandle (HANDLE hHandle ); - -typedef DWORD (__stdcall * LPTHREAD_START_ROUTINE)(LPVOID lpThreadParameter); -HANDLE __stdcall CreateThread( - void * lpThreadAttributes, - DWORD dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - LPVOID lpParameter, - DWORD dwCreationFlags, - PDWORD lpThreadId -); - -void __stdcall XapiBootToDash( - DWORD dwReason, - DWORD dwParameter1, - DWORD dwParameter2 -); - - -// Every program is supposed to have a main(), so we can just assume its -// existence with a declaration here -int main(void); - - -// Address: 0x00147FB4 -// Status: unimplemented -DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter) { -/* Runs some Xbox-specific initialization and then calls main() */ - main(); - return 0; -} - -// Address: 0x00148023 -// Status: nonmatching -void mainCRTStartup(void) { -/* The true entrypoint of the game, spawning a thread for the rest to run in -The linker automatically sets this function to the entrypoint. -*/ - HANDLE thread; - - // Figure out available thread-local storage - XapiTlsSize = ( - (_tls_used.EndAddressOfRawData - _tls_used.StartAddressOfRawData) + - _tls_used.SizeOfZeroFill - ) + 15 & 0xFFFFFFF0; // Round up to nearest 0x10 - *_tls_used.AddressOfIndex = XapiTlsSize / (-4); - - // Launch program as a thread - thread = CreateThread(NULL, 0, mainXapiStartup, NULL, 0, NULL); - - // Boot back to dashboard with an error message if launching failed - if (thread == NULL) - XapiBootToDash(XLD_LAUNCH_DASHBOARD_ERROR, XLD_ERROR_INVALID_XBE, 0); - - CloseHandle(thread); -} diff --git a/decompile/target/XDK/CRT/.gitkeep b/decompile/target/XDK/CRT/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/decompile/target/XDK/Xapi/.gitkeep b/decompile/target/XDK/Xapi/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/ghidra/ghidra_scripts/MSVC7Mangle.java b/ghidra/ghidra_scripts/MSVC7Mangle.java index f913567..3192ecc 100644 --- a/ghidra/ghidra_scripts/MSVC7Mangle.java +++ b/ghidra/ghidra_scripts/MSVC7Mangle.java @@ -66,10 +66,8 @@ import ghidra.program.model.symbol.Symbol; import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.zip.CRC32; @@ -90,35 +88,28 @@ public class MSVC7Mangle extends GhidraScript { setCurrentSelection(addr); } - final HashSet seenSymbols = new HashSet<>(1024); for (final Symbol s : currentProgram.getSymbolTable() .getPrimarySymbolIterator(currentSelection, true)) { - mangle(s, seenSymbols); + mangle(s); // Also mangle everything referenced inside functions // if headless if ( isRunningHeadless() && s.getObject() instanceof Function f - ) mangleRefs(f, seenSymbols); + ) mangleRefs(f); } } - private void mangle( - final Symbol s, - final Set seenSymbols - ) throws Exception { + private void mangle(final Symbol s) throws Exception { /* Set the given symbol's name to its mangled version */ // Skip if already mangled; skip jump tables final String name = s.getName(true); if ( - seenSymbols.contains(s) || name.charAt(0) == '?' || name.startsWith("switchD_") ) return; - seenSymbols.add(s); - // Get mangled name final String mangled = switch (s.getObject()) { case Function f -> mangleFn (f); @@ -631,10 +622,7 @@ public class MSVC7Mangle extends GhidraScript { return (int)crc.getValue() ^ 0xFFFFFFFF; } - private void mangleRefs( - final Function f, - final Set seenSymbols - ) throws Exception { + private void mangleRefs(final Function f) throws Exception { /* Mangle all symbols referenced in the body of a function */ for ( Instruction ins = getFirstInstruction(f); @@ -662,7 +650,7 @@ public class MSVC7Mangle extends GhidraScript { continue; } - mangle(symbol, seenSymbols); + mangle(symbol); } } } diff --git a/ghidra/objects.csv b/ghidra/objects.csv index 5344983..0206fb8 100644 --- a/ghidra/objects.csv +++ b/ghidra/objects.csv @@ -3,14 +3,13 @@ JSRF/Core.obj,true,0x00011000-0x00013FEB,,,0x00186BA0-0x00186C14,,,,,,0x001C4390 JSRF/GameData.obj,true,0x00039B50-0x0003B937,0x0018AD60-0x0018AD75,0x0018C9A0-0x0018C9AA,,,,,,,0x001CA16C-0x001CA3DB,,0x001EB790-0x001EB793,0x001EFC88-0x001F7047, JSRF/Jet2.obj,true,0x0006F9E0-0x0006FA6F,,,0x00187710-0x00187724,,,,,,,0x001E620C-0x001E622F,,0x0022FCE0-0x0022FCE3, ADX (need to decompose),false,0x0013A570-0x0014555F,?,?,?,?,,,,,,?,?,?, -Xapi (need to decompose),false,0x00145560-0x0014B79F,?,?,?,?,,,,,,?,?,?, -XDK/Xapi/xapi0.obj,true,0x00147FB4-0x0014807C,,,,,,,,,,,,, +XDK Core (need to decompose),false,0x00145560-0x0014B79F,?,?,?,?,,,,,,?,?,?, Smilebit libs (need to decompose),false,0x0014B7A0-0x0017BF3F,?,?,?,?,,,,,,?,?,?-0x0022ED2B, -C runtime (need to decompose),false,0x0017BF40-0x00182B80,?,?,?,,,,,?,?,0x0022ED2C-?,?,?, +C runtime,false,0x0017BF40-0x00182B80,?,?,?,,,,,?,?,0x0022ED2C-?,?,?, Unknown MS math lib,false,0x00182B81-0x0018694F,?,?,?,,,,,?,?,?,?,?, Another (tiny) Smilebit math lib,false,0x00186950-0x00186B7F,?,?,?,,,,,?,?,?,?,?, Direct3D8 (need to decompose),false,,?,,0x0018CB40-0x0019E334,,,,,?,?,?,?,?, DirectSound8 (need to decompose),false,,?,?,,,0x0019E340-0x001BA89B,,,,?,?,?,?,0x0027E080-0x00284E17 -Smilebit/MMatrix.obj,false,,?,,,,0x001BA8A0-0x001BBAAF,,,,,?,?,0x00264BD8-0x00264C13, +MMatrix.obj,false,,?,,,,0x001BA8A0-0x001BBAAF,,,,,?,?,0x00264BD8-0x00264C13, Xgraphics (need to decompose),false,,?,,,,,0x001BBAC0-0x001BC7BB,,,,?,?,, XDK Peripherals (need to decompose),false,,?,,,,,,0x001BC7C0-0x001C3F57,,,?,?,, diff --git a/readme.md b/readme.md index 49cfa1e..c865555 100644 --- a/readme.md +++ b/readme.md @@ -2,8 +2,8 @@ A matching decompilation of the Xbox game Jet Set Radio Future. ## Progress -- Delinking progress: 1.03% (26559 out of 2574172 bytes in XBE address space) -- Decompilation progress: 18.5% (31 out of the 168 functions delinked so far) +- Delinking progress: 1.02% (26359 out of 2574172 bytes in XBE address space) +- Decompilation progress: 18.7% (31 out of the 166 functions delinked so far) - **Estimated total progress: 0.19%** (previous two multiplied together) ## Roadmap