Commit Graph

251 Commits

Author SHA1 Message Date
nmlgc 6204fdd450 [Separate translation units] [th02/th03/th04] frame_delay_2()
Completes P0113, funded by Lmocinemod.
2020-09-07 21:18:38 +02:00
nmlgc f0511221b7 [Maintenance] [th02/th03/th04/th05] Establish a common name for code segment 2
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.
2020-09-07 21:18:38 +02:00
wintiger0222 db206f9d41 [Reverse-engineering] [th02/th04/th05] HUD: Bar colors
Reviewed and merged as part of P0112, funded by [Anonymous] and Blue
Bolt.
2020-08-28 16:21:13 +02:00
nmlgc db0adbc58f [Maintenance] [th02/th04/th05] Rename `HUD_TRAM_W` to `HUD_KANJI_W`
Right, *_TRAM_W refers to 8-pixel halfwidth characters, and *_KANJI_W
to 16-pixel full-width characters… which also include gaiji, which are
what the entire HUD is made out of.

Part of P0112, funded by [Anonymous] and Blue Bolt.
2020-08-28 15:30:34 +02:00
nmlgc fb67d4d054 [Maintenance] Rename all old *_X and *_Y constants to *_LEFT and *_TOP
Part of P0112, funded by [Anonymous] and Blue Bolt.
2020-08-28 15:14:22 +02:00
nmlgc c5b5dc0201 [Reverse-engineering] General bomb-related globals
Yup, function pointers, frame counters, and general state variables for
all 5 games.

Part of P0111, funded by [Anonymous] and Blue Bolt.
2020-08-28 15:03:03 +02:00
nmlgc ba29539fc7 [Maintenance] Declare a distinct type for VRAM offsets
… and this one, while I'm at it. I've been using pretty much every
possible type for VRAM offset variables, depending on my mood that day,
since signedness apparently never matters for those.
Except that it does. And so, just like with most of our high-level
types, we also have to account for ZUN's little signedness
inconsistencies here. Oh well, at least it's now only one of two types,
and there's no need to choose between `int` or `unsigned int` or
`short` or `unsigned short` or `int16_t` or `uint16_t` or `size_t` or…

Part of P0111, funded by [Anonymous] and Blue Bolt.
2020-08-28 14:53:33 +02:00
nmlgc d6f634631f [Maintenance] Declare distinct types for pixel and VRAM sizes
Oh wait, we also need one of those for an upcoming structure!

Part of P0111, funded by [Anonymous] and Blue Bolt.
2020-08-28 14:53:33 +02:00
nmlgc 368f151759 [Maintenance] Declare distinct types for screen, VRAM, and TRAM coordinates
Whew, time to look at every `int` variable we ever declared! The best
moment to do this would have been a year ago, but well, better late
than never. No need to communicate that in comments anymore.

These shouldn't be used for widths, heights, or sprite-space
coordinates. Maybe we'll cover that another time, this commit is
already large enough.

Part of P0111, funded by [Anonymous] and Blue Bolt.
2020-08-28 14:53:30 +02:00
nmlgc 8b5c1463f6 [Position independence] [th02/th03/th04/th05] References to known gaiji
Completes P0110, funded by [Anonymous] and Blue Bolt.
2020-08-19 20:12:02 +02:00
nmlgc 18a8eccd2f [Decompilation] [th05] Bosses: Smooth random movement
Part of P0109, funded by [Anonymous] and Blue Bolt.
2020-08-16 21:41:34 +02:00
nmlgc bd1c2ee7de [Maintenance] #define the number of dots in a byte
One fewer magic number. And one more deliberate dependency on a
PC-98-specific hardware constant, to further drive home just how
unportable these games are, even once decompilation will be complete.

Part of P0105, funded by Yanga.
2020-08-12 16:16:58 +02:00
nmlgc 67d35115e6 [Maintenance] Use inline functions for all VRAM offset calculations
At least those can all be moved to a single place.

Part of P0105, funded by Yanga.
2020-08-12 16:16:18 +02:00
nmlgc a75e0f8f53 [Maintenance] Compile all VRAM-accessing translation units as C++
Leading to slight complications in TH02's Music Room and shot type
selection menus. Thought about leaving those in C for a while, but I
still think it's worth it for the consistency we get with the VRAM
offset functions. Also, we'll have similar code for the main menus of
later games, and I'll surely won't be using C++ when starting out with
these.

Part of P0105, funded by Yanga.
2020-08-12 16:16:09 +02:00
nmlgc 8367a41d46 [Maintenance] Decide on *_id for 0-based, and *_num for 1-based IDs
Which we've been already subconciously doing with the resident
`demo_num` variable.

Part of P0104, funded by Ember2528.
2020-07-27 17:22:28 +02:00
nmlgc 5735c1622e [Decompilation] [th01] Pellets: Reset and decay functions
Or, in more relevant news: That's the function that forced TH01's
pellet sprites to be defined in C land. First sprite to make that jump.

Part of P0102, funded by Yanga.
2020-07-12 16:34:16 +02:00
nmlgc e3a78bd19b [Maintenance] Fix vector creation function declarations and calls
Part of P0099, funded by Ember2528.
2020-07-12 15:22:50 +02:00
nmlgc 1799d67782 [Build] Convert all known hardcoded sprites during the 32-bit build part
You can now mod them by simply editing .BMP files!
2020-07-09 22:28:15 +02:00
nmlgc c9eef45724 [Maintenance] Fix inconsistencies in sprite declarations 2020-07-09 22:28:14 +02:00
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
wintiger0222 1317273aa0 [Reduction] [th03/th04/th05] Music Room code identical to TH02 2019-12-17 23:26:56 +01:00
wintiger0222 25903719a3 [Naming] [th02] Current and high score 2019-12-17 23:26:55 +01:00
wintiger0222 1ffa121821 [Naming] [th02] Gaiji loading
Renaming these to gaiji_load() and gaiji_free() for consistency with
other functions that load files. --Nmlgc
2019-12-17 23:26:54 +01:00
wintiger0222 0b084b83c3 [Reverse-engineering] [th04/th05] graph_putsa_fx 2019-12-17 23:26:54 +01:00
nmlgc a23dab3154 [Reverse-engineering] MMD ticks-per-quarter-note constant
And then, ZUN hardcodes all measure-related functions to 4/4…
2019-12-17 22:40:05 +01:00
nmlgc a6a805f008 [ZUN symbols] key_det / shiftkey
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…
2019-11-30 19:32:10 +01:00
nmlgc 5bffab4f43 [Position independence] [th04/th05] Remaining references to PI slots
Part of P0060, funded by Touhou Patch Center.
2019-11-28 23:23:30 +01:00
wintiger0222 37fb6eba32 [Naming] [th02/th04/th05] Demo loading and playback 2019-11-24 14:14:13 +01:00
wintiger0222 22bf71d170 [Reduction] [th03/th04/th05] game_init_main 2019-11-24 14:14:13 +01:00
wintiger0222 09edcab744 [Reduction] [th03/th04/th05] game_init_op 2019-11-24 14:04:36 +01:00
nmlgc 71c737c4ee [Maintenance] Move DOS memory assignment sizes to separate files
Ideally, these could be calculated from some other game-specific
parameters? Anyone else who wants to look into this?
2019-11-24 14:04:36 +01:00
nmlgc 3f25caa5df [Reverse-engineering] [th02/th03/th04/th05] DOS memory assignment sizes
Changing the variable suffix to _paras rather than _siz here, since
master.lib uses the latter for byte sizes, while these are paragraphs.
2019-11-24 14:04:34 +01:00
wintiger0222 0009c3c161 [Reduction] [th03/th04/th05] game_exit_to_dos 2019-11-24 12:45:25 +01:00
wintiger0222 34b7b61964 [Reduction] [th03/th04/th05] game_exit 2019-11-24 12:45:17 +01:00
nmlgc 6c4852f789 [Position independence] False positives in master.lib GRCG function calls
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-.
2019-11-14 00:51:48 +01:00
nmlgc db4de240e9 [Decompilation] Prepare the C side for the shot type control functions
That should make this convoluted copypasta a bit easier to read. And
sure, I could have done something about the loop as well, but
SHOT_FUNC_INIT already hides enough control flow behind a macro…

Part of P0037, funded by zorg.
2019-10-14 23:42:20 +02:00
nmlgc f33a3ef220 [Maintenance] [th04/th05] Separate constant for the player↔option distance
Used in pretty much all shot type control functions.

Part of P0036, funded by zorg.
2019-10-14 23:41:57 +02:00
nmlgc 7887f53ea8 [Maintenance] Move the playfield constants to a separate .inc file
With both 16- and 32-bit build parts soon having full dependency
tracking, having more small includes wins out over having fewer, larger
ones – and also, over having to fix tons of macro conflicts that stem
from most .inc files assuming the context of the big .asm files.

Case in point, including ReC98.inc doesn't work right now without
defining a .MODEL, which is counter-productive for ASM compilation
units.

Part of P0035, funded by zorg.
2019-09-24 22:00:48 +02:00
nmlgc e65cf0d05d [Maintenance] Change a few ASM .inc files to use 8.3 names
Part of P0035, funded by zorg.
2019-09-24 21:58:18 +02:00
nmlgc 290935fe3e [Reverse-engineering] [th04/th05] Player character display
Including options and the death explosions.

Part of P0035, funded by zorg.
2019-09-24 21:58:09 +02:00
nmlgc 6f1f36722f [Reverse-engineering] [th01/th02/th04/th05] Player invincibility frames
Completes P0034, funded by zorg.
2019-09-24 21:57:53 +02:00
nmlgc e6294c2c1a [Reverse-engineering] [th02/th04/th05] Score update and display
The TH02 version is a piece of cake…

… but TH04 starts turning it into this un-decompilable piece of
unnecessarily micro-optimized ZUN code. Couldn't have chosen anything
better for the first separate ASM translation unit.

Aside from now having to convert names of exported *variables* to
uppercase for visibility in ASM translation units, the most notable
lesson in this was the one about avoiding fixup overflows. From the
Borland C++ Version 4.0 User's Guide:

	"In an assembly language program, a fixup overflow frequently
	 occurs if you have declared an external variable within a
	 segment definition, but this variable actually exists in a
	 different segment."

Can't be restated often enough.

Completes P0032, funded by zorg.
2019-09-21 14:01:47 +02:00
nmlgc 88c05e48e5 [Maintenance] Move a few more ASM definitions to their own .inc files
Part of P0032, funded by zorg.
2019-09-21 13:05:54 +02:00
nmlgc f07089017f [Maintenance] Rename the extension of game-specific ASM includes to .inc
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.
2019-09-21 13:03:56 +02:00
nmlgc 3b7561a711 [Maintenance] Export all pascal functions with their proper uppercase names
Yup, that was one massive screw-up.

Part of P0030, funded by zorg.
2019-09-15 20:29:47 +02:00
nmlgc fac879f8e6 [Reverse-engineering] [th05] Number display using the bold gaiji font
Many thanks to http://bytepointer.com/tasm/index.htm for providing a
better searchable resource for TASM's default `LEA imm16` → `MOV imm16`
optimization, which we initially had to hack around here.

Funded by -Tom-.
2019-03-06 19:32:38 +01:00
nmlgc d9e9b38736 [Reverse-engineering] [th04/th05] Spark animation
Also seen when midbosses explode. Class CSparkEffect in uth05win.

Funded by -Tom-.
2019-02-28 17:43:15 +01:00
nmlgc da284cacaf [Reverse-engineering] [th02/th04/th05] Hardcoded spark sprites
As seen when killing stage enemies or grazing.

Funded by -Tom-.
2019-02-28 17:43:15 +01:00
nmlgc c2ef9d51b6 [Reverse-engineering] [th02/th03/th04/th05] Back/front page pairs
Because using just one variable would have totally been too
straightforward.

Funded by -Tom-.
2018-12-30 00:16:18 +01:00
nmlgc e1e4f819ed [Reverse-engineering] [th02/th04/th05] Stage background tile ring buffer
Funded by -Tom-.
2018-12-29 17:03:24 +01:00
nmlgc 8ee87233b8 [Reverse-engineering] [th02/th05] Player movement speed
Yes, both characters in TH04 have the same speed!

Funded by -Tom-.
2018-12-26 22:07:34 +01:00
nmlgc b62a8b29a6 [Reverse-engineering] [th02/th04/th05] Boss-related function pointers
No idea what these other ones in TH02 are.

Funded by zorg.
2018-12-18 19:52:41 +01:00
nmlgc b487d6fc20 [Reverse-engineering] [th02/th04/th05] Power overflow bonus
Funded by zorg.
2018-09-02 20:48:31 +02:00
nmlgc 4b8baf1413 [Reverse-engineering] [th02/th03/th04/th05] Random number ring buffer
Yes, you're reading that correctly. If the cursor is at 255, reading a
16-bit value will fill the upper 8 bits with the neighboring cursor
value, which always is 0xFF.

