Commit Graph

173 Commits

Author SHA1 Message Date
nmlgc 89fbec0a79 [Reverse-engineering] [th01] Test mode damage flag
Part of P0131, funded by Yanga.
2020-12-18 01:38:50 +01:00
nmlgc f80001d34b [Reverse-engineering] [th01] Bosses: Current HP
And once again, SinGyoku is the only boss to get its own variable.
Maybe this means that it was the first boss to be implemented after
all?

Part of P0131, funded by Yanga.
2020-12-18 01:38:49 +01:00
nmlgc d5fd70c458 [Decompilation] [th01] HUD: HP rendering
And we're right back to things not being nice. Because yeah, why
shouldn't these three distinct rendering functions be part of a single
function, selected by magic numbers?
Or why shouldn't the 16×16 wrapper around a 32×32 set of graphics
functions be used to handle backgrounds for 16×8 sprites, resulting in
needlessly complex parameter calculations that lead to sloppy code?

Part of P0131, funded by Yanga.
2020-12-18 01:38:48 +01:00
nmlgc 576def5293 [Decompilation] [th01] HUD: Blitting individual hit points
Nice GRCG use! The 8 dots of its tile register, which are commonly just
set to the same color value, can of course hold an arbitrary bit
pattern for every bitplane. This allows you to get different colors for
every pixel, with still just a single VRAM write of the alpha mask to
one bitplane.

And I thought TH01 only suffered the drawbacks of PC-98 hardware, and
made so little use of its actual features that it's perhaps not even
fair to call it "a PC-98 game"…

Completes P0130, funded by Yanga.
2020-12-18 01:38:48 +01:00
nmlgc b4d500b2de [Decompilation] [th01] Bosses: Generic no-op callback
Made truly generic by its use in both the upcoming boss collision
handling, as well as some SinGyoku pellet spawning function.

Part of P0130, funded by Yanga.
2020-12-18 01:38:46 +01:00
nmlgc 64f872e5c5 [Decompilation] [th01] Difficulty-based value selection
And with that, TH01 is pushed over the 50% completion mark! 🎉

This time, it's only YuugenMagan who gets no own copy. Giant RE% gains
from all these calls, but let's hope I don't regret already decompiling
this one for all bosses. It's not quite at the beginning of SinGyoku's,
Mima's, and Elis' code segment, after all…

Part of P0130, funded by Yanga.
2020-12-18 00:59:41 +01:00
nmlgc 2c180c3825 [Reverse-engineering] [th01] Bosses: Current phase frame
One shared variable for all bosses except SinGyoku. Maybe the
biggest single set of PI false positives left in TH01?

Part of P0130, funded by Yanga.
2020-12-18 00:55:23 +01:00
nmlgc aaea18aa8f [Decompilation] [th01] Retrieving and setting the default boss palette
The placement at the beginning of Kikuri's code segment makes you think
this is only used for the barely noticeable white-in effect during
Kikuri's entrance animation. It's also used to periodically reset boss
sprite colors during the flashing effect after getting hit by the Orb,
though.

Part of P0130, funded by Yanga.
2020-12-18 00:55:21 +01:00
nmlgc 0bfff60a0a [Maintenance] Define `bool` as unsigned
Wait, we can just do that, and nothing breaks?! All this time, we
could have avoided the `unsigned char` workaround???

Part of P0130, funded by Yanga.
2020-12-18 00:45:54 +01:00
nmlgc f4c2e45671 [Decompilation] [th01] Stage objects: Initialization
Lol @ Konngara decompilation being blocked by this giant card-flipping
function that took 2 pushes to understand, only for it to start with

	if((stage % 5) == 4) {
		return;
	}

…

Completes P0129, funded by Yanga.
2020-12-01 00:34:22 +01:00
nmlgc dd74e8a3cd [Reverse-engineering] [th01] Stage objects: Sprite IDs
Part of P0129, funded by Yanga.
2020-12-01 00:34:22 +01:00
nmlgc 35b4461b22 [Decompilation] [th01] Stage objects: VRAM page 0 → 1 copies
This is where the code generation actually confirms the SoA layout of
the global obstacle structure, rather than it being distinct pointers.

