Oh wow, it's exactly how I always naively imagined collision detection
to be implemented in a fixed-resolution 2D bullet hell game with small
hitboxes.
Part of P0182, funded by Lmocinemod and [Anonymous].
Makes sense for this game as well, even if it can only serve
documentary purpose due to it not knowing which playfield it's on.
Part of P0182, funded by Lmocinemod and [Anonymous].
Second PC-98 Touhou boss completely decompiled, 29 to go! But meh,
ZUN's original code did in fact force the three leaf pattern sprites
into separate 1-sprite sheets…
Completes P0181, funded by Ember2528.
The one where Sariel's second form shoots sparks towards the top of the
playfield, which then turn into leaf-like sprites that sway towards the
bottom, killing Reimu on contact.
And wow, what a finish! A weird "decimal subpixel" type, hardcoded
sprites, and effectively unused non-hardcoded sprites. Too bad that it
also ruins the nice `dot_rect_t(w, h)` parameter abstraction for
grcg_put_8x8_mono()…
Completes P0180, funded by Yanga.
The one where evenly spaced, randomly aimed pellets rain down from an
imaginary horizontal line at the seal's center Y coordinate. Featuring
an equally broken symmetric spawn ray variant.
Part of P0180, funded by Yanga.
The one where decelerating pellets form a curve shape, by being fired
from the center and aimed along the bottom left and right edges of the
playfield.
First pattern of Sariel's second form… which is where ZUN apparently
learned to pass the frame count as a parameter. Would have been even
nicer if the return value indicated when the pattern is done instead of
mutating a reference to the frame count.
Completes P0179, funded by Ember2528.
The one where Sariel fires vertical 3-stacks with two spawners moving
from between the two bottom edges of the playfield, followed by
randomly raining bullets from two spawners moving between the two top
edges of the playfield. Final pattern of Sariel's first form, and
surprisingly fair by never spawning pellets on top of Reimu.
Also, about time I found a way of bypassing the -Z -3 function
parameter optimization in order to keep using nice structures like
these.
Part of P0179, funded by Ember2528.
The one where Sariel fires four semicircle spreads from their shield,
10 frames apart.
So nice and simple that it warrants trying out a more compact coding
style for these `for` loops with two loop variables. The more I look at
it, the more I like it? I do think it's good.
Completes P0178, funded by Ember2528.
The one where symmetric birds spawn from the bottom of the playfield,
then fly to the top while shooting bullets at random angles.
Part of P0178, funded by Ember2528.
The one with a single spawn ray spinning from Sariel's shield across
the seal, followed by radial pellet stacks and lasers being fired from
the same position.
Completes P0177, funded by Yanga.
The one where pellets rain from the top of the playfield every 8
frames, at random angles on Lunatic and straight down on every other
difficulty.
Part of P0177, funded by Yanga.
> use 64-bit floating-point for particles that move on strictly
one-dimensional lines
> use integer pixels for particles with a sine wave motion
Part of P0177, funded by Yanga.
The one with the 2-rings firing from the two orbs on the left and right
side of the playfield.
4th pattern, and it took 4 pushes in this series to get there… Looks
like it's going to get easier from here on, though.
Part of P0177, funded by Yanga.
Maximum floating-point decadence yet again, for an effect that you
barely even notice (and your brain probably didn't, either).
Fun fact: They stop animating during the background transition
animation I've just decompiled previously.
Completes P0176, funded by Ember2528.
One of the hardest decompilations in a long while:
• Required new research into code generation for pointer arithmetic
• ZUN needlessly calculating intermediate results over and over again,
making the function tedious to read
• GRCG reads in TCR mode, which I haven't seen so far either
Part of P0176, funded by Ember2528.
TDW and TCR modes share the same bit in the GRCG mode register and are
thus indistinguishable when looking at a disassembly, but only apply to
writing (TDW) or reading (TCR), respectively. TH01 only performs read
operations in this mode, so it's unambiguously TCR.
Part of P0176, funded by Ember2528.
The one where red birds hatch on an ellipse arc, then fly away while
shooting a randomly selected pellet group type. Containing Sariel's
first ZUN bug, resulting in unused sprite movement.
Completes P0175, funded by Ember2528.
The one where two vortex sprites wall Reimu inside a continuously fired
static 3-spread stack.
Whose per-difficulty density is only controlled by the amount of
frames they have moved towards each other, interestingly.
(And yes, second pattern in the fight, first one in the code.)
Part of P0175, funded by Ember2528.
Surprise, this .PTN sprite isn't actually just the background, but a
complete opaque copy of the 128×128 pixels in the .GRP image that
contain the initial position of the wand. This is what allows Sariel
to lower it again after blitting the raised sprites from BOSS6_2.BOS.
Part of P0175, funded by Ember2528.
In which the black part in BOSS6_2.BOS's second cel is indeed meant to
unblit the purple part in the first cel, leaving a hole in both the
seal and the red HUD border. Shouldn't it rather contain the original
pixels, including the part of the seal that is covered by the sphere on
top of the wand even in the .GRP?
Part of P0175, funded by Ember2528.
I appreciate that this design allows all bird state to be scoped to
this function, but *come on*, one function doing 6 different jobs?
Also, maximum floating-point decadence… but perhaps the worst part is
that the initial bird eggs are a *different* entity.
Completes P0174, funded by Ember2528.
Very helpful at this small scale, as it allows us to directly decompile
floating-point literals. These will be added to Sariel's regular
translation unit in the same order, so we merely have to remove them
from this temporary translation unit then.
Part of P0174, funded by Ember2528.
So if Sariel's version of this function is worse than Konngara's, can
we conclude that Sariel's code was written first?
(Edit, after having decompiled more of the fight: Sariel's functions
are predominantly `near` in contrast to Konngara's 100% `far` ones,
which is just as much of an indicator for the opposite.)
Part of P0174, funded by Ember2528.
Every other motion type requires the other parameters to make sense.
If none of those are given, PM_NORMAL is redundant as well.
Part of P0174, funded by Ember2528.