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.
Rather than preferring either the Microsoft/Watcom `(in|out)pw?` style,
or the Borland `(in|out)portb?` style, master.lib had to introduce its
own `(OUT|IN)P[BW]` naming scheme… Insert obligatory xkcd standards
comic.
Part of P0126, funded by [Anonymous] and Blue Bolt.
Not really surprising why this works, and probably was how the original
code looked all along: The function is never called from anywhere, and
as long as the next function still lies on the same 16-byte paragraph,
it makes no difference whether the unused one is placed at the end of
the previous segment, or the beginning of the next.
Which means we can choose whatever leads to fewer translation units 👍
(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.
All this CPU time spent optimizing the unblitting mask, yet the code
still ends up glitching if the two sprites are more than 2 horizontal
bytes away. So, Reimu's slide speed can only be as high as 8 pixels per
frame, before this function fails to unblit the previous sprite and
leaves little Reimu parts in VRAM.
Part of P0123, funded by Yanga.
Some of the unused interleave masks are not that straightforward, so it
makes sense to have all of them as a bitmap. I'm positive that this
sort of thing could have been EGC-accelerated… although, simply
writing better C would probably already go a long way.
Part of P0121, funded by Yanga.
Well well, the choice between sorting this function mechanically (and
putting it next to the EGC functions) or contextually (and putting it
next to the GDC SCROLL function)… Any choice would eventually turned
out suboptimal, I'm sure. 😅
Part of P0121, funded by Yanga.
The main effect behind the discoloration seen in the bomb animation,
as well as the exploding squares at the end of Kikuri's and Sariel's
entrance animation.
Single-function segments are lovely, by the way!
Part of P0121, funded by Yanga.
Wait, so if this is only used for the rotating white squares around
Mima, that must mean that the white star in the YuugenMagan fight got a
completely redundant reimplementation…
Part of P0121, funded by Yanga.
Not only getting rid of the "useless" (and thankfully, consistent)
bitplane parameter, but also allowing those shortened macros to be
redefined for the upcoming little ZUN inconsistency.
Part of P0120, funded by Yanga.
Not really PC-98-hardware-related, not really master.lib-related, so
yeah, that's really the best place for it.
Part of P0116, funded by [Anonymous] and Lmocinemod.
… 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.
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.
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.
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.
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.
Surprise, it's the (terribly suboptimal) setgsta() example function
from the PC-9801 Programmers' Bible! 100% identical, so ZUN must have
read that book as well.
Used for screen shaking effects, as well as the scrolling backgrounds
at the start of the Final Boss stages.
Completes P0095, funded by Yanga.
Too bad we still have to bother with renaming the function via #define
in the few cases where an executable contains two or more copies of
this function. We can't just make it `static`, since TH02 MAINE.EXE
actually does far-call it from a different segment (and thus,
translation unit).
Part of P0094, funded by Yanga.
It's exactly as terrible as you would have expected after hearing
"alphabet cursor actually stored as on-screen position". Nothing gained
in reducing redundancy any further here, any meaningful change would
pretty much have to rewrite the entire thing.
Part of P0093, funded by Ember2528.
Lol, the internal alphabet cursor position is actually stored as the
on-screen top-left position of the selected character, which this
function then maps back to a character index. At least that gets rid of
quite a bunch of PI false positives now.
Part of P0092, funded by Yanga.
Yes, TH01's memory info screen will recurse into itself for every 3
frames the PgUp key is held, requiring one additional PgDown press per
recursion to actually get out of it.
You can, of course, also crash the system via a stack overflow this
way, if that's your thing.
Part of P0091, funded by Ember2528.
Of which we can express precisely *nothing* as an inline function,
because Turbo C++ always emits a useless `JMP SHORT $+2` at the end of
such an inlined function if it contains nested `if` statements. This is
also what forced some of the functions in 90252cc to be expressed as
macros. By now, this is clear enough to be documented separately.
And to warrant this separate commit.
Completes P0090, funded by Yanga.
Starting with the odd one out, the one that doesn't use master.lib and
has two input sense functions: one for the main menu, and one for the
option window.
Both of which also immediately perform the ring arithmetic on the menu
cursor variable… because there's nothing else to be done with these
inputs in OP.EXE? Separating input sensing from processing apparently
wasn't all too obvious of a thought, and it's only truly done in TH02
and later.
Part of P0090, funded by Yanga.
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-.
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-.
Which actually does inline… in C++, because Turbo C++ doesn't support
the `inline` keyword in C mode. So much for the superiority of that
language, even in 1994…
Part of P0083, funded by Yanga.