Fully decompile xapi0

This commit is contained in:
KeybadeBlox 2026-02-22 14:04:18 -05:00
parent 4e20347b7c
commit 823b19371c
3 changed files with 97 additions and 10 deletions

View file

@ -50,7 +50,7 @@
"target_path": "target/XDK/Xapi/xapi0.obj",
"base_path": "src/XDK/Xapi/xapi0.obj",
"metadata": {
"complete": false,
"complete": true,
"source_path": "src/XDK/Xapi/xapi0.c"
}
}

View file

@ -21,11 +21,14 @@ extern struct IMAGE_TLS_DIRECTORY {
DWORD SizeOfZeroFill;
DWORD Characteristics;
} _tls_used;
extern int _tls_array;
extern int _tls_index;
extern int XapiTlsSize;
DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter);
BOOL __stdcall CloseHandle (HANDLE hHandle );
void __stdcall XapiInitProcess(void);
BOOL __stdcall CloseHandle (HANDLE hHandle);
typedef DWORD (__stdcall * LPTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);
HANDLE __stdcall CreateThread(
@ -43,18 +46,102 @@ void __stdcall XapiBootToDash(
DWORD dwParameter2
);
void __stdcall _rtinit(void);
void __stdcall _cinit (void);
// Every program is supposed to have a main(), so we can just assume its
// existence with a declaration here
int main(void);
// existence with a declaration here. Interestingly, it's called with
// arguments here despite being declared without any on the developer's side.
int main(
int argc,
char * * argv,
char * * envp
);
// Address: 0x00147FB4
// Status: unimplemented
DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter) {
/* Runs some Xbox-specific initialization and then calls main() */
main();
return 0;
// Status: matching
__declspec(naked) DWORD __stdcall mainXapiStartup(LPVOID lpThreadParameter) {
/* 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
without writing assembly, and also for inline assembly to write to a variable
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

View file

@ -3,7 +3,7 @@ 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: 19.0% (32 out of the 168 functions delinked so far)
- Decompilation progress: 19.6% (33 out of the 168 functions delinked so far)
- **Estimated total progress: 0.20%** (previous two multiplied together)
## Roadmap