Part of P0129, funded by Yanga.
2020-12-01 00:34:21 +01:00
nmlgc 4b24c13d3d [Decompilation] [th01] Stage objects: Obstacle initialization
Part of P0129, funded by Yanga.
2020-12-01 00:34:21 +01:00
nmlgc 9f9d27554b [Decompilation] [th01] Stage objects: STAGE?.DAT loading
Final set of file loading calls in TH01!

Part of P0129, funded by Yanga.
2020-12-01 00:34:20 +01:00
nmlgc dde36f7f89 [Decompilation] [th01] Stage objects: Background snapping
Completes P0128, funded by Yanga.
2020-12-01 00:34:20 +01:00
nmlgc 73f62a5ba2 [Decompilation] [th01] Stage objects: Background allocation and blitting
Continuing the good error handling from the .PTN functions they're
based on… if only its sole caller actually cared.

Also: A sort-of limit of 102 objects per stage, just because someone
didn't use huge pointers where they would have been necessary…
:tannedcirno:

Part of P0128, funded by Yanga.
2020-12-01 00:34:18 +01:00
nmlgc 27b3f29a0a [Reverse-engineering] [th01] Stage objects: Card flip scores
Case in point: This structure member, which is located after all the
obstacle members. Sure, it'll look weird to see this one initialized by
a class method, but it'll be much weirder to somehow group both cards
and obstacles into one class.

Part of P0128, funded by Yanga.
2020-11-29 18:03:39 +01:00
nmlgc 7df4e0517b [Reverse-engineering] [th01] Stage objects: Obstacle class
And another one for all the obstacle types we saw earlier. The original
game probably combined all SoA pointers for both cards and obstacles
into a single "stage object". But that'll get way too unwieldy in the
functions later, given that those aren't even methods, and simply
reference one global variable. `stageobjs.obstacles.member`… yeah, no.

Part of P0128, funded by Yanga.
2020-11-29 17:59:03 +01:00
nmlgc 8e43f48b69 [Reverse-engineering] [th01] Stage objects: Card class
Sure, a SoA layout might actually be genius and what you should be
doing most of the time on modern systems, but you still wouldn't
allocate every member separately.

Part of P0128, funded by Yanga.
2020-11-29 17:59:01 +01:00
nmlgc 0ea53cf841 [Reverse-engineering] [th01] Stage objects: Obstacle types
An enum to distinguish between bumpers, turrets, portals, bumper bars…
and cards that have to be flipped more than once?!

Part of P0128, funded by Yanga.
2020-11-29 17:01:14 +01:00
nmlgc 3fc43a3dba [Maintenance] [th01] Start a new header file for stage objects
As we're going to see, some of these share some of the allocations.

Part of P0128, funded by Yanga.
2020-11-29 16:53:58 +01:00
nmlgc 9c36df72e5 [Maintenance] [th01] Get rid of th01.h
Part of P0126, funded by [Anonymous] and Blue Bolt.
2020-11-15 21:27:41 +01:00
nmlgc b104b3316b [Maintenance] Consistently use Borland's I/O port intrinsics
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.
2020-11-15 21:16:40 +01:00
nmlgc e8ae29ca4e [Maintenance] Remove the old `planar(8|16|32)_t` types
All code that used them has transitioned to C++, and can use the
Planar<> template.

Part of P0125, funded by [Anonymous].
2020-11-02 23:04:54 +01:00
nmlgc f1c63ab3a1 [Reverse-engineering] Assign names to all graph_putsa_fx() effects
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.
2020-11-02 22:33:50 +01:00
nmlgc 72dfa096d1 [Decompilation] [th01] Setting the default stage palette
Completes P0123, funded by Yanga.
2020-10-13 21:48:54 +02:00
nmlgc 7b2653fcab [Decompilation] [th01] Reimu's animations: .BOS freeing function
*Still* no need for the classic `if(ptr) { delete[] ptr; ptr = NULL }`
macro, because who cares about dangling pointers anyway, right?
:zunpet:

