[Decompilation] [th01] Mima: Pattern 3/8

The one where Mima takes the final static part from the first pattern,
and replicates it with two squares that rotate in opposite directions.
Also demonstrates the 34th unblitting bug in this game.

Part of P0205, funded by [Anonymous] and Yanga.
This commit is contained in:
nmlgc 2022-07-13 01:02:26 +02:00
parent 12eb04cc9c
commit 1772a2907a
2 changed files with 88 additions and 289 deletions

View File

@ -67,10 +67,12 @@ extern int invincibility_frame;
extern bool16 invincible;
extern bool initial_hp_rendered;
// Whether meteor_put() has any effect.
extern bool meteor_active;
// Amount of frames between the individual steps of the spread-in transition
extern uint8_t spreadin_interval;
// Sprite pixels to spread in per frame, in one half of Mima's sprite
extern uint8_t spreadin_speed;
@ -172,7 +174,12 @@ void meteor_put(void)
void mima_put_cast_both(void)
{
// ZUN bug: Does not unblit the meteor if `true`, and C_CAST does not
// completely overlap any C_METEOR cel. In that case, small parts of the
// meteor are guaranteed to be left in VRAM until they're unblitted as a
// result of another sprite flying over them.
meteor_active = false;
ent_anim_sync_with_still_and_put_both(C_CAST);
}
@ -398,6 +405,14 @@ struct SquareState {
screen_x_t name##_center_x; \
screen_y_t name##_center_y;
#define SquareLocal2(name) \
screen_x_t name##_corners_ccw_x[SQUARE_POINTS]; \
screen_y_t name##_corners_ccw_y[SQUARE_POINTS]; \
screen_x_t name##_corners_cw_x[SQUARE_POINTS]; \
screen_y_t name##_corners_cw_y[SQUARE_POINTS]; \
screen_x_t name##_center_x; \
screen_y_t name##_center_y;
#define square_center_set(sql) { \
sql##_center_x = ent_still.cur_center_x(); \
sql##_center_y = ent_still.cur_center_y(); \
@ -563,3 +578,74 @@ void pattern_aimed_missiles_from_square_corners(void)
#undef target_left
#undef sq
}
void pattern_static_pellets_from_corners_of_two_squares(void)
{
#define sq pattern2_sq
extern SquareState sq;
SquareLocal2(sql);
if(boss_phase_frame == 50) {
mima_put_cast_both();
}
if(boss_phase_frame < 100) {
return;
}
if(boss_phase_frame == 100) {
sq.init();
select_subpixel_for_rank(pattern_state.speed, 4.0f, 4.5f, 5.0f, 5.5f);
mdrv2_se_play(8);
}
if((boss_phase_frame % SQUARE_INTERVAL) == 0) {
square_center_set(sql);
square_corners_set(sql, sql_corners_ccw, sq.radius, sq.angle);
square_corners_set(sql, sql_corners_cw, sq.radius, (0x00 - sq.angle));
square_unput(sql_corners_ccw);
square_unput(sql_corners_cw);
sq.angle -= 0x06;
Pellets.spawn_with_cloud = true;
if(sq.radius < SEAL_CIRCUMSQUARE_RADIUS) {
sq.radius += SQUARE_RADIUS_STEP;
} else {
// Same corner coordinate quirk as seen in the first pattern.
for(int i = 0; i < SQUARE_POINTS; i++) {
unsigned char angle;
fire_static_from_corner(
angle,
sql,
sql_corners_ccw_x[i],
sql_corners_ccw_y[i],
pattern_state.speed
);
fire_static_from_corner(
angle,
sql,
sql_corners_cw_x[i],
sql_corners_cw_y[i],
pattern_state.speed
);
mdrv2_se_play(7);
}
}
square_corners_set(sql, sql_corners_ccw, sq.radius, sq.angle);
square_corners_set(sql, sql_corners_cw, sq.radius, (0x00 - sq.angle));
square_put(sql_corners_ccw);
square_put(sql_corners_cw);
Pellets.spawn_with_cloud = false;
}
if(boss_phase_frame > 320) {
square_center_set(sql); // Not redundant!
square_corners_set(sql, sql_corners_ccw, sq.radius, sq.angle);
square_corners_set(sql, sql_corners_cw, sq.radius, (0x00 - sq.angle));
square_unput(sql_corners_ccw);
square_unput(sql_corners_cw);
boss_phase_frame = 0;
meteor_activate();
}
#undef sq
}

View File

