[Decompilation] [th01] Sariel: Pattern 2/16

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.
This commit is contained in:
nmlgc 2021-12-29 06:15:34 +01:00
parent 97e7a2ff6d
commit 0054b10480
2 changed files with 229 additions and 618 deletions

View File

@ -9,7 +9,9 @@ extern "C" {
#include "planar.h"
#include "master.hpp"
#include "th01/common.h"
#include "th01/v_colors.hpp"
#include "th01/math/area.hpp"
#include "th01/math/dir.hpp"
#include "th01/math/overlap.hpp"
#include "th01/math/subpixel.hpp"
#include "th01/hardware/frmdelay.h"
@ -64,6 +66,7 @@ enum sariel_colors_t {
#define invincibility_frame sariel_invincibility_frame
#define initial_hp_rendered sariel_initial_hp_rendered
extern union {
int frame;
int unknown;
} pattern_state;
extern bool16 invincible;
@ -125,6 +128,25 @@ inline void sariel_grc_free(void) {
#define sloppy_unput_32x32(left, top) \
egc_copy_rect_1_to_0_16(left, top, 48, 32);
// Vortex and debris sprites (BOSS6GR1.GRC)
// ----------------------------------------
static const pixel_t VORTEX_W = 32;
static const pixel_t VORTEX_H = 32;
static const int VORTEX_COUNT = 2;
enum vortex_or_debris_cel_t {
VORTEX_CELS = 3,
C_VORTEX = 0,
C_VORTEX_last = (C_VORTEX + VORTEX_CELS - 1),
};
#define vortex_or_debris_put_8(left, top, cel) \
grc_put_8(left, top, GRC_SLOT_VORTEX_DEBRIS, cel, V_WHITE);
// ----------------------------------------
// Birds (BOSS6GR2.GRC)
// --------------------
@ -521,3 +543,193 @@ void near dress_render_both(void)
graph_accesspage_func(1); anm_dress.put_8();
graph_accesspage_func(0); anm_dress.put_8();
}
static const subpixel_t VORTEX_PELLET_SPEED = TO_SP(7);
#define vortex_pellet_left(vortex_left) \
((vortex_left) + ((VORTEX_W / 2) - (PELLET_W / 2)))
#define vortex_pellet_top(vortex_top) \
((vortex_top) + ((VORTEX_H / 2) - (PELLET_H / 2)))
inline screen_y_t vortex_pellet_bottom(screen_y_t vortex_bottom) {
return (vortex_bottom - ((VORTEX_H / 2) - (PELLET_H / 2)));
}
// Shouldn't really take [angle] as a parameter...
void pascal near vortex_fire_3_spread(
const screen_x_t left[VORTEX_COUNT],
const vram_y_t top[VORTEX_COUNT],
int i,
unsigned char angle
)
{
Pellets.add_single(
vortex_pellet_left(left[i]),
vortex_pellet_top(top[i]),
0x40,
VORTEX_PELLET_SPEED
);
angle = iatan2(
(vortex_pellet_bottom(PLAYFIELD_BOTTOM) - top[i]),
(left[1 - i] - left[i])
);
Pellets.add_single(
vortex_pellet_left(left[i]),
vortex_pellet_top(top[i]),
angle,
VORTEX_PELLET_SPEED
);
Pellets.add_single(
vortex_pellet_left(left[i]),
vortex_pellet_top(top[i]),
(0x80 - angle),
VORTEX_PELLET_SPEED
);
}
void near pattern_vortices(void)
{
#define wand_raise_animation_done pattern1_wand_raise_animation_done
#define cur_left pattern1_cur_left
#define cur_top pattern1_cur_top
#define prev_left pattern1_prev_left
#define prev_top pattern1_prev_top
#define dir_first pattern1_dir_first
#define dir_second pattern1_dir_second
extern bool16 wand_raise_animation_done;
extern screen_x_t cur_left[VORTEX_COUNT];
extern vram_y_t cur_top[VORTEX_COUNT];
extern screen_x_t prev_left[VORTEX_COUNT];
extern vram_y_t prev_top[VORTEX_COUNT];
extern bool16 dir_first; // x_direction_t
extern bool16 dir_second; // x_direction_t
#define vortex_unput_and_put_8(i) { \
sloppy_unput_32x32(prev_left[i], prev_top[i]); \
vortex_or_debris_put_8( \
cur_left[i], \
cur_top[i], \
(C_VORTEX + (boss_phase_frame % VORTEX_CELS)) \
); \
}
#define vortex_fire_down(i) { \
Pellets.add_group( \
vortex_pellet_left(cur_left[i]), \
vortex_pellet_top(cur_top[i]), \
PG_1, \
VORTEX_PELLET_SPEED \
); \
}
#define vortex_unput_put_3_spread(i) { \
vortex_unput_and_put_8(i); \
if((boss_phase_frame % 4) == 0) { \
vortex_fire_3_spread(cur_left, cur_top, i, angle); \
} \
}
unsigned char angle;
if(wand_raise_animation_done == false) {
wand_raise_animation_done = wand_render_raise_both();
}
if(boss_phase_frame < 50) {
return;
} else if(boss_phase_frame == 50) {
select_for_rank(pattern_state.frame, 140, 145, 150, 155);
}
if(boss_phase_frame < 100) {
for(int i = 0; i < VORTEX_COUNT; i++) {
cur_left[i] = (i * (PLAYFIELD_RIGHT - VORTEX_W));
cur_top[i] = (PLAYFIELD_TOP + playfield_fraction_y(17 / 42.0f));
vortex_unput_and_put_8(i);
if((boss_phase_frame % 4) == 0) {
vortex_fire_down(i);
}
prev_left[i] = cur_left[i];
prev_top[i] = cur_top[i];
}
} else if(boss_phase_frame < pattern_state.frame) {
for(int i = 0; i < VORTEX_COUNT; i++) {
cur_left[i] += (i == 0) ? 5 : -5;
cur_top[i] -= 2;
vortex_unput_and_put_8(i);
if((boss_phase_frame % 4) == 0) {
vortex_fire_down(i);
angle = iatan2(
vortex_pellet_top(PLAYFIELD_BOTTOM - cur_top[i]),
vortex_pellet_left(cur_left[i] +
(i * ((PLAYFIELD_W / 8) * 2)) - (PLAYFIELD_W / 8) -
cur_left[i])
);
Pellets.add_single(
vortex_pellet_left(cur_left[i]),
vortex_pellet_top(cur_top[i]),
angle,
VORTEX_PELLET_SPEED
);
}
prev_left[i] = cur_left[i];
prev_top[i] = cur_top[i];
}
} else if(boss_phase_frame < 200) {
for(int i = 0; i < VORTEX_COUNT; i++) {
vortex_unput_put_3_spread(i);
}
} else if(boss_phase_frame < 240) {
if(boss_phase_frame == 200) {
static_cast<int>(dir_first) = (rand() % 2);
if(dir_first == X_LEFT) {
wand_lower_both();
}
}
for(int i = 0; i < VORTEX_COUNT; i++) {
cur_left[i] += (2 - (dir_first * 4));
vortex_unput_put_3_spread(i);
prev_left[i] = cur_left[i];
}
} else if(boss_phase_frame < 320) {
if(boss_phase_frame == 240) {
static_cast<int>(dir_second) = (rand() % 2);
if((dir_second == X_RIGHT) && (dir_second == dir_first)) {
wand_lower_both();
} else if((dir_second == X_LEFT) && (dir_second == dir_first)) {
wand_raise_animation_done = false;
}
}
for(int i = 0; i < VORTEX_COUNT; i++) {
if(dir_second != dir_first) {
cur_left[i] -= (2 - (dir_second * 4));
} else {
cur_left[i] -= (4 - (dir_second * 8));
}
vortex_unput_put_3_spread(i);
prev_left[i] = cur_left[i];
}
} else if(boss_phase_frame > 300) {
for(int i = 0; i < VORTEX_COUNT; i++) {
sloppy_unput_32x32(cur_left[i], cur_top[i]);
}
wand_lower_both();
boss_phase_frame = 0;
wand_raise_animation_done = false;
}
#undef vortex_unput_put_3_spread
#undef vortex_fire_down
#undef vortex_unput_and_put_8
#undef dir_second
#undef dir_first
#undef prev_top
#undef prev_left
#undef cur_top
#undef cur_left
#undef wand_raise_animation_done
}

