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

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.
This commit is contained in:
nmlgc 2022-01-20 13:38:21 +01:00
parent 77858c1337
commit 091f19f69b
10 changed files with 255 additions and 671 deletions

View File

@ -23,6 +23,7 @@ BMP2ARR = bin\\Pipeline\\bmp2arr.exe
!bmp2arr = | $(BMP2ARR) |> $(BMP2ARR) -q -i %f -o %o |> %o
: th01/sprites/leaf.bmp |> !bmp2arr -sym _sLEAF -of asm -sw 8 -sh 8 |> th01/sprites/leaf.asp
: th01/sprites/ileave_m.bmp |> !bmp2arr -sym _sINTERLEAVE_MASKS -of asm -sw 8 -sh 8 |> th01/sprites/ileave_m.asp
# ZUN bug: Supposed to be 8 preshifted sprites, with a height of 1 and a width
@ -57,6 +58,7 @@ BMP2ARR = bin\\Pipeline\\bmp2arr.exe
: th01_op.asm |> !as |> bin\\th01\\op.obj
: th01_reiiden.asm | \
th01/sprites/leaf.asp \
th01/sprites/ileave_m.asp \
th01/sprites/laser_s.asp \
th01/sprites/pellet_c.asp \

View File

@ -3,6 +3,7 @@
: if the Tupfile changes.
@echo on
bcc32 -w-8004 -w-8012 -O2 -v- -x- -nbin/Pipeline/ Pipeline/bmp2arr.c Pipeline/bmp2arrl.c
bin\\Pipeline\\bmp2arr.exe -q -i th01/sprites/leaf.bmp -o th01/sprites/leaf.asp -sym _sLEAF -of asm -sw 8 -sh 8
bin\\Pipeline\\bmp2arr.exe -q -i th01/sprites/ileave_m.bmp -o th01/sprites/ileave_m.asp -sym _sINTERLEAVE_MASKS -of asm -sw 8 -sh 8
bin\\Pipeline\\bmp2arr.exe -q -i th01/sprites/laser_s.bmp -o th01/sprites/laser_s.asp -sym _sSHOOTOUT_LASER -of asm -sw 16 -sh 8
bin\\Pipeline\\bmp2arr.exe -q -i th01/sprites/pellet.bmp -o th01/sprites/pellet.csp -sym sPELLET -of c -sw 8 -sh 8 -pshf inner

View File