Part of P0123, funded by Yanga.
2020-10-13 21:48:07 +02:00
nmlgc d2ba0c7b3b [Decompilation] [th01] Reimu's animations: Byte-aligned overlapped blitting
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.
2020-10-13 21:36:07 +02:00
nmlgc 0be79aa641 [Decompilation] [th01] Reimu's animations: Byte-aligned blitting
Part of P0123, funded by Yanga.
2020-10-13 21:34:41 +02:00
nmlgc d391dd4a3b [Decompilation] [th01] Reimu's animations: Byte-aligned unblitting
"Let's add a row to the offset, and then subtract it again" :zunpet:
This could only *possibly* have been intended as a DoS attack against a
future manual decompilation, right?

Part of P0123, funded by Yanga.
2020-10-13 21:34:35 +02:00
nmlgc b75556c06e [Maintenance] [th01] Reorder shared .BOS code
Part of P0123, funded by Yanga.
2020-10-13 21:34:24 +02:00
nmlgc 10666131ec [Decompilation] [th01] Reimu's animations: .BOS load function
Part of P0123, funded by Yanga.
2020-10-13 21:15:19 +02:00
nmlgc cacb9361c7 [Decompilation] [th01] Skipping past the palette when loading .BOS files
At least the upcoming player animation load function was smart enough
to do that.

Part of P0123, funded by Yanga.
2020-10-13 20:51:52 +02:00
nmlgc 11f65e4afb [Reverse-engineering] [th01] Reimu's animations: Structure
Part of P0123, funded by Yanga.
2020-10-13 20:50:09 +02:00
nmlgc 4406c3d815 [Decompilation] [th01] Shootout lasers: Broken reset function
Two ZUN bugs in a single function call! These end up causing
effectively random sprite pixels to disappear during the transition to
the boss clear tally screen, if the boss was killed while any shootout
lasers were on screen. And once again, one of those bugs would have
been a non-issue with strong enough typing…

Oh well, that's all there is to this class.

Completes P0122, funded by Yanga.
2020-10-06 18:35:30 +02:00
nmlgc 60c1031d31 [Decompilation] [th01] Shootout lasers: Update/collision/render function
A public interface of two functions… nice.

Part of P0122, funded by Yanga.
2020-10-06 18:35:27 +02:00
nmlgc 243dbf8d0d [Decompilation] [th01] Shootout lasers: Rendering and collision detection
Part of P0122, funded by Yanga.
2020-10-06 18:35:24 +02:00
nmlgc 61559859e3 [Decompilation] [th01] Shootout lasers: Spawn function
Part of P0122, funded by Yanga.
2020-10-06 14:16:40 +02:00
nmlgc 800d7173aa [Reverse-engineering] [th01] Shootout lasers: Structure
Not to be confused with stationary lasers (as used by YuugenMagan, for
example), which are just regular lines with collision detection. 🥴

Also, 22 unused bytes out of 69, with another 11 that could have easily
been exchanged for better code…

Part of P0122, funded by Yanga.
2020-10-06 14:16:13 +02:00
nmlgc 1610d7b63d [Maintenance] Decide on a consistent place for file-wide `#pragma`s
(Maintenance mode commit)
2020-10-01 16:35:56 +02:00
nmlgc 37d191d903 [Decompilation] [th01] Player invincibility sprite rendering
So ZUN *did* want to clip those at the left and right edges of VRAM,
but accidentally tested the Y instead of the X coordinate 🎺

Part of P0121, funded by Yanga.
2020-09-28 13:02:34 +02:00
nmlgc 668b9033ab [Decompilation] [th01] Line loop unblitting
Same here.

Part of P0121, funded by Yanga.
2020-09-28 13:01:07 +02:00
nmlgc 60389473aa [Decompilation] [th01] Line loop blitting
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.
2020-09-28 12:56:52 +02:00
nmlgc 3c008b6a4f [Decompilation] [th01] Invincibility sprite blitting
In which ZUN accidentally the GRCG rather than the EGC in what should
have been (?) the unblitting function. Which then ends up actually
blitting yet another randomly background-masked version of the same
sprite on top of the old one. And after just a few frames, you get
those fully filled red diamonds you don't see in the sprite sheet.

Then again, if the 16w×h rectangle unblitting function is all you
have, and you can't be bothered to actually learn the EGC, this *is*
the better option 🎺

Completes P0120, funded by Yanga.
2020-09-28 12:56:05 +02:00
nmlgc b974c1a915 [Maintenance] Add separate macros for GRCG/EGC-accelerated reads and writes
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.
2020-09-28 12:51:01 +02:00
nmlgc c12cddfe47 [Decompilation] [th01] Sloppy ellipse arc unblitting
The usual case where ZUN should have just written a custom EGC-powered
unblitter, instead of resorting to the word-aligned rectangle one…

Part of P0120, funded by Yanga.
2020-09-28 12:50:16 +02:00
nmlgc 23f5645be5 [Decompilation] [th01] Ellipse arc blitting
Most frequently used for complete circles, though… but who cares, as
of this commit, ReC98, as a whole, is ⅓ done!

Part of P0120, funded by Yanga.
2020-09-28 12:46:29 +02:00
nmlgc fe4c92a066 [Maintenance] [th01] Add separate functions for polar coordinate calculation
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.
2020-09-28 12:43:29 +02:00
nmlgc 95c6936d99 [Decompilation] [th01] Non-entity boss animations: .BOS slot freeing function
What was the thought process behind this inconsistency?! Oh well, that
was still an entire class decompiled for almost free.

Part of P0120, funded by Yanga.
2020-09-28 12:42:24 +02:00
nmlgc 8d39276732 [Decompilation] [th01] Non-entity boss animations: Byte-aligned blitting
And that's all we have for this class. Again, ever so slightly not
identical to the same CBossEntity function.

Part of P0120, funded by Yanga.
2020-09-28 12:38:31 +02:00
nmlgc 719668d51e [Decompilation] [th01] Non-entity boss animations: .BOS load function
Only adding a single stupidly placed `for` loop into the CBossEntity
version of the same function…

Part of P0120, funded by Yanga.
2020-09-28 12:37:42 +02:00
nmlgc 1efa34ce05 [Reverse-engineering] [th01] Non-entity boss animation classes
I did consider calling them "boss aesthetics" instead, but
that didn't really seem to fit Sariel's dress and wand animations,
which are the only things this class is used for. Or does it?

Part of P0120, funded by Yanga.
2020-09-28 12:37:34 +02:00
nmlgc 9738ba921a [Decompilation] [th01] Boss entities: .BOS slot freeing function
Still no need for the classic `if(ptr) { delete[] ptr; ptr = NULL }`
macro, since the `ptr` is unconditionally set to NULL here…

Part of P0120, funded by Yanga.
2020-09-28 12:37:33 +02:00
nmlgc d48e553d9e [Maintenance] [th01] Move shared .BOS loading snippets to separate functions
Part of P0120, funded by Yanga.
2020-09-28 12:33:02 +02:00
nmlgc 0fe23cb8a0 [Maintenance] [th01] Clearly distinguish entity and animation .BOS slots
… now that we have a better idea about the differences of both classes.
Also, no transitive dependency on bos.hpp for either class.

Part of P0120, funded by Yanga.
2020-09-28 12:32:52 +02:00
nmlgc 4bf2e41faf [Decompilation] [th01] Boss entities: Orb collision detection
Why does it use the Orb's position from the previous frame though?

Part of P0120, funded by Yanga.
2020-09-28 12:29:37 +02:00
nmlgc 84baa1d477 [Maintenance] Rename the `_FORCE_INT` enum members to indicate signedness
Part of P0116, funded by [Anonymous] and Lmocinemod.
2020-09-12 12:09:30 +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 5a1e16de60 [Maintenance] Subpixels: Rename to_screen() to to_pixel()
We've been establishing `screen` as meaning "a coordinate rooted at the
top-left corner of the display", whereas most of the Subpixels in >TH01
are rooted at the top-left of the playfield.

Part of P0112, funded by [Anonymous] and Blue Bolt.
2020-08-28 15:14:17 +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 2ef3db3052 [Maintenance] Remove the `operator =` overloads for Subpixels
At least we've now documented their negative effects.

