From e491cd7b0396453ebfc0561e23fc94c1747d8bd3 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Sun, 26 Sep 2021 18:48:02 +0200 Subject: [PATCH] [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. --- th01/main/stage/card_r.cpp | 74 +++++++++++ th01/main/stage/stageobj.hpp | 10 +- th01_reiiden.asm | 240 +---------------------------------- 3 files changed, 84 insertions(+), 240 deletions(-) diff --git a/th01/main/stage/card_r.cpp b/th01/main/stage/card_r.cpp index c05ee73e..f4c962c8 100644 --- a/th01/main/stage/card_r.cpp +++ b/th01/main/stage/card_r.cpp @@ -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; + } +} diff --git a/th01/main/stage/stageobj.hpp b/th01/main/stage/stageobj.hpp index 25cbf868..ef34d6f5 100644 --- a/th01/main/stage/stageobj.hpp +++ b/th01/main/stage/stageobj.hpp @@ -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" diff --git a/th01_reiiden.asm b/th01_reiiden.asm index 38b6bf1c..58b7fa70 100644 --- a/th01_reiiden.asm +++ b/th01_reiiden.asm @@ -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