Commit Graph

132 Commits

Author SHA1 Message Date
nmlgc ed4d7282a0 [Pipeline] Add .BMP versions of all hardcoded 1bpp sprites found so far
A future sprite converter (documented in #8) could then convert these
to C or ASM arrays.

(Except for the piano sprites for TH05's Music Room, which are stored
and used in such a compressed way that it defeats the purpose of
storing them as bitmaps.
2020-06-21 23:03:45 +02:00
nmlgc 43c97ccaa1 [Maintenance] Decide on __asm as the keyword for inline assembly
Which works in both Borland C++, Open Watcom, and Visual C++.

Not that we're about to port any of the games to these compilers, just
something I noticed while evaluating 32-bit compilers for ReC98's own
32-bit pipeline tools. Modders might want to look into that though,
since 100% position independence also makes it easier to change
compilers.
2020-06-21 22:18:00 +02:00
nmlgc 97dce75446 [Maintenance] Proofread all comments in C land 2020-06-21 22:14:08 +02:00
nmlgc dd89843fae [Decompilation] [th01] Pellet rendering
So even TH01 wasn't 100% C++ after all. Turns out that this function
was the only instance in all of REIIDEN.EXE where ReC98 previously had
different encodings for identical x86 instructions.

Part of P0096, funded by Ember2528.
2020-06-13 21:11:53 +02:00
nmlgc 94dc9ef251 [Maintenance] Move the pellet sprite to TH01
That's where it actually originated.

Part of P0096, funded by Ember2528.
2020-06-12 21:49:16 +02:00
nmlgc 90252cc59a [Decompilation] [th04/th05] Stage and BGM title popups
Completes P0089, funded by [Anonymous] and Blue Bolt.
2020-05-04 16:14:21 +02:00
nmlgc 8b58e193bd [Maintenance] Reorganize gaiji definitions
Part of P0089, funded by [Anonymous] and Blue Bolt.
2020-05-04 00:05:32 +02:00
nmlgc 708d9fc8ac [Maintenance] [th02/th04/th05] Declare more stage and player symbols in C land
Part of P0089, funded by [Anonymous] and Blue Bolt.
2020-05-04 00:03:17 +02:00
nmlgc 17434fe848 [Decompilation] [th04/th05] Declare stage tile data and functions in C land
tiles_invalidate_around() must have had the hardest function signature
to figure out in all of PC-98 Touhou… because it seems impossible to
handle all three ways of passing parameters. No way around separately
declaring it in every translation unit then, with the parameter list
expected by that segment's code generation.

Part of P0089, funded by [Anonymous] and Blue Bolt.
2020-05-03 23:52:30 +02:00
nmlgc 021280b25c [Maintenance] Don't modify master.h to #undef grcg_off() for TH02
Because TH04 and TH05 actually do use this macro.

Part of P0089, funded by [Anonymous] and Blue Bolt.
2020-05-03 23:30:47 +02:00
nmlgc 5f047fdab1 [Reverse-engineering] [th04/th05] Clearing the playfield's text RAM area
master.lib's text_boxfillca() function would have been perfectly
suitable here…

Part of P0089, funded by [Anonymous] and Blue Bolt.
2020-05-03 23:25:59 +02:00
nmlgc da6b856dc5 [Reverse-engineering] [th04/th05] Stage enemy structure
Last one of the shared entity types! The TH05 version of the .STD enemy
VM would now be ready for decompilation in one single future push.

Completes P0088, funded by -Tom-.
2020-05-03 23:21:30 +02:00
nmlgc 97ce7b78cd [Maintenance] Consistently use forward slashes in #include paths
Completes P0087, funded by -Tom-.
2020-04-15 21:34:32 +02:00
nmlgc 4e58dadc74 [Reverse-engineering] [th02/th04/th05] Rendering of individual point numerals
Part of P0087, funded by -Tom-.
2020-04-15 21:34:22 +02:00
nmlgc 8f824c4297 [Reverse-engineering] [th02/th04/th05] Point numeral sprites
Part of P0087, funded by -Tom-.
2020-04-15 21:34:21 +02:00
nmlgc d1f3dcd620 [Maintenance] Move all features exclusive to MAIN.EXE to a main/ subdirectory
Adding op/, main/, and end/ directories does nicely cover a great
majority of the "not really further classifiable slices" implied in
d56bd45.

Part of P0086, funded by [Anonymous] and Blue Bolt.
2020-04-15 20:58:01 +02:00
nmlgc 02f0a0afcc [Build] Don't word-align everything by default
Again, 11 necessary workarounds, vs. forcing byte aligment in at least
18 places, and that number would have significantly grown in the
future.

Part of P0085, funded by -Tom-.
2020-04-03 17:35:57 +02:00
nmlgc ffad8cc897 [Build] Use the minimum possible size for enums by default
5 enums where code generation wants an `int`, vs. 11 cases where using
the minimum size is exactly the right default. So it's way more
idiomatic to force those 5 to 16 bits via a dummy element… except that
we can't give it a single, consistent name, because you can't redeclare
the same element in a different enum later.

Oh well, let's have this ugly naming convention instead, which makes it
totally clear that the force element not, in fact, a valid value of
that enum.

Part of P0085, funded by -Tom-.
2020-04-03 17:33:58 +02:00
nmlgc 65816a43db [Reverse-engineering] [th02/th04/th05] Pellet rendering
… which allows a split into first rendering the top part of every
pellet, then the bottom part. This way, the game only needs two
grcg_setcolor() calls for any number of pellets.

Part of P0085, funded by -Tom-.
2020-04-03 17:32:51 +02:00
nmlgc 4843d17aae [Reverse-engineering] [th02/th04/th05] Hardcoded 8×8 pellet sprites
The bottom gray part of pellets in TH04 and TH05 is actually a separate
8×4 sprite…

Part of P0085, funded by -Tom-.
2020-04-03 17:32:50 +02:00
nmlgc bc9a88d3b9 [Maintenance] Decide how to handle pre-shifted sprites in C land
Ideally, the future sprite compiler should automatically pre-shift such
sprites, and correctly place the shifted variants in memory, by merely
parsing the C header. On disk, you'd then only have a .BMP with each
individual cel at x=0.

And that's why we need macros and consistent naming: To express these
semantics, without having to duplicate the sprite declaration in some
other format. sSPARKS[8][8][8] wouldn't help anyone 😛

Now, we could go even further there by defining a separate type
(`preshifted_dots8_t`), and maybe get rid of the _W macro by replacing
it with a method on that type. However,
• that would be inconsistent, since we'll need the _H macro anyway, for
  both the actual rendering code and the sprite compiler
• we couldn't directly call such a method on a 2D or 3D array, and have
  to go down to a single element to do so (`sSPARKS[0][0][0].w()`)
• making it a static method instead duplicates the type all over the
  code
• and any variables of that type would no longer be scalar-type values
  that can be stored in registers, requiring weird workarounds in those
  places. As we've already seen with subpixels.

Part of P0085, funded by -Tom-.
2020-04-03 17:32:50 +02:00
nmlgc 580fa8301a [Decompilation] [th02] Random number ring buffer reads, instance #2
And that's how you decompile from the beginning of a segment.

Part of P0085, funded by -Tom-.
2020-04-03 17:32:49 +02:00
nmlgc 54e5bf39fc [Maintenance] Use `dots` for 1bpp lines, and `planar` for B/R/G/E dot structs
I tried `brge` for the latter, but that had *the* most horrible
ergonomics, and I misspelled it as `bgre` 100% of the times I typed it
manually. Turns out that `dots` is also consistent with master.lib's
naming scheme, leaving `planar` to *actually* refer to types storing
multiple planes worth of pixels. These types are showing up more and
more, and deserve something better than their previous long-winded and
misleading name.

Part of P0081, funded by Ember2528.
2020-03-07 21:19:25 +01:00
nmlgc cd48aa351e [Position independence] [th02/th04/th05] False positives in input constants
Completes P0079, funded by -Tom-.
2020-02-29 16:01:13 +01:00
nmlgc f99d7a571c [Maintenance] Remove all dependencies on Borland C++ run-time source headers
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-.
2020-02-23 17:53:18 +01:00
nmlgc ebd214bbb2 [Decompilation] [th05] RES_KSO.COM
And of course, TH05 ruins the consistency once again. Sure, the added
file error handling is nice, but we also have changes in the playful
messages (lol), and now need a third distinct optimization barrier
(🤦)… But as it turns out, inlined calls to empty functions work as
well. They also seem closer to what ZUN might have actually written
there, given that their function body could have been removed by the
preprocessor, similar to the logging functions in the Windows Touhou
games. (With the difference that the latter infamously *aren't*
inlined…)

Part of P0077, funded by Splashman and -Tom-.
2020-02-23 17:53:17 +01:00
nmlgc 4e53b97552 [Decompilation] [th04] RES_HUMA.COM
Part of P0077, funded by Splashman and -Tom-.
2020-02-23 17:53:17 +01:00
nmlgc 803c079a5d [Decompilation] [th03] RES_YUME.COM
Huh, C++ wants its `char`s to be unsigned in order to *not* sign-extend
them to 16 bits for comparison against ASCII literals?!
Anyway, that completes TH03's ZUN.COM, with bascially no new C code.

Part of P0077, funded by Splashman and -Tom-.
2020-02-23 17:53:16 +01:00
nmlgc a2961b02da [Reverse-engineering] [th03/th04/th05] Configuration file
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-.
2020-02-23 17:24:17 +01:00
nmlgc c5a18ecfa0 [Naming] [th02/th04/th05] Maximum and default starting lives and bombs
Oh wow, caff4fe introduced wrong bytes into RES_KSO.COM by confusing
[cfg_bombs] with [credit_lives] -.- Which I didn't find out back then
because all the RES_*.COM binaries still had some different instruction
encodings anyway and I just didn't care enough to base my diff of those
files on the wrong encoding versions to notice the bug…
Whoops.

Part of P0077, funded by Splashman and -Tom-.
2020-02-23 17:22:46 +01:00
nmlgc 9ae9754fb3 [Maintenance] [th02] Move .CFG/resident initialization to separate files
All future RES_*.COM binaries reuse this code.

Completes P0076, funded by [Anonymous] and -Tom-.
2020-02-23 17:14:43 +01:00
nmlgc b8ca607c38 [Decompilation] [th02] Get zun_res1.c right
4½ years after aa56a7c, it turns out that the correct decompilation
involves… no-ops generated by assigning variables that just happen to
be in registers to themselves?! Which does get optimized out, but only
after TCC folded identical tail code in all branches of a function,
thus effectively functioning as an optimization barrier.

The initial attempt used register pseudovariables, but this definitely
is the best possible way this could work – portable, and doesn't
unnecessarily shred the code into tiny inlined functions pieces. The
mindblowing thing here is that ZUN could have actually written this to
have additional, albeit unnecessary, lines to place breakpoints on. But
that means he must have chosen those two local variables in SI and DI
completely by chance… 🤯

The best thing though? ~#pragma inline is gone~

Part of P0076, funded by [Anonymous] and -Tom-.
2020-02-23 17:12:35 +01:00
nmlgc 942373e640 [Maintenance] [th02] Split ZUN_RES.COM into three translation units
Necessary to make string literals from the first one end up at their
correct positions in the data segment even after the upcoming
deduplication…

Part of P0076, funded by [Anonymous] and -Tom-.
2020-02-23 17:12:26 +01:00
nmlgc 6363a37d7a [Maintenance] Move TH02's sound functions to a separate header
Oh hey, guarding declarations with complicated types via #ifdef limits
the header files we additionally have to #include!

Part of P0076, funded by [Anonymous] and -Tom-.
2020-02-23 16:51:45 +01:00
nmlgc d6f356da45 [Maintenance] Use a single per-game, per-binary file for super_*() patnum IDs
Since they're determined by the order of sprites in a .BFT file,
they're best auto-generated by an enum as much as possible.

Part of P0074, funded by Myles.
2020-02-16 21:43:08 +01:00
nmlgc 0f3359e1b3 [Maintenance] Use @@locals for self-modifying code in bfnt_entry_pat()
Which finally allows us to use the PLANE_SIZE macro in ASM land. Yeah,
(ROW_SIZE * RES_Y) has finally got old.

Part of P0073, funded by [Anonymous] and -Tom-.
2020-02-16 21:35:16 +01:00
nmlgc b5cef6eb69 [Maintenance] Define VRAM access macros for arbitrary bit counts
Templates would have been nicer, but as soon as you add just one
non-immediate parameter, Turbo C++ generates a useless store to a new
local variable, ruining the generated code.

Part of P0069, funded by [Anonymous] and Yanga.
2020-01-14 22:09:51 +01:00
wintiger0222 e0d0dcd51d [Maintenance] [th02] Move remaining OP.EXE variables from ASM land to C land 2020-01-14 22:09:01 +01:00
nmlgc 4340b5d6ae [Maintenance] [th01/th02] Split graph_putsa_fx() into its shared parts
I did consider not doing this, because "well, can't anyone who's
*actually* interested just diff the TH01 and TH02 implementations to
figure out the differences themselves", but that duplication ended up
feeling too filthy after all.

And hey, it's a nice excuse to update TH02's version to current naming
standards! 😛

Part of P0068, funded by Yanga.
2020-01-14 22:03:00 +01:00
nmlgc f87b0d4f9e [Maintenance] [th01] Don't #define away master.lib's graph_accesspage() macro
We will in fact have to use both the function call and the macro
version, even within the same translation unit.

Part of P0067, funded by Splashman.
2020-01-14 21:49:38 +01:00
nmlgc 5a7fb6879f [Maintenance] Use the same resident structure pointer name for every game
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.
2020-01-03 21:26:10 +01:00
nmlgc 0eaa142684 [Position independence] master.lib graph_* function calls
Part of P0064, funded by Touhou Patch Center.
2019-12-29 21:15:38 +01:00
nmlgc 5eeed67113 [Reverse-engineering] [th04/th05] GENSOU.SCR structure
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-.
2019-12-28 12:18:43 +01:00
nmlgc b7de999705 [Maintenance] Improve score data file-related type and function names
So many things named `score_*`, so many things named `hiscore_*`…
Let's go with `scoredat_*`, which clearly indicates that this stuff is
saved into a file, while still being only 8 characters.

Part of P0063, funded by -Tom-.
2019-12-28 12:14:02 +01:00
nmlgc 83f422c61a [Decompilation] [th05] Character-independent shot type functions
Part of P0062, funded by Touhou Patch Center.
2019-12-22 15:37:36 +01:00
nmlgc 75a779e82a [Maintenance] Clean up PI function declarations and comments 2019-12-17 23:27:01 +01:00
nmlgc deb1b73016 [Maintenance] Use a single DEFCONV definition file to cover all games
This makes a lot more sense in C land, where we can then #include this
tiny file in front of all DEFCONV declarations.
2019-12-17 23:27:01 +01:00
nmlgc 417ba80c00 [Decompilation] Add a separate segment type
At least wherever Turbo C++ and master.lib want us to use a
non-pointer, since both use uint16_t for segment values throughout
their APIs instead of the more sensible void __seg*. Maybe, integer
arithmetic on segment values was widely considered more important than
dereferencing?
2019-12-17 23:26:59 +01:00
nmlgc 59bbe313ad [Decompilation] Add separate types for 1bpp planar pixel lines 2019-12-17 23:26:59 +01:00
nmlgc 9cb6cc527a [Decompilation] Finally declare <stdint.h> types
*Finally*. We already used `(unsigned) int` in quite a few places where
we actually want a 16-bit value, which was bound to annoy future port
developers.
2019-12-17 23:26:58 +01:00