I wonder if this was mostly a manual effort, or used one of the various automatic decompilers which have become available in the past few years? I can already decompile manually into C/C++ about as quickly as I can read the Asm, but IDA/Hexrays can do it several orders of magnitude faster.
Automatically decompiled code is often gibberish that may do the same thing, but is not organized in any sensible way. It's often harder to understand than the assembly and may contain plenty of goto statements if the decompiler couldn't come up with sensible if-statements or figure out something used to be a function.
This happens because of optimizations (inlining, re-ordering, ...) performed by compilers, as well as information being lost (like variable names and which registers/addresses even are variables as opposed to intermediate values).
For example:
// Original
pre_tax_cost = shipping_cost + checkout_total;
total_cost = (shipping_cost + checkout_total) * (1 + VAT);
show();
// Decompiled, found somewhere in a nondescript 200 line function it was inlined into:
k = 1 + m;
x = a + b;
c = k * x;
goto b_5634;
It takes a lot of manual work to produce something akin to what the original source code may have looked like.
I learnt the most about compilation, and really raw computing, when as a late teenager I was trying to make sense of decompiled code[1]. I would thoroughly recommend it to anybody trying to learn. The laboriousness is what makes it worthwhile in that instance. I can't speak to any productivity standards, though.
[1]: interestingly enough, it's also how I learn foreign or dead languages. That might be a specific cognitive property.
My experience with decompilers like Hexrays is that they do a much faster and more accurate job at figuring out typical compiler output than I can do manually.
You are right that naming stuff is the important part, which is what a decompiler lets you focus on. OOP code with lots of getters and setters is particularly irritating --- I don't want to manually decompile "mov eax, [esp+8] ; mov [ecx+12], eax" several dozen times when the decompiler can turn all of those into setters/getters for the right fields quickly and accurately.
Of course, when you are dealing with typically-obfuscated binaries like malware or DRM-related stuff, the situation is completely different.
Huh. I didn't know that the old PC-98 Touhou games used C++.
I always assumed that Zun used C - possibly including some custom ASM - due to the relative low power of the PC-98. (It's a custom 68000 machine in the vein of the Amiga for those unaware)
Still, I should have guessed. Plenty of DOS games used C++.
One thing I'm interested to see right off the bat is if Zun bothered with collision partitioning or not.
8 comments
[ 5.1 ms ] story [ 31.3 ms ] threadThis happens because of optimizations (inlining, re-ordering, ...) performed by compilers, as well as information being lost (like variable names and which registers/addresses even are variables as opposed to intermediate values).
For example:
It takes a lot of manual work to produce something akin to what the original source code may have looked like.[1]: interestingly enough, it's also how I learn foreign or dead languages. That might be a specific cognitive property.
You are right that naming stuff is the important part, which is what a decompiler lets you focus on. OOP code with lots of getters and setters is particularly irritating --- I don't want to manually decompile "mov eax, [esp+8] ; mov [ecx+12], eax" several dozen times when the decompiler can turn all of those into setters/getters for the right fields quickly and accurately.
Of course, when you are dealing with typically-obfuscated binaries like malware or DRM-related stuff, the situation is completely different.
I always assumed that Zun used C - possibly including some custom ASM - due to the relative low power of the PC-98. (It's a custom 68000 machine in the vein of the Amiga for those unaware)
Still, I should have guessed. Plenty of DOS games used C++.
One thing I'm interested to see right off the bat is if Zun bothered with collision partitioning or not.
I recall working on early games in C++ where a lot of the conveniences of the language were used like local variables but the form was more like C.