> assigning to the DI register immediately before a CALL
Yeah, no amount of comma operator trickery can get *that* out of this
compiler. Also, these TH05 .PI functions are the only place in PC-98
Touhou with a `IMUL DI, imm8` instruction, which is impossible to get
out of Turbo C++'s built-in assembler.
Well, at least the `if` branches decompile somewhat nicely.
Part of P0134, funded by [Anonymous].
… especially because this one *is* actually undecompilable. Reason:
Base pointer assignment to BX, before saving the SI register on the
stack.
Part of P0134, funded by [Anonymous].
Well, it *would* have been decompilable, but that ridiculous placement
of the nullptr assignment would have forced the entire function call to
be spelled out in inline ASM, verbatim. No amount of comma operator
trickery would have generated the same instructions either. And for a
function this small and obvious in what its decompilation *should* be,
it really defeated the purpose of adding a separate translation unit…
Part of P0134, funded by [Anonymous].
Reason: Manual "tail call optimization" of input_reset_sense(), with
execution falling through to input_sense() immediately below.
Part of P0133, funded by [Anonymous].
Umm… but this can't be in the same translation unit as frame_delay(),
because OP.EXE has cdg_put_nocolors() inbetween, which means we'd have
to compile it twice.
What probably happened there: ZUN originally wrote this in C when
frame_delay() was still next to it, then generated ASM from it,
tinkered with that, and ultimately only linked that ASM into the final
game, with the NOPCALL still in there. That might very well be the one
temporary NOPCALL workaround we can never get rid of…
Oh well, at least we got lucky with the padding, and can keep the
cdg_put_nocolors() decompilation from the last commit.
Part of P0133, funded by [Anonymous].
Finishing this push with another highly questionable one… Let's hope
that the port developers will certainly appreciate that they just have
to remove the weirdness here, and not mess with defining entirely new
functions in C land.
Completes P0127, funded by [Anonymous].
Undecompilable again. The loading functions have these *_noalpha()
variants that simply set a global variable and fall through to the
regular functions, while cdg_free() has its first `PUSH DI` instruction
after the first expression we'd be decompiling. cdg_free_all() *could*
be decompiled… but would also require _FLAGS trickery, and it's simply
not worth starting a translation unit for one such small function.
Part of P0127, funded by [Anonymous].
Actually fairly average, as far as unreasonable decompilations are
concerned. No `goto`, at least! Another place that would benefit from
EGC raster op documentation, though.
Also, got one more padding byte in TH05's MAINE.EXE correct. 🙂
Part of P0126, funded by [Anonymous] and Blue Bolt.
There's the better name, in ALLCAPS for improved grepping. TH01 is also
going to need a pseudo-binary to bundle translation units that appear
in more than one .EXE, and since "segment 2" would be wrong for that
game, it makes more sense to have one consistent name for these
pseudo-binaries in all games.
(Maintenance mode commit)
And get rid of the constraining FX() macro, with its spacing parameter
that we haven't even seen used so far.
Part of P0124, funded by [Anonymous] and Blue Bolt.
By now, it's become obvious where it has to be. Apparently, the order
of translation units inside ZUN's modified master.lib did somehow
change with TH02?
(Maintenance mode commit)
I didn't know that extra staff roll cutscene order is different for
each character --WindowsTiger
Final actual data references in TH05's MAINE.EXE! 🎉 --Nmlgc
Reviewed and merged as part of P0118, funded by -Tom- and Ember2528.
… with either the port or the argument in registers. This is one of the
few actually dumb concessions to the PI counter on the website.
Then again, binary *is* a better representation for the contents of the
GRCG tile register than hex…
Part of P0117, funded by [Anonymous].
28,160 bytes of global data just for a overly large 320×704 bitmap
that allows you to scroll between the general verdict and the
individual end-of-stage scores with the Up and Down keys. That's one
benefit of splitting your game into multiple executables, I guess?
Completes P0115, funded by Lmocinemod and Blue Bolt.
Subpixels with 32-bit X and Y components?! That's new.
And yeah, they still just use 4 bits for the fractional part.
Also, let's try something revolutionary for these declarations that are
only used in a single .ASM dump file, and put them all straight before
the first function they are used in. Then we certainly don't forget to
delete them once we're done decompiling that stuff 🙃
Part of P0115, funded by Lmocinemod and Blue Bolt.
Wow, this is the first time we're about to call any of these from C
land in ≥TH03? Found no built-in way to just uppercase an identifier
in TASM, so apparently we have to spell out the names in both lower-
and uppercase.
So, let's go back to regular, non-macro PUBLIC / PROC / ENDP code
wherever we can – for all functions introduced in ≥TH03, and for
everything that takes no parameters. It's simply not worth the
trouble.
Part of P0114, funded by Lmocinemod.
In which we exchange variable names for the ability to decompile more
than just 3 instructions here.
… yeah, "decompilation" is still a stretch.
Part of P0114, funded by Lmocinemod.
About time I finally developed this piece of tech. Towards TH05, this
segment got more and more undecompilable ASM functions mixed inbetween
C ones. Which means that pretty much all of the current ASM land
`#include`s in that segment will have to become translation units. And
we *really* don't want an additional layer of numbered, per-binary
translation units that just `#include` maybe one or two functions.
Also yeah, no _TEXT suffix, to drive home the point that this is a
"library" segment, and not really "owned" by any one file.
Part of P0113, funded by Lmocinemod.
No need to make the function names more complicated if we already
expressed the one subtle format difference between TH03 and TH04/TH05
in the plane layout enum.
Part of P0113, funded by Lmocinemod.
ZUN might have gotten the impression that the EGC can *only* work with
multiples of 16 pixels per load or store? Which might explain why…
Part of P0102, funded by Yanga.
Also something that any future ReC project should be doing right at the
start. Finally, it made sense to do it here as well, because…
Part of P0084, funded by Yanga.
And with all possible .COM executables decompiled, this set of changes
reaches an acceptable scope, allowing us to *finally*…
Part of P0077, funded by Splashman and -Tom-.
The supposedly low-hanging fruit that almost every outside contributor
wanted to grab a lot earlier, but (of course) always just for a single
game… Comprehensively covering all of them has only started to make
sense recently 😛
Also, yes, the variable with the uppercase .CFG filename has itself a
lowercase name and vice versa…
Part of P0077, funded by Splashman and -Tom-.
The TH04/TH05 BGM/SE mode setup is a good example for code where
different structure field offsets will vanish completely upon reverse-
engineering. If we continued to use the per-game ID string as the
variable name, we'd only have another game-specific "difference" there.
Part of P0065, funded by Touhou Patch Center.
WTF. Fine, let's have separate, micro-optimized ASM implementations for
decoding and encoding inr MAIN.EXE, but still, all those minute
difference between OP.EXE and MAINE.EXE…
This is as far as anyone should reasonably go before decompilation;
things will get really ugly with the loading functions once the file
name is involved as well…
Completes P0063, funded by -Tom-.
Funny how the actual scores are stored as little-endian gaiji strings
in the bold font, yet never actually used as such.
Part of P0063, funded by -Tom-.
Waiting with the `fx` parameter in TH01's calls for the decompilation
of this game's version of this function…
Part of P0062, funded by Touhou Patch Center.
As used for the title screen fade-in effect. Another function that
apparently was deliberately written to run not that fast, by blitting
each row individually to the 400th VRAM row just so that it can then
turn on the EGC, perform the *actual* masked blit to the VRAM
destination, and then turn the EGC off before moving to the next now.
The same effect could have entirely been accomplished by copying
graph_pack_put_8() and applying the mask there; it's not like ZUN
didn't know how to modify master.lib…
(See also 44ad3eb4) --Nmlgc
"bgimage" really was the best name I could come up with here, given
what it's used for. Everything else sounded way too ambiguous. Even
something like "mempage", in the meaning of "a third memory-backed
graphics page"… --Nmlgc
The pascal calling convention for TH03's input mode functions actually
sort of matters, since we have this nice function pointer type that
expects pascal.
Not applying this leak to TH03 since it would have more than one
`key_det` variable, resulting in names that are as much fanfiction as
the current ones…
Raw, uninteresting position independence work. Or maybe not, given that
this was one of the few things that also apply to TH01, and reveal just
how chaotically this game was coded. And so we've got three ways that
ZUN stored regular 2D points: Regularly (X first, Y second), Y first
and X second, and multiple points stored in a structure of arrays…
Completes P0059, funded by [Anonymous] and -Tom-.
Yup, function parameters that can clearly be identified as coordinates
are by far the fastest way to raise the calculated position
independence percentage. Kinda makes it sound like useless work, which
I'm only doing because it's dictated by some counting algorithm on a
website, but decompilation will want to un-hex all of these values
anyway. We're merely doing that right now, across all games.
Part of P0058, funded by -Tom-.
Rule of thumb going forward: Everything that emits data is .asm,
everything that doesn't is .inc.
(Let's hope that th01_reiiden_2.inc won't exist for that much longer!)
Part of P0032, funded by zorg.
No leading underscore for functions with Pascal calling convention, but
we do have one for all variables, because it's not worth it to put
keywords in front of everything for no reason.
Seemed to have forgotten this rule in 2017?
Part of P0030, funded by zorg.
…unlike these two identical functions, which hopefully become clearer
after more reverse-engineering has been done around them. It's not like
they're directly related to CDG slot data anyway, they just apply the
TH05 version of the dissolution effect in the staff roll on top of the
already displayed image.
And that concludes all CDG/CD2-related code!
Funded by DTM.
With TH05 definitely being the Galaxy Brain version of this function.
You'll see once I get to push the C decompilation for that one…
Anyway, that covers all shared input functions of TH02-TH05!
Funded by zorg.