[Decompilation] [th01] Stage objects: Card update and rendering

Including firing the revenge pellets on Lunatic. And that's all
non-boilerplate card code done as well!

Completes P0159, funded by Yanga.
This commit is contained in:
nmlgc 2021-09-26 18:48:02 +02:00
parent 36068acb02
commit e491cd7b03
3 changed files with 84 additions and 240 deletions

View File

@ -1,3 +1,8 @@
#include "th01/hardware/input.hpp"
#include "th01/sprites/pellet.h"
#include "th01/math/subpixel.hpp"
#include "th01/main/bullet/pellet.hpp"
static const unsigned int CARD_SCORE_CAP_DIGITS = digit_count(CARD_SCORE_CAP);
static const pixel_t CARD_SCORE_W = (CARD_SCORE_CAP_DIGITS * GLYPH_HALF_W);
@ -67,3 +72,72 @@ void cards_score_render(void)
}
}
}
#define card_put_8(i) \
stageobj_put_8( \
cards.left[i], \
cards.top[i], \
CARD_ANIM[cards.hp[i]][cards.flip_frames[i] / CARD_FRAMES_PER_CEL], \
i \
);
void cards_update_and_render(void)
{
int i;
int cards_removed = 0;
// ZUN bug: Why is this called first? The animated card sprites will
// therefore overlap the score popup every [CARD_FRAMES_PER_CEL] frames,
// leading to some minor flickering.
cards_score_render();
for(i = 0; i < cards.count; i++) {
if(cards.flag[i] == CARD_FLIPPING) {
if(
(cards.flip_frames[i] < FRAME_ANIM_DONE) &&
((cards.flip_frames[i] % CARD_FRAMES_PER_CEL) == 0)
) {
graph_accesspage_func(1); card_put_8(i);
graph_accesspage_func(0); card_put_8(i);
}
cards.flip_frames[i]++;
if(cards.flip_frames[i] >= card_first_frame_of(CARD_CEL_FLIPPED)) {
if(rank == RANK_LUNATIC) {
pellet_group_t group;
if(stage_num < 10) {
group = PG_1_AIMED;
} else {
group = PG_1_RANDOM_NARROW_AIMED;
}
if(cards.flip_frames[i] == FRAME_ANIM_DONE) {
Pellets.add_group(
(cards.left[i] + (STAGEOBJ_W / 2) - (PELLET_W / 2)),
(cards.top[i] + (STAGEOBJ_H / 2) - (PELLET_H / 2)),
group,
to_sp(3.5f)
);
}
}
if(cards.flip_frames[i] >= card_first_frame_of(CARD_CELS)) {
if(cards.hp[i] == 0) {
cards.flag[i] = CARD_REMOVED;
cards.flip_frames[i] = 0;
} else {
cards.flag[i] = CARD_ALIVE;
cards.flip_frames[i] = 0;
cards.hp[i]--;
}
}
}
}
if(cards.flag[i] == CARD_REMOVED) {
cards_removed++;
}
}
if(cards_removed == cards.count) {
stage_cleared = true;
done = true;
}
}

View File

