mirror of
https://codeberg.org/KeybadeBlox/JSRF-Decompilation.git
synced 2026-04-07 04:50:23 +03:00
Compare commits
No commits in common. "823b19371ccdf6dcef61f226edcd4973fa8f6222" and "d7abbb79c0235b814477f2f478f2bf83f5d031d2" have entirely different histories.
823b19371c
...
d7abbb79c0
9 changed files with 25 additions and 114 deletions
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
# All object files to link together
|
# All object files to link together
|
||||||
OBJ = src/JSRF/Jet2.obj src/JSRF/Core.obj src/JSRF/GameData.obj\
|
OBJ = src/JSRF/Jet2.obj src/JSRF/Core.obj src/JSRF/GameData.obj\
|
||||||
src/XDK/Xapi/xapi0.obj
|
src/XDK/CRT/CRT0.obj
|
||||||
|
|
||||||
# Import library for the only thing we don't compile ourselves, the Xbox kernel
|
# Import library for the only thing we don't compile ourselves, the Xbox kernel
|
||||||
LIB = lib/xboxkrnl.lib
|
LIB = lib/xboxkrnl.lib
|
||||||
|
|
@ -14,7 +14,7 @@ all: $(OBJ) # For now, just compile all the object files
|
||||||
|
|
||||||
|
|
||||||
## Build commands
|
## Build commands
|
||||||
.SUFFIXES: .c .cpp .obj .def .lib .exe.xbe
|
.SUFFIXES: .cpp .obj .def .lib .exe.xbe
|
||||||
|
|
||||||
# Convert compiled executable into a working Xbox executable
|
# Convert compiled executable into a working Xbox executable
|
||||||
# (TODO: we may want to fork cxbe to add section checksums and the game ID)
|
# (TODO: we may want to fork cxbe to add section checksums and the game ID)
|
||||||
|
|
@ -32,7 +32,7 @@ src/JSRF/Jet2.exe: $(OBJ) $(LIB)
|
||||||
|
|
||||||
# Compile object files from source
|
# Compile object files from source
|
||||||
.c.obj:
|
.c.obj:
|
||||||
CL.EXE /nologo /Wall /W4 /O1giy /Fo$@ /c $<
|
CL.EXE /nologo /Wall /W4 /Ogityb0 /GfX /Fo$@ /c $<
|
||||||
.cpp.obj:
|
.cpp.obj:
|
||||||
CL.EXE /nologo /Wall /W4 /Ogityb0 /GfX /Fo$@ /c $<
|
CL.EXE /nologo /Wall /W4 /Ogityb0 /GfX /Fo$@ /c $<
|
||||||
|
|
||||||
|
|
@ -41,9 +41,9 @@ src/JSRF/Jet2.exe: $(OBJ) $(LIB)
|
||||||
src/JSRF/Jet2.obj: src/JSRF/Core.hpp src/XDK/CRT/stddef.h src/XDK/D3D.h\
|
src/JSRF/Jet2.obj: src/JSRF/Core.hpp src/XDK/CRT/stddef.h src/XDK/D3D.h\
|
||||||
src/XDK/Win32.h
|
src/XDK/Win32.h
|
||||||
|
|
||||||
src/JSRF/Core.obj: src/JSRF/Core.hpp src/MUSASHI/MMatrix.hpp\
|
src/JSRF/Core.obj: src/JSRF/Core.hpp src/Smilebit/MMatrix.hpp\
|
||||||
src/XDK/CRT/stddef.h src/XDK/D3D.h src/XDK/Win32.h
|
src/XDK/CRT/stddef.h src/XDK/D3D.h src/XDK/Win32.h
|
||||||
|
|
||||||
src/JSRF/GameData.obj: src/JSRF/GameData.hpp
|
src/JSRF/GameData.obj: src/JSRF/GameData.hpp
|
||||||
|
|
||||||
src/XDK/Xapi/xapi0.obj: src/XDK/Win32.h
|
src/XDK/CRT/CRT0.obj: src/XDK/Win32.h
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
{
|
{
|
||||||
"custom_make": "NMAKE.EXE",
|
"custom_make": "NMAKE.EXE",
|
||||||
"watch_patterns": [
|
"watch_patterns": [
|
||||||
"*.c",
|
|
||||||
"*.h",
|
|
||||||
"*.cpp",
|
"*.cpp",
|
||||||
"*.hpp"
|
"*.hpp"
|
||||||
],
|
],
|
||||||
|
|
@ -50,9 +48,9 @@
|
||||||
"target_path": "target/XDK/Xapi/xapi0.obj",
|
"target_path": "target/XDK/Xapi/xapi0.obj",
|
||||||
"base_path": "src/XDK/Xapi/xapi0.obj",
|
"base_path": "src/XDK/Xapi/xapi0.obj",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"complete": true,
|
"complete": false,
|
||||||
"source_path": "src/XDK/Xapi/xapi0.c"
|
"source_path": "src/XDK/Xapi/xapi0.c"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ Game and GameObj classes that form the foundation of the JSRF game code.
|
||||||
#ifndef CORE_HPP
|
#ifndef CORE_HPP
|
||||||
#define CORE_HPP
|
#define CORE_HPP
|
||||||
|
|
||||||
#include "../MUSASHI/MMatrix.hpp"
|
#include "../Smilebit/MMatrix.hpp"
|
||||||
#include "../XDK/CRT/stddef.h"
|
#include "../XDK/CRT/stddef.h"
|
||||||
#include "../XDK/D3D.h"
|
#include "../XDK/D3D.h"
|
||||||
#include "../XDK/Win32.h"
|
#include "../XDK/Win32.h"
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,11 @@ extern struct IMAGE_TLS_DIRECTORY {
|
||||||
DWORD SizeOfZeroFill;
|
DWORD SizeOfZeroFill;
|
||||||
DWORD Characteristics;
|
DWORD Characteristics;
|
||||||
} _tls_used;
|
} _tls_used;
|
||||||
extern int _tls_array;
|
|
||||||
extern int _tls_index;
|
|
||||||
|
|
||||||
extern int XapiTlsSize;
|
extern int XapiTlsSize;
|
||||||
|
|
||||||
DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter);
|
DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter);
|
||||||
void __stdcall XapiInitProcess(void);
|
BOOL __stdcall CloseHandle (HANDLE hHandle );
|
||||||
BOOL __stdcall CloseHandle (HANDLE hHandle);
|
|
||||||
|
|
||||||
typedef DWORD (__stdcall * LPTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);
|
typedef DWORD (__stdcall * LPTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);
|
||||||
HANDLE __stdcall CreateThread(
|
HANDLE __stdcall CreateThread(
|
||||||
|
|
@ -46,106 +43,22 @@ void __stdcall XapiBootToDash(
|
||||||
DWORD dwParameter2
|
DWORD dwParameter2
|
||||||
);
|
);
|
||||||
|
|
||||||
void __stdcall _rtinit(void);
|
|
||||||
void __stdcall _cinit (void);
|
|
||||||
|
|
||||||
|
|
||||||
// Every program is supposed to have a main(), so we can just assume its
|
// Every program is supposed to have a main(), so we can just assume its
|
||||||
// existence with a declaration here. Interestingly, it's called with
|
// existence with a declaration here
|
||||||
// arguments here despite being declared without any on the developer's side.
|
int main(void);
|
||||||
int main(
|
|
||||||
int argc,
|
|
||||||
char * * argv,
|
|
||||||
char * * envp
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Address: 0x00147FB4
|
// Address: 0x00147FB4
|
||||||
// Status: matching
|
// Status: unimplemented
|
||||||
__declspec(naked) DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter) {
|
DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter) {
|
||||||
/* Runs some Xbox-specific initialization and then calls main()
|
/* Runs some Xbox-specific initialization and then calls main() */
|
||||||
It appears to be truly impossible in Visual C++ 7.0 to access the FS register
|
main();
|
||||||
without writing assembly, and also for inline assembly to write to a variable
|
return 0;
|
||||||
in a register rather than on the stack. Thus, the only apparent way to make
|
|
||||||
the middle part of the function match is through writing the instructions
|
|
||||||
directly. Given that the C parts of this function are so simple that a human
|
|
||||||
and a compiler would reasonably produce the exact same code, and this function
|
|
||||||
exhibits other oddities mentioned in the body, it's likely this whole function
|
|
||||||
was originally written purely in assemblys. In the spirit of decompilation,
|
|
||||||
however, we'll lift what we can into C.
|
|
||||||
*/
|
|
||||||
XapiInitProcess();
|
|
||||||
|
|
||||||
// Honestly unsure what's being done here, as FS doesn't seem to follow
|
|
||||||
// the same structure as 32-bit Windows
|
|
||||||
__asm {
|
|
||||||
mov eax, fs:[0x20]
|
|
||||||
mov eax, [eax+0x250]
|
|
||||||
test eax, eax
|
|
||||||
je zero
|
|
||||||
mov ecx, [eax+0x24]
|
|
||||||
jmp store
|
|
||||||
|
|
||||||
/*
|
|
||||||
All this jumping around is strange, as it could easily be a
|
|
||||||
single branch, which is very plain to see if written out as C
|
|
||||||
(in fact, while MSVC's behaviour hasn't been tested, it
|
|
||||||
wouldn't take a very smart compiler to optimize this out if it
|
|
||||||
was written this way in C). It seems likely this is awkward
|
|
||||||
human-written assembly.
|
|
||||||
*/
|
|
||||||
zero:
|
|
||||||
xor ecx, ecx
|
|
||||||
|
|
||||||
store:
|
|
||||||
test ecx, ecx
|
|
||||||
je end
|
|
||||||
|
|
||||||
/*
|
|
||||||
This section is suspect because of how it preserves edi despite
|
|
||||||
it not being used anywhere else, as if it was a separately
|
|
||||||
written function. If it was a function, it must have been
|
|
||||||
inlined, but it couldn't be because it must be called from
|
|
||||||
assembly to use the value in ecx that never went on the stack
|
|
||||||
(as passing data from C to assembly has to do). Notably, this
|
|
||||||
function's calling convention does require edi to be preserved,
|
|
||||||
but if left up to the compiler, it will push and pop edi in the
|
|
||||||
prologue and epilogue, not here (which this function must be
|
|
||||||
declared as naked to avoid).
|
|
||||||
|
|
||||||
It may be that this function was originally written entirely in
|
|
||||||
assembly and declared naked, with the author deciding to
|
|
||||||
preserve edi only in this one section using it.
|
|
||||||
*/
|
|
||||||
push edi
|
|
||||||
mov eax, fs:[0x28]
|
|
||||||
mov edi, fs:[_tls_array]
|
|
||||||
mov edx, [_tls_index]
|
|
||||||
mov edx, [edi + edx*0x4]
|
|
||||||
sub edx, [eax + 0x28]
|
|
||||||
mov byte ptr [ecx], 0x1
|
|
||||||
add edx, _tls_array
|
|
||||||
mov [ecx + 0x4], edx
|
|
||||||
pop edi
|
|
||||||
|
|
||||||
end:
|
|
||||||
};
|
|
||||||
|
|
||||||
_rtinit();
|
|
||||||
_cinit();
|
|
||||||
main(0, NULL, NULL);
|
|
||||||
|
|
||||||
XapiBootToDash(XLD_LAUNCH_DASHBOARD_ERROR, XLD_ERROR_INVALID_XBE, 0);
|
|
||||||
|
|
||||||
// Return 0 to satisfy signature required for thread functions
|
|
||||||
_asm {
|
|
||||||
xor eax, eax
|
|
||||||
ret 4
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address: 0x00148023
|
// Address: 0x00148023
|
||||||
// Status: matching
|
// Status: nonmatching
|
||||||
void mainCRTStartup(void) {
|
void mainCRTStartup(void) {
|
||||||
/* The true entrypoint of the game, spawning a thread for the rest to run in
|
/* The true entrypoint of the game, spawning a thread for the rest to run in
|
||||||
The linker automatically sets this function to the entrypoint.
|
The linker automatically sets this function to the entrypoint.
|
||||||
|
|
@ -153,11 +66,11 @@ The linker automatically sets this function to the entrypoint.
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
|
|
||||||
// Figure out available thread-local storage
|
// Figure out available thread-local storage
|
||||||
XapiTlsSize = 4 + ((
|
XapiTlsSize = (
|
||||||
(_tls_used.EndAddressOfRawData - _tls_used.StartAddressOfRawData) +
|
(_tls_used.EndAddressOfRawData - _tls_used.StartAddressOfRawData) +
|
||||||
_tls_used.SizeOfZeroFill
|
_tls_used.SizeOfZeroFill
|
||||||
) + 15 & 0xFFFFFFF0); // Round up to nearest 0x10
|
) + 15 & 0xFFFFFFF0; // Round up to nearest 0x10
|
||||||
*_tls_used.AddressOfIndex = -1 * XapiTlsSize/4;
|
*_tls_used.AddressOfIndex = XapiTlsSize / (-4);
|
||||||
|
|
||||||
// Launch program as a thread
|
// Launch program as a thread
|
||||||
thread = CreateThread(NULL, 0, mainXapiStartup, NULL, 0, NULL);
|
thread = CreateThread(NULL, 0, mainXapiStartup, NULL, 0, NULL);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ HEADERS="
|
||||||
Std.hpp
|
Std.hpp
|
||||||
XDK/Win32.h
|
XDK/Win32.h
|
||||||
XDK/D3D.h
|
XDK/D3D.h
|
||||||
MUSASHI/MMatrix.hpp
|
Smilebit/MMatrix.hpp
|
||||||
JSRF/Core.hpp
|
JSRF/Core.hpp
|
||||||
JSRF/GameData.hpp
|
JSRF/GameData.hpp
|
||||||
"
|
"
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@ JSRF/Jet2.obj,true,0x0006F9E0-0x0006FA6F,,,0x00187710-0x00187724,,,,,,,0x001E620
|
||||||
ADX (need to decompose),false,0x0013A570-0x0014555F,?,?,?,?,,,,,,?,?,?,
|
ADX (need to decompose),false,0x0013A570-0x0014555F,?,?,?,?,,,,,,?,?,?,
|
||||||
Xapi (need to decompose),false,0x00145560-0x0014B79F,?,?,?,?,,,,,,?,?,?,
|
Xapi (need to decompose),false,0x00145560-0x0014B79F,?,?,?,?,,,,,,?,?,?,
|
||||||
XDK/Xapi/xapi0.obj,true,0x00147FB4-0x0014807C,,,,,,,,,,,,,
|
XDK/Xapi/xapi0.obj,true,0x00147FB4-0x0014807C,,,,,,,,,,,,,
|
||||||
Smilebit MUSASHI libs (need to decompose),false,0x0014B7A0-0x0017BF3F,?,?,?,?,,,,,,?,?,?-0x0022ED2B,
|
Smilebit libs (need to decompose),false,0x0014B7A0-0x0017BF3F,?,?,?,?,,,,,,?,?,?-0x0022ED2B,
|
||||||
C runtime (need to decompose),false,0x0017BF40-0x00182B80,?,?,?,,,,,?,?,0x0022ED2C-?,?,?,
|
C runtime (need to decompose),false,0x0017BF40-0x00182B80,?,?,?,,,,,?,?,0x0022ED2C-?,?,?,
|
||||||
Unknown MS math lib,false,0x00182B81-0x0018694F,?,?,?,,,,,?,?,?,?,?,
|
Unknown MS math lib,false,0x00182B81-0x0018694F,?,?,?,,,,,?,?,?,?,?,
|
||||||
Another (tiny) Smilebit math lib,false,0x00186950-0x00186B7F,?,?,?,,,,,?,?,?,?,?,
|
Another (tiny) Smilebit math lib,false,0x00186950-0x00186B7F,?,?,?,,,,,?,?,?,?,?,
|
||||||
Direct3D8 (need to decompose),false,,?,,0x0018CB40-0x0019E334,,,,,?,?,?,?,?,
|
Direct3D8 (need to decompose),false,,?,,0x0018CB40-0x0019E334,,,,,?,?,?,?,?,
|
||||||
DirectSound8 (need to decompose),false,,?,?,,,0x0019E340-0x001BA89B,,,,?,?,?,?,0x0027E080-0x00284E17
|
DirectSound8 (need to decompose),false,,?,?,,,0x0019E340-0x001BA89B,,,,?,?,?,?,0x0027E080-0x00284E17
|
||||||
MUSASHI/MMatrix.obj,false,,?,,,,0x001BA8A0-0x001BBAAF,,,,,?,?,0x00264BD8-0x00264C13,
|
Smilebit/MMatrix.obj,false,,?,,,,0x001BA8A0-0x001BBAAF,,,,,?,?,0x00264BD8-0x00264C13,
|
||||||
Xgraphics (need to decompose),false,,?,,,,,0x001BBAC0-0x001BC7BB,,,,?,?,,
|
Xgraphics (need to decompose),false,,?,,,,,0x001BBAC0-0x001BC7BB,,,,?,?,,
|
||||||
XDK Peripherals (need to decompose),false,,?,,,,,,0x001BC7C0-0x001C3F57,,,?,?,,
|
XDK Peripherals (need to decompose),false,,?,,,,,,0x001BC7C0-0x001C3F57,,,?,?,,
|
||||||
|
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ A matching decompilation of the Xbox game Jet Set Radio Future.
|
||||||
|
|
||||||
## Progress
|
## Progress
|
||||||
- Delinking progress: 1.03% (26559 out of 2574172 bytes in XBE address space)
|
- Delinking progress: 1.03% (26559 out of 2574172 bytes in XBE address space)
|
||||||
- Decompilation progress: 19.6% (33 out of the 168 functions delinked so far)
|
- Decompilation progress: 18.5% (31 out of the 168 functions delinked so far)
|
||||||
- **Estimated total progress: 0.20%** (previous two multiplied together)
|
- **Estimated total progress: 0.19%** (previous two multiplied together)
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
The approach of this decompilation is to:
|
The approach of this decompilation is to:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue