Will make it easier to comprehend that the bullet update function is
actually correct with regards to only looking at a single variable.
(Yes, I know, hard to believe!)
Part of P0149, funded by Blue Bolt, Ember2528, and -Tom-.
Yup, P0148 didn't actually solve the issue it was meant to solve, and
I still had to research this workaround.
Part of P0149, funded by Blue Bolt, Ember2528, and -Tom-.
At least I *hope* it's an improvement. `point` should be reserved for
actual structures with .x and .y members.
Part of P0149, funded by Blue Bolt, Ember2528, and -Tom-.
Well. The more random bullets at constrained angles are added to a
bullet group, the closer that group will invariably approximate a
spread shape. That's why it probably appeared as a "spread" to me in
2020. But the implementation for this group type
• neither uses any of the spread code,
• nor does it ensure a consistent angle between the bullets (which a
hypothetical "random angle spread" group type would probably do).
Also, look at its number within the enum! How could I ever get that
confused?!
Part of P0149, funded by Blue Bolt, Ember2528, and -Tom-.
And actually document them correctly.
Clear: Custom duration, awards constant points per bullet during the
entire duration, plays a decay animation
Zap: Fixed duration, awards a semi-exponential bonus for all bullets
alive on the first frame, plays a, um, "zapping" animation… in
TH04, because it's bugged in TH05 :zunpet:
Part of P0149, funded by Blue Bolt, Ember2528, and -Tom-.
Boom! Decompilable after all. And look what that made us finally point
out: In all 4 games that use this function, its return value is
undefined if BGM is inactive. (That is, if the user disabled it, or if
no FM sound board is installed.)
Part of P0148, funded by [Anonymous].
Well, we *could* pointlessly decompile this function into an unreadable
mess, but only if we throw away the semantics of the return value, and
replace its type with `void` or `uint32_t`.
(Turbo C++ can't cast registers to a struct value, and adding a
constructor to SPPoint would break everything else, if it even works.)
ZUN's original usage code doesn't care either way, because it only ever
accesses the returned value directly through DX:AX.
Part of P0148, funded by [Anonymous].
… Wait, we *can* decompile functions with both parameters, no stack
frame, and a Pascal calling convention?! Good that I already forgot how
impossible it was to decompile the first function I looked at that fell
into this category!
Part of P0148, funded by [Anonymous].
Including the pointless DOS I/O variation in TH05's MAIN.EXE.
I'm slowly running out of characters to remove from the first segment
name in that file, though…
Part of P0148, funded by [Anonymous].
It shouldn't need a comment to communicate that this function does in
fact not load all values from the .CFG file that are part of the
resident structure, but only loads and sets the global pointer to that
structure.
Part of P0148, funded by [Anonymous].
The bullet update function really needs this one declared in C land to
link without a fixup overflow? Guess we'll have another technical debt
push before then…
Part of P0148, funded by [Anonymous].
Palette hacks not included yet. Yup, that's how all phases can use
hardware color #0 as their background color.
Completes P0147, funded by -Tom- and Ember2528.
64 slots reserved, 16 slots actually used, another 768 bytes of
conventional RAM wasted…
(And yes, that naming convention is indeed meant as a shoutout to all
the RPG Maker veterans out there.)
Part of P0147, funded by -Tom- and Ember2528.
Oh wow, we never used that one; I only added it in 042b780 to make it
easier for tool authors to #include "th04/resident.hpp". Bad idea –
if we don't ensure that it *actually works* (and it didn't, as of
d1f3dcd), it's of no help to them either.
Part of P0147, funded by -Tom- and Ember2528.
That could have easily been architected without forcing every boss to
manually set the "background to be drawn while bombing" function
pointer.
And without the laziness of just redrawing all tiles during the blocky
opening animation of certain bombs…
Part of P0147, funded by -Tom- and Ember2528.
Not exclusively used for the boss entrance animations, even though its
data is declared in that general vicinity. It's also used for all bombs
in TH04, and Reimu's and Yuuka's bomb in TH05.
Part of P0147, funded by -Tom- and Ember2528.
Sure, it's still a micro-optimization, but at least it's __fastcall for
once! And doesn't assume ES to have been set to a VRAM segment. So not
*that* optimized 😛
Part of P0147, funded by -Tom- and Ember2528.
The one in the first four phases, with the two parallel zooming lines
that give the impression of flying into a corridor, and random blue
particles shooting out from the center.
Part of P0146, funded by -Tom- and Ember2528.
We really wouldn't have wanted to start writing inline ASM in the
middle of a conditional expression just to get that janky `CMP AX, 0`
instead of TCC's sensible `OR AX, AX` optimization.
Part of P0146, funded by -Tom- and Ember2528.
Oh hey, a uth05win naming convention I have no qualms about adopting,
for once!
(Note from the future: It's actually really smart! The animation you
see is dependent on the state from previous background types, so it
makes sense to reduce the names to the original sequence.)
Part of P0146, funded by -Tom- and Ember2528.
The one where Konngara fires 4 diamonds in a cross-shaped motion
towards the edges of the screen, with random pellets raining down for
200 frames afterwards.
Completes P0142, funded by Yanga.
Oh no, another place in which I'm going too far?! Just because I'm sick
of hardcoded number literals after 6 years? Hm…
Part of P0142, funded by Yanga.
We're going to need some name for the longer, boss-specific danmaku
animations. Turns out that these are exactly called "patterns" in
Sparen's glossary:
https://sparen.github.io/ph3tutorials/ddsg0.html#sub4
So what we called a "pattern" is actually called a "group". Whoops!
Part of P0142, funded by Yanga.
Amazing how both an `int` and an `unsigned char` parameter generate the
exact same ASM if they're only passed on to a single function that
widens them to a 16-bit type.
Part of P0142, funded by Yanga.
It's script-like code, what can you say. Maybe minimally sloppy in some
places, but ultimately harmless.
Oh, the Siddhaṃ seed syllables are supposed to show up immediately, with
no delay between them? Good to know – clocking your emulator too low
tends to roll them down from the top of the screen, and does add a
noticeable delay between the individual images.
… Wait, but this means that ZUN could have *intended* this "effect".
Why else would he not only put those syllables into four individual
images, but also show them on the foreground VRAM page?
Completes P0141, funded by [Anonymous] and rosenrose.