From 20bac8200579ae6124a91b26f11f1a9ff0fb2b21 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Sun, 7 Apr 2024 10:55:23 +0200 Subject: [PATCH] [Decompilation] [th02] Stage bonus calculation and rendering For both regular and extra stages. Completes P0279, funded by Yanga and Blue Bolt. --- th02/main/hud/overlay.cpp | 2 +- th02/main/stage/bonus.cpp | 168 +++++++++++++++++++ th02/shiftjis/bonus.hpp | 15 ++ th02_main.asm | 341 +++----------------------------------- 4 files changed, 210 insertions(+), 316 deletions(-) diff --git a/th02/main/hud/overlay.cpp b/th02/main/hud/overlay.cpp index 96b47eee..e1402477 100644 --- a/th02/main/hud/overlay.cpp +++ b/th02/main/hud/overlay.cpp @@ -1,4 +1,4 @@ -#pragma option -zCmain_03_TEXT +#pragma option -zCmain_03_TEXT -d- #include "platform.h" #include "pc98.h" diff --git a/th02/main/stage/bonus.cpp b/th02/main/stage/bonus.cpp index dc857d8e..1498b783 100644 --- a/th02/main/stage/bonus.cpp +++ b/th02/main/stage/bonus.cpp @@ -1,4 +1,14 @@ #include "shiftjis.hpp" +#include "th02/resident.hpp" +#include "th02/hardware/input.hpp" +extern "C" { +#include "th02/snd/snd.h" +} +#include "th02/core/globals.hpp" +#include "th02/main/playperf.hpp" +#include "th02/main/score.hpp" +#include "th02/main/stage/bonus.hpp" +#include "th02/main/boss/bosses.hpp" #include "th02/shiftjis/bonus.hpp" static const int VALUE_DIGITS = 5; @@ -10,8 +20,34 @@ static const tram_cell_amount_t PADDING = 2; static const tram_x_t LABEL_LEFT = (PLAYFIELD_TRAM_LEFT + 4); static const tram_x_t VALUE_LEFT = (LABEL_LEFT + BONUS_LABEL_TRAM_W + PADDING); +static const tram_cell_amount_t VALUE_TRAM_W = (VALUE_DIGITS * GAIJI_TRAM_W); // ----------- +struct hack { + char x[6]; // ACTUAL TYPE: gaiji_th02_t +}; + +inline void bonus_title_put(const struct hack& title) { + // ZUN bloat: Not `static`, gets needlessly copied into a local variable. + const struct hack gBONUS = title; + + overlay_wipe(); + + palette_settone(62); + gaiji_putsa( + // ZUN bug: Not *quite* centered. + (PLAYFIELD_TRAM_CENTER_X - (((sizeof(title) - 1) / 2) * 2)), + + 4, + gBONUS.x, + TX_WHITE + ); +} + +// ZUN bloat: Both values should be `score_t` or *at least* unsigned to avoid +// readers having to double-check why this won't overflow with the values +// passed to this function. (It won't because [val_x10] never exceeds 32,767, +// and only 1/10th of that value gets added to [total].) void pascal near bonus_row_put_and_add( tram_y_t y, const shiftjis_t *label, int& sum, int val_x10 ) @@ -25,3 +61,135 @@ void pascal near bonus_row_put_and_add( sum += val; #undef val } + +inline void bonus_multiply_add_put_and_delay( + score_t& bonus_total, int bonus_total_digits, const int& sum +) { + enum { + POINT_ITEM_DIGITS = 3, + Y = 18, + + POINT_LABEL_LEFT = (LABEL_LEFT - 2), + POINT_ITEMS_LEFT = ( + POINT_LABEL_LEFT + (sizeof(BONUS_POINT) - 1) + PADDING + ), + TIMES_LEFT = ( + POINT_ITEMS_LEFT + (POINT_ITEM_DIGITS * GAIJI_TRAM_W) + PADDING + ), + SUM_LEFT = (TIMES_LEFT + (sizeof(BONUS_TIMES) - 1) + PADDING), + EQUALS_LEFT = (SUM_LEFT + (VALUE_DIGITS * GAIJI_TRAM_W) + PADDING), + }; + + text_putsa(POINT_LABEL_LEFT, Y, BONUS_POINT, TX_WHITE); + overlay_uint_put( + POINT_ITEMS_LEFT, Y, POINT_ITEM_DIGITS, point_items_collected + ); + text_putsa(TIMES_LEFT, Y, BONUS_TIMES, TX_WHITE); + + bonus_total = sum; + bonus_total *= 10; + overlay_uint_put(SUM_LEFT, Y, VALUE_DIGITS, bonus_total); + text_putsa(EQUALS_LEFT, Y, BONUS_EQUALS, TX_WHITE); + + bonus_total *= point_items_collected; + overlay_uint_put( + // Right-aligning even the 7-digit value of the Extra Stage was more + // important than ensuring padding after the =? + (PLAYFIELD_TRAM_RIGHT - PADDING - (bonus_total_digits * GAIJI_TRAM_W)), + + Y, + bonus_total_digits, + bonus_total + ); + + bonus_total /= 10; + score_delta += bonus_total; + + snd_se_reset(); + + // Not a quirk because the game either + // β€’ immediately moves to the next stage and calls score_reset() before + // rendering the next game frame (for regular stages), or + // β€’ launches MAINE.EXE soon afterward (for the Extra Stage). + score_grant_current_delta_as_bonus(); + + snd_se_update(); + + // ZUN bloat: Has no effect, and isn't read before the next call to + // input_reset_sense(). + key_det = INPUT_UP; + + key_delay(); +} + +void near stage_clear_bonus_animate(void) +{ + int val; + score_t bonus_total; + int sum = 0; + + extern struct hack gBONUS_0; + bonus_title_put(gBONUS_0); + + bonus_row_put_and_add(6, BONUS_RANK, sum, (rank * 2000)); + bonus_row_put_and_add(8, BONUS_PLAYPERF, sum, ((playperf + 16) * 200)); + + val = (2500 - (stage_bombs_used * 500)); + if(val < 0) { + val = 0; + } + bonus_row_put_and_add(10, BONUS_BOMBS, sum, val); + + val = (3000 - (stage_miss_count * 1000)); + if(val < 0) { + val = 0; + } + bonus_row_put_and_add(12, BONUS_LIVES, sum, val); + bonus_row_put_and_add( + 14, BONUS_START_BOMBS, sum, ((4 - resident->start_bombs) * 800) + ); + bonus_row_put_and_add( + 16, BONUS_START_LIVES, sum, ((4 - resident->start_lives) * 1000) + ); + + // The maximum possible sum (divided by 10) is 1910... + if(sum > 25600) { + sum = 25600; + } + + bonus_multiply_add_put_and_delay(bonus_total, 6, sum); +} + +void near stage_extra_clear_bonus_animate(void) +{ + int val; + score_t bonus_total; + int sum = 0; + + extern struct hack gBONUS_1; + bonus_title_put(gBONUS_1); + + bonus_row_put_and_add(6, BONUS_EXTRA_CLEAR, sum, 10000); + + val = (20000 - (stage_miss_count * 4000)); + if(val < 0) { + val = 0; + } + bonus_row_put_and_add(8, BONUS_EXTRA_LIVES, sum, val); + + val = (20000 - (stage_bombs_used * 4000)); + if(val < 0) { + val = 0; + } + bonus_row_put_and_add(10, BONUS_EXTRA_BOMBS, sum, val); + + val = (20000 - sigma_frames); + if(val < 0) { + val = 0; + } + val /= 10; + val *= 10; + bonus_row_put_and_add(12, BONUS_EXTRA_SIGMA_FRAMES, sum, val); + + bonus_multiply_add_put_and_delay(bonus_total, 7, sum); +} diff --git a/th02/shiftjis/bonus.hpp b/th02/shiftjis/bonus.hpp index b4cdc3e5..8474422d 100644 --- a/th02/shiftjis/bonus.hpp +++ b/th02/shiftjis/bonus.hpp @@ -1,2 +1,17 @@ +extern const shiftjis_t BONUS_RANK[]; +extern const shiftjis_t BONUS_PLAYPERF[]; +extern const shiftjis_t BONUS_BOMBS[]; +extern const shiftjis_t BONUS_LIVES[]; +extern const shiftjis_t BONUS_START_BOMBS[]; +extern const shiftjis_t BONUS_START_LIVES[]; +extern const shiftjis_t BONUS_POINT[3]; +extern const shiftjis_t BONUS_TIMES[3]; +extern const shiftjis_t BONUS_EQUALS[]; + +extern const shiftjis_t BONUS_EXTRA_CLEAR[]; +extern const shiftjis_t BONUS_EXTRA_LIVES[]; +extern const shiftjis_t BONUS_EXTRA_BOMBS[]; +extern const shiftjis_t BONUS_EXTRA_SIGMA_FRAMES[]; + // TRANSLATORS: Replace with your longest label. static const tram_cell_amount_t BONUS_LABEL_TRAM_W = 12; diff --git a/th02_main.asm b/th02_main.asm index 3a5142bb..618c7799 100644 --- a/th02_main.asm +++ b/th02_main.asm @@ -6512,307 +6512,9 @@ DIALOG_TEXT segment byte public 'CODE' use16 @randring2_next16$qv procdesc near PELLET_RENDER procdesc pascal near \ left:word, top:word - @OVERLAY_UINT_PUT$QIIIL procdesc pascal near \ - left_and_y:dword, digits:word, val:dword extern @overlay_wipe$qv:far - @BONUS_ROW_PUT_AND_ADD$QINXUCMII procdesc pascal near \ - y:word, label:dword, total:dword, val_x10:word - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame -public @stage_clear_bonus_animate$qv -@stage_clear_bonus_animate$qv proc near - -var_C = byte ptr -0Ch -@@sum = word ptr -6 -var_4 = dword ptr -4 - - enter 0Ch, 0 - push si - mov [bp+@@sum], 0 - lea ax, [bp+var_C] - push ss - push ax - push ds - push offset gBONUS - mov cx, 6 - call SCOPY@ - call @overlay_wipe$qv - mov PaletteTone, 62 - call far ptr palette_show - push (24 shl 16) + 4 - push ss - lea ax, [bp+var_C] - push ax - push TX_WHITE - call gaiji_putsa - push 6 ; y - push ds ; label (segment) - push offset aUqiUx ; " “οˆΥ“x" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - mov al, _rank - cbw - imul ax, 2000 - push ax ; val_x10 - call @bonus_row_put_and_add$qinxucmii - push 8 ; y - push ds ; label (segment) - push offset aGxgebGw ; "ƒXƒe[ƒW" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - mov ax, _playperf - add ax, 16 - imul ax, 200 - push ax ; val_x10 - call @bonus_row_put_and_add$qinxucmii - mov al, _stage_bombs_used - mov ah, 0 - imul ax, 500 - mov dx, 2500 - sub dx, ax - mov si, dx - or si, si - jge short loc_FCD6 - xor si, si - -loc_FCD6: - push 10 ; y - push ds ; label (segment) - push offset aGGa ; "ƒ{ƒ€" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - push si ; val_x10 - call @bonus_row_put_and_add$qinxucmii - mov al, _stage_miss_count - mov ah, 0 - imul ax, 1000 - mov dx, 3000 - sub dx, ax - mov si, dx - or si, si - jge short loc_FCFB - xor si, si - -loc_FCFB: - push 12 ; y - push ds ; label (segment) - push offset aGGx ; "ƒ~ƒX" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - push si ; val_x10 - call @bonus_row_put_and_add$qinxucmii - push 14 ; y - push ds ; label (segment) - push offset aSMvpik ; "θˌ‚‰Šϊ”" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - les bx, _resident - mov al, es:[bx+mikoconfig_t.start_bombs] - mov ah, 0 - mov dx, 4 - sub dx, ax - imul dx, 800 - push dx ; val_x10 - call @bonus_row_put_and_add$qinxucmii - push 16 - push ds ; label (segment) - push offset aSCPik ; "θΛ–²‰Šϊ”" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - les bx, _resident - mov al, es:[bx+mikoconfig_t.start_lives] - mov ah, 0 - mov dx, 4 - sub dx, ax - imul dx, 1000 - push dx ; val_x10 - call @bonus_row_put_and_add$qinxucmii - cmp [bp+@@sum], 25600 - jle short loc_FD5A - mov [bp+@@sum], 25600 - -loc_FD5A: - call text_putsa pascal, (6 shl 16) + 18, ds, offset aU_, TX_WHITE - push (10 shl 16) or 18 - push 3 - movsx eax, _point_items_collected - push eax - call @overlay_uint_put$qiiil - call text_putsa pascal, (18 shl 16) + 18, ds, offset aB, TX_WHITE - movsx eax, [bp+@@sum] - mov [bp+var_4], eax - imul eax, 0Ah - mov [bp+var_4], eax - call @overlay_uint_put$qiiil pascal, (22 shl 16) or 18, 5, eax - call text_putsa pascal, (34 shl 16) + 18, ds, offset aBb, TX_WHITE - movsx eax, _point_items_collected - imul eax, [bp+var_4] - mov [bp+var_4], eax - call @overlay_uint_put$qiiil pascal, (38 shl 16) or 18, 6, eax - mov ebx, 0Ah - mov eax, [bp+var_4] - cdq - idiv ebx - mov [bp+var_4], eax - add _score_delta, eax - call _snd_se_reset - - ; Not a quirk because the game immediately moves to the next stage and - ; calls score_reset() before rendering the next game frame. - call @score_grant_current_delta_as_bon$qv - - call _snd_se_update - mov _key_det, 1 - call @key_delay$qv - pop si - leave - retn -@stage_clear_bonus_animate$qv endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame -public @stage_extra_clear_bonus_animate$qv -@stage_extra_clear_bonus_animate$qv proc near - -var_C = byte ptr -0Ch -@@sum = word ptr -6 -var_4 = dword ptr -4 - - enter 0Ch, 0 - push si - mov [bp+@@sum], 0 - lea ax, [bp+var_C] - push ss - push ax - push ds - push offset gBONUS_0 - mov cx, 6 - call SCOPY@ - call @overlay_wipe$qv - mov PaletteTone, 62 - call far ptr palette_show - push (24 shl 16) + 4 - push ss - lea ax, [bp+var_C] - push ax - push TX_WHITE - call gaiji_putsa - push 6 ; y - push ds ; label (segment) - push offset aGngkga ; "ƒNƒŠƒA" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - push 10000 ; val_x10 - call @bonus_row_put_and_add$qinxucmii - mov al, _stage_miss_count - mov ah, 0 - imul ax, 4000 - mov dx, 20000 - sub dx, ax - mov si, dx - or si, si - jge short loc_FE76 - xor si, si - -loc_FE76: - push 8 ; y - push ds ; label (segment) - push offset aGGxi ; "ƒ~ƒX‰ρ”" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - push si ; val_x10 - call @bonus_row_put_and_add$qinxucmii - mov al, _stage_bombs_used - mov ah, 0 - imul ax, 4000 - mov dx, 20000 - sub dx, ax - mov si, dx - or si, si - jge short loc_FE9B - xor si, si - -loc_FE9B: - push 10 ; y - push ds ; label (segment) - push offset aGGai ; "ƒ{ƒ€‰ρ”" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - push si ; val_x10 - call @bonus_row_put_and_add$qinxucmii - mov ax, 20000 - sub ax, word ptr _sigma_frames - mov si, ax - or si, si - jge short loc_FEB9 - xor si, si - -loc_FEB9: - mov bx, 10 - mov ax, si - cwd - idiv bx - mov si, ax - mov ax, 10 - imul si - mov si, ax - push 12 ; y - push ds ; label (segment) - push offset aGngkgagGcga ; "ƒNƒŠƒAƒ^ƒCƒ€" ; label (offset) - push ss ; sum (segment) - lea ax, [bp+@@sum] - push ax ; sum (offset) - push si ; val_x10 - call @bonus_row_put_and_add$qinxucmii - call text_putsa pascal, (6 shl 16) + 18, ds, offset aU_, TX_WHITE - push (10 shl 16) or 18 - push 3 - movsx eax, _point_items_collected - push eax - call @overlay_uint_put$qiiil - call text_putsa pascal, (18 shl 16) + 18, ds, offset aB, TX_WHITE - movsx eax, [bp+@@sum] - mov [bp+var_4], eax - imul eax, 0Ah - mov [bp+var_4], eax - call @overlay_uint_put$qiiil pascal, (22 shl 16) or 18, 5, eax - call text_putsa pascal, (34 shl 16) + 18, ds, offset aBb, TX_WHITE - movsx eax, _point_items_collected - imul eax, [bp+var_4] - mov [bp+var_4], eax - call @overlay_uint_put$qiiil pascal, (36 shl 16) or 18, 7, eax - mov ebx, 0Ah - mov eax, [bp+var_4] - cdq - idiv ebx - mov [bp+var_4], eax - add _score_delta, eax - call _snd_se_reset - - ; Not a quirk because the game launches MAINE.EXE soon afterward. - call @score_grant_current_delta_as_bon$qv - - call _snd_se_update - mov _key_det, 1 - call @key_delay$qv - pop si - leave - retn -@stage_extra_clear_bonus_animate$qv endp - + @stage_clear_bonus_animate$qv procdesc near + @stage_extra_clear_bonus_animate$qv procdesc near ; =============== S U B R O U T I N E ======================================= @@ -29546,21 +29248,30 @@ _rank db RANK_NORMAL _stage_id db 0 aHuuma_cfg db 'huuma.cfg',0 include th02/sprites/pellet.asp -gBONUS db 0ABh, 0B8h, 0B6h, 0BEh, 0BCh, 0 -gBONUS_0 db 0ABh, 0B8h, 0B6h, 0BEh, 0BCh, 0 -aUqiUx db ' “οˆΥ“x',0 -aGxgebGw db 'ƒXƒe[ƒW',0 -aGGa db 'ƒ{ƒ€',0 -aGGx db 'ƒ~ƒX',0 -aSMvpik db 'θˌ‚‰Šϊ”',0 -aSCPik db 'θΛ–²‰Šϊ”',0 -aU_ db '“_',0 -aB db '~',0 -aBb db '',0 -aGngkga db 'ƒNƒŠƒA',0 -aGGxi db 'ƒ~ƒX‰ρ”',0 -aGGai db 'ƒ{ƒ€‰ρ”',0 -aGngkgagGcga db 'ƒNƒŠƒAƒ^ƒCƒ€',0 +public _gBONUS_0, _gBONUS_1 +_gBONUS_0 db 0ABh, 0B8h, 0B6h, 0BEh, 0BCh, 0 +_gBONUS_1 db 0ABh, 0B8h, 0B6h, 0BEh, 0BCh, 0 +public _BONUS_RANK, _BONUS_PLAYPERF, _BONUS_BOMBS, _BONUS_LIVES +public _BONUS_START_BOMBS, _BONUS_START_LIVES, _BONUS_POINT, _BONUS_TIMES +public _BONUS_EQUALS, _BONUS_EXTRA_CLEAR, _BONUS_EXTRA_LIVES +public _BONUS_EXTRA_BOMBS, _BONUS_EXTRA_SIGMA_FRAMES + +; ZUN bug: Why is that space here? None of the other labels even attempt to be +; centered. +_BONUS_RANK db ' “οˆΥ“x',0 + +_BONUS_PLAYPERF db 'ƒXƒe[ƒW',0 +_BONUS_BOMBS db 'ƒ{ƒ€',0 +_BONUS_LIVES db 'ƒ~ƒX',0 +_BONUS_START_BOMBS db 'θˌ‚‰Šϊ”',0 +_BONUS_START_LIVES db 'θΛ–²‰Šϊ”',0 +_BONUS_POINT db '“_',0 +_BONUS_TIMES db '~',0 +_BONUS_EQUALS db '',0 +_BONUS_EXTRA_CLEAR db 'ƒNƒŠƒA',0 +_BONUS_EXTRA_LIVES db 'ƒ~ƒX‰ρ”',0 +_BONUS_EXTRA_BOMBS db 'ƒ{ƒ€‰ρ”',0 +_BONUS_EXTRA_SIGMA_FRAMES db 'ƒNƒŠƒAƒ^ƒCƒ€',0 include th02/gaiji/gameover[data].asm asc_1E47E db ' ',0 db 0