Funded by -Tom-.
2018-03-16 18:12:21 +01:00
nmlgc f98fba3c9d [Reverse-engineering] [th02/th04/th05] .map file loading
Funded by -Tom-.
2018-03-16 08:02:14 +01:00
nmlgc f8d8d56cd1 [Reduction] Bouncing Music Room polygons 2017-01-09 21:10:33 +01:00
nmlgc 915f780e73 [Reverse-engineering] [th02/maine] Identify all remaining global arrays
Which is the last step on the way to completely position-independent
code, with no random hex numbers that should have been data pointers,
but weren't automatically turned into data pointers by IDA because
they're only ever addressed in the indirect fashion of

	mov bx, [bp-array_index]
	mov ax, [bx+0D00h] ; 0D00h is obviously an array of some sort

Removing all of these makes it practicable to add or delete code without
breaking the game in the process. Basic "modding", so to speak.

Automatically catching all possible cases where this happens actually
amounts to emulating the entire game, and *even then*, we're not
guaranteed that the *size* of the array just falls out as a byproduct
of this emulation and the tons of heuristics I would have thrown on top
of that. ZUN hates proper bounds checking and the correct size of each
array may simply never be implied anywhere.

So, rather than going through all that trouble of that (and hell, I
haven't even finished *parsing* this nasty MASM assembly format), and
since nothing really has happened in this project for almost two years,
I chose to just turn this into a text manipulation issue and figure out
the rest manually. Yeah, quick and dirty, and it probably won't scale if
I ever end up doing the same for PC-98 Policenauts, but it'd better work
at least for the rest of PC-98 Touhou.

Trying to do one of those per day from now on. Probably won't make it
due to the reverse-engineering effort required for the big main
executables of each game, but it'd sure be cool if I did.
2017-01-04 20:52:21 +01:00
nmlgc aa56a7cb18 [C decompilation] [th02] ZUN_RES.COM
This, hands down, has been the single worst stretch of decompilation so far.
Three extremely difficult functions that each still required inline assembly.
And no, this didn't even work out with any of the optimization features in
Borland C++ that aren't included in Turbo C++.
2015-09-17 03:43:28 +02:00
nmlgc 697407d658 [Maintenance] [th02] Split off HUUHI.DAT pre-save encoding into a separate file
Necessary for ZUN_RES.COM as well.
2015-09-09 17:08:42 +02:00
nmlgc 547dafe071 [Maintenance] [th02] Move the menu options in huuma_cfg_t to their own structure
Necessary for ZUN_RES.COM.
2015-09-08 17:19:32 +02:00
nmlgc 43001161e3 [Maintenance] Fix any whitespace issues in our own code 2015-09-07 15:44:48 +02:00
nmlgc 75b8765e44 [C decompilation] Finish TH02's OP.EXE 2015-03-16 22:36:50 +01:00
nmlgc c5f53d9cf1 [Maintenance] Rename snd_kaja_func() to snd_kaja_interrupt()
Oh, right, these functions can have parameters. So, let's turn snd_kaja_func()
into a macro that combines the function number and the parameter into the AX
value for the driver.
2015-03-15 23:51:11 +01:00
nmlgc de491f225d [Maintenance] Move the sound driver function slices from hardware/ to snd/
And renaming them all to the short filenames they will be decompiled to for
consistency. These functions aren't really immediately hardware-related, as
we've established earlier in the decompilation.
2015-03-15 23:01:31 +01:00
nmlgc 92979e8f31 [C decompilation] [th02] Code segment #2 of all three executables
Only one code segment left in both OP and FUUIN! its-happening.gif

Yeah, that commit is way larger than I'm comfortable with, but none of these
functions is particularly large or difficult to decompile (with the exception
of graph_putsa_fx(), which I actually did weeks ago), and OP and MAIN have
their own unique functions in between the shared ones, so…
2015-03-14 23:25:50 +01:00
nmlgc f3b8ae2851 [C decompilation] [th02/op] Second set of sound driver calls
So yeah, after ignoring this issue for a week, we indeed have no choice but to
decompile these functions into this horrible mess of C and inline assembly.
And you know what? Since the compiled result still matches with ZUN's binary,
it's entirely possible that this *was* the original format this code was
written in! Seriously, how intoxicated do you have to be to write (or rather,
slur) code like this?

Keeping these functions entirely in assembly would have surely been better.
However, it would have made linking practically impossible, especially for the
later games which still need them in the current assembly slice format.
2015-03-12 12:46:51 +01:00
nmlgc 519e24c459 Rename the *_copy_region_* functions to *_copy_rect_*
TH01 copies a lot of different shapes from plane 1 to 0, so "region" feels
awfully unspecific.
2015-03-10 14:18:28 +01:00
nmlgc 160d4eb69f [C decompilation] [th01/op] [th01/reiiden] Random resident structure stuff 2015-03-07 17:43:39 +01:00
nmlgc a3ae0095f0 [C decompilation] [th02] PI display 2015-03-04 04:28:16 +01:00
nmlgc ed0437f80e [C decompilation] [th02] First set of sound driver calls 2015-03-04 02:47:22 +01:00
nmlgc 404044f32b [C decompilation] [th02/op] [th03/op] [th04/op] Frame delay #1 2015-03-04 02:47:16 +01:00
nmlgc a8384c925f [C decompilation] [th02/maine] HUUMA.CFG loading 2015-03-03 07:40:29 +01:00
nmlgc 2ccad4f5a4 Centrally include master.h in ReC98.h 2015-03-03 06:47:23 +01:00
nmlgc 63299cdf42 [C decompilation] [th02/op] High score screen 2015-03-03 04:25:19 +01:00
nmlgc 87b1fb9e14 [C decompilation] [th02/maine] High score screen
MAIN.EXE shares most of the code in this segment, but I can't remove it from
there right now due to the weird ordering of the data segments in that
executable…

And yes, once again, those three seemingly random type casts in here are
*necessary* to build a bit-perfect binary.
2015-03-02 06:30:06 +01:00
nmlgc 37fc899c42 Add some useful increment and decrement macros
Which we'd really like to have for the highscore entering screen.
2015-03-01 22:52:25 +01:00
nmlgc d058666929 [C decompilation] [th02/maine] Rotating rectangle animation
Small detour into MAINE.EXE because it has all the juicy algorithms that will
explain the remaining unknown members of the highscore data structure, and
there's this one code segment here we need to get out of the way first.
2015-02-28 22:37:40 +01:00
nmlgc 1f514b5a6c [C decompilation] [th02/op] Shot type selection
Oh, OK, so this is what the PC-98 GRCG is all about. You call grcg_setcolor(),
and that puts the PC-98 hardware in some sort of "monochromatic mode". Then,
you just write your pixels into any *single* one of the 4 VRAM bitplanes. This
causes the hardware to automatically write to *all* bitplanes in such a way
that the final palette index for each of the 8, 16, or 32 pixels you just wrote
a 1 value to will actually end up to match the color you set earlier.

Don't forget to call grcg_off() at the end though, or you can't draw any
non-monochromatic graphics, heh.
2015-02-25 23:05:20 +01:00
nmlgc cd33367b51 [C decompilation] [th02/op] Music Room
Yes, all of it. Including the bouncing polygons, of course. And since it's
placed at the end of ZUN's code inside the executable, the code's already
position-independent and fully hackable.
2015-02-24 22:38:44 +01:00
nmlgc ad9d6f97eb [Reverse-engineering] [th02] MIKOConfig structure 2015-02-23 23:48:03 +01:00
nmlgc 22332a71fa Make all sound functions and variables available to C 2015-02-23 18:28:38 +01:00
nmlgc 46eb3792cf Move frame_delay into the hardware/ subdirectory 2015-02-23 10:29:12 +01:00
nmlgc f0be7dadf4 [Reverse-engineering] [th02] Keyboard input
Don't really understand the other games yet because they start introducing
joystick support and TH03 has multiplayer and then there are these master.lib
modifications that don't really make any sense to me, especially when you add
that TH04 seemingly does not read js_stat *at all*, yet still works just fine
with a gamepad and... urgh.
2015-02-22 22:33:07 +01:00
nmlgc ed8d0e28f5 [C decompilation] [th02/op] Title screen flashing animation 2015-02-21 14:16:27 +01:00
nmlgc 6d8ff6b72e Make previously reduced ZUN functions available to C 2015-02-21 14:12:22 +01:00
nmlgc 2cac434455 [Reverse-engineering] Sound effect playback 2015-02-13 12:56:51 +01:00
nmlgc 0b89233e48 [Reverse-engineering] Music Room comment loading 2014-12-24 21:39:34 +01:00
nmlgc a07e5fad42 [Reverse-engineering] Slot-based PI display
Also covering the two variations for blitting only every second row or
blitting only a 320x200 quarter, as seen in the endings.

So yeah, there's indeed nothing wrong with piread.cpp. TH03 just uses that
separate function that only blits every second row of an image, and indeed
always loads the entire image as it would appear in a PNG conversion. Here's
what happens if you display these images using the non-interlacing function:
https://www.dropbox.com/s/885krj09d9l0890/th03%20PI%20no%20interlace.png
2014-12-18 14:36:43 +01:00
nmlgc bead27b781 Use TASM calling convention syntax for previously identified ZUN functions
With TH03 changing the calling convention for most of the code from __cdecl to
__pascal, I've been getting more and more confused about this myself. So,
let's settle on the following consistent syntax for function calls:

* C where the calling convention is actually __cdecl and where TASM's emitted
  __cdecl code matches the original binary
* PASCAL where the calling convention is actually __pascal
* STDCALL where the calling convention is actually __cdecl, but where
  the caller either defers stack cleanup (summing up the stack size of
  multiple functions, then cleaning it all in a single "add sp" instruction)
  or where the stack is cleared in a different way (e.g. "pop cx").

Unfortunately though, when using the ARG directive to automatically generate
an appropriate RET instruction for the given calling convention, TASM always
emits ENTER and LEAVE instructions even when no local variables are declared,
which greatly limits the number of functions where we can use that syntax. -.-
2014-12-16 05:53:56 +01:00
nmlgc 46b2d67143 [Reverse-engineering] Music and sound effect loader 2014-11-30 00:18:40 +01:00
nmlgc 08db7d6392 [Reverse-engineering] Sound mode determination
Note how it's only one *mode* in TH02/TH03, but two *modes* in TH04/TH05,
since you can't select between FM and Beep sound effect modes in TH02/TH03 (or
even disable sounds altogether). Might be a bit confusing, but it seemed
appropriate enough to distinguish the two functions.
2014-11-29 00:56:26 +01:00
nmlgc 181d2920af [Reverse-engineering] Symbols for PMD and MMD API calls 2014-11-27 19:35:54 +01:00
nmlgc de25d6de3e [Reverse-engineering] PMD and MMD function call wrapper
Well, the naming.

