diff --git a/th02/main/hud/hud.h b/th02/main/hud/hud.h new file mode 100644 index 00000000..a19bbba4 --- /dev/null +++ b/th02/main/hud/hud.h @@ -0,0 +1,2 @@ +#define HUD_LEFT 56 +#define BAR_MAX 128 diff --git a/th04/gaiji/gaiji.h b/th04/gaiji/gaiji.h index 023321e8..5184c519 100644 --- a/th04/gaiji/gaiji.h +++ b/th04/gaiji/gaiji.h @@ -6,6 +6,7 @@ #include "th04/gaiji/bar.h" typedef enum { + g_NULL = '\0', g_EMPTY = 0x02, gaiji_bar(0x20), gaiji_bar_max(0x30), diff --git a/th04/main/hud/hud.h b/th04/main/hud/hud.h index 31c4f387..35a55f03 100644 --- a/th04/main/hud/hud.h +++ b/th04/main/hud/hud.h @@ -5,6 +5,17 @@ // Renders the "Enemy!!" caption and the HP bar, showing the given [bar_value] // between 0 and BAR_MAX. void pascal hud_hp_put(int bar_value); + +#if (GAME == 5) + // Prints [points] using the bold gaiji font, right-aligned at + // ([left+8], [y]), + // in white, using up to 7 digits (8 if the "continue" digit is included). + // Larger numbers will overflow the most significant digit into the A-Z + // range. + void pascal hud_points_put( + utram_x_t left, utram_y_t y, unsigned long points + ); +#endif // --------- // High-level diff --git a/th04/main/hud/popup.asm b/th04/main/hud/popup.asm index 3cd60935..f63f42bb 100644 --- a/th04/main/hud/popup.asm +++ b/th04/main/hud/popup.asm @@ -1,188 +1,7 @@ -public POPUP_UPDATE_AND_RENDER -popup_update_and_render proc near - -@@i = byte ptr -1 - - enter 2, 0 - mov al, _popup_id_new - cmp al, _popup_id_cur - jz short @@needs_init? - cmp _popup_frame, 64 - jb short @@needs_init? - call text_putsa pascal, (PLAYFIELD_TRAM_LEFT shl 16) + POPUP_TRAM_Y, _PLAYFIELD_BLANK_ROW, TX_WHITE - call text_putsa pascal, (PLAYFIELD_TRAM_LEFT shl 16) + 23, _PLAYFIELD_BLANK_ROW, TX_WHITE - mov _popup_frame, 0 - -@@needs_init?: - cmp _popup_frame, 0 - jnz short @@done? - mov al, _popup_id_new - mov _popup_id_cur, al - mov [bp+@@i], 0 - jmp short @@shiftbuf_init_more? -; --------------------------------------------------------------------------- - -@@shiftbuf_init_loop: - mov al, [bp+@@i] - mov ah, 0 - mov bx, ax - mov _popup_shiftbuf[bx], g_EMPTY - inc [bp+@@i] - -@@shiftbuf_init_more?: - cmp [bp+@@i], POPUP_LEN - jb short @@shiftbuf_init_loop - mov al, _popup_id_cur - mov ah, 0 - shl ax, 2 - mov bx, ax - pushd _POPUP_STRINGS[bx] - call _strlen - add sp, 4 - mov _popup_gaiji_len, ax - mov bx, _popup_gaiji_len - mov _popup_shiftbuf[bx], 0 - add ax, ax - mov dx, PLAYFIELD_TRAM_LEFT + PLAYFIELD_TRAM_W - sub dx, ax - mov _popup_cur_tram_x, dx - cmp _popup_id_new, POPUP_ID_BONUS - jz short @@enforce_bonus_text_width - mov ax, PLAYFIELD_TRAM_LEFT + (PLAYFIELD_TRAM_W / 2) - sub ax, _popup_gaiji_len - mov _popup_dest_tram_x, ax - jmp short @@finish_init -; --------------------------------------------------------------------------- - -; Since we print the number of points separately... -@@enforce_bonus_text_width: - mov _popup_dest_tram_x, 16 - -@@finish_init: - mov _popup_dest_reached, 0 - -@@done?: - cmp _popup_frame, POPUP_DURATION - jb short @@shift_needed? - call text_putsa pascal, (PLAYFIELD_TRAM_LEFT shl 16) + POPUP_TRAM_Y, _PLAYFIELD_BLANK_ROW, TX_WHITE - mov _popup_frame, 0 - mov _popup, offset nullfunc_near - leave - retn -; --------------------------------------------------------------------------- - -@@shift_needed?: - mov al, _popup_frame - mov ah, 0 - mov dx, _popup_gaiji_len - dec dx - cmp ax, dx - jge short @@use_unshifted_string - mov [bp+@@i], 0 - jmp short @@shift_more? -; --------------------------------------------------------------------------- - -@@shift_loop: - mov al, [bp+@@i] - mov ah, 0 - mov bx, ax - mov al, _popup_shiftbuf[bx+1] - mov dl, [bp+@@i] - mov dh, 0 - mov bx, dx - mov _popup_shiftbuf[bx], al - inc [bp+@@i] - -@@shift_more?: - mov al, [bp+@@i] - mov ah, 0 - mov dx, _popup_gaiji_len - dec dx - cmp ax, dx - jl short @@shift_loop - mov al, _popup_id_cur - mov ah, 0 - shl ax, 2 - mov bx, ax - les bx, _POPUP_STRINGS[bx] - assume es:nothing - mov al, _popup_frame - mov ah, 0 - add bx, ax - mov al, es:[bx] - mov bx, offset _popup_shiftbuf - dec bx - add bx, _popup_gaiji_len - mov [bx], al - call gaiji_putsa pascal, _popup_cur_tram_x, POPUP_TRAM_Y, ds, offset _popup_shiftbuf, TX_WHITE - jmp @@ret -; --------------------------------------------------------------------------- - -@@use_unshifted_string: - mov ax, _popup_cur_tram_x - cmp ax, _popup_dest_tram_x - jle short @@dest_reached - push ax - push 2 - mov al, _popup_id_cur - mov ah, 0 - shl ax, 2 - mov bx, ax - pushd _POPUP_STRINGS[bx] - push TX_WHITE - call gaiji_putsa - mov ax, _popup_gaiji_len - add ax, ax - add ax, _popup_cur_tram_x - cmp ax, PLAYFIELD_TRAM_LEFT + PLAYFIELD_TRAM_W - GAIJI_TRAM_W - jg short @@still_shifting - mov ax, _popup_gaiji_len - add ax, ax - add ax, _popup_cur_tram_x - call text_putca pascal, ax, (POPUP_TRAM_Y shl 16) or ' ', TX_WHITE - -@@still_shifting: - sub _popup_cur_tram_x, GAIJI_TRAM_W - jmp short @@ret -; --------------------------------------------------------------------------- - -@@dest_reached: - cmp _popup_dest_reached, 0 - jnz short @@put_regular - mov _popup_dest_reached, 1 - call text_putsa pascal, (PLAYFIELD_TRAM_LEFT shl 16) + POPUP_TRAM_Y, _PLAYFIELD_BLANK_ROW, TX_WHITE - -@@put_regular: - push _popup_dest_tram_x - push POPUP_TRAM_Y - mov al, _popup_id_cur - mov ah, 0 - shl ax, 2 - mov bx, ax - pushd _POPUP_STRINGS[bx] - push TX_WHITE - call gaiji_putsa - cmp _popup_id_cur, POPUP_ID_BONUS - jnz short @@ret -if GAME eq 5 - call hud_points_put pascal, ((PLAYFIELD_TRAM_LEFT + (PLAYFIELD_TRAM_W / 2)) shl 16) + 2, large [_popup_bonus] -else - call popup_points_put pascal, large [_popup_bonus] -endif - -@@ret: - inc _popup_frame - leave - retn -popup_update_and_render endp - - if GAME eq 4 ; Yes, specific to the bonus popup, due to the hardcoded position. - -; void pascal near popup_points_put(unsigned long points); -public POPUP_POINTS_PUT -popup_points_put proc pascal near +public POPUP_PUT_POINTS_TH04 +popup_put_points_th04 proc pascal near arg @@points:dword local @@digit:dword, @@divisor:dword, @@buf:byte:SCORE_DIGITS + 2 ; padding... @@ -240,5 +59,5 @@ popup_points_put proc pascal near pop di pop si ret -popup_points_put endp +popup_put_points_th04 endp endif diff --git a/th04/main/hud/popup.cpp b/th04/main/hud/popup.cpp index e6f1e000..4bd93459 100644 --- a/th04/main/hud/popup.cpp +++ b/th04/main/hud/popup.cpp @@ -12,6 +12,7 @@ #include "th04/main/playfld.hpp" #include "th04/main/tile/tile.hpp" #include "th04/main/scroll.hpp" +#include "th04/main/hud/hud.h" #include "th04/main/hud/popup.hpp" #include "th04/main/stage/stage.hpp" #include "th04/main/item/items.hpp" @@ -25,6 +26,13 @@ void pascal near tiles_invalidate_around( subpixel_t center_y, subpixel_t center_x ); +// MODDERS: Keep this up-to-date! +static const unsigned int POPUP_STRING_MAX_LEN = 8; + +extern const gaiji_th04_t* POPUP_STRINGS[]; + +extern const char* PLAYFIELD_BLANK_ROW; + /// Stage and BGM titles /// -------------------- extern unsigned char popup_dissolve_sprite; @@ -50,6 +58,7 @@ extern const char gEXTRA_STAGE[12]; #define STAGE_NUM_CENTER_Y 168 #define STAGE_TITLE_CENTER_Y 200 #define BGM_CENTER_Y 360 +static const tram_y_t POPUP_TRAM_Y = (PLAYFIELD_TRAM_TOP + 1); #define POPUP_FRAMES_UNTIL_OUT_DISSOLVE 192 @@ -62,7 +71,7 @@ extern const char gEXTRA_STAGE[12]; #define STAGE_NUM_TRAM_CENTER_Y (vram_y_to_tram(STAGE_NUM_CENTER_Y)) #define STAGE_TITLE_TRAM_CENTER_Y (vram_y_to_tram(STAGE_TITLE_CENTER_Y)) -#define BGM_TRAM_CENTER_Y (vram_y_to_tram(BGM_CENTER_Y)) +#define BGM_TRAM_Y (vram_y_to_tram(BGM_CENTER_Y)) #define BGM_TRAM_RIGHT (PLAYFIELD_TRAM_RIGHT - 1) inline tram_x_t bgm_note_tram_left(int title_len) @@ -127,8 +136,8 @@ inline void bgm_title_dissolve_put(const int& len) } #define bgm_string_put(str, len) \ - gaiji_putca(bgm_note_tram_left(len), BGM_TRAM_CENTER_Y, 3, TX_YELLOW); \ - text_putsa(bgm_title_tram_left(len), BGM_TRAM_CENTER_Y, str, TX_WHITE); + gaiji_putca(bgm_note_tram_left(len), BGM_TRAM_Y, 3, TX_YELLOW); \ + text_putsa(bgm_title_tram_left(len), BGM_TRAM_Y, str, TX_WHITE); inline void titles_dissolve_put(const int& bgm_len) { @@ -290,3 +299,127 @@ void pascal near popup_boss_bgm_update_and_render(void) #undef frames } /// -------------------- + +const unsigned char POPUP_DURATION = 128; + +inline void popup_line_wipe(tram_y_t y) { + text_putsa(PLAYFIELD_TRAM_LEFT, y, PLAYFIELD_BLANK_ROW, TX_WHITE); +} + +#define popup_put(left, y, str) \ + gaiji_putsa(left, y, reinterpret_cast(str), TX_WHITE); + +inline void near popup_put_points(const unsigned long &points) { + #if (GAME == 5) + hud_points_put(PLAYFIELD_TRAM_CENTER_X, POPUP_TRAM_Y, points); + #else + void pascal near popup_put_points_th04(unsigned long points); + popup_put_points_th04(points); + #endif +} + +void pascal near popup_update_and_render(void) +{ + #define frame popup_frame + #define gaiji_len popup_gaiji_len + #define id_cur popup_id_cur + #define dest_reached popup_dest_reached + #define shiftbuf popup_shiftbuf + #define cur_tram_left popup_cur_tram_left + #define dest_tram_left popup_dest_tram_left + + #define cur_tram_right() \ + (cur_tram_left + (gaiji_len * GAIJI_TRAM_W)) + + extern unsigned char frame; + extern int gaiji_len; + extern popup_id_t id_cur; + extern bool dest_reached; + + // Buffer used for shifting in the popup text from the right of the + // playfield. Only used while the text isn't fully visible. + extern gaiji_th04_t shiftbuf[POPUP_STRING_MAX_LEN + 1]; + + extern tram_x_t cur_tram_left; + extern tram_x_t dest_tram_left; + + unsigned char i; + + // Make sure that the current popup is shown for at least 64 frames before + // switching to a new one. Of course, it would have been cleaner to keep + // popup events in a queue instead - with this approach, you only see the + // last popup that happened within 64 frames, and any other potential + // popups happening during that time are ignored. + // Also note how the lack of a POPUP_NONE constant is the only reason why + // this function has to be conditionally executed via the [popup] function + // pointer... + if((popup_id_new != id_cur) && (frame >= (POPUP_DURATION / 2))) { + popup_line_wipe(POPUP_TRAM_Y); + popup_line_wipe(BGM_TRAM_Y); // Why though? + frame = 0; // Re-initialize + } + if(frame == 0) { + id_cur = popup_id_new; + for(i = 0; i < (sizeof(shiftbuf) - 1); i++) { + shiftbuf[i] = g_EMPTY; + } + gaiji_len = strlen( + reinterpret_cast(POPUP_STRINGS[id_cur]) + ); + shiftbuf[gaiji_len] = g_NULL; + cur_tram_left = (PLAYFIELD_TRAM_RIGHT - (gaiji_len * GAIJI_TRAM_W)); + if(popup_id_new != POPUP_ID_BONUS) { + // Technically * (GAIJI_TRAM_W / 2), since the popup is centered. + popup_dest_tram_left = (PLAYFIELD_TRAM_CENTER_X - gaiji_len); + } else { + // This one is off-center anyway, though. + popup_dest_tram_left = (PLAYFIELD_TRAM_CENTER_X - 12); + } + dest_reached = false; + } + + if(frame >= POPUP_DURATION) { + popup_line_wipe(POPUP_TRAM_Y); + frame = 0; + popup = nullfunc_near; + return; + } + + if(frame < (gaiji_len - 1)) { + // Shift in a new gaiji + for(i = 0; i < (gaiji_len - 1); i++) { + shiftbuf[i] = shiftbuf[i + 1]; + } + shiftbuf[gaiji_len - 1] = POPUP_STRINGS[id_cur][frame]; + popup_put(cur_tram_left, POPUP_TRAM_Y, shiftbuf); + } else if(cur_tram_left > dest_tram_left) { + // (Should really be !=, but whatever.) Use the full, unshifted string + popup_put(cur_tram_left, POPUP_TRAM_Y, POPUP_STRINGS[id_cur]); + if(cur_tram_right() <= (PLAYFIELD_TRAM_RIGHT - GAIJI_TRAM_W)) { + text_putca(cur_tram_right(), POPUP_TRAM_Y, ' ', TX_WHITE); + } + // "If I'd move at 1 TRAM column per frame, I'd have to clip the + // overhanging second half of the last gaiji. Nah, let's just go twice + // the speed :zunpet:" + popup_cur_tram_left -= 2; + } else { + if(!dest_reached) { + dest_reached = true; + popup_line_wipe(POPUP_TRAM_Y); + } + popup_put(dest_tram_left, POPUP_TRAM_Y, POPUP_STRINGS[id_cur]); + if(id_cur == POPUP_ID_BONUS) { + popup_put_points(popup_bonus); + } + } + frame++; + + #undef cur_tram_right + #undef dest_tram_left + #undef cur_tram_left + #undef shiftbuf + #undef dest_reached + #undef id_cur + #undef gaiji_len + #undef frame +} diff --git a/th04/main/hud/popup.hpp b/th04/main/hud/popup.hpp index 4a6745f4..dabc4bac 100644 --- a/th04/main/hud/popup.hpp +++ b/th04/main/hud/popup.hpp @@ -6,6 +6,8 @@ enum popup_id_t { #if (GAME == 5) POPUP_ID_DREAMBONUS_MAX = 4, #endif + + _popup_id_t_FORCE_UINT8 = 0xFF }; extern unsigned char bgm_title_id; // only used in TH04 diff --git a/th04/main/hud/popup.inc b/th04/main/hud/popup.inc index e1cbda60..d59d3a89 100644 --- a/th04/main/hud/popup.inc +++ b/th04/main/hud/popup.inc @@ -1,6 +1,4 @@ POPUP_TRAM_Y = 2 -POPUP_LEN = 8 -POPUP_DURATION = 128 POPUP_ID_HISCORE_ENTRY = 0 POPUP_ID_EXTEND = 1 diff --git a/th04/main/hud/popup[bss].asm b/th04/main/hud/popup[bss].asm index 1a048f1f..070f65e4 100644 --- a/th04/main/hud/popup[bss].asm +++ b/th04/main/hud/popup[bss].asm @@ -1,3 +1,5 @@ +POPUP_LEN = 8 + public _stage_title_len, _stage_bgm_title_len, _boss_bgm_title_len _stage_title_len dw ? _stage_bgm_title_len dw ? @@ -9,25 +11,22 @@ endif _boss_bgm_title_len dw ? public _popup_gaiji_len, _popup_id_cur, _popup_dest_reached, _popup_shiftbuf -public _popup_cur_tram_x, _popup_dest_tram_x, _bgm_title_id, _popup_id_new +public _popup_cur_tram_left, _popup_dest_tram_left, _bgm_title_id, _popup_id_new public _overlay_text, _popup, _popup_titles_frame, _popup_bonus _popup_gaiji_len dw ? _popup_id_cur db ? _popup_dest_reached db ? - -; Buffer used for shifting in the popup text from the right of the playfield. -; Only used while the text isn't fully visible. _popup_shiftbuf db (POPUP_LEN + 1) dup(?) - db ? ; (word alignment) + evendata if GAME eq 5 dd ? ; endif -_popup_cur_tram_x dw ? -_popup_dest_tram_x dw ? +_popup_cur_tram_left dw ? +_popup_dest_tram_left dw ? _bgm_title_id db ? _popup_id_new db ? _overlay_text dw ? _popup dw ? _popup_titles_frame db ? - db ? + evendata _popup_bonus dd ? diff --git a/th04_main.asm b/th04_main.asm index 9b057881..2d26b9ea 100644 --- a/th04_main.asm +++ b/th04_main.asm @@ -40,7 +40,6 @@ include th04/main/enemy/enemy.inc extern SCOPY@:proc extern _execl:proc extern _memcpy:proc - extern _strlen:proc extern _tolower:proc extern __ctype:byte @@ -9779,9 +9778,9 @@ main_0_TEXT ends POPUP_TITLES_INVALIDATE procdesc near POPUP_TITLES_UPDATE_AND_RENDER procdesc near POPUP_BOSS_BGM_UPDATE_AND_RENDER procdesc near + POPUP_UPDATE_AND_RENDER procdesc near main_01_TEXT segment byte public 'CODE' use16 - include th04/main/hud/popup.asm include th04/formats/bb_txt_load.asm diff --git a/th05/main/hud/number_put.asm b/th05/main/hud/number_put.asm index 1e064e6b..5ae0ac4e 100644 --- a/th05/main/hud/number_put.asm +++ b/th05/main/hud/number_put.asm @@ -24,11 +24,6 @@ hud_int_put endp nop -; Prints [points] using the bold gaiji font, right-aligned at ([left+8], [y]), -; in white, using up to 7 digits (8 if the "continue" digit is included). -; Larger numbers will overflow the most significant digit into the A-Z range. - -; void pascal far hud_points_put(utram_x_t left, utram_y_t y, unsigned long points); public HUD_POINTS_PUT hud_points_put proc far diff --git a/th05_main.asm b/th05_main.asm index 14e8894a..74d2f611 100644 --- a/th05_main.asm +++ b/th05_main.asm @@ -8313,10 +8313,9 @@ main_0_TEXT ends POPUP_TITLES_INVALIDATE procdesc near POPUP_TITLES_UPDATE_AND_RENDER procdesc near POPUP_BOSS_BGM_UPDATE_AND_RENDER procdesc near + POPUP_UPDATE_AND_RENDER procdesc near main_01_TEXT segment byte public 'CODE' use16 - -include th04/main/hud/popup.asm include th04/main/player/pos_update_and_clamp.asm ; =============== S U B R O U T I N E =======================================