Commit Graph

1537 Commits

Author SHA1 Message Date
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
nmlgc 1c5ed4b06e [Maintenance] Copy <dos.h>'s 16-bit x86 Real Mode declarations to a new file
DOS is not the same thing as the underlying CPU, after all. A separate
file not only indicates to future port authors which parts of the code
are x86-specific, but it also speeds up build times…

… in theory, because removing 677 lines from 49 files each doesn't seem
to speed up the build as much as I had hoped? But apparently my whole
system mysteriously got faster in the meantime, and I was getting 22-23
seconds for the entire repo even before this commit. Good enough.

Part of P0134, funded by [Anonymous].
2021-02-20 23:49:45 +01:00
nmlgc a42b6c5ceb [Maintenance] Define `(u)int16_t` as `int` rather than `short`
Turbo C++ 4.0J considers them different types internally, even though
they have the same size and signedness. Using `int` allows us to
more correctly redeclare a bunch of functions that originally use
`(unsigned) int` parameters as `(u)int16_t`.

Part of P0134, funded by [Anonymous].
2021-02-20 15:49:20 +01:00
nmlgc 59fb8753bc [Maintenance] Only use the `far` keyword to declare intent
Part of P0134, funded by [Anonymous].
2021-02-20 15:47:30 +01:00
nmlgc 604b2c83ac [Maintenance] Avoid MK_FP() where possible
It's not necessary for assigning `__seg` pointers to `far` ones, which
might even remove the <dos.h> dependency in some translation units.

Part of P0134, funded by [Anonymous].
2021-02-20 15:47:00 +01:00
nmlgc 7a44adf8d0 [Maintenance] Use the C++ resdata_*() wrappers in all ZUN.COM sub-binaries
Getting us completely macro-free there… even though it did require a
separate version of those functions if the ID is a pointer.

Part of P0134, funded by [Anonymous].
2021-02-20 15:46:48 +01:00
nmlgc 1d5db7155a [Separate translation units] [th02/th03/th05] game_init_op()
Completes P0133, funded by [Anonymous].
2021-01-31 16:53:59 +01:00
nmlgc e8588b1b0a [Separate translation units] [th02] game_exit()
Part of P0133, funded by [Anonymous].
2021-01-31 16:53:55 +01:00
nmlgc 84d4914a3b [Separate translation units] [th02] snd_mmd_resident() (undecompilable)
Reason: Wants to be word-aligned, and the previous version in OP.EXE,
game_exit(), is not, despite having an even length :(
Oh well, at least I'm confident enough about it by now to document it.
And out of all decompilations to be thrown away, this is a pretty
dispensable one.

Part of P0133, funded by [Anonymous].
2021-01-31 15:21:11 +01:00
nmlgc cdbd621f91 [Separate translation units] [th02] snd_determine_mode()
Perfectly decompilable with pseudo-registers. Why did I decide against
them in 2015?

Part of P0133, funded by [Anonymous].
2021-01-31 15:18:09 +01:00
nmlgc 5bbc08c3ef [Separate translation units] [th02] snd_pmd_resident()
Seemingly impossible to decompile further.

Part of P0133, funded by [Anonymous].
2021-01-31 15:18:06 +01:00