@ -9,6 +9,8 @@ enum card_flag_t {
CARD_FLIPPING = 1,
CARD_REMOVED = 2,
_card_flag_t_FORCE_INT16 = 0x7FFF
};
static const int CARD_FRAMES_PER_CEL = 6;
@ -42,7 +44,7 @@ extern unsigned long *cards_score;
struct CCards {
screen_x_t *left;
vram_y_t *top;
card_flag_t *flag;
char *flag; // card_flag_t
int count;
// Current frame within the CARD_FLIPPING animation.
@ -56,7 +58,7 @@ struct CCards {
if(count > 0) {
left = new screen_x_t[count];
top = new vram_y_t[count];
flag = new card_flag_t[count];
flag = new char[count];
flip_frames = new int[count];
hp = new char[count];
cards_score = new unsigned long[count];
@ -72,6 +74,10 @@ extern bool16 stage_cleared;
// immediate effects of such collisions. Score points for collisisions are
// granted in relation to the [stage_num].
void cards_hittest(int stage_num);
// Also sets the [stage_cleared] flag if all cards were cleared, and fires
// revenge pellets on Lunatic.
void cards_update_and_render(void);
// -----
// "Obstacles"

View File

@ -66,7 +66,6 @@ main_21 group main_21_TEXT, main_21__TEXT
main_25 group main_25_TEXT, main_25__TEXT
main_27 group main_27_TEXT, main_27__TEXT
main_29 group main_29_TEXT, main_29__TEXT
main_30 group main_30_TEXT, main_30__TEXT
main_31 group main_31_TEXT, main_31__TEXT
main_32 group main_32_TEXT, main_32__TEXT
main_33 group main_33_TEXT, main_33__TEXT
@ -1039,7 +1038,7 @@ loc_C879:
idiv bx
cmp dx, 4
jz short loc_C88B
call sub_201BE
call @cards_update_and_render$qv
loc_C88B:
cmp _orb_in_portal, 0
@ -15684,237 +15683,11 @@ main_29__TEXT ends
; Segment type: Pure code
main_30_TEXT segment byte public 'CODE' use16
assume cs:main_30
;org 3
assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing
; panel_flag_t
PANEL_ALIVE = 0
PANEL_FLIPPING = 1
PANEL_REMOVED = 2
extern @cards_hittest$qi:proc
extern @STR_RIGHT_ALIGNED_FROM_UINT16$QNCUIUI:proc
extern @cards_score_render$qv:proc
extern @cards_update_and_render$qv:proc
main_30_TEXT ends
main_30__TEXT segment byte public 'CODE' use16
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_201BE proc far
@@group = word ptr -2
enter 2, 0
push si
push di
xor di, di
call @cards_score_render$qv
xor si, si
jmp loc_2037C
; ---------------------------------------------------------------------------
loc_201CF:
les bx, _cards_flag
mov al, es:[bx+si]
cbw
cmp ax, PANEL_FLIPPING
jnz loc_2036D
mov ax, si
add ax, ax
les bx, _cards_flip_frames
add bx, ax
cmp word ptr es:[bx], 25
jge loc_202A6
mov ax, es:[bx]
mov bx, 6
cwd
idiv bx
or dx, dx
jnz loc_202A6
push 1
call _graph_accesspage_func
pop cx
push si ; bg_slot
les bx, _cards_hp
mov al, es:[bx+si]
cbw
imul ax, CARD_ANIM_CELS
mov dx, si
add dx, dx
les bx, _cards_flip_frames
add bx, dx
push ax
mov ax, es:[bx]
mov bx, 6
cwd
idiv bx
pop bx
add bx, ax
mov al, _CARD_ANIM[bx]
mov ah, 0
push ax ; ptn_id
mov ax, si
add ax, ax
les bx, _cards_top
add bx, ax
push word ptr es:[bx] ; top
mov ax, si
add ax, ax
les bx, _cards_left
add bx, ax
push word ptr es:[bx] ; left
call @stageobj_put_8$qiiii
push 0
call _graph_accesspage_func
add sp, 0Ah
push si ; bg_slot
les bx, _cards_hp
mov al, es:[bx+si]
cbw
imul ax, CARD_ANIM_CELS
mov dx, si
add dx, dx
les bx, _cards_flip_frames
add bx, dx
push ax
mov ax, es:[bx]
mov bx, 6
cwd
idiv bx
pop bx
add bx, ax
mov al, _CARD_ANIM[bx]
mov ah, 0
push ax ; ptn_id
mov ax, si
add ax, ax
les bx, _cards_top
add bx, ax
push word ptr es:[bx] ; top
mov ax, si
add ax, ax
les bx, _cards_left
add bx, ax
push word ptr es:[bx] ; left
call @stageobj_put_8$qiiii
add sp, 8
loc_202A6:
mov ax, si
add ax, ax
les bx, _cards_flip_frames
add bx, ax
inc word ptr es:[bx]
cmp word ptr es:[bx], 24
jl loc_2036D
mov al, _rank
cbw
cmp ax, RANK_LUNATIC
jnz short loc_2031C
mov al, _stage_num
cbw
cmp ax, 10
jge short loc_202D4
mov [bp+@@group], PG_1_AIMED
jmp short loc_202D9
; ---------------------------------------------------------------------------
loc_202D4:
mov [bp+@@group], PG_1_RANDOM_NARROW_AIMED
loc_202D9:
mov ax, si
add ax, ax
les bx, _cards_flip_frames
add bx, ax
cmp word ptr es:[bx], 25
jnz short loc_2031C
push (3 shl 4) + 8
push [bp+@@group]
mov ax, si
add ax, ax
les bx, _cards_top
add bx, ax
mov ax, es:[bx]
add ax, 12
push ax
mov ax, si
add ax, ax
les bx, _cards_left
add bx, ax
mov ax, es:[bx]
add ax, 12
push ax
push ds
push offset _Pellets
call @CPellets@add_group$qii14pellet_group_ti
add sp, 0Ch
loc_2031C:
mov ax, si
add ax, ax
les bx, _cards_flip_frames
add bx, ax
cmp word ptr es:[bx], 30
jl short loc_2036D
les bx, _cards_hp
cmp byte ptr es:[bx+si], 0
jnz short loc_2034F
les bx, _cards_flag
mov byte ptr es:[bx+si], PANEL_REMOVED
mov ax, si
add ax, ax
les bx, _cards_flip_frames
add bx, ax
mov word ptr es:[bx], 0
jmp short loc_2036D
; ---------------------------------------------------------------------------
loc_2034F:
les bx, _cards_flag
mov byte ptr es:[bx+si], PANEL_ALIVE
mov ax, si
add ax, ax
les bx, _cards_flip_frames
add bx, ax
mov word ptr es:[bx], 0
les bx, _cards_hp
dec byte ptr es:[bx+si]
loc_2036D:
les bx, _cards_flag
mov al, es:[bx+si]
cbw
cmp ax, PANEL_REMOVED
jnz short loc_2037B
inc di
loc_2037B:
inc si
loc_2037C:
cmp si, _card_count
jl loc_201CF
cmp di, _card_count
jnz short loc_20395
mov _stage_cleared, 1
loc_20390:
mov _done, 1
loc_20395:
pop di
pop si
leave
retf
sub_201BE endp
main_30__TEXT ends
; ===========================================================================
; Segment type: Pure code
@ -35553,15 +35326,6 @@ public _default_grp_fn, _default_bgm_fn, _scene_fn_, _CARD_ANIM
_default_grp_fn db 'ST .GRP', 0, 0, 0, 0, 0, 0, 0, 0
_default_bgm_fn db 'ST .MDT', 0, 0, 0, 0, 0, 0, 0, 0
STAGEOBJ_W = PTN_W
STAGEOBJ_H = PTN_H
STAGEOBJS_X = (PLAYFIELD_W / STAGEOBJ_W)
STAGEOBJS_Y = (PLAYFIELD_H / STAGEOBJ_H)
STAGEOBJS_COUNT = (STAGEOBJS_X * STAGEOBJS_Y)
CARD_ANIM_CELS = 5
CARD_HP_MAX = 5
_CARD_ANIM label byte
db PTN_CARD_0HP, PTN_CARD_0HP_HALF, PTN_CARD_0HP_EDGE, PTN_CARD_REMOVED_HALF, PTN_CARD_REMOVED
db PTN_CARD_1HP, PTN_CARD_1HP_HALF, PTN_CARD_1HP_EDGE, PTN_CARD_0HP_HALF, PTN_CARD_0HP