Resident Evil 4 (GameCube) – complete byte-identical decompilation to C/C++
Thread
Unofficial Hacker News client; not affiliated with Y Combinator.
Resident Evil 4 (GameCube) – complete byte-identical decompilation to C/C++
Unofficial Hacker News client; not affiliated with Y Combinator.
wk_end · · focus · HN ↗
Made using the leaked debug build and its symbols, which shows how meaningful the work the game preservation community that acquires and distributes these things is.
OTOH this is pretty off-putting:
> Where the compiler needed a particular source shape to reproduce a register choice or a schedule and no natural spelling was found, the construct is marked with a // COMPILER-DIFF: comment (644 of them: dead tests, empty asm("") launders and anchors, register T x asm("rN") pins, padding statements).
To me the value of a decomp isn't reproducing the original bytes per se (we already have the original bytes after all) - it's about reconstructing the understanding of the original game as represented by human-readable source code; getting byte-for-byte is just an indication that you've gotten it right. Needing to add a bunch of slop to force the compiler to match the original output is actually just an indication that you've gotten it wrong - and it's a demonstration of the danger of Goodhart's law, especially as it applies to AI.
jchw · · focus · HN ↗
There is also value in decomps beyond just understanding and general interest. They can also be used to make more advanced mods, better translation patches, etc. The fidelity here matters, like having asm code accessing structures makes it hard to modify structures, but any fidelity improvement beyond pure asm is very welcome.
Of course I still prefer to try to recover the original code that caused the compiler to do what it did, but it's a really challenging problem sometimes. I've been working on decompiling code from old versions of MSVC for literally years now and you accumulate some knowledge of what things impact register allocation or the order of symbols but some of it comes from things that get fully erased from the source. Like for example, debug builds generally seem to retain symbols that aren't actually referenced anywhere, but those symbols only actually make it into an object file if they are. For functions that were only ever inlined and not actually referenced anywhere... They still wind up in the object files and thus in debug builds, despite nothing referencing them. They are also COMDAT any'd because they can appear in multiple objects legally, which means the exact object that winds up retaining it in the final linked executable is arbitrary (and the compilation flags of the object containing it, too - I bet that was fun for developers to debug.) This is incredibly useful but very challenging, needless to say. It may even be feasible to construct examples that would be legitimately infeasible to simply guess back to equivalent source, which I suspect is a major reason why until it was finally shown to be possible in larger scale projects many people wrote fully matching decomps off as a fool's errand..
StilesCrisis · · focus · HN ↗
void foo() { bar(); }
int foo(int x, float y) { return bar(x, y); }
This is because parameter-passing and return-value handling can sometimes be done in zero instructions in PPC, if the values are already in the right registers. So you need to continually go back and reassess old functions once you learn the signatures of newer ones!
jchw · · focus · HN ↗
There are plenty of examples where two very semantically different source codes can have the same output, which is really counter-intuitive when combined with the difficulty that often comes with trying to find a single source code that does match.
This is just another reason why debug information is such a godsend; having symbol names for C++ code will usually give you most of the function signature, and type information will give you the rest. That greatly enriches the disassembly, and the automated decompilation output, and no doubt constrains the number of possible source codes that could match both the output and the debug information, somewhat alleviating this issue.
StilesCrisis · · focus · HN ↗
It's a huge benefit that things like the OS and SDK are known and predictable. This got me a foothold. Otherwise I would have gotten nowhere.
I'm still impressed that this decomp has macros (fully lost in the assembly) and nearly-100% meaningful variable names and struct layouts. That's not easy!
jchw · · focus · HN ↗
StilesCrisis · · focus · HN ↗
jchw · · focus · HN ↗
StilesCrisis · · focus · HN ↗