I'm still impressed that something like this perfectly inlines in every
place that uses this functionality so far. Maybe something about each
parameter only being used once inside the single expression of the
function?
Part of P0120, funded by Yanga.
Why does this function also have to load sprites for the viewing mode
of the high score menu?! Oh well, ridiculous functions deserve
ridiculous names…
Part of P0119, funded by [Anonymous] and -Tom-.
Oh, wait. Due to ridiculously unlucky alignment, we can't actually
approach TH03's OP.EXE from the top of code segment 2… without
covering way too many functions at once, that is.
At least TH02 works out with "just" three functions at once. *If* we
add seg2 back to OP.EXE, where we previously needed to delete it… 😵
Part of P0114, funded by Lmocinemod.
Wow, this is the first time we're about to call any of these from C
land in ≥TH03? Found no built-in way to just uppercase an identifier
in TASM, so apparently we have to spell out the names in both lower-
and uppercase.
So, let's go back to regular, non-macro PUBLIC / PROC / ENDP code
wherever we can – for all functions introduced in ≥TH03, and for
everything that takes no parameters. It's simply not worth the
trouble.
Part of P0114, funded by Lmocinemod.
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.
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.
… 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.
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.
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.
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.
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.
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.
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-.
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.
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 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-.
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-.