Part of P0110, funded by [Anonymous] and Blue Bolt.
2020-08-19 20:10:08 +02:00
nmlgc 2fbde57631 [Maintenance] Turn the left/right/top/bottom area structure into a template
Part of P0109, funded by [Anonymous] and Blue Bolt.
2020-08-16 21:40:35 +02:00
nmlgc dcf4e2cadd [Decompilation] [th01] Boss entities: Clamped movement + blitting
And here, the whole clamped movement part remains entirely unused.

Completes P0108, funded by Yanga.
2020-08-12 18:02:19 +02:00
nmlgc 52def53fd3 [Decompilation] [th01] Boss entities: Clamped movement + unblitting + blitting
A function which does so many individual things that I can't even
summarize it in a comment without spelling out each line of code. And
then, this entire clamped movement system is only used for Kikuri's
soul sprites. The usage code for every other entity just parties on
the [cur_left] and [cur_top] members, and passes a delta of (0, 0) to
this function. 🤷

Part of P0108, funded by Yanga.
2020-08-12 18:02:18 +02:00
nmlgc 2a091eed3b [Decompilation] [th01] Boss entities: Sloppy unblitting function
Unused, thankfully!

Part of P0108, funded by Yanga.
2020-08-12 18:02:18 +02:00
nmlgc d9bc75d28e [Decompilation] [th01] Boss entities: Position and movement clamp area setter
Yay, 7 parameters.

Part of P0108, funded by Yanga.
2020-08-12 18:02:18 +02:00
nmlgc 9ce0034934 [Decompilation] [th01] Boss entities: 16×8 section unblitting + blitting
Yet another unused function. No idea what it could have been intended
for – no boss sprite has animated sections that small.

But come on, out of all places that could have required the macro form
of a VRAM offset function, it had to be a unused one…

Anyway, that completes the low-level blitting functions for boss
entities!

Part of P0108, funded by Yanga.
2020-08-12 18:02:17 +02:00
nmlgc a2c4aadda9 [Decompilation] [th01] Boss entities: Broken wavy unblitting of two sprites
Another unused function! This might indicate that Elis could originally
split herself into two sprites, similar to TH04 Stage 6 Yuuka?
Or it might just have been some other kind of animation effect, who
knows.

Part of P0108, funded by Yanga.
2020-08-12 18:02:16 +02:00
nmlgc bc9b7cdfcd [Decompilation] [th01] Boss entities: Wavy blitting
Used for Elis' entrance animation. Including an unused unblitting +
blitting function – apparently, ZUN wrote that one before the sloppy
EGC-accelerated wavy unblitting function that I decompiled way back in
6d2fa9f.
Oh well, the latter one is fine in context, since there are no other
sprites on screen during the animation.

Part of P0108, funded by Yanga.
2020-08-12 18:01:33 +02:00
nmlgc 1650241f07 [Decompilation] [th01] Boss entities: Byte-aligned unblitting
A precise unblitting function, actually using the alpha plane of the
sprite… and it's unused.

Completes P0107, funded by Yanga.
2020-08-12 17:51:44 +02:00
nmlgc de688ddc20 [Decompilation] [th01] Boss entities: Byte-aligned unblitting + blitting
And we're back to not using functions, and needing our own VRAM access
macros…

Part of P0107, funded by Yanga.
2020-08-12 17:51:43 +02:00
nmlgc 96f3b1057c [Decompilation] [th01] Boss entities: Unaligned 1-line unblitting + blitting
… except that those single-plane functions provide basically no
useful abstraction in the context of a 4-plane image format. Should
have just gone all the way and directly take something like our
Planar<dots16_t> type to operate on all 4 planes, so that I wouldn't
have had to add that layer of abstraction myself.

Apparently, early ZUN was allergic to passing structures by reference?

Part of P0107, funded by Yanga.
2020-08-12 17:51:43 +02:00
nmlgc 816ba8342c [Decompilation] [th01] Background + foreground VRAM blit functions
Yes, functions! Those would have been nice earlier!
Also documented another overly specific Borland C++ code generation
quirk with regard to assigning expression results to elements of 16-bit
arrays…

Part of P0107, funded by Yanga.
2020-08-12 17:51:42 +02:00
nmlgc 34a5f4d183 [Decompilation] [th01] Boss entities: Unaligned 1-line blitting
"Oh wait, actually, I *do* want to blit 8 pixels at a time in some
cases" :zunpet:

First time in a long while that the VRAM access macros couldn't do the
job, because code generation wants *both* pointer arithmetic *and*
subscripts within the same expression.

But *come on*, just blit the 16 pixels for the byte-aligned case!

Part of P0107, funded by Yanga.
2020-08-12 17:51:42 +02:00
nmlgc 32c57c32e7 [Decompilation] [th01] Boss entities: Regular, byte-aligned blitting
That attempt at clipping the sprite at the left and right edges of
VRAM… is serviceable, I guess?

Part of P0107, funded by Yanga.
2020-08-12 17:51:42 +02:00
nmlgc 1f1829d2d8 [Decompilation] [th01] Boss entities: Copying .BOS metadata
So if the boss entity class stores all non-pixel metadata for its
associated .BOS file, how can YuugenMagan have 5 independent eye
sprites, or Kikuri have more than one soul and tear sprite?
By duplicating that data, of course!

Those structure copies to local variables seen in the load functions
of these bosses still remain pointless, though.

Completes P0106, funded by Yanga.
2020-08-12 17:51:40 +02:00
nmlgc 342e6450bc [Decompilation] [th01] Boss entities: .BOS load function
"Hm, I have this format that specifies sprite width in multiples of 8,
but *actually*, I'd like to blit 16 pixels at a time… well, time to
pepper the code with divisions and casts, I guess :zunpet:"

Which becomes even more hilarious once you realize that the `operator
new` function does require bytes after all. Which leads

	new dots16_t[image_size / 2];

to compile to

	operator new((image_size / 2) * 2);

:tannedcirno:

Part of P0106, funded by Yanga.
2020-08-12 17:49:35 +02:00
nmlgc 5f5eb8aa4e [Decompilation] [th01] .BOS: Unused and broken plane pointer reset function
Because that's not how you free dynamically allocated memory?

Part of P0106, funded by Yanga.
2020-08-12 17:49:34 +02:00
nmlgc 1a595cf60c [Reverse-engineering] [th01] Boss entity classes
What else to call something a boss can have multiple of, that may or
may not be part of a larger boss sprite, may or may not be animated,
and that may or may not have a orb hitbox?

Needed to be RE'd before the .BOS loading functions, because those are
actually methods of this class. And because renaming all these
variables in ASM land is tedious anyway, we might as well name each
individual entity of every boss.

Still, what's with the pointless local variable copies in the
YuugenMagan and Kikuri functions?

Part of P0106, funded by Yanga.
2020-08-12 17:49:34 +02:00
nmlgc 11b776b32e [Decompilation] [th01] 8×8 diamond, star, and snowflake sprite blitting
More hardcoded sprites! These are prominently seen in the Konngara,
Elis, and Sariel battles, respectively.

Completes P0105, funded by Yanga.
2020-08-12 16:24:04 +02:00
nmlgc 3622eb6298 [Decompilation] [th01] HUD: Stage number rendering
Completes P0104, funded by Ember2528.
2020-07-27 17:23:06 +02:00
nmlgc a0215ea85c [Decompilation] [th01] HUD: Life and bomb count rendering
If you've ever cheated more than 6 lives in TH01, you might have
noticed that those additional lives appear in additional rows in the
HUD. And well, that had to be coded somewhere…

Part of P0104, funded by Ember2528.
2020-07-27 17:20:29 +02:00
nmlgc e0bcdafb00 [Maintenance] [th01] Declare proper IDs for all .PTN sprites seen so far
Part of P0104, funded by Ember2528.
2020-07-27 17:19:48 +02:00
nmlgc f3093a802c [Decompilation] [th01] HUD: Inter-page row-sized rectangle blitting
Both inlined and non-inlined page switching within the same function,
together with an approach that doesn't correspond to our other planar
access macros? That code must have been written during a very
experimental phase very early in the development of this game.

Part of P0104, funded by Ember2528.
2020-07-27 17:19:12 +02:00
nmlgc edd9a14273 [Decompilation] [th01] HUD: Background (MASK.GRF) loading and rendering
Look, it's a memory leak!