Even though only TH02 actually uses MIDI (and thus, the MMD driver), every
game since then contains interrupt instructions for both functions. We could
just name it "pmd", since it seems like that's what came first - the AH
numbers of the 6 functions that make up MMD's interrupt API are identical to
those of the equivalent functions in PMD, even including gaps in the numbering
for PMD functions that don't have an equivalent in MIDI. However, except for
the FM sound effect handling and the key display in TH05's Music Room, these 6
functions are all the games actually use. Also, we already distinguish between
PMD and MMD in the driver check functions, and it might be confusing to only
imply PMD from now on?

So, "kaja" it is, collectively referring to the shared aspects of both
drivers.
2014-11-26 21:21:57 +01:00
nmlgc 2da9a458ab [Reverse-engineering] snd_delay_until_volume
Only really used to delay during fade-outs, though.
2014-11-25 21:21:17 +01:00
nmlgc 98de0abfab [Reverse-engineering] Sound driver and hardware checks 2014-11-24 22:36:57 +01:00
nmlgc f40819b0e5 [Reverse-engineering] frame_delay 2014-11-23 22:32:26 +01:00
nmlgc 510a3a5070 [Reverse-engineering] pi_slot_palette_apply 2014-11-22 09:29:09 +01:00
nmlgc b532a96c7e [JWasm move] Avoid "push large"
For 32-bit immediate values, PUSH by itself is enough. For everything else,
PUSHD works in both TASM and JWasm.

Also, could it be...? Could we actually move to JWasm without breaking the
build in TASM at all?
2014-11-19 12:09:22 +01:00
nmlgc f54b85577d [Reverse-engineering] Slot-based PI file loading and freeing 2014-11-18 17:56:13 +01:00
nmlgc b4361e8487 [Reduction] #700-704: pfopen
... and then I end up copying modified versions into the individual game
subdirectories after all, because the changes between games were simply too
drastic. (That's also why I'm counting pfopen() itself twice.)

Only one slice left now, and then we're done with reduction!
2014-11-17 04:54:40 +01:00
nmlgc f303222ffc Replace MASTERMOD with a per-game constant
Yup, packfiles finally proved that we really have a different set of changes
to master.lib in every game. Also, there are bound to be more of these game-
specific small changes to otherwise identical code in ZUN's own code.

And hey, no need to define that value in the build scripts anymore.

(I've also considered just copying modified versions into the individual game
subdirectories, but it's not too nice to expect people to diff them in order
to actually understand why these copies exist and where the changes actually
are.)
2014-11-15 02:03:41 +01:00