View File

@ -22438,6 +22438,7 @@ main_36_TEXT segment byte public 'CODE' use16
restart:word
@wand_lower_both$qv procdesc near
@dress_render_both$qv procdesc near
@pattern_vortices$qv procdesc near
main_36_TEXT ends
main_36__TEXT segment byte public 'CODE' use16
@ -22449,616 +22450,6 @@ include th01/main/boss/anim.inc
sariel_shield equ <boss_entity_0>
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_29015 proc near
@@angle = byte ptr 4
arg_2 = word ptr 6
arg_4 = dword ptr 8
arg_8 = dword ptr 0Ch
push bp
mov bp, sp
push si
mov si, [bp+arg_2]
pushd 0 or (0 shl 16)
pushd PM_NORMAL or (0 shl 16)
push (7 shl 4)
push 40h
mov ax, si
add ax, ax
les bx, [bp+arg_4]
add bx, ax
mov ax, es:[bx]
add ax, 12
push ax
mov ax, si
add ax, ax
les bx, [bp+arg_8]
add bx, ax
mov ax, es:[bx]
add ax, 12
push ax
push ds
push offset _Pellets
call @CPellets@add_single$qiiuci15pellet_motion_tiii
mov ax, si
add ax, ax
les bx, [bp+arg_4]
add bx, ax
mov ax, 388
sub ax, es:[bx]
push ax
mov ax, 1
sub ax, si
add ax, ax
les bx, [bp+arg_8]
add bx, ax
mov ax, es:[bx]
mov dx, si
add dx, dx
mov bx, word ptr [bp+arg_8]
add bx, dx
sub ax, es:[bx]
push ax
call iatan2
mov [bp+@@angle], al
pushd 0 or (0 shl 16)
pushd PM_NORMAL or (0 shl 16)
push (7 shl 4)
push word ptr [bp+@@angle]
mov ax, si
add ax, ax
les bx, [bp+arg_4]
add bx, ax
mov ax, es:[bx]
add ax, 12
push ax
mov ax, si
add ax, ax
les bx, [bp+arg_8]
add bx, ax
mov ax, es:[bx]
add ax, 12
push ax
push ds
push offset _Pellets
call @CPellets@add_single$qiiuci15pellet_motion_tiii
add sp, 28h
pushd 0 or (0 shl 16)
pushd PM_NORMAL or (0 shl 16)
push (7 shl 4)
mov al, 80h
sub al, [bp+@@angle]
push ax
mov ax, si
add ax, ax
les bx, [bp+arg_4]
add bx, ax
mov ax, es:[bx]
add ax, 12
push ax
mov ax, si
add ax, ax
les bx, [bp+arg_8]
add bx, ax
mov ax, es:[bx]
add ax, 12
push ax
push ds
push offset _Pellets
call @CPellets@add_single$qiiuci15pellet_motion_tiii
add sp, 14h
pop si
pop bp
retn 0Ch
sub_29015 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_290F9 proc near
@@angle = byte ptr -1
enter 2, 0
push si
cmp word_35DDF, 0
jnz short loc_2910D
call @wand_render_raise_both$qi pascal, 0
mov word_35DDF, ax
loc_2910D:
cmp _boss_phase_frame, 50
jl loc_29589
cmp _boss_phase_frame, 50
jnz short loc_29134
call @sariel_select_for_rank$qmiiiii c, offset _sariel_pattern_state, ds, large 140 or (145 shl 16), large 150 or (155 shl 16)
loc_29134:
cmp _boss_phase_frame, 100
jge loc_291FD
xor si, si
jmp loc_291F3
; ---------------------------------------------------------------------------
loc_29142:
mov ax, si
imul ax, 260h
mov bx, si
add bx, bx
mov [bx+61FCh], ax
mov bx, si
add bx, bx
mov word ptr [bx+6200h], 0C8h ; '?'
push (32 shl 16) or 48
mov bx, si
add bx, bx
push word ptr [bx+6208h]
mov bx, si
add bx, bx
push word ptr [bx+6204h]
call _egc_copy_rect_1_to_0_16
push 7 ; col
mov ax, _boss_phase_frame
mov bx, 3
cwd
idiv bx
push dx ; image
push GRC_SLOT_BOSS_1 ; slot
mov bx, si
add bx, bx
push word ptr [bx+6200h] ; top
mov bx, si
add bx, bx
push word ptr [bx+61FCh] ; left
call _grc_put_8
add sp, 12h
mov ax, _boss_phase_frame
mov bx, 4
cwd
idiv bx
or dx, dx
jnz short loc_291D2
push PG_1 or ((7 shl 4) shl 16)
mov bx, si
add bx, bx
mov ax, [bx+6200h]
add ax, 12
push ax
mov bx, si
add bx, bx
mov ax, [bx+61FCh]
add ax, 12
push ax
push ds
push offset _Pellets
call @CPellets@add_group$qii14pellet_group_ti
add sp, 0Ch
loc_291D2:
mov bx, si
add bx, bx
mov ax, [bx+61FCh]
mov bx, si
add bx, bx
mov [bx+6204h], ax
mov bx, si
add bx, bx
mov ax, [bx+6200h]
mov bx, si
add bx, bx
mov [bx+6208h], ax
inc si
loc_291F3:
cmp si, 2
jl loc_29142
jmp loc_29589
; ---------------------------------------------------------------------------
loc_291FD:
mov ax, _boss_phase_frame
cmp ax, _sariel_pattern_state
jge loc_29331
xor si, si
jmp loc_29327
; ---------------------------------------------------------------------------
loc_2920D:
or si, si
jnz short loc_29216
mov ax, 5
jmp short loc_29219
; ---------------------------------------------------------------------------
loc_29216:
mov ax, 0FFFBh
loc_29219:
mov bx, si
add bx, bx
add [bx+61FCh], ax
mov bx, si
add bx, bx
sub word ptr [bx+6200h], 2
push (32 shl 16) or 48
mov bx, si
add bx, bx
push word ptr [bx+6208h]
mov bx, si
add bx, bx
push word ptr [bx+6204h]
call _egc_copy_rect_1_to_0_16
push 7 ; col
mov ax, _boss_phase_frame
mov bx, 3
cwd
idiv bx
push dx ; image
push GRC_SLOT_BOSS_1 ; slot
mov bx, si
add bx, bx
push word ptr [bx+6200h] ; top
mov bx, si
add bx, bx
push word ptr [bx+61FCh] ; left
call _grc_put_8
add sp, 12h
mov ax, _boss_phase_frame
mov bx, 4
cwd
idiv bx
or dx, dx
jnz loc_29306
push PG_1 or ((7 shl 4) shl 16)
mov bx, si
add bx, bx
mov ax, [bx+6200h]
add ax, 12
push ax
mov bx, si
add bx, bx
mov ax, [bx+61FCh]
add ax, 12
push ax
push ds
push offset _Pellets
call @CPellets@add_group$qii14pellet_group_ti
mov bx, si
add bx, bx
mov ax, PLAYFIELD_BOTTOM
sub ax, [bx+6200h]
add ax, 12
push ax
mov bx, si
add bx, bx
mov ax, [bx+61FCh]
mov dx, si
imul dx, 160
add ax, dx
add ax, -80
mov bx, si
add bx, bx
sub ax, [bx+61FCh]
add ax, 12
push ax
call iatan2
mov [bp+@@angle], al
pushd 0 or (0 shl 16)
pushd PM_NORMAL or (0 shl 16)
push (7 shl 4)
push word ptr [bp+@@angle]
mov bx, si
add bx, bx
mov ax, [bx+6200h]
add ax, 12
push ax
mov bx, si
add bx, bx
mov ax, [bx+61FCh]
add ax, 12
push ax
push ds
push offset _Pellets
call @CPellets@add_single$qiiuci15pellet_motion_tiii
add sp, 20h
loc_29306:
mov bx, si
add bx, bx
mov ax, [bx+61FCh]
mov bx, si
add bx, bx
mov [bx+6204h], ax
mov bx, si
add bx, bx
mov ax, [bx+6200h]
mov bx, si
add bx, bx
mov [bx+6208h], ax
inc si
loc_29327:
cmp si, 2
jl loc_2920D
jmp loc_29589
; ---------------------------------------------------------------------------
loc_29331:
cmp _boss_phase_frame, 200
jge short loc_293A3
xor si, si
jmp short loc_2939B
; ---------------------------------------------------------------------------
loc_2933D:
push (32 shl 16) or 48
mov bx, si
add bx, bx
push word ptr [bx+6208h]
mov bx, si
add bx, bx
push word ptr [bx+6204h]
call _egc_copy_rect_1_to_0_16
push 7 ; col
mov ax, _boss_phase_frame
mov bx, 3
cwd
idiv bx
push dx ; image
push GRC_SLOT_BOSS_1 ; slot
mov bx, si
add bx, bx
push word ptr [bx+6200h] ; top
mov bx, si
add bx, bx
push word ptr [bx+61FCh] ; left
call _grc_put_8
add sp, 12h
mov ax, _boss_phase_frame
mov bx, 4
cwd
idiv bx
or dx, dx
jnz short loc_2939A
push ds
push offset unk_3AB9C
push ds
push offset unk_3ABA0
push si
push word ptr [bp+@@angle]
call sub_29015
loc_2939A:
inc si
loc_2939B:
cmp si, 2
jl short loc_2933D
jmp loc_29589
; ---------------------------------------------------------------------------
loc_293A3:
cmp _boss_phase_frame, 240
jge loc_2945E
cmp _boss_phase_frame, 200
jnz short loc_293CE
call IRand
mov bx, 2
cwd
idiv bx
mov word_3ABAC, dx
cmp word_3ABAC, 1
jnz short loc_293CE
call @wand_lower_both$qv
loc_293CE:
xor si, si
jmp loc_29454
; ---------------------------------------------------------------------------
loc_293D3:
mov ax, word_3ABAC
shl ax, 2
mov dx, 2
sub dx, ax
mov bx, si
add bx, bx
add [bx+61FCh], dx
push (32 shl 16) or 48
mov bx, si
add bx, bx
push word ptr [bx+6208h]
mov bx, si
add bx, bx
push word ptr [bx+6204h]
call _egc_copy_rect_1_to_0_16
push 7 ; col
mov ax, _boss_phase_frame
mov bx, 3
cwd
idiv bx
push dx ; image
push GRC_SLOT_BOSS_1 ; slot
mov bx, si
add bx, bx
push word ptr [bx+6200h] ; top
mov bx, si
add bx, bx
push word ptr [bx+61FCh] ; left
call _grc_put_8
add sp, 12h
mov ax, _boss_phase_frame
mov bx, 4
cwd
idiv bx
or dx, dx
jnz short loc_29443
push ds
push offset unk_3AB9C
push ds
push offset unk_3ABA0
push si
push word ptr [bp+@@angle]
call sub_29015
loc_29443:
mov bx, si
add bx, bx
mov ax, [bx+61FCh]
mov bx, si
add bx, bx
mov [bx+6204h], ax
inc si
loc_29454:
cmp si, 2
jl loc_293D3
jmp loc_29589
; ---------------------------------------------------------------------------
loc_2945E:
cmp _boss_phase_frame, 320
jge loc_2954A
cmp _boss_phase_frame, 240
jnz short loc_294AA
call IRand
mov bx, 2
cwd
idiv bx
mov word_3ABAE, dx
cmp word_3ABAE, 0
jnz short loc_29494
mov ax, word_3ABAE
cmp ax, word_3ABAC
jnz short loc_29494
call @wand_lower_both$qv
jmp short loc_294AA
; ---------------------------------------------------------------------------
loc_29494:
cmp word_3ABAE, 1
jnz short loc_294AA
mov ax, word_3ABAE
cmp ax, word_3ABAC
jnz short loc_294AA
mov word_35DDF, 0
loc_294AA:
xor si, si
jmp loc_29541
; ---------------------------------------------------------------------------
loc_294AF:
mov ax, word_3ABAE
cmp ax, word_3ABAC
jz short loc_294C0
shl ax, 2
mov dx, 2
jmp short loc_294C9
; ---------------------------------------------------------------------------
loc_294C0:
mov ax, word_3ABAE
shl ax, 3
mov dx, 4
loc_294C9:
sub dx, ax
mov bx, si
add bx, bx
sub [bx+61FCh], dx
push (32 shl 16) or 48
mov bx, si
add bx, bx
push word ptr [bx+6208h]
mov bx, si
add bx, bx
push word ptr [bx+6204h]
call _egc_copy_rect_1_to_0_16
push 7 ; col
mov ax, _boss_phase_frame
mov bx, 3
cwd
idiv bx
push dx ; image
push GRC_SLOT_BOSS_1 ; slot
mov bx, si
add bx, bx
push word ptr [bx+6200h] ; top
mov bx, si
add bx, bx
push word ptr [bx+61FCh] ; left
call _grc_put_8
add sp, 12h
mov ax, _boss_phase_frame
mov bx, 4
cwd
idiv bx
or dx, dx
jnz short loc_29530
push ds
push offset unk_3AB9C
push ds
push offset unk_3ABA0
push si
push word ptr [bp+@@angle]
call sub_29015
loc_29530:
mov bx, si
add bx, bx
mov ax, [bx+61FCh]
mov bx, si
add bx, bx
mov [bx+6204h], ax
inc si
loc_29541:
cmp si, 2
jl loc_294AF
jmp short loc_29589
; ---------------------------------------------------------------------------
loc_2954A:
cmp _boss_phase_frame, 300
jle short loc_29589
xor si, si
jmp short loc_29575
; ---------------------------------------------------------------------------
loc_29556:
push (32 shl 16) or 48
mov bx, si
add bx, bx
push word ptr [bx+6200h]
mov bx, si
add bx, bx
push word ptr [bx+61FCh]
call _egc_copy_rect_1_to_0_16
add sp, 8
inc si
loc_29575:
cmp si, 2
jl short loc_29556
call @wand_lower_both$qv
mov _boss_phase_frame, 0
mov word_35DDF, 0
loc_29589:
pop si
leave
retn
sub_290F9 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -27651,7 +27042,7 @@ loc_2C3BE:
loc_2C40D:
cmp word_35E95, 1
jnz short loc_2C419
call sub_290F9
call @pattern_vortices$qv
jmp short loc_2C423
; ---------------------------------------------------------------------------
@ -29186,6 +28577,7 @@ _spawnray_target_prev_x dw 999
_spawnray_target_prev_y dw 999
BIRD_COUNT = 30
VORTEX_COUNT = 2
public _birds_alive
_birds_alive db BIRD_COUNT dup(0)
@ -29193,7 +28585,9 @@ _birds_alive db BIRD_COUNT dup(0)
public _wand_raise_frames
_wand_raise_frames dw 0
word_35DDF dw 0
public _pattern1_wand_raise_animation_do
_pattern1_wand_raise_animation_do dw 0
byte_35DE1 db 0
byte_35DE2 db 0
word_35DE3 dw 0
@ -29636,12 +29030,17 @@ CBirds ends
public _birds
_birds CBirds <?>
unk_3AB9C db ? ;
db 3 dup(?)
unk_3ABA0 db ? ;
db 11 dup(?)
word_3ABAC dw ?
word_3ABAE dw ?
public _pattern1_cur_left, _pattern1_cur_top
public _pattern1_prev_left, _pattern1_prev_top
public _pattern1_dir_first, _pattern1_dir_second
_pattern1_cur_left dw VORTEX_COUNT dup(?)
_pattern1_cur_top dw VORTEX_COUNT dup(?)
_pattern1_prev_left dw VORTEX_COUNT dup(?)
_pattern1_prev_top dw VORTEX_COUNT dup(?)
_pattern1_dir_first dw ?
_pattern1_dir_second dw ?
db 160 dup(?)
subpixel_point_3AC50 Point <?>
word_3AC54 dw ?