Part of P0104, funded by Ember2528.
2020-07-27 17:17:59 +02:00
nmlgc 05c00287e9 [Decompilation] [th01] HUD: Initial score and card combo rendering
Hey look, this one *does* only render to a single page, and then blits
the area to the other one! Using an unnecessary new function that isn't
even EGC-accelerated…

Completes P0103, funded by Ember2528.
2020-07-27 17:17:22 +02:00
nmlgc b9038be04d [Decompilation] [th01] HUD: Current score and card combo rendering
Part of P0103, funded by Ember2528.
2020-07-27 17:13:35 +02:00
nmlgc b73762ba12 [Decompilation] [th01] HUD: Maximum card combo rendering
Nice and consistent…

Part of P0103, funded by Ember2528.
2020-07-27 17:12:21 +02:00
nmlgc f92c2a637c [Decompilation] [th01] HUD: High score update/render function
The scores are rendered to *both* VRAM pages…? Which means that we
need a separate set of sprites to store the background behind the
numbers. This does not bode well for animated backgrounds…

Part of P0103, funded by Ember2528.
2020-07-27 17:11:43 +02:00
nmlgc b60f38d42d [Decompilation] [th01] Pellets: Delay cloud unblit/update/render function
And with that, we're actually *done* with TH01 pellets, and never have
to look at them again! 🎉

Completes P0102, funded by Yanga.
2020-07-12 16:45:53 +02:00
nmlgc dbc8da99d5 [Decompilation] [th01] Pellets: Player collision
How optimized is TH01? Well, since the player Y is constant, checking
for Y ≥ 368 first would rule out a collision for the majority of
entities during gameplay after just 1 check.

TH01 still checks X first.

Part of P0102, funded by Yanga.
2020-07-12 16:35:31 +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 63dafdb9c7 [Decompilation] [th01] Pellets: Unblit/update/render function
… pellet unblitting uses a *doubly* sloppy 16×8 rectangle. 🤦
The resulting terrible flickering is probably why the Stage 15 and 20
battles enable this weird "interlace" mode that only renders and
hit-tests half of the pellets each frame… except that player shots
are still hit-tested every frame?
So yeah, your eyes aren't deceiving you, the game does effectively drop
its perceived frame rate in the Elis, Kikuri, Sariel, and Konngara
fights, and it does so deliberately.

And *then* you realize that those weird hit tests are actually a
futile attempt to mitigate the disastrous effects of a way too large
unblitting rectangle. Congratulations, you've found the most stupid
piece of code in this game.

Part of P0102, funded by Yanga.
2020-07-12 16:29:51 +02:00
nmlgc d840841a2b [Naming] Rename egc_copy_rect_1_to_0() to emphasize its 16-dot alignment
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.
2020-07-12 16:27:56 +02:00
nmlgc edb70162e0 [Decompilation] [th01] Pellets: Manager class constructor
Note how Turbo C++ auto-generates that call to `operator new`, which
you don't see in the decompilation anymore. So yeah, as soon as you add
a constructor, Turbo C++ enforces heap allocation for any instance of
that class, even function-local ones that would otherwise be
stack-allocated.

That's where the bad reputation of C++ comes from, I guess?

Part of P0102, funded by Yanga.
2020-07-12 16:23:12 +02:00
nmlgc c11a95666b [Decompilation] [th01] Pellets: Shot/Orb/deflecting player collision
First off: 👏 Just 👏 pass 👏 a 👏 reference 👏 to 👏 the 👏
currently 👏 iterated 👏 pellet 👏 if 👏 you 👏 need 👏 to 👏
modify 👏 it 👏
Second: Don't we hit-test pellets vs. shots already, in the CShots
class? So what is this garbage…?!

Completes P0101, funded by Yanga and Ember2528.
2020-07-12 16:21:17 +02:00
nmlgc 8328905f46 [Decompilation] [th01] Pellets: Multi-pellet patterns
Actually quite cute with their hardcoded limitations, since the created
patterns do follow a clear logic.
But yeah, no 6-way spreads for you, we only support 2-, 3-, 4-, and
5-way ones here :zunpet:

Part of P0101, funded by Yanga and Ember2528.
2020-07-12 16:15:24 +02:00