Paper Mario decompilation (to match) is possible.
Users browsing this thread: 1 Guest(s)

I'm a new user, but I'm posting my findings here.

I'm a GBA decompiler by trade, however, I recently took a vested interest in n64 decompilation to match instead of functional equivalence. This means being able to recompile the functions and they match the ROM/binary.

I started my research on n64 decomp a month ago and initially my target was Super Mario 64: no luck there. The problem turned out to be 2 different SDK versions: sdk1 and sdk2. sdk1 uses MipsPRO while sdk2 uses gcc 2.7.2. I really tried to get it to match: but the main issue was $ra allocation which seems to be 8-aligned + 4 on sdk1 and perfectly 8-aligned on sdk2: there are also register differences that I couldn't resolve.

So I thought: what if I could prove a later game could be decompiled? Well...

I started off by splitting out Paper Mario to check its asm out. Surely enough, it's $ra was allocated correctly! Hmm, that must be good news. But I wasn't satisfied because I wanted to prove it can be matched.

I plucked out a simple function, namely this one:

Code:
func_80028EE0:
/* 0042E0 80028EE0 27BDFFE8 */  addiu $sp, $sp, -0x18
/* 0042E4 80028EE4 AFBF0010 */  sw    $ra, 0x10($sp)
/* 0042E8 80028EE8 0C017FBC */  jal   func_8005FEF0
/* 0042EC 80028EEC 0000202D */   move  $a0, $zero
/* 0042F0 80028EF0 0000202D */  move  $a0, $zero
/* 0042F4 80028EF4 0C017FE4 */  jal   func_8005FF90
/* 0042F8 80028EF8 24050002 */   li    $a1, 2
/* 0042FC 80028EFC 8FBF0010 */  lw    $ra, 0x10($sp)
/* 004300 80028F00 03E00008 */  jr    $ra

I loaded up my linux VM and built gcc 2.7.2 for MIPS target and ran a test. The test code was:

Code:
void func_80028EE0(void)
{
   func_8005FEF0(0);
   func_8005FF90(0, 2);
}

using
Code:
cpp test.c | ./cc1 -o test.s -mips2 -O0 -fomit-frame-pointer
,

Code:
gcc2_compiled.:
__gnu_compiled_c:
   .text
   .align    2
   .globl    func_80028EE0
   .ent    func_80028EE0
func_80028EE0:
   .frame    $sp,24,$ra        # vars= 0, regs= 1/0, args= 16, extra= 0
   .mask    0x80000000,-8
   .fmask    0x00000000,0
   subu    $sp,$sp,24
   sw    $ra,16($sp)
   move    $a0,$zero
   jal    func_8005FEF0
   move    $a0,$zero
   li    $a1,0x00000002        # 2
   jal    func_8005FF90
$L1:
   lw    $ra,16($sp)
   addu    $sp,$sp,24
   j    $ra
   .end    func_80028EE0

Uh oh. No double a0 load in a row.. hmm. I tried fiddling with stuff, but then I tried -O1. all of a sudden:

Code:
gcc2_compiled.:
__gnu_compiled_c:
   .text
   .align    2
   .globl    func_80028EE0

   .text
   .text
   .ent    func_80028EE0
func_80028EE0:
   .frame    $sp,24,$ra        # vars= 0, regs= 1/0, args= 16, extra= 0
   .mask    0x80000000,-8
   .fmask    0x00000000,0
   subu    $sp,$sp,24
   sw    $ra,16($sp)
   .set    noreorder
   .set    nomacro
   jal    func_8005FEF0
   move    $a0,$zero
   .set    macro
   .set    reorder

   move    $a0,$zero
   .set    noreorder
   .set    nomacro
   jal    func_8005FF90
   li    $a1,0x00000002        # 2
   .set    macro
   .set    reorder

   lw    $ra,16($sp)
   addu    $sp,$sp,24
   j    $ra
   .end    func_80028EE0

...I think it matches! So yeah, I think its possible to decompile and get matching C code for Paper Mario. I want to stress that I need to test more candidate functions and settings just in case the actual settings required don't affect this function.

So basically what you're saying is that you can translate Paper Mario into C code?

(05-10-2017, 02:29 AM)Protozoa Wrote: So basically what you're saying is that you can translate Paper Mario into C code?

It's not just translating it into C but into C that can recompile into the exact same assembly after figuring out the original gcc settings (due to Paper Mario likely using sdk2). So this process can apply to each chunk of assembly (a file, due to not using O3, so assembly is loaded in order due to ld_script) repeatedly until we have a C base.

Paper Mario decompilation (to match) is possible.
Users browsing this thread: 1 Guest(s)


  EN ・日本語