Commit Graph

1647 Commits

Author SHA1 Message Date
nmlgc c2f6abd091 [Translation unit catch-up] [th04] cdg_put_8()
Part of P0138, funded by [Anonymous] and Blue Bolt.
2021-04-21 16:24:18 +02:00
nmlgc 8d953dc42e [Decompilation] [th03/th04/th05] 2D direction vector construction
Hey, a disgustingly impossible "decompilation" again, for a change!

Completes P0137, funded by [Anonymous].
2021-04-04 00:02:50 +02:00
nmlgc bda7b16758 [Maintenance] Move the polar coordinate conversion functions to their own file
math/vector.hpp needs zero dependencies, this needs master.hpp.

Part of P0137, funded by [Anonymous].
2021-04-03 22:31:00 +02:00
nmlgc 6264ca743c [Translation unit catch-up] [th03/th04] game_exit()
Part of P0137, funded by [Anonymous].
2021-04-03 22:29:12 +02:00
nmlgc 731990b0aa [Decompilation] [th03] 1D vector construction
Exhibit A for the theory that ZUN did *not* set the default calling
convention to `pascal` for TH03.
… Then again, at this point, it's way more likely that ZUN simply
didn't have a unified build setup for any of the games, and rather
pieced them together with manually compiled .OBJ files.

Part of P0137, funded by [Anonymous].
2021-04-03 22:27:12 +02:00
nmlgc f7da96a504 [Separate translation units] [th03] .CDG display (undecompilable)
Reason: Self-modifying. -.-

Part of P0137, funded by [Anonymous].
2021-04-03 22:19:51 +02:00
nmlgc 1d05642866 [Maintenance] [th03/th04/th05] .CDG: Mirror implementation macros in ASM land
We introduced those in 25caa85.

Part of P0137, funded by [Anonymous].
2021-04-03 22:16:01 +02:00
nmlgc 2527e6ee7c [Translation unit catch-up] [th03] frame_delay()
Also requires more workarounds for TH02 so that we can share this
translation unit across the two games.

Part of P0137, funded by [Anonymous].
2021-04-03 22:15:51 +02:00
nmlgc c85f444b07 [Decompilation] [th02/th03] Sound effect playback
Second previously undecompilable translation unit, second creative
workaround for the workaround. We can't compile snd_se_play() with -WX,
as that function needs a stack frame, and it's also illegal to disable
-WX in the middle of a translation unit. But since we only need word
alignment in front of snd_se_reset() *and* that function is identical
in all 4 games, it makes sense to move it to its own translation unit.

And then you notice that the TH02/TH03 and TH04/TH05 versions of the
other two functions are basically identical. The small differences can
easily be moved out to inline functions, leaving us with a single
implementation file for all 4 games. Nice!

Part of P0137, funded by [Anonymous].
2021-04-03 22:11:45 +02:00
nmlgc 8de326792c [Decompilation] [th02] snd_mmd_resident()
Now actually decompilable with the discovery of -WX… even though it
now requires additional workarounds for the drawbacks of the -WX
workaround.

Part of P0137, funded by [Anonymous].
2021-04-03 22:10:41 +02:00
nmlgc f1a8d98dbc [Decompilation] [th03] Low-level input
Lovely. Turns out that all it needed to motivate the previous research
was one function that is simply too precious to be kept in ASM…

