Short, sweet, fits more nicely into 8.3 filenames than "curve bullets"
does, and 76.7% of fans agree:
https://twitter.com/ReC98Project/status/1500256959785746434
OMAKE.TXT calls them "homing lasers", but… eh, nah.
Part of P0190, funded by nrook.
Wait, wouldn't it be cool if we could keep the render, spawn, and
update functions in the same translation unit, by switching code
segments in the middle of the file? Let's hope this works out, and give
the source file an all-encompassing generic name.
Part of P0188, funded by [Anonymous] and nrook.
The algorithm for gradually rotating these clockwise or counterclockwise
towards the player could have been 5 lines long. ZUN blows it up to 26
lines.
Also, a 16×16 killbox for the head node, and a 12×12 one for trail
nodes.
Part of P0185, funded by [Anonymous], -Tom-, and Blue Bolt.
Too bad that alignment constraints do in fact force us to compile
th04/bullet_u.cpp and th04/bullet_a.cpp separately. 😕
Part of P0184, funded by -Tom-.
Also not worth decompiling, because:
• It would break return value semantics
• The algorithm is identical to TH04 (except for that one divisor)
• Small function
• Next to a bunch of more critical, undecompiled functions
• Decompilation would be messy anyway
Part of P0152, funded by -Tom- and [Anonymous].
And that's it! Finally RE'd every bullet spawning function in TH04 and
TH05! 🎉
These really aren't worth adding a translation unit for either, in the
end. Not least because they decide to keep bullet_template.speed from
being mutated via PUSH and POP, which we can only express via inline
assembly in C land.
Part of P0152, funded by -Tom- and [Anonymous].
Reason: That switch statement. How should we even?
Well, the code *is* fairly good. After looking very deep into it, and
spending 35% of that function on blank lines (for logical grouping) and
explanatory comments, that is…
Part of P0152, funded by -Tom- and [Anonymous].
Deciding whether to decompile this one or not seemed to be a tough
choice. Should we *really* introduce two more translation units just
for the sake of decompiling another function that's identical to its
TH04 counterpart anyway?
Well, turns out it actually isn't: TH05 does in fact *not* immediately
clip bullets that are spawned on top of the player. Which might sound
like it has a notably different effect on gameplay… except that it
doesn't.
So yeah, good we've decompiled it, and got to show that more clearly.
Part of P0152, funded by -Tom- and [Anonymous].
Spent 4 pushes on the basic types and constants in 2020, still ended up
up getting this wrong and documenting the opposite of what TH05 actually
does…
Part of P0152, funded by -Tom- and [Anonymous].
motion_t is also used for certain animations in MAINE.EXE, so not all
instances refer to entities in playfield space. Explicitly specifying
the latter now allows us to gain…
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-.
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].
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.
`cPtrSize` is simply the wrong constant for calculating parameter
offsets on the stack, because it corresponds to the memory model's
default distance, not the function's distance. Luckily, ARG has a
RETURNS clause, and if you declare all parameters in there, ARG won't
emit that pesky and unnecessary `ENTER 0, 0` instruction. Big discovery
right there!
Sadly, ARG is unusable for ZUN's silly functions that keep the base
pointer in BX. TASM declares the resulting equates as `[BP+offset]`,
and it's apparently impossible to only get `offset` out of such an
equate later.
So, rather than staying with numbers, let's reimplement ARG for these
functions instead. This way, we can even abstract away the stack clear
size for the `RET` instructions.
It's a bit rough around the edges though, forcing you to explicitly
specify the function distance, and to pass the parameters in reverse
order compared to the C declaration (thankfully, all of these use the
PASCAL calling convention). It also doesn't work with more complex
types yet. But certainly better than numbers.
Part of P0134, funded by [Anonymous].
*Technically* also a uth05win inaccuracy. That codebase went with
"KnifeBullet", which seemed right, so I just ran with it without
researching it further… My bad.
(Maintenance mode commit)
Making sure that we don't ever have to iterate over the 8×8 pellet part
of the bullet array during rendering… sure, but why not give the same
optimization treatment to the 16×16 bullets?
Part of P0112, 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.
If C allowed labels of other functions as `goto` targets, this *might*
have been decompilable into something useful to modders. But like this,
there's no point in even trying.
Yeah, you *really* don't want to base your fangame mod on TH05.
Part of P0109, funded by [Anonymous] and Blue Bolt.
TH04's z_super_roll_put_tiny_32x32(), which this is based on, had
checks for not writing empty rows to VRAM. Why would ZUN remove them
here?
Completes P0086, funded by [Anonymous] and Blue Bolt.
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.