[Decompilation] [th02] Stage bonus calculation and rendering

For both regular and extra stages.

Completes P0279, funded by Yanga and Blue Bolt.
This commit is contained in:
nmlgc 2024-04-07 10:55:23 +02:00
parent 0935e84a83
commit 20bac82005
4 changed files with 210 additions and 316 deletions

View File

@ -1,4 +1,4 @@
#pragma option -zCmain_03_TEXT
#pragma option -zCmain_03_TEXT -d-
#include "platform.h"
#include "pc98.h"

View File

@ -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);
}

View File

@ -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;

View File

@ -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 ; " 難易度" ; 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 ; "ステージ" ; 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 ; "ミス" ; 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 ; "クリア" ; 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 ; "ミス回数" ; 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 ; "クリアタイム" ; 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 ' 難易度',0
aGxgebGw db 'ステージ',0
aGGa db 'ボム',0
aGGx db 'ミス',0
aSMvpik db '靈撃初期数',0
aSCPik db '靈夢初期数',0
aU_ db '点',0
aB db '×',0
aBb db '',0
aGngkga db 'クリア',0
aGGxi db 'ミス回数',0
aGGai db 'ボム回数',0
aGngkgagGcga db 'クリアタイム',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 ' 難易度',0
_BONUS_PLAYPERF db 'ステージ',0
_BONUS_BOMBS db 'ボム',0
_BONUS_LIVES db 'ミス',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 'クリア',0
_BONUS_EXTRA_LIVES db 'ミス回数',0
_BONUS_EXTRA_BOMBS db 'ボム回数',0
_BONUS_EXTRA_SIGMA_FRAMES db 'クリアタイム',0
include th02/gaiji/gameover[data].asm
asc_1E47E db ' ',0
db 0