@ -3,12 +3,12 @@
void grcg_put_8x8_mono(
vram_offset_t vram_offset_topleft,
char first_bit,
const dot_rect_t(8, 8)& sprite,
const dots8_t sprite[8],
int col
)
{
grcg_setcolor_rmw(col);
for(pixel_t y = 0; y < sprite.h(); y++) {
for(pixel_t y = 0; y < 8; y++) {
dots16_t d = (
(sprite[y] >> first_bit) + (sprite[y] << (16 - first_bit))
);

View File

@ -3,6 +3,6 @@
void grcg_put_8x8_mono(
vram_offset_t vram_offset_topleft,
char first_bit,
const dot_rect_t(8, 8)& sprite,
const dots8_t sprite[8],
int col
);

View File

@ -20,6 +20,7 @@ extern "C" {
#include "th01/math/vector.hpp"
#include "th01/hardware/frmdelay.h"
#include "th01/hardware/graph.h"
#include "th01/hardware/grcg8x8m.hpp"
#include "th01/hardware/egc.h"
#include "th01/hardware/palette.h"
#include "th01/hardware/ptrans.hpp"
@ -32,6 +33,7 @@ extern "C" {
#include "th01/formats/grp.h"
#include "th01/formats/ptn.hpp"
#include "th01/formats/stagedat.hpp"
#include "th01/sprites/leaf.hpp"
#include "th01/sprites/pellet.h"
#include "th01/sprites/shape8x8.hpp"
#include "th01/main/spawnray.hpp"
@ -232,6 +234,16 @@ static const pixel_t SPAWNCROSS_W = 32;
static const pixel_t SPAWNCROSS_H = 32;
static const int SPAWNCROSS_CELS = 2;
// --------------------------
// Leaf splash animation (BOSS6GR4.GRC)
// ------------------------------------
// Never seen in the original game, due to a ZUN bug in the only pattern that
// uses it.
static const pixel_t LEAFSPLASH_W = 32;
static const pixel_t LEAFSPLASH_H = 32;
static const int LEAFSPLASH_CELS = 3;
// ------------------------------------
/// -------------
// .PTN
@ -2513,3 +2525,207 @@ void pascal near pattern_curved_spray_leftright_twice(int &frame)
#undef spray
}
// Subpixels with one decimal digit of fractional resolution?! Sure, if you
// absolutely want those precise multiples of 0.1 in your movement code...
typedef int decimal_subpixel_t;
struct DecimalSubpixel {
decimal_subpixel_t v;
pixel_t to_pixel() const {
return static_cast<pixel_t>(v / 10);
}
};
inline decimal_subpixel_t to_dsp(float pixel_v) {
return static_cast<decimal_subpixel_t>(pixel_v * 10);
}
void pascal near pattern_swaying_leaves(int &frame, int spawn_interval_or_reset)
{
enum {
LEAF_COUNT = 30,
};
enum leaf_flag_t {
LF_FREE = 0,
LF_SPARK = 1,
LF_SPLASH = 2,
// Separate state because it assigns the velocity for the next one.
LF_SPLASH_DONE = (LF_SPLASH + LEAFSPLASH_CELS),
LF_LEAF,
_leaf_flag_t_FORCE_INT16 = 0x7FFF,
};
#define flag pattern15_flag
#define left pattern15_left
#define top pattern15_top
#define velocity_x pattern15_velocity_x
#define velocity_y pattern15_velocity_y
extern leaf_flag_t flag[LEAF_COUNT];
extern DecimalSubpixel left[LEAF_COUNT];
extern DecimalSubpixel top[LEAF_COUNT];
extern DecimalSubpixel velocity_x[LEAF_COUNT];
extern DecimalSubpixel velocity_y[LEAF_COUNT];
#define leaf_on_screen(i) \
overlap_xy_rltb_lt_ge( \
left[i].v, \
top[i].v, \
to_dsp(0.0f), \
to_dsp(0.0f), \
to_dsp(RES_X - LEAF_W), \
to_dsp(RES_Y - LEAF_H) \
)
#define leaf_put(tmp_vo, tmp_first_bit, i, sprite) { \
if(leaf_on_screen(i)) { \
vo = vram_offset_divmul(left[i].to_pixel(), top[i].to_pixel()); \
tmp_first_bit = (left[i].to_pixel() % BYTE_DOTS); \
grcg_put_8x8_mono(vo, tmp_first_bit, sprite, V_WHITE); \
} \
}
const dot_rect_t(8, 8) sSPARK = sLEAF[0];
const dot_rect_t(8, 8) sLEAF_LEFT = sLEAF[1];
const dot_rect_t(8, 8) sLEAF_RIGHT = sLEAF[2];
int i;
vram_offset_t vo;
int first_bit;
if(spawn_interval_or_reset == 999) {
for(i = 0; i < LEAF_COUNT; i++) {
flag[i] = LF_FREE;
}
return;
}
if((frame % spawn_interval_or_reset) == 0) {
for(i = 0; i < LEAF_COUNT; i++) {
if(flag[i] != LF_FREE) {
continue;
}
left[i].v = (
to_dsp(PLAYFIELD_LEFT) + (rand() % to_dsp(PLAYFIELD_W))
);
top[i].v = (
to_dsp(FACE_CENTER_Y) +
(rand() % to_dsp((PLAYFIELD_H * 25) / 84))
);
vector2_between(
left[i].to_pixel(),
top[i].to_pixel(),
(PLAYFIELD_LEFT + playfield_rand_x()),
PLAYFIELD_TOP,
velocity_x[i].v,
velocity_y[i].v,
to_dsp(4.0f)
);
flag[i] = LF_SPARK;
break;
}
}
if((frame % 2) != 0) {
return;
}
// Unblit and update
for(i = 0; i < LEAF_COUNT; i++) {
if(flag[i] == LF_FREE) {
continue;
}
if(flag[i] == LF_SPARK) {
if(leaf_on_screen(i)) {
egc_copy_rect_1_to_0_16_word_w(
left[i].to_pixel(), top[i].to_pixel(), LEAF_W, LEAF_H
);
}
left[i].v += velocity_x[i].v;
top[i].v += velocity_y[i].v;
if(top[i].v < to_dsp(PLAYFIELD_TOP)) {
flag[i] = LF_SPLASH;
}
} else if(flag[i] <= LF_SPLASH_DONE) {
if(leaf_on_screen(i)) {
sloppy_unput_32x32(left[i].to_pixel(), top[i].to_pixel());
}
if(flag[i] == LF_SPLASH_DONE) {
flag[i] = LF_LEAF;
velocity_y[i].v = (to_dsp(0.3f) + (rand() % to_dsp(0.2f)));
velocity_x[i].v = to_dsp(0.2f);
}
} else if(flag[i] == LF_LEAF) {
if(leaf_on_screen(i)) {
egc_copy_rect_1_to_0_16_word_w(
left[i].to_pixel(), top[i].to_pixel(), LEAF_W, LEAF_H
);
}
left[i].v += velocity_x[i].v;
top[i].v += velocity_y[i].v;
velocity_y[i].v--;
if(velocity_y[i].v < to_dsp(-0.1f)) {
velocity_y[i].v = (to_dsp(3.0f) + (rand() % to_dsp(2.0f)));
velocity_x[i].v = (velocity_x[i].v < to_dsp(0.0f))
? to_dsp(+2.0f)
: to_dsp(-2.0f);
}
if(top[i].to_pixel() > PLAYFIELD_BOTTOM) {
flag[i] = LF_FREE;
}
}
}
// Render and detect player collisions
for(i = 0; i < LEAF_COUNT; i++) {
if(flag[i] == LF_FREE) {
continue;
}
if(flag[i] == LF_SPARK) {
leaf_put(vo, first_bit, i, sSPARK.row);
} else if(flag[i] <= LF_SPLASH_DONE) {
if(leaf_on_screen(i)) {
// ZUN bug: Another missing conversion to screen pixels,
// resulting in the entire leaf splash animation never being
// actually rendered, and becoming effectively unused.
grc_put_8(
left[i].v, // should be pixels
top[i].v, // should be pixels
GRC_SLOT_LEAFSPLASH,
(flag[i] - LF_SPLASH),
V_WHITE
);
}
if((frame % 4) == 0) {
static_cast<int>(flag[i])++;
}
} else if(flag[i] == LF_LEAF) {
leaf_put(vo, first_bit, i, ((velocity_x[i].v < to_dsp(0.0f))
? sLEAF_LEFT.row
: sLEAF_RIGHT.row
));
if(
(top[i].v > to_dsp(player_top)) &&
(top[i].v < to_dsp(player_bottom() - LEAF_H)) &&
(left[i].to_pixel() > player_left) &&
(left[i].to_pixel() < (player_left + PLAYER_W - LEAF_W)) &&
!player_invincible
) {
done = true;
}
}
}
#undef leaf_put
#undef leaf_on_screen
#undef velocity_y
#undef velocity_x
#undef top
#undef left
#undef flag
}

View File

@ -9,7 +9,7 @@
if((left < 0) || (left >= RES_X) || (top < 0) || (top >= RES_Y)) { \
return; \
} \
grcg_put_8x8_mono(vram_offset_topleft, first_bit, sprite, col);
grcg_put_8x8_mono(vram_offset_topleft, first_bit, sprite.row, col);
void shape8x8_diamond_put(screen_x_t left, vram_y_t top, int col)
{

View File

@ -41,6 +41,13 @@
((y1) >= (top2)) \
)
#define overlap_xy_rltb_lt_ge(x1, y1, left2, top2, right2, bottom2) ( \
((x1) < (right2)) && \
((x1) >= (left2)) && \
((y1) >= (top2)) && \
((y1) < (bottom2)) \
)
#define overlap_xy_xywh_le_ge(x1, y1, x2, y2, w2, h2) \
overlap_xy_lrtb_le_ge(x1, y1, x2, y2, (x2 + w2), (y2 + h2))

BIN
th01/sprites/leaf.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 B

4
th01/sprites/leaf.hpp Normal file
View File

@ -0,0 +1,4 @@
#define LEAF_W 8
#define LEAF_H 8
extern const dot_rect_t(LEAF_W, LEAF_H) sLEAF[3];

View File

@ -5158,7 +5158,6 @@ main_22_TEXT ends
main_23_TEXT segment byte public 'CODE' use16
extern _grc_load:proc
extern _grc_put_8:proc
extern _grcg_put_8x8_mono:proc
extern @shape_ellipse_arc_put$qiiiiiucucuc:proc
extern @shape_ellipse_arc_sloppy_unput$qiiiiucucuc:proc
extern _graph_r_lineloop_put:proc
@ -22456,6 +22455,8 @@ main_36_TEXT segment byte public 'CODE' use16
frame_seg:word, frame_off:word
@PATTERN_CURVED_SPRAY_LEFTRIGHT_T$QMI procdesc pascal near \
frame_seg:word, frame_off:word
@PATTERN_SWAYING_LEAVES$QMII procdesc pascal near \
frame_seg:word, frame_off:word, spawn_interval_or_reset:word
main_36_TEXT ends
main_36__TEXT segment byte public 'CODE' use16
@ -22467,619 +22468,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_2BB46 proc near
@@first_bit = word ptr -1Ah
var_18 = byte ptr -18h
var_10 = byte ptr -10h
var_8 = byte ptr -8
arg_0 = word ptr 4
arg_2 = dword ptr 6
enter 1Ah, 0
push si
push di
lea ax, [bp+var_8]
push ss
push ax
push ds
push offset unk_35E7D
mov cx, 8
call SCOPY@
lea ax, [bp+var_10]
push ss
push ax
push ds
push offset unk_35E85
mov cx, 8
call SCOPY@
lea ax, [bp+var_18]
push ss
push ax
push ds
push offset unk_35E8D
mov cx, 8
call SCOPY@
cmp [bp+arg_0], 3E7h
jnz short loc_2BB9D
xor si, si
jmp short loc_2BB95
; ---------------------------------------------------------------------------
loc_2BB8A:
mov bx, si
add bx, bx
mov word ptr [bx+14A1h], 0
inc si
loc_2BB95:
cmp si, 1Eh
jl short loc_2BB8A
jmp loc_2C0C4
; ---------------------------------------------------------------------------
loc_2BB9D:
les bx, [bp+arg_2]
mov ax, es:[bx]
cwd
idiv [bp+arg_0]
or dx, dx
jnz loc_2BC43
xor si, si
jmp loc_2BC3C
; ---------------------------------------------------------------------------
loc_2BBB2:
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 0
jnz short loc_2BC3B
call IRand
mov bx, 1900h
cwd
idiv bx
mov bx, si
add bx, bx
mov [bx+69A1h], dx
call IRand
mov bx, 3E8h
cwd
idiv bx
add dx, 4B0h
mov bx, si
add bx, bx
mov word_3B37D[bx], dx
push 28h ; '('
push ds
mov ax, si
add ax, ax
add ax, offset word_3B3F5
push ax
push ds
mov ax, si
add ax, ax
add ax, offset word_3B3B9
push ax
push 40h
call IRand
mov bx, 280h
cwd
idiv bx
push dx
mov bx, si
add bx, bx
mov ax, word_3B37D[bx]
mov bx, 0Ah
cwd
idiv bx
push ax
mov bx, si
add bx, bx
mov ax, word_3B341[bx]
mov bx, 0Ah
cwd
idiv bx
push ax
call _vector2_between
add sp, 12h
mov bx, si
add bx, bx
mov word ptr [bx+14A1h], 1
jmp short loc_2BC43
; ---------------------------------------------------------------------------
loc_2BC3B:
inc si
loc_2BC3C:
cmp si, 1Eh
jl loc_2BBB2
loc_2BC43:
les bx, [bp+arg_2]
mov ax, es:[bx]
mov bx, 2
cwd
idiv bx
or dx, dx
jnz loc_2C0C4
xor si, si
jmp loc_2BE93
; ---------------------------------------------------------------------------
loc_2BC5A:
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 0
jz loc_2BE92
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 1
jnz loc_2BD09
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 18B0h
jge short loc_2BCCE
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 0
jl short loc_2BCCE
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0
jl short loc_2BCCE
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0F50h
jge short loc_2BCCE
push (8 shl 16) or 16
mov bx, si
add bx, bx
mov ax, [bx+69DDh]
mov bx, 0Ah
cwd
idiv bx
push ax
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
push ax
call _egc_copy_rect_1_to_0_16
add sp, 8
loc_2BCCE:
mov bx, si
add bx, bx
mov ax, [bx+6A19h]
mov bx, si
add bx, bx
add [bx+69A1h], ax
mov bx, si
add bx, bx
mov ax, [bx+6A55h]
mov bx, si
add bx, bx
add [bx+69DDh], ax
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 280h
jge loc_2BE92
mov bx, si
add bx, bx
mov word ptr [bx+14A1h], 2
jmp loc_2BE92
; ---------------------------------------------------------------------------
loc_2BD09:
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 5
jg loc_2BDAA
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 18B0h
jge short loc_2BD70
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 0
jl short loc_2BD70
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0
jl short loc_2BD70
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0F50h
jge short loc_2BD70
push (32 shl 16) or 48
mov bx, si
add bx, bx
mov ax, [bx+69DDh]
mov bx, 0Ah
cwd
idiv bx
push ax
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
push ax
call _egc_copy_rect_1_to_0_16
add sp, 8
loc_2BD70:
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 5
jnz loc_2BE92
mov bx, si
add bx, bx
mov word ptr [bx+14A1h], 6
call IRand
mov bx, 2
cwd
idiv bx
add dx, 3
mov bx, si
add bx, bx
mov [bx+6A55h], dx
mov bx, si
add bx, bx
mov word ptr [bx+6A19h], 2
jmp loc_2BE92
; ---------------------------------------------------------------------------
loc_2BDAA:
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 6
jnz loc_2BE92
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 18B0h
jge short loc_2BE11
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 0
jl short loc_2BE11
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0
jl short loc_2BE11
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0F50h
jge short loc_2BE11
push (8 shl 16) or 16
mov bx, si
add bx, bx
mov ax, [bx+69DDh]
mov bx, 0Ah
cwd
idiv bx
push ax
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
push ax
call _egc_copy_rect_1_to_0_16
add sp, 8
loc_2BE11:
mov bx, si
add bx, bx
mov ax, [bx+6A19h]
mov bx, si
add bx, bx
add [bx+69A1h], ax
mov bx, si
add bx, bx
mov ax, [bx+6A55h]
mov bx, si
add bx, bx
add [bx+69DDh], ax
mov bx, si
add bx, bx
dec word ptr [bx+6A55h]
mov bx, si
add bx, bx
cmp word ptr [bx+6A55h], 0FFFFh
jge short loc_2BE75
call IRand
mov bx, 14h
cwd
idiv bx
add dx, 1Eh
mov bx, si
add bx, bx
mov [bx+6A55h], dx
mov bx, si
add bx, bx
cmp word ptr [bx+6A19h], 0
jge short loc_2BE6A
mov ax, 14h
jmp short loc_2BE6D
; ---------------------------------------------------------------------------
loc_2BE6A:
mov ax, 0FFECh
loc_2BE6D:
mov bx, si
add bx, bx
mov [bx+6A19h], ax
loc_2BE75:
mov bx, si
add bx, bx
mov ax, [bx+69DDh]
mov bx, 0Ah
cwd
idiv bx
cmp ax, 190h
jle short loc_2BE92
mov bx, si
add bx, bx
mov word ptr [bx+14A1h], 0
loc_2BE92:
inc si
loc_2BE93:
cmp si, 1Eh
jl loc_2BC5A
xor si, si
jmp loc_2C0BD
; ---------------------------------------------------------------------------
loc_2BE9F:
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 0
jz loc_2C0BC
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 1
jnz loc_2BF45
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 18B0h
jge loc_2C0BC
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 0
jl loc_2C0BC
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0
jl loc_2C0BC
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0F50h
jge loc_2C0BC
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
mov bx, 8
cwd
idiv bx
mov bx, si
add bx, bx
push ax
mov ax, [bx+69DDh]
mov bx, 0Ah
cwd
idiv bx
imul ax, ROW_SIZE
pop dx
add dx, ax
mov di, dx
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
mov bx, 8
cwd
idiv bx
mov [bp+@@first_bit], dx
push 7 ; col
push ss ; sprite (segment)
lea ax, [bp+var_8]
push ax ; sprite (offset)
push dx ; first_bit
push di ; vram_offset_topleft
call _grcg_put_8x8_mono
add sp, 0Ah
jmp loc_2C0BC
; ---------------------------------------------------------------------------
loc_2BF45:
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 5
jg short loc_2BFC3
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 18B0h
jge short loc_2BFA6
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 0
jl short loc_2BFA6
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0
jl short loc_2BFA6
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0F50h
jge short loc_2BFA6
push 7
mov bx, si
add bx, bx
mov ax, [bx+14A1h]
add ax, 0FFFEh
push ax
push GRC_SLOT_BOSS_4
mov bx, si
add bx, bx
push word ptr [bx+69DDh] ; top
mov bx, si
add bx, bx
push word ptr [bx+69A1h] ; left
call _grc_put_8
add sp, 0Ah
loc_2BFA6:
les bx, [bp+arg_2]
mov ax, es:[bx]
mov bx, 4
cwd
idiv bx
or dx, dx
jnz loc_2C0BC
mov bx, si
add bx, bx
inc word ptr [bx+14A1h]
jmp loc_2C0BC
; ---------------------------------------------------------------------------
loc_2BFC3:
mov bx, si
add bx, bx
cmp word ptr [bx+14A1h], 6
jnz loc_2C0BC
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 18B0h
jge loc_2C06B
mov bx, si
add bx, bx
cmp word ptr [bx+69A1h], 0
jl loc_2C06B
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0
jl short loc_2C06B
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0F50h
jge short loc_2C06B
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
mov bx, 8
cwd
idiv bx
mov bx, si
add bx, bx
push ax
mov ax, [bx+69DDh]
mov bx, 0Ah
cwd
idiv bx
imul ax, 50h
pop dx
add dx, ax
mov di, dx
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
mov bx, 8
cwd
idiv bx
mov [bp+@@first_bit], dx
push 7 ; col
mov bx, si
add bx, bx
cmp word ptr [bx+6A19h], 0
jge short loc_2C058
mov dx, ss
lea ax, [bp+var_10]
jmp short loc_2C05D
; ---------------------------------------------------------------------------
loc_2C058:
mov dx, ss
lea ax, [bp+var_18]
loc_2C05D:
push dx ; sprite (segment)
push ax ; sprite (offset)
push [bp+@@first_bit] ; first_bit
push di ; vram_offset_topleft
call _grcg_put_8x8_mono
add sp, 0Ah
loc_2C06B:
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0E60h
jle short loc_2C0BC
mov bx, si
add bx, bx
cmp word ptr [bx+69DDh], 0F50h
jge short loc_2C0BC
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
cmp ax, _player_left
jle short loc_2C0BC
mov bx, si
add bx, bx
mov ax, [bx+69A1h]
mov bx, 0Ah
cwd
idiv bx
mov dx, _player_left
add dx, 24
cmp ax, dx
jge short loc_2C0BC
cmp _player_invincible, 0
jnz short loc_2C0BC
mov _done, 1
loc_2C0BC:
inc si
loc_2C0BD:
cmp si, 1Eh
jl loc_2BE9F
loc_2C0C4:
pop di
pop si
leave
retn 6
sub_2BB46 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -23936,10 +23324,7 @@ loc_2C9DA:
mov _hud_hp_first_white, 10
mov _hud_hp_first_redwhite, 3
mov _sariel_initial_hp_rendered, 0
push ds
push offset _boss_phase_frame
push 3E7h
call sub_2BB46
call @pattern_swaying_leaves$qmii pascal, ds, offset _boss_phase_frame, 999
jmp loc_2CDCE
; ---------------------------------------------------------------------------
@ -23980,10 +23365,7 @@ loc_2CB05:
jz loc_2CB9D
cmp word_35E95, 4
jnz short loc_2CB38
push ds
push offset _boss_phase_frame
push _sariel_pattern_state
call sub_2BB46
call @pattern_swaying_leaves$qmii pascal, ds, offset _boss_phase_frame, _sariel_pattern_state
cmp _boss_phase_frame, 300
jle short loc_2CBA4
jmp short loc_2CB51
@ -23992,10 +23374,7 @@ loc_2CB05:
loc_2CB38:
cmp word_35E95, 5
jnz short loc_2CB59
push ds
push offset _boss_phase_frame
push 1F4h
call sub_2BB46
call @pattern_swaying_leaves$qmii pascal, ds, offset _boss_phase_frame, 500
cmp _boss_phase_frame, 200
jle short loc_2CBA4
@ -24007,10 +23386,7 @@ loc_2CB51:
loc_2CB59:
cmp word_35E95, 6
jnz short loc_2CB73
push ds
push offset _boss_phase_frame
push 1F4h
call sub_2BB46
call @pattern_swaying_leaves$qmii pascal, ds, offset _boss_phase_frame, 500
loc_2CB6A:
call @pattern_curved_spray_leftright_o$qmi pascal, ds, offset _boss_phase_frame
@ -24020,10 +23396,7 @@ loc_2CB6A:
loc_2CB73:
cmp word_35E95, 7
jnz short loc_2CB8D
push ds
push offset _boss_phase_frame
push 1F4h
call sub_2BB46
call @pattern_swaying_leaves$qmii pascal, ds, offset _boss_phase_frame, 500
loc_2CB84:
call @pattern_rain_from_seal_center$qmi pascal, ds, offset _boss_phase_frame
@ -24033,10 +23406,7 @@ loc_2CB84:
loc_2CB8D:
cmp word_35E95, 8
jnz short loc_2CBA4
push ds
push offset _boss_phase_frame
push 20h ; ' '
call sub_2BB46
call @pattern_swaying_leaves$qmii pascal, ds, offset _boss_phase_frame, 32
loc_2CB9D:
call @pattern_curved_spray_leftright_t$qmi pascal, ds, offset _boss_phase_frame
@ -24904,6 +24274,7 @@ _spawnray_target_prev_y dw 999
BIRD_COUNT = 30
VORTEX_COUNT = 2
PARTICLE2X2_COUNT = 30
LEAF_COUNT = 30
public _birds_alive
_birds_alive db BIRD_COUNT dup(0)
@ -24932,31 +24303,11 @@ _particles2x2_wavy_col db PARTICLE2X2_COUNT dup(0)
public _particles2x2_horizontal_col
_particles2x2_horizontal_col db PARTICLE2X2_COUNT dup(0)
db 60 dup(0)
unk_35E7D db 10h
db 18h
db 18h
db 7Fh
db 0FEh
db 18h
db 18h
db 8
unk_35E85 db 1
db 0Eh
db 3Eh ; >
db 7Eh ; ~
db 7Ch ; |
db 7Ch ; |
db 0F8h
db 0C0h ; À
unk_35E8D db 80h
db 70h ; p
db 7Ch ; |
db 7Eh ; ~
db 3Eh ; >
db 3Eh ; >
db 1Fh
db 3
public _pattern15_flag
_pattern15_flag dw LEAF_COUNT dup(0)
include th01/sprites/leaf.asp
word_35E95 dw 0
word_35E97 dw 0
word_35E99 dw 0
@ -25444,10 +24795,13 @@ _pattern13_debris_cel_prev dw ?
public _pattern14_spray
_pattern14_spray CurvedSpray <?>
word_3B341 dw 30 dup(?)
word_3B37D dw 30 dup(?)
word_3B3B9 dw 30 dup(?)
word_3B3F5 dw 30 dup(?)
public _pattern15_left, _pattern15_top
public _pattern15_velocity_x, _pattern15_velocity_y
_pattern15_left dw LEAF_COUNT dup(?)
_pattern15_top dw LEAF_COUNT dup(?)
_pattern15_velocity_x dw LEAF_COUNT dup(?)
_pattern15_velocity_y dw LEAF_COUNT dup(?)
public _sariel_invincible, _sariel_invincibility_frame
_sariel_invincible dw ?
_sariel_invincibility_frame dw ?