@ -8783,298 +8783,11 @@ mima_still equ <boss_entity_0>
corners_x:dword, corners_y:dword, center_x:word, center_y:word, radius:word, angle:byte, points:word
extern @pattern_aimed_then_static_pellet$qv:proc
extern @pattern_aimed_missiles_from_squa$qv:proc
extern @pattern_static_pellets_from_corn$qv:proc
main_29_TEXT ends
main_29__TEXT segment byte public 'CODE' use16
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_1ECF0 proc far
@@angle = byte ptr -23h
@@sq_center_y = word ptr -22h
@@corners_y_2 = byte ptr -20h
@@corners_x_2 = byte ptr -18h
@@corners_y_1 = byte ptr -10h
@@corners_x_1 = byte ptr -8
enter 24h, 0
push si
push di
cmp _boss_phase_frame, 50
jnz short loc_1ED01
call @mima_put_cast_both$qv
loc_1ED01:
cmp _boss_phase_frame, 100
jl loc_1EF81
cmp _boss_phase_frame, 100
jnz short loc_1ED3A
mov _pattern2_sq.S_radius, 32
mov _pattern2_sq.S_angle, 0
call @mima_select_for_rank$qmiiiii stdcall, offset _mima_pattern_state, ds, large 40h or (48h shl 16), large 50h or (58h shl 16)
push 8
call _mdrv2_se_play
add sp, 0Eh
loc_1ED3A:
mov ax, _boss_phase_frame
mov bx, 8
cwd
idiv bx
or dx, dx
jnz loc_1EF00
mov ax, mima_still.BE_cur_left
add ax, 64
mov di, ax
mov ax, mima_still.BE_cur_top
add ax, 80
mov [bp+@@sq_center_y], ax
push ss ; corners_x (segment)
lea ax, [bp+@@corners_x_1]
push ax ; corners_x (offset)
push ss ; corners_y (segment)
lea ax, [bp+@@corners_y_1]
push ax ; corners_y (offset)
push di ; center_x
push [bp+@@sq_center_y] ; center_y
push _pattern2_sq.S_radius ; radius
push word ptr _pattern2_sq.S_angle ; angle
push 4 ; points
call @regular_polygon$qnit1iiiuci
push ss ; corners_x (segment)
lea ax, [bp+@@corners_x_2]
push ax ; corners_x (offset)
push ss ; corners_y (segment)
lea ax, [bp+@@corners_y_2]
push ax ; corners_y (offset)
push di ; center_x
push [bp+@@sq_center_y] ; center_y
push _pattern2_sq.S_radius ; radius
mov al, 0
sub al, _pattern2_sq.S_angle ; angle
push ax ; angle
push 4 ; points
call @regular_polygon$qnit1iiiuci
push 4 ; point_count
push ss
lea ax, [bp+@@corners_y_1]
push ax
push ss
lea ax, [bp+@@corners_x_1]
push ax
call _graph_r_lineloop_unput
push 4 ; point_count
push ss
lea ax, [bp+@@corners_y_2]
push ax
push ss
lea ax, [bp+@@corners_x_2]
push ax
call _graph_r_lineloop_unput
add sp, 14h
mov al, _pattern2_sq.S_angle
add al, -06h
mov _pattern2_sq.S_angle, al
mov _Pellets.PELLET_spawn_with_cloud, 1
cmp _pattern2_sq.S_radius, 112
jge short loc_1EDD4
add _pattern2_sq.S_radius, 8
jmp loc_1EE95
; ---------------------------------------------------------------------------
loc_1EDD4:
xor si, si
jmp loc_1EE8E
; ---------------------------------------------------------------------------
loc_1EDD9:
mov bx, si
add bx, bx
lea ax, [bp+@@corners_y_1]
add bx, ax
mov ax, ss:[bx]
sub ax, [bp+@@sq_center_y]
push ax
mov bx, si
add bx, bx
lea ax, [bp+@@corners_x_1]
add bx, ax
mov ax, ss:[bx]
sub ax, di
push ax
call iatan2
mov [bp+@@angle], al
pushd 0 or (0 shl 16)
pushd PM_REGULAR or (0 shl 16)
push _mima_pattern_state
push word ptr [bp+@@angle]
mov bx, si
add bx, bx
lea ax, [bp+@@corners_y_1]
add bx, ax
push word ptr ss:[bx]
mov bx, si
add bx, bx
lea ax, [bp+@@corners_x_1]
add bx, ax
push word ptr ss:[bx]
push ds
push offset _Pellets
call @CPellets@add_single$qiiuci15pellet_motion_tiii
mov bx, si
add bx, bx
lea ax, [bp+@@corners_y_2]
add bx, ax
mov ax, ss:[bx]
sub ax, [bp+@@sq_center_y]
push ax
mov bx, si
add bx, bx
lea ax, [bp+@@corners_x_2]
add bx, ax
mov ax, ss:[bx]
sub ax, di
push ax
call iatan2
mov [bp+@@angle], al
pushd 0 or (0 shl 16)
pushd PM_REGULAR or (0 shl 16)
push _mima_pattern_state
push word ptr [bp+@@angle]
mov bx, si
add bx, bx
lea ax, [bp+@@corners_y_2]
add bx, ax
push word ptr ss:[bx]
mov bx, si
add bx, bx
lea ax, [bp+@@corners_x_2]
add bx, ax
push word ptr ss:[bx]
push ds
push offset _Pellets
call @CPellets@add_single$qiiuci15pellet_motion_tiii
push 7
call _mdrv2_se_play
add sp, 2Ah
inc si
loc_1EE8E:
cmp si, 4
jl loc_1EDD9
loc_1EE95:
push ss ; corners_x (segment)
lea ax, [bp+@@corners_x_1]
push ax ; corners_x (offset)
push ss ; corners_y (segment)
lea ax, [bp+@@corners_y_1]
push ax ; corners_y (offset)
push di ; center_x
push [bp+@@sq_center_y] ; center_y
push _pattern2_sq.S_radius ; radius
push word ptr _pattern2_sq.S_angle ; angle
push 4 ; points
call @regular_polygon$qnit1iiiuci
push ss ; corners_x (segment)
lea ax, [bp+@@corners_x_2]
push ax ; corners_x (offset)
push ss ; corners_y (segment)
lea ax, [bp+@@corners_y_2]
push ax ; corners_y (offset)
push di ; center_x
push [bp+@@sq_center_y] ; center_y
push _pattern2_sq.S_radius ; radius
mov al, 0
sub al, _pattern2_sq.S_angle ; angle
push ax ; angle
push 4 ; points
call @regular_polygon$qnit1iiiuci
push 4 or (7 shl 16) ; (point_count) or (col shl 16)
push ss
lea ax, [bp+@@corners_y_1]
push ax
push ss
lea ax, [bp+@@corners_x_1]
push ax
call _graph_r_lineloop_put
push 4 or (7 shl 16) ; (point_count) or (col shl 16)
push ss
lea ax, [bp+@@corners_y_2]
push ax
push ss
lea ax, [bp+@@corners_x_2]
push ax
call _graph_r_lineloop_put
add sp, 18h
mov _Pellets.PELLET_spawn_with_cloud, 0
loc_1EF00:
cmp _boss_phase_frame, 320
jle short loc_1EF81
mov ax, mima_still.BE_cur_left
add ax, 64
mov di, ax
mov ax, mima_still.BE_cur_top
add ax, 80
mov [bp+@@sq_center_y], ax
push ss ; corners_x (segment)
lea ax, [bp+@@corners_x_1]
push ax ; corners_x (offset)
push ss ; corners_y (segment)
lea ax, [bp+@@corners_y_1]
push ax ; corners_y (offset)
push di ; center_x
push [bp+@@sq_center_y] ; center_y
push _pattern2_sq.S_radius ; radius
push word ptr _pattern2_sq.S_angle ; angle
push 4 ; points
call @regular_polygon$qnit1iiiuci
push ss ; corners_x (segment)
lea ax, [bp+@@corners_x_2]
push ax ; corners_x (offset)
push ss ; corners_y (segment)
lea ax, [bp+@@corners_y_2]
push ax ; corners_y (offset)
push di ; center_x
push [bp+@@sq_center_y] ; center_y
push _pattern2_sq.S_radius ; radius
mov al, 0
sub al, _pattern2_sq.S_angle ; angle
push ax ; angle
push 4 ; points
call @regular_polygon$qnit1iiiuci
push 4 ; point_count
push ss
lea ax, [bp+@@corners_y_1]
push ax
push ss
lea ax, [bp+@@corners_x_1]
push ax
call _graph_r_lineloop_unput
push 4 ; point_count
push ss
lea ax, [bp+@@corners_y_2]
push ax
push ss
lea ax, [bp+@@corners_x_2]
push ax
call _graph_r_lineloop_unput
add sp, 14h
mov _boss_phase_frame, 0
call @meteor_activate$qv
loc_1EF81:
pop di
pop si
leave
retf
sub_1ECF0 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -10325,7 +10038,7 @@ loc_1FB5E:
loc_1FB6B:
cmp word_39E78, 2
jnz short loc_1FB78
call sub_1ECF0
call @pattern_static_pellets_from_corn$qv
jmp short loc_1FB86
; ---------------------------------------------------------------------------