Skip to content

Commit

Permalink
[Anniversary] [th01] Shootout lasers: Remove unblitting on reset
Browse files Browse the repository at this point in the history
Freezing the lasers in place during the defeat animation is arguably
nicer than trying to unblit them, *and* we don't need to work around
the graph_r_line() General Protection Fault!

Completes P0234, funded by Ember2528.
  • Loading branch information
nmlgc committed Mar 5, 2023
1 parent 80ee9b2 commit 12f29c6
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 44 deletions.
2 changes: 1 addition & 1 deletion th01/main/boss/b10j.cpp
Expand Up @@ -1341,7 +1341,7 @@ void mima_main(void)
mdrv2_bgm_fade_out_nonblock();
Pellets.unput_and_reset();
Missiles.reset();
shootout_lasers_unput_and_reset_broken(i, 5); // 5? Doubly broken...
shootout_lasers_reset();
boss_defeat_animate();
}
}
Expand Down
2 changes: 1 addition & 1 deletion th01/main/boss/b15j.cpp
Expand Up @@ -1138,7 +1138,7 @@ void kikuri_main(void)
if(boss_hp <= 0) {
mdrv2_bgm_fade_out_nonblock();
Pellets.unput_and_reset();
shootout_lasers_unput_and_reset_broken(i, 4); // 4? Doubly broken...
shootout_lasers_reset();
boss_defeat_animate();
}
}
Expand Down
2 changes: 1 addition & 1 deletion th01/main/boss/b15m.cpp
Expand Up @@ -2111,7 +2111,7 @@ void elis_main(void)
Pellets.unput_and_reset();
girl_bg_put(1);
Missiles.reset();
shootout_lasers_unput_and_reset_broken(i, SHOOTOUT_LASER_COUNT);
shootout_lasers_reset();
boss_defeat_animate();
}
}
Expand Down
2 changes: 1 addition & 1 deletion th01/main/boss/b20m.cpp
Expand Up @@ -2707,7 +2707,7 @@ void sariel_main(void)

Shots.unput_and_reset();
Pellets.unput_and_reset();
shootout_lasers_unput_and_reset_broken(i, SHOOTOUT_LASER_COUNT);
shootout_lasers_reset();

// MODDERS: Move this to a common player reset function.
orb_cur_left = ORB_LEFT_START;
Expand Down
7 changes: 7 additions & 0 deletions th01/main/bullet/laser_s.cpp
Expand Up @@ -150,3 +150,10 @@ void CShootoutLaser::update_hittest_and_render(void)
hittest_and_render(SL_RAY_PUT);
grcg_off_func();
}

void shootout_lasers_reset(void)
{
for(int i = 0; i < SHOOTOUT_LASER_COUNT; i++) {
shootout_lasers[i].alive = false;
}
}
43 changes: 3 additions & 40 deletions th01/main/bullet/laser_s.hpp
Expand Up @@ -82,41 +82,6 @@ class CShootoutLaser {

// Directly sets [done] if the laser collides with the player.
void update_hittest_and_render(void);

// Tries to unblit the entire laser, but fails hilariously and potentially
// even crashes the game.
void unput_and_reset(void) {
if(alive) {
// ZUN bug: And even two of them:
//
// 1) Surely this should have unblitted from the start to the end
// of the ray instead? Except that this class doesn't explicitly
// store that end point… so the best alternative would be the
// target point. But given that we use our own blitting routine,
// who knows how accurate that actually is?
//
// 2) graph_r_line_unput() takes screen_x_t and vram_y_t, not
// LaserPixels truncated to 16-bits. :zunpet: The function then
// interpolates and clips these values in a rather clumsy
// attempt to find a line segment between those garbage
// coordinates that actually falls within the boundaries of
// VRAM. At best, this search fails, and the function simply
// does nothing. At worst, the resulting line triggers the ZUN
// bugs in graph_r_line_unput(), raising a General Protection
// Fault.
// The latter is exactly the cause behind potential crashes when
// defeating bosses while there are diagonally moving lasers on
// screen, which are most commonly reported for Elis and Mima.
//
// So yeah, not doing anything would have been the much better
// choice.
graph_r_line_unput(
ray_start_left.v, ray_start_y.v, origin_left.v, origin_y.v
);

alive = false;
}
}
};

extern CShootoutLaser shootout_lasers[SHOOTOUT_LASER_COUNT];
Expand All @@ -125,8 +90,6 @@ extern CShootoutLaser shootout_lasers[SHOOTOUT_LASER_COUNT];
#define shootout_laser_safe(i) \
shootout_lasers[(i) % SHOOTOUT_LASER_COUNT]

#define shootout_lasers_unput_and_reset_broken(i, count) { \
for(i = 0; i < count; i++) { \
shootout_lasers[i].unput_and_reset(); \
} \
}
// Resets all lasers, but leaves them in VRAM. The boss defeat animation is
// supposed to get rid of them.
void shootout_lasers_reset(void);

0 comments on commit 12f29c6

Please sign in to comment.