Part of P0137, funded by [Anonymous].
2021-04-03 22:09:26 +02:00
nmlgc 0f75a77dee [Research] Discover a workaround to word-align code segments from Turbo C++
Turns out that this is one of the effects of the -WX option ("Create
DPMI application")… along with generally messing up code generation.
Nothing we can't work around though, luckily! Finally getting to cross
that off the list of reasons that prevent decompilation.

Part of P0137, funded by [Anonymous].
2021-04-03 20:19:41 +02:00
nmlgc 1244bd74e7 [Maintenance] Prefer the -zC and -zP options over `#pragma codeseg`
Might look uglier, but has the advantage of not generating an empty
segment with the default name… *and* the default padding, which will
really come in handy with the following breakthrough.

Part of P0137, funded by [Anonymous].
2021-04-03 20:12:09 +02:00
nmlgc 8bcf5d7b84 [Regression] Explicitly request 16-bit default segments when using .MODEL
Whoops, turns out that the build has been broken on TASM32 version 5.3
(the one in the DevKit) ever since 7897bf1. In contrast to version 5.0
(which I use for my development), 5.3 actually defines 32-bit segments
if you specify a .386 CPU before using .MODEL.

That might have been the reason for the .286 workaround all along?
Turns out there's the USE16 modifier, which makes this much more
explicit than switching CPUs.
2021-03-29 22:39:11 +02:00
nmlgc 7b9194a391 [Regression] Add th04/bgimager.asm to Tupfile.bat -.-
Need to fix `tup generate` soon…
2021-03-29 22:39:10 +02:00
nmlgc 07bfcf2841 [Separate translation units] [th02] input_sense()
Finishing this push with some semi-maintenance… and yet another `inline`
function replacing a `#define` ASM macro with fully idiomatic C++ code.

Completes P0136, funded by [Anonymous].
2021-03-20 02:36:43 +01:00
nmlgc af13720486 [Translation unit catch-up] [th03] .PI blitting
Part of P0136, funded by [Anonymous].
2021-03-20 02:36:43 +01:00
nmlgc 0d82f113e9 [Translation unit catch-up] [th04] game_init_op(), game_init_main()
Padding byte-induced undecompilability of cdg_put_noalpha_8() avoided 👌

Part of P0136, funded by [Anonymous].
2021-03-20 02:36:41 +01:00
nmlgc 25caa85ef8 [Decompilation] [th04/th05] cdg_put_noalpha_8()
Getting better at making this more readable…

Part of P0136, funded by [Anonymous].
2021-03-20 02:36:40 +01:00
nmlgc 547a9d95d8 [Separate translation units] [th04] cdg_put_plane_roll_8() (undecompilable)
Reason: Self-modifying. -.-

Also, why no GRCG? Would have allowed blitting via REP MOVSD… Might as
well optimize all the way if you're going the ASM route to begin with.

Part of P0136, funded by [Anonymous].
2021-03-20 02:36:39 +01:00
nmlgc a2e515534c [Translation unit catch-up] [th04] Low-level input
Part of P0136, funded by [Anonymous].
2021-03-20 02:36:38 +01:00
nmlgc 16899204df [Decompilation] [th04/th05] Sound effect playback
At least it's decompilable in these games, and quite nicely so!

Part of P0136, funded by [Anonymous].
2021-03-20 02:36:38 +01:00
nmlgc a935a8b1bd [Translation unit catch-up] [th04] egc_copy_rect_1_to_0_16()
Time to delete stuff!

Part of P0136, funded by [Anonymous].
2021-03-20 02:36:36 +01:00
nmlgc 8164c71d22 [Decompilation] [th04/th05] bgimage_snap(), bgimage_put(), bgimage_free()
Eh, REP MOVSD is used too inconsistently across the games to justify
replacing these macros with an `inline` function. Still can use a
custom one here to make the register usage a bit more explicit, though.

Part of P0136, funded by [Anonymous].
2021-03-20 02:36:36 +01:00
nmlgc 85019517e2 [Separate translation units] [th04/th05] cdg_put_8() (undecompilable)
Reason: Self-modifying. -.-
The TH05 version *might* be decompilable into a mess. Don't have time
for that right now, though.

Part of P0136, funded by [Anonymous].
2021-03-20 02:36:34 +01:00
nmlgc 46359e643e [Translation unit catch-up] [th05] game_exit()
Part of P0136, funded by [Anonymous].
2021-03-20 02:36:32 +01:00
nmlgc 29abdd5b6a [Maintenance] Make decomp.h exclusive to C++
eeb4e7e changed the final C translation unit that used this header to
C++, and we got some more helpful inline functions upcoming.

Part of P0136, funded by [Anonymous].
2021-03-20 02:17:08 +01:00
nmlgc c6c724ac21 [Decompilation] [th03] pi_put_interlace_8()
Obvious copy-pasta…

Part of P0136, funded by [Anonymous].
2021-03-20 02:17:08 +01:00
nmlgc 1ad64dc514 [Translation unit catch-up] [th03] Sound effect playback
Part of P0136, funded by [Anonymous].
2021-03-20 02:17:07 +01:00
nmlgc 0929d91e50 [Translation unit catch-up] [th03] snd_kaja_interrupt()
Part of P0136, funded by [Anonymous].
2021-03-20 02:17:05 +01:00
nmlgc 0263439fac [Decompilation] [th04/th05] vector1_at(), vector2_at()
Almost undecompilable, until you remember that you can inhibit the
optimization of keeping a function parameter in a register by having an
`inline` function take a reference. Yet another function that wouldn't
have decompiled that nicely if we had restricted us to C…

Part of P0136, funded by [Anonymous].
2021-03-19 23:29:26 +01:00
nmlgc 252c13d383 [Decompilation] [th05] Music Room piano (decompilable functions)
If anything, these decompilations of barely decompilable functions can
at least indicate that I tried. 🤷 Nice __fastcall abuse though, which
allows us to least formalize *some* of the implicit state passed
between those functions.

Completes P0135, funded by [Anonymous].
2021-03-19 23:26:16 +01:00
nmlgc 152ecaa496 [Separate translation units] [th05] Music Room piano (undecompilable functions)
Reasons:
• piano_fm_part_put_raw(): SI register referenced and not saved on
  the stack
• piano_current_note_from(): Would be decompilable… into a mess.
  Not worth adding a separate translation unit just for it.
• piano_part_keys_put_raw(): DI register saved before the SI register
• piano_pressed_key_put(): DI register referenced and not immediately
  saved on the stack
• piano_label_put_raw(): SI and DI registered referenced and not saved
  on the stack
• grcg_setcolor_direct_seg1_raw(): Let's procrastinate this one until
  we have to reference all of these instances in C land.

And we could have even emitted that PIANO_KEY_PRESSED_TOP pixel data
into the code segment, by using `#pragma option -z` to give identical
names to both the code and the data segment. At least we can decompile
the first two functions here.

Part of P0135, funded by [Anonymous].
2021-03-19 23:23:06 +01:00
nmlgc f35b051edd [Separate translation units] [th04/th05] bgimage_put_rect() (undecompilable)
Reason: Self-modifying. -.-

Part of P0135, funded by [Anonymous].
2021-03-19 23:19:48 +01:00
nmlgc 88c019eb91 [Maintenance] Move the bgimage_*() functions to the hardware/ directory
Not that it really fits there either, but I've been trying to keep the
th0?/ directories free from any actual code. They should only contain
the distinct translation units within the original three .EXE binaries,
`#include`ing files from subdirectories, along with maybe game-specific
`#pragma`s, but contain no code on their own. Port authors would simply
ignore those, and link everything from the subdirectories into one
binary. That approach has seemed to make the most sense for all of this
so far.

Part of P0135, funded by [Anonymous].
2021-03-19 20:06:54 +01:00
nmlgc d25daf7075 [Maintenance] Move the number of VRAM planes to pc98.h
Allowing us to consistently mirror the declaration in pc98.inc
without adding a planar.inc file. 😛 And points us to two more
dots8_t* arrays that should have used the Planar<> template.

Part of P0135, funded by [Anonymous].
2021-03-19 19:29:17 +01:00
nmlgc 01c92da1ac [Decompilation] [th05] snd_load()
A decompilation of ZUN-written ASM that was almost worth it, for once!
Too bad that those aren't the <string.h> intrinsics that the
Wolfenstein 3D disassembly hinted at, though.

Part of P0135, funded by [Anonymous].
2021-03-19 19:22:57 +01:00
nmlgc 903f5b55de [Separate translation units] [th05] snd_kaja_interrupt() (undecompilable)
Reason: Pascal calling convention with function parameters but no stack
frame.

Part of P0135, funded by [Anonymous].
2021-03-19 19:16:01 +01:00
nmlgc a6eed55258 [Decompilation] [th05] pi_put_masked_8(), pi_put_quarter_masked_8()
Completes P0135, funded by [Anonymous].
2021-02-21 14:04:52 +01:00
nmlgc 69111bd862 [Separate translation units] .PI: Row loop for masked blitting (undecompilable)
Reason: Pascal calling convention with function parameters but no stack
frame. Theoretically we can __emit__() everything inside this function,
but there's no way we can get a `RETN 8` this way. Oh, and it also
accesses SI and DI without backing them up to the stack.

And thanks to TLINK apparently not reporting fixup overflows when
segments are small enough (?), it took quite a while to get that CALL
correct and not weirdly offset by 32 bytes. 😕

Part of P0134, funded by [Anonymous].
2021-02-21 14:04:51 +01:00
nmlgc a064267a0b [Build] Use Borland's extended .OBJ dictionaries to speed up linking
> try to debug weird linker error
> find performance secret sauce

Removes roughly 1 second from the build time of the full repo!

Part of P0134, funded by [Anonymous].
2021-02-21 14:04:51 +01:00
nmlgc 0dfe3bc3c9 [Decompilation] [th05] .PI: EGC setup for masked blitting
And again.

Part of P0134, funded by [Anonymous].
2021-02-21 14:04:50 +01:00
nmlgc 76cefb1e37 [Decompilation] [th05] pi_load()
That assembly is *worse* than what you would have gotten out of your
1994 C++ compiler with the 386 code generation switch!

Part of P0134, funded by [Anonymous].
2021-02-21 14:04:48 +01:00
nmlgc ffcc46d32f [Decompilation] [th05] pi_put_8(), pi_put_quarter_8()
> 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].
2021-02-20 23:50:03 +01:00
nmlgc 25d26824a1 [Separate translation units] [th05] pi_palette_apply() (undecompilable)
… 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].
2021-02-20 23:50:03 +01:00
nmlgc 2777bae55b [Separate translation units] [th05] pi_free() (undecompilable)
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].
2021-02-20 23:50:02 +01:00
nmlgc 0d66e748d1 [Maintenance] Replace wrong `cPtrSize` usage with the ARG directive
Turns out that ARG RETURNS is only really necessary in DEFCONV
functions, which are explicitly declared to use either the C or PASCAL
calling convention. In functions without such a declaration, ARG by
itself works just fine, and won't emit any instructions on its own.
The parameter lists for PASCAL functions still have to be reversed in
that case, though… oh well, let's just comment these cases to hopefully
reduce the confusion.

Part of P0134, funded by [Anonymous].
2021-02-20 23:50:01 +01:00
nmlgc 0dcd0b8136 [Maintenance] Reimplement TASM's ARG directive for `MOV BX, SP` functions
`cPtrSize` is simply the wrong constant for calculating parameter
offsets on the stack, because it corresponds to the memory model's
default distance, not the function's distance. Luckily, ARG has a
RETURNS clause, and if you declare all parameters in there, ARG won't
emit that pesky and unnecessary `ENTER 0, 0` instruction. Big discovery
right there!
Sadly, ARG is unusable for ZUN's silly functions that keep the base
pointer in BX. TASM declares the resulting equates as `[BP+offset]`,
and it's apparently impossible to only get `offset` out of such an
equate later.

So, rather than staying with numbers, let's reimplement ARG for these
functions instead. This way, we can even abstract away the stack clear
size for the `RET` instructions.
It's a bit rough around the edges though, forcing you to explicitly
specify the function distance, and to pass the parameters in reverse
order compared to the C declaration (thankfully, all of these use the
PASCAL calling convention). It also doesn't work with more complex
types yet. But certainly better than numbers.

Part of P0134, funded by [Anonymous].
2021-02-20 23:50:00 +01:00
nmlgc 8cfe883466 [Maintenance] Declare PiHeader at a common place in ASM land
The longer you look at master.lib, the worse it looks.

Part of P0134, funded by [Anonymous].
2021-02-20 23:49:59 +01:00
nmlgc f158e393e8 [Maintenance] Mirror recent pc98.h and master.hpp declarations in ASM land
Part of P0134, funded by [Anonymous].
2021-02-20 23:49:58 +01:00