mirror of https://github.com/nmlgc/ReC98.git
[Reverse-engineering] [th02/th04/th05] Score update and display
The TH02 version is a piece of cake… … but TH04 starts turning it into this un-decompilable piece of unnecessarily micro-optimized ZUN code. Couldn't have chosen anything better for the first separate ASM translation unit. Aside from now having to convert names of exported *variables* to uppercase for visibility in ASM translation units, the most notable lesson in this was the one about avoiding fixup overflows. From the Borland C++ Version 4.0 User's Guide: "In an assembly language program, a fixup overflow frequently occurs if you have declared an external variable within a segment definition, but this variable actually exists in a different segment." Can't be restated often enough. Completes P0032, funded by zorg.
This commit is contained in:
parent
88c05e48e5
commit
e6294c2c1a
19
Makefile.mak
19
Makefile.mak
|
@ -19,6 +19,16 @@ th03:: $(TH03:\=bin\th03\)
|
|||
th04:: $(TH04:\=bin\th04\)
|
||||
th05:: $(TH05:\=bin\th05\)
|
||||
|
||||
# Shared TH04/TH05 assembly units
|
||||
# -------------------------------
|
||||
# Need to go into separate .obj directories since they will have different
|
||||
# AFLAGS per game.
|
||||
{th04}.asm{bin\th04}.obj:
|
||||
$(AS) /dGAME=4 $**, $@
|
||||
{th04}.asm{bin\th05}.obj:
|
||||
$(AS) /dGAME=5 $**, $@
|
||||
# -------------------------------
|
||||
|
||||
.obj.exe:
|
||||
$(CC) $(CFLAGS) -ml $**
|
||||
|
||||
|
@ -73,7 +83,14 @@ bin\th04\op.exe: bin\th04\op.obj th04\op_02.c
|
|||
$**
|
||||
|
|
||||
|
||||
bin\th05\main.exe: bin\th05\main.obj th05\main_01.cpp
|
||||
bin\th04\scoreupd.obj: th04\scoreupd.asm
|
||||
bin\th04\main.exe: bin\th04\main.obj bin\th04\scoreupd.obj
|
||||
$(CC) $(CFLAGS) -ml -DGAME=4 -nbin\th04\ -eMAIN.EXE @&&|
|
||||
$**
|
||||
|
|
||||
|
||||
bin\th05\scoreupd.obj: th04\scoreupd.asm
|
||||
bin\th05\main.exe: bin\th05\main.obj bin\th05\scoreupd.obj th05\main012.cpp
|
||||
$(CC) $(CFLAGS) -ml -3 -Z -DGAME=5 -nbin\th05\ -eMAIN.EXE @&&|
|
||||
$**
|
||||
|
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
; ReC98
|
||||
; Relevant function definitions from master.h, together with the necessary
|
||||
; types. Meant as a master.h equivalent for standalone, non-slice ASM
|
||||
; translation units.
|
||||
|
||||
include libs/master.lib/macros.inc
|
||||
|
||||
GAIJI_PUTSA procdesc pascal far \
|
||||
x:word, y:word, strp_seg:word, strp_off:word, atrb:word
|
|
@ -1,9 +0,0 @@
|
|||
public _POWERS_OF_10_LONG
|
||||
_POWERS_OF_10_LONG label dword
|
||||
dd 1000000
|
||||
dd 100000
|
||||
dd 10000
|
||||
dd 1000
|
||||
dd 100
|
||||
dd 10
|
||||
dd 1
|
|
@ -0,0 +1,71 @@
|
|||
HUD_CONTINUES_X = HUD_X + ((SCORE_DIGITS - 1) * 2)
|
||||
|
||||
; Only prints the seven score digits, in contrast to the TH04/TH05 version!
|
||||
|
||||
; void pascal near hud_score_put(unsigned int y, long value);
|
||||
public HUD_SCORE_PUT
|
||||
hud_score_put proc near
|
||||
@@result = word ptr [bp-4]
|
||||
@@digit = word ptr [bp-2]
|
||||
@@value = dword ptr [bp+4]
|
||||
@@y = word ptr [bp+8]
|
||||
|
||||
push bp
|
||||
mov bp, sp
|
||||
sub sp, 4
|
||||
push si
|
||||
push di
|
||||
mov si, offset _SEVEN_DIGIT_POWERS_OF_10
|
||||
mov di, HUD_X
|
||||
jmp short @@more_digits?
|
||||
|
||||
@@put:
|
||||
mov eax, @@value
|
||||
cdq
|
||||
idiv dword ptr [si]
|
||||
mov @@result, ax
|
||||
movsx eax, @@result
|
||||
imul eax, [si]
|
||||
sub @@value, eax
|
||||
add si, 4
|
||||
mov ax, @@result
|
||||
add ax, GB_DIGITS
|
||||
mov @@digit, ax
|
||||
call gaiji_putca pascal, di, @@y, ax, TX_WHITE
|
||||
add di, 2
|
||||
|
||||
@@more_digits?:
|
||||
cmp di, HUD_CONTINUES_X
|
||||
jl short @@put
|
||||
pop di
|
||||
pop si
|
||||
leave
|
||||
retn 6
|
||||
hud_score_put endp
|
||||
|
||||
|
||||
; void pascal near hud_continues_put(unsigned int y, int continues_used);
|
||||
public HUD_CONTINUES_PUT
|
||||
hud_continues_put proc near
|
||||
|
||||
@@continues_displayed = word ptr [bp-2]
|
||||
@@continues_used = word ptr [bp+4]
|
||||
@@y = word ptr [bp+6]
|
||||
|
||||
push bp
|
||||
mov bp, sp
|
||||
sub sp, 2
|
||||
push si
|
||||
mov si, @@continues_used
|
||||
cmp si, 10
|
||||
jl short @@put
|
||||
mov si, 9
|
||||
|
||||
@@put:
|
||||
lea ax, [si+GB_DIGITS]
|
||||
mov @@continues_displayed, ax
|
||||
call gaiji_putca pascal, HUD_CONTINUES_X, @@y, ax, TX_WHITE
|
||||
pop si
|
||||
leave
|
||||
retn 4
|
||||
hud_continues_put endp
|
|
@ -0,0 +1,9 @@
|
|||
public _SEVEN_DIGIT_POWERS_OF_10
|
||||
_SEVEN_DIGIT_POWERS_OF_10 label dword
|
||||
dd 1000000
|
||||
dd 100000
|
||||
dd 10000
|
||||
dd 1000
|
||||
dd 100
|
||||
dd 10
|
||||
dd 1
|
|
@ -3,7 +3,7 @@ include defconv_c.inc
|
|||
|
||||
include th02/hardware/input.inc
|
||||
include th02/math/randring_next.inc
|
||||
include th02/gaiji_boldfont.inc
|
||||
include th02/gaiji/boldfont.inc
|
||||
include th02/hud/hud.inc
|
||||
include th02/score.inc
|
||||
|
||||
|
|
106
th02_main.asm
106
th02_main.asm
|
@ -6694,81 +6694,7 @@ sub_DC4B proc near
|
|||
retn
|
||||
sub_DC4B endp
|
||||
|
||||
|
||||
; =============== S U B R O U T I N E =======================================
|
||||
|
||||
; Attributes: bp-based frame
|
||||
|
||||
sub_DC55 proc near
|
||||
|
||||
var_4 = word ptr -4
|
||||
var_2 = word ptr -2
|
||||
arg_0 = dword ptr 4
|
||||
arg_4 = word ptr 8
|
||||
|
||||
push bp
|
||||
mov bp, sp
|
||||
sub sp, 4
|
||||
push si
|
||||
push di
|
||||
mov si, offset _POWERS_OF_10_LONG
|
||||
mov di, HUD_X
|
||||
jmp short loc_DC9A
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
loc_DC65:
|
||||
mov eax, [bp+arg_0]
|
||||
cdq
|
||||
idiv dword ptr [si]
|
||||
mov [bp+var_4], ax
|
||||
movsx eax, [bp+var_4]
|
||||
imul eax, [si]
|
||||
sub [bp+arg_0], eax
|
||||
add si, 4
|
||||
mov ax, [bp+var_4]
|
||||
add ax, GB_DIGITS
|
||||
mov [bp+var_2], ax
|
||||
call gaiji_putca pascal, di, [bp+arg_4], ax, TX_WHITE
|
||||
add di, 2
|
||||
|
||||
loc_DC9A:
|
||||
cmp di, HUD_X + ((SCORE_DIGITS - 1) * 2)
|
||||
jl short loc_DC65
|
||||
pop di
|
||||
pop si
|
||||
leave
|
||||
retn 6
|
||||
sub_DC55 endp
|
||||
|
||||
|
||||
; =============== S U B R O U T I N E =======================================
|
||||
|
||||
; Attributes: bp-based frame
|
||||
|
||||
sub_DCA5 proc near
|
||||
|
||||
var_2 = word ptr -2
|
||||
arg_0 = word ptr 4
|
||||
arg_2 = word ptr 6
|
||||
|
||||
push bp
|
||||
mov bp, sp
|
||||
sub sp, 2
|
||||
push si
|
||||
mov si, [bp+arg_0]
|
||||
cmp si, 0Ah
|
||||
jl short loc_DCB7
|
||||
mov si, 9
|
||||
|
||||
loc_DCB7:
|
||||
lea ax, [si+GB_DIGITS]
|
||||
mov [bp+var_2], ax
|
||||
call gaiji_putca pascal, HUD_X + ((SCORE_DIGITS - 1) * 2), [bp+arg_2], ax, TX_WHITE
|
||||
pop si
|
||||
leave
|
||||
retn 4
|
||||
sub_DCA5 endp
|
||||
|
||||
include th02/hud/score_put.asm
|
||||
|
||||
; =============== S U B R O U T I N E =======================================
|
||||
|
||||
|
@ -6885,16 +6811,12 @@ loc_DDCE:
|
|||
mov dword_218AC, eax
|
||||
movzx eax, word_218B0
|
||||
add dword_1E598, eax
|
||||
push 6
|
||||
pushd [dword_1E598]
|
||||
call sub_DC55
|
||||
call hud_score_put pascal, 6, large [dword_1E598]
|
||||
mov eax, dword_1E598
|
||||
cmp eax, dword_252F8
|
||||
jle short loc_DE01
|
||||
mov dword_252F8, eax
|
||||
push 4
|
||||
push eax
|
||||
call sub_DC55
|
||||
call hud_score_put pascal, 4, eax
|
||||
|
||||
loc_DE01:
|
||||
mov bx, word_1E5B6
|
||||
|
@ -6944,16 +6866,12 @@ sub_DE4E proc far
|
|||
mov bp, sp
|
||||
mov eax, dword_218AC
|
||||
add dword_1E598, eax
|
||||
push 6
|
||||
pushd [dword_1E598]
|
||||
call sub_DC55
|
||||
call hud_score_put pascal, 6, large [dword_1E598]
|
||||
mov eax, dword_1E598
|
||||
cmp eax, dword_252F8
|
||||
jle short loc_DE7A
|
||||
mov dword_252F8, eax
|
||||
push 4
|
||||
push eax
|
||||
call sub_DC55
|
||||
call hud_score_put pascal, 4, eax
|
||||
|
||||
loc_DE7A:
|
||||
mov bx, word_1E5B6
|
||||
|
@ -7185,23 +7103,19 @@ sub_E012 proc near
|
|||
push bp
|
||||
mov bp, sp
|
||||
call gaiji_putsa pascal, (61 shl 16) + 5, ds, offset gsSCORE, TX_YELLOW
|
||||
push 6
|
||||
pushd [dword_1E598]
|
||||
call sub_DC55
|
||||
call hud_score_put pascal, 6, large [dword_1E598]
|
||||
push 6
|
||||
les bx, mikoconfig
|
||||
assume es:nothing
|
||||
push es:[bx+mikoconfig_t.continues_used]
|
||||
call sub_DCA5
|
||||
call hud_continues_put
|
||||
call gaiji_putsa pascal, (60 shl 16) + 3, ds, offset gsHISCORE, TX_YELLOW
|
||||
push 4
|
||||
pushd [dword_252F8]
|
||||
call sub_DC55
|
||||
call hud_score_put pascal, 4, large [dword_252F8]
|
||||
push 4
|
||||
mov al, byte_252FC
|
||||
mov ah, 0
|
||||
push ax
|
||||
call sub_DCA5
|
||||
call hud_continues_put
|
||||
call gaiji_putsa pascal, (57 shl 16) + 17, ds, offset gsREIMU, TX_YELLOW
|
||||
call sub_DF76
|
||||
call gaiji_putsa pascal, (57 shl 16) + 15, ds, offset gsREIGEKI, TX_YELLOW
|
||||
|
@ -34557,7 +34471,7 @@ bombs db 3
|
|||
db 5
|
||||
word_1E5B6 dw 0
|
||||
dword_1E5B8 dd 9C40h
|
||||
include th02/hud/number_put[data].asm
|
||||
include th02/hud/score_put[data].asm
|
||||
word_1E5D8 dw 4140h
|
||||
word_1E5DA dw 4342h
|
||||
word_1E5DC dw 44h
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
; Shared buffer for one full row of gaiji characters. Used for temporarily
|
||||
; storing the two scores, and the enemy health, dream, and power bars.
|
||||
HUD_TRAM_W = 8
|
||||
public _hud_gaiji_row
|
||||
public _HUD_GAIJI_ROW
|
||||
_hud_gaiji_row db (HUD_TRAM_W + 1) dup (0)
|
||||
db 0 ; (word alignment)
|
|
@ -1,6 +1,6 @@
|
|||
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 _overlay_text_fp, _popup_fp, _popup_byte_unknown, _popup_bonus
|
||||
public _popup_cur_tram_x, _popup_dest_tram_x, _bgm_title_id, _POPUP_ID_NEW
|
||||
public _overlay_text_fp, _POPUP_FP, _popup_byte_unknown, _popup_bonus
|
||||
_popup_gaiji_len dw ?
|
||||
_popup_id_cur db ?
|
||||
_popup_dest_reached db ?
|
||||
|
|
|
@ -3,17 +3,15 @@
|
|||
; which is then taken "times 10" ([score_delta] += 1 → 10 more on-screen
|
||||
; points).
|
||||
|
||||
; Also ignoring the last digit. (= 61,110 points)
|
||||
SCORE_DELTA_FRAME_LIMIT = 6111
|
||||
|
||||
public _continues_used, _score_lebcd, _hiscore_lebcd
|
||||
public _score_delta, _score_delta_frame
|
||||
public _CONTINUES_USED, _SCORE_LEBCD, _HISCORE_LEBCD
|
||||
public _SCORE_DELTA, _SCORE_DELTA_FRAME
|
||||
|
||||
label _continues_used byte
|
||||
_score_lebcd db SCORE_DIGITS dup(?)
|
||||
_hiscore_lebcd db SCORE_DIGITS dup(?)
|
||||
|
||||
if GAME eq 4
|
||||
public _SCORE_UNUSED
|
||||
_score_unused db ?
|
||||
endif
|
||||
_score_delta dd ?
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
public _is_hiscore
|
||||
_is_hiscore db 0
|
||||
public _HISCORE_POPUP_SHOWN
|
||||
_hiscore_popup_shown db 0
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
.386
|
||||
locals
|
||||
|
||||
include libs/master.lib/master.inc
|
||||
include th02/hud/hud.inc
|
||||
include th04/hud/popup.inc
|
||||
include th02/score.inc
|
||||
include th02/gaiji/boldfont.inc
|
||||
|
||||
SCORE_DIGIT_HIGHEST = SCORE_DIGITS - 1
|
||||
; Also ignoring the last digit. (= 61,110 points)
|
||||
SCORE_DELTA_FRAME_LIMIT = 6111
|
||||
if SCORE_DELTA_FRAME_LIMIT ge 100000
|
||||
.err "SCORE_DELTA_FRAME_LIMIT can't have more than 5 decimal digits"
|
||||
endif
|
||||
|
||||
; Declaring everything here rather than inside a segment avoids fixup
|
||||
; overflows… yup.
|
||||
|
||||
extrn _score_lebcd:byte:SCORE_DIGITS
|
||||
extrn _hiscore_lebcd:byte:SCORE_DIGITS
|
||||
extrn _hiscore_popup_shown:byte
|
||||
extrn _score_delta:dword
|
||||
extrn _score_delta_frame:dword
|
||||
|
||||
extrn _FIVE_DIGIT_POWERS_OF_10:word
|
||||
|
||||
extrn _hud_gaiji_row:byte:SCORE_DIGITS
|
||||
|
||||
extrn _popup_id_new:byte
|
||||
extrn _popup_fp:word
|
||||
POPUP_UPDATE_AND_RENDER procdesc near
|
||||
|
||||
if GAME eq 4
|
||||
extrn _score_unused:byte
|
||||
extrn _temp_lebcd:byte
|
||||
SCORE_EXTEND_UPDATE procdesc near
|
||||
else
|
||||
_temp_lebcd equ _hud_gaiji_row
|
||||
endif
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
|
||||
main_01_TEXT segment word public 'CODE' use16
|
||||
assume cs:main_01_TEXT
|
||||
|
||||
; ============================================================================
|
||||
|
||||
; Renders both the current and high score. In contrast to TH02, it also
|
||||
; displays the continues digit.
|
||||
|
||||
; void pascal near hud_score_put(void);
|
||||
public HUD_SCORE_PUT
|
||||
hud_score_put proc pascal near
|
||||
@@gaiji_p equ bx
|
||||
@@score_p equ si
|
||||
@@y equ di
|
||||
|
||||
push si
|
||||
push di
|
||||
|
||||
mov @@score_p, offset _hiscore_lebcd[SCORE_DIGIT_HIGHEST]
|
||||
mov @@y, 4
|
||||
|
||||
@@lebcd_to_gaiji:
|
||||
mov cx, SCORE_DIGITS
|
||||
mov @@gaiji_p, offset _hud_gaiji_row
|
||||
|
||||
@@digit_loop:
|
||||
mov al, [@@score_p]
|
||||
add al, GB_DIGITS
|
||||
mov [@@gaiji_p], al
|
||||
inc @@gaiji_p
|
||||
dec @@score_p
|
||||
loop @@digit_loop
|
||||
call gaiji_putsa pascal, HUD_X, @@y, ds, offset _hud_gaiji_row, TX_WHITE
|
||||
add @@y, 2
|
||||
|
||||
; Put exactly two lines, high score at (56, 4), and current score at
|
||||
; (56, 6).
|
||||
; You might notice that @@score_p is only assigned once. Yes, the code
|
||||
; assumes that @@score_p now points at the end of _score_lebcd, which in
|
||||
; turn assumes it's placed exactly before _hiscore_lebcd in memory, with
|
||||
; no padding.
|
||||
cmp @@y, 6
|
||||
jz @@lebcd_to_gaiji
|
||||
|
||||
; And if that wasn't enough already, ZUN pops the registers in the wrong
|
||||
; order. Good thing it doesn't matter for any caller of this function!
|
||||
;
|
||||
; This could have easily been fixed by either defining two (or better,
|
||||
; three) LOCAL variables, or the USES directive if you *really* insist on
|
||||
; using registers. Both of which would have automatically inserted the
|
||||
; correct cleanup instructions before RET. Even in the 90's, "using an
|
||||
; assembler" did very much *not* mean "having to manually spell out every
|
||||
; instruction executed on the CPU"…
|
||||
pop si
|
||||
pop di
|
||||
ret
|
||||
hud_score_put endp
|
||||
|
||||
; ============================================================================
|
||||
|
||||
; void pascal near score_update_and_render(void);
|
||||
public SCORE_UPDATE_AND_RENDER
|
||||
score_update_and_render proc near
|
||||
|
||||
; The TH04 version is functionally identical, just less optimized.
|
||||
if GAME eq 5
|
||||
@@delta_remaining_word equ dx
|
||||
@@delta_remaining_char equ dl
|
||||
else
|
||||
@@delta_remaining_word equ cx
|
||||
@@delta_remaining_char equ cl
|
||||
endif
|
||||
|
||||
mov eax, _score_delta
|
||||
or eax, eax
|
||||
jz short @@ret
|
||||
cmp _score_delta_frame, eax
|
||||
jbe short @@calculate_frame_delta
|
||||
mov word ptr _score_delta_frame, ax
|
||||
|
||||
@@calculate_frame_delta:
|
||||
shr eax, 5
|
||||
or eax, eax
|
||||
jnz short @@clamp_delta_to_frame_limit
|
||||
inc ax
|
||||
jmp short @@prefer_larger_delta
|
||||
|
||||
@@clamp_delta_to_frame_limit:
|
||||
cmp eax, SCORE_DELTA_FRAME_LIMIT
|
||||
jbe short @@prefer_larger_delta
|
||||
mov ax, SCORE_DELTA_FRAME_LIMIT
|
||||
|
||||
@@prefer_larger_delta:
|
||||
cmp word ptr _score_delta_frame, ax
|
||||
jnb short @@commit_frame_delta
|
||||
mov word ptr _score_delta_frame, ax
|
||||
|
||||
@@commit_frame_delta:
|
||||
mov @@delta_remaining_word, word ptr _score_delta_frame
|
||||
jmp short @@update
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
@@render:
|
||||
cmp _hiscore_popup_shown, 0
|
||||
jnz short @@subtract_frame_delta_and_render
|
||||
or al, al
|
||||
jz short @@subtract_frame_delta_and_render
|
||||
mov _hiscore_popup_shown, 1
|
||||
mov _popup_id_new, POPUP_ID_HISCORE_ENTRY
|
||||
mov _popup_fp, offset popup_update_and_render
|
||||
|
||||
@@subtract_frame_delta_and_render:
|
||||
mov eax, _score_delta_frame
|
||||
sub _score_delta, eax
|
||||
call hud_score_put
|
||||
if GAME eq 4
|
||||
mov _score_unused, 0
|
||||
call score_extend_update
|
||||
endif
|
||||
|
||||
@@ret:
|
||||
retn
|
||||
; ---------------------------------------------------------------------------
|
||||
even
|
||||
|
||||
@@update:
|
||||
push si
|
||||
push di
|
||||
if GAME eq 5
|
||||
push ds
|
||||
pop es
|
||||
|
||||
@@bcd_p equ di
|
||||
@@po10_p equ bx
|
||||
|
||||
; Since the delta can have at most 5 digits, we only have to work on the
|
||||
; range from _temp_lebcd[4] (highest) to _temp_lebcd[0] (lowest).
|
||||
; Zeroing the remaining 3 digits is simply more convenient to do in a
|
||||
; single 32-bit instruction if _temp_lebcd[4] is also (unnecessarily)
|
||||
; zeroed.
|
||||
mov dword ptr _temp_lebcd[4], 0
|
||||
else
|
||||
@@bcd_p equ bx
|
||||
@@po10_p equ si
|
||||
endif
|
||||
mov @@bcd_p, offset _temp_lebcd[4]
|
||||
mov @@po10_p, offset _FIVE_DIGIT_POWERS_OF_10
|
||||
if GAME eq 5
|
||||
; 4 divisions, the units place doesn't need a separate one.
|
||||
mov cx, 4
|
||||
endif
|
||||
|
||||
@@delta_to_bcd:
|
||||
mov ax, @@delta_remaining_word
|
||||
; 16-bit DIV interprets DX:AX as a 32-bit divisor…
|
||||
xor dx, dx
|
||||
; … and returns the remainder in DX, so we actually aren't losing
|
||||
; anything here.
|
||||
div word ptr [@@po10_p]
|
||||
if GAME eq 5
|
||||
add @@po10_p, 2
|
||||
else
|
||||
mov @@delta_remaining_word, dx
|
||||
endif
|
||||
|
||||
mov [@@bcd_p], al
|
||||
dec @@bcd_p
|
||||
|
||||
if GAME eq 5
|
||||
loop @@delta_to_bcd
|
||||
else
|
||||
add @@po10_p, 2
|
||||
cmp word ptr [@@po10_p], 1
|
||||
ja @@delta_to_bcd
|
||||
endif
|
||||
|
||||
@@last_digit:
|
||||
mov [@@bcd_p], @@delta_remaining_char
|
||||
|
||||
; Obviously skipping the continues digit…
|
||||
mov si, offset _score_lebcd[1]
|
||||
; … and the last one seen from there doesn't need special BCD treatment
|
||||
; either.
|
||||
mov cx, SCORE_DIGITS - 2
|
||||
; Yes, completely unnecessary in TH05, considering the next instruction.
|
||||
xor ah, ah
|
||||
|
||||
; @@bcd_p == _temp_lebcd[0]
|
||||
@@add_next_digit_to_score:
|
||||
if GAME eq 5
|
||||
movzx ax, byte ptr [@@bcd_p]
|
||||
else
|
||||
mov al, [@@bcd_p]
|
||||
endif
|
||||
add al, [si]
|
||||
aaa ; AL < 9, AH = carry
|
||||
mov [si], al
|
||||
inc @@bcd_p
|
||||
inc si
|
||||
; Add the carry to next score digit. May now be 0Ah, but who cares, it's
|
||||
; fixed via AAA on the next digit anyway… *except* if it's already the
|
||||
; highest one, which is exactly where the infamous >100 million score
|
||||
; glitch comes from.
|
||||
add [si], ah
|
||||
if GAME eq 4
|
||||
mov ah, 0
|
||||
endif
|
||||
loop @@add_next_digit_to_score
|
||||
mov al, [@@bcd_p]
|
||||
add [si], al
|
||||
|
||||
; Is this the high score?
|
||||
@@is_hiscore equ dl ; Never read, though
|
||||
|
||||
if GAME eq 4
|
||||
push ds
|
||||
pop es
|
||||
; assume es:_DATA
|
||||
endif
|
||||
mov si, offset _score_lebcd[SCORE_DIGIT_HIGHEST]
|
||||
mov di, offset _hiscore_lebcd[SCORE_DIGIT_HIGHEST]
|
||||
xor @@is_hiscore, @@is_hiscore
|
||||
mov cx, SCORE_DIGITS
|
||||
cmp _hiscore_popup_shown, 0
|
||||
jnz short @@hiscore_confirmed
|
||||
|
||||
@@check_next_digit_for_hiscore:
|
||||
mov al, [si]
|
||||
cmp [di], al
|
||||
ja short @@hiscore_denied
|
||||
jb short @@hiscore_confirmed
|
||||
dec di
|
||||
dec si
|
||||
loop @@check_next_digit_for_hiscore
|
||||
|
||||
@@hiscore_confirmed:
|
||||
; Copy the remaining number of digits in CX, backwards (STD!)
|
||||
if GAME eq 5
|
||||
cli
|
||||
endif
|
||||
std
|
||||
rep movsb
|
||||
cld
|
||||
if GAME eq 5
|
||||
sti
|
||||
endif
|
||||
inc @@is_hiscore
|
||||
|
||||
@@hiscore_denied:
|
||||
mov al, @@is_hiscore
|
||||
pop di
|
||||
pop si
|
||||
jmp @@render
|
||||
score_update_and_render endp
|
||||
main_01_TEXT ends
|
||||
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
public _FIVE_DIGIT_POWERS_OF_10
|
||||
_FIVE_DIGIT_POWERS_OF_10 dw 10000, 1000, 100, 10, 1
|
||||
|
||||
if GAME eq 4
|
||||
; Temporary BCD conversion buffer. TH05 just uses _hud_gaiji_row instead.
|
||||
public _TEMP_LEBCD
|
||||
_temp_lebcd db SCORE_DIGITS dup(0)
|
||||
endif
|
|
@ -125,6 +125,7 @@ void pascal far explosions_small_reset(void);
|
|||
|
||||
/// Score
|
||||
/// -----
|
||||
#define score_delta SCORE_DELTA
|
||||
extern unsigned long score_delta;
|
||||
|
||||
void pascal near score_update_and_render(void);
|
||||
|
|
|
@ -14,7 +14,7 @@ include th04/hardware/grcg.inc
|
|||
include th04/hardware/input.inc
|
||||
include th04/math/randring_next.inc
|
||||
include th04/math/motion.inc
|
||||
include th02/gaiji_boldfont.inc
|
||||
include th02/gaiji/boldfont.inc
|
||||
include th04/gaiji.inc
|
||||
include th04/hud/popup.inc
|
||||
include th02/score.inc
|
||||
|
|
198
th04_main.asm
198
th04_main.asm
|
@ -966,7 +966,7 @@ sub_B1D0 proc near
|
|||
call sub_1DA1B
|
||||
call main_01:sub_FFA4
|
||||
call sparks_init
|
||||
call main_01:sub_11692
|
||||
call hud_score_put
|
||||
call sub_15D74
|
||||
call main_01:sub_BCB2
|
||||
nopcall main_01:sub_F204
|
||||
|
@ -6951,7 +6951,7 @@ loc_E796:
|
|||
nopcall main_01:sub_EFA1
|
||||
inc _continues_used
|
||||
call sub_EEB0
|
||||
call sub_11692
|
||||
call hud_score_put
|
||||
mov al, 0
|
||||
jmp short loc_E7DA
|
||||
; ---------------------------------------------------------------------------
|
||||
|
@ -7760,8 +7760,8 @@ playfield_fillm_0_120_384_128 endp
|
|||
; =============== S U B R O U T I N E =======================================
|
||||
|
||||
; Attributes: bp-based frame
|
||||
|
||||
sub_EE06 proc near
|
||||
public SCORE_EXTEND_UPDATE
|
||||
score_extend_update proc near
|
||||
|
||||
var_1 = byte ptr -1
|
||||
|
||||
|
@ -7836,7 +7836,7 @@ loc_EE8C:
|
|||
locret_EEA3:
|
||||
leave
|
||||
retn
|
||||
sub_EE06 endp
|
||||
score_extend_update endp
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
db 0
|
||||
|
@ -7869,7 +7869,7 @@ loc_EEBF:
|
|||
mov _score_delta_frame, 0
|
||||
mov _score_unused, 0
|
||||
mov byte_22DA6, 0
|
||||
mov _is_hiscore, 0
|
||||
mov _hiscore_popup_shown, 0
|
||||
pop si
|
||||
pop bp
|
||||
retn
|
||||
|
@ -8311,7 +8311,7 @@ sub_F204 proc far
|
|||
mov bp, sp
|
||||
call gaiji_putsa pascal, (60 shl 16) + 3, ds offset gsHISCORE, TX_YELLOW
|
||||
call gaiji_putsa pascal, (61 shl 16) + 5, ds offset gsSCORE, TX_YELLOW
|
||||
call sub_11692
|
||||
call hud_score_put
|
||||
les bx, _humaconfig
|
||||
cmp byte ptr es:[bx+12h], 30h ; '0'
|
||||
jnz short loc_F245
|
||||
|
@ -12550,159 +12550,11 @@ loc_1168E:
|
|||
pop bp
|
||||
retn
|
||||
sub_11647 endp
|
||||
|
||||
|
||||
; =============== S U B R O U T I N E =======================================
|
||||
|
||||
|
||||
sub_11692 proc near
|
||||
push si
|
||||
push di
|
||||
mov si, offset _hiscore_lebcd[SCORE_DIGITS - 1]
|
||||
mov di, 4
|
||||
|
||||
loc_1169A:
|
||||
mov cx, SCORE_DIGITS
|
||||
mov bx, 1EC6h
|
||||
|
||||
loc_116A0:
|
||||
mov al, [si]
|
||||
add al, 0A0h
|
||||
mov [bx], al
|
||||
inc bx
|
||||
dec si
|
||||
loop loc_116A0
|
||||
call gaiji_putsa pascal, 56, di, ds, offset unk_23206, TX_WHITE
|
||||
add di, 2
|
||||
cmp di, 6
|
||||
jz short loc_1169A
|
||||
pop si
|
||||
pop di
|
||||
retn
|
||||
sub_11692 endp
|
||||
|
||||
|
||||
; =============== S U B R O U T I N E =======================================
|
||||
|
||||
|
||||
score_update_and_render proc near
|
||||
mov eax, _score_delta
|
||||
or eax, eax
|
||||
jz short locret_1172C
|
||||
cmp _score_delta_frame, eax
|
||||
jbe short loc_116D7
|
||||
mov word ptr _score_delta_frame, ax
|
||||
|
||||
loc_116D7:
|
||||
shr eax, 5
|
||||
or eax, eax
|
||||
jnz short loc_116E3
|
||||
inc ax
|
||||
jmp short loc_116EE
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
loc_116E3:
|
||||
cmp eax, SCORE_DELTA_FRAME_LIMIT
|
||||
jbe short loc_116EE
|
||||
mov ax, SCORE_DELTA_FRAME_LIMIT
|
||||
|
||||
loc_116EE:
|
||||
cmp word ptr _score_delta_frame, ax
|
||||
jnb short loc_116F7
|
||||
mov word ptr _score_delta_frame, ax
|
||||
|
||||
loc_116F7:
|
||||
mov cx, word ptr _score_delta_frame
|
||||
jmp short loc_1172E
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
loc_116FD:
|
||||
cmp _is_hiscore, 0
|
||||
jnz short loc_11718
|
||||
or al, al
|
||||
jz short loc_11718
|
||||
mov _is_hiscore, 1
|
||||
mov _popup_id_new, POPUP_ID_HISCORE_ENTRY
|
||||
mov _popup_fp, offset popup_update_and_render
|
||||
|
||||
loc_11718:
|
||||
mov eax, _score_delta_frame
|
||||
sub _score_delta, eax
|
||||
call sub_11692
|
||||
mov _score_unused, 0
|
||||
call sub_EE06
|
||||
|
||||
locret_1172C:
|
||||
retn
|
||||
; ---------------------------------------------------------------------------
|
||||
nop
|
||||
|
||||
loc_1172E:
|
||||
push si
|
||||
push di
|
||||
mov bx, 1EC2h
|
||||
mov si, 1EB4h
|
||||
|
||||
loc_11736:
|
||||
mov ax, cx
|
||||
xor dx, dx
|
||||
div word ptr [si]
|
||||
mov cx, dx
|
||||
mov [bx], al
|
||||
dec bx
|
||||
add si, 2
|
||||
cmp word ptr [si], 1
|
||||
ja short loc_11736
|
||||
mov [bx], cl
|
||||
mov si, offset _score_lebcd[1]
|
||||
mov cx, SCORE_DIGITS - 2
|
||||
xor ah, ah
|
||||
|
||||
loc_11753:
|
||||
mov al, [bx]
|
||||
add al, [si]
|
||||
aaa
|
||||
mov [si], al
|
||||
inc bx
|
||||
inc si
|
||||
add [si], ah
|
||||
mov ah, 0
|
||||
loop loc_11753
|
||||
mov al, [bx]
|
||||
add [si], al
|
||||
push ds
|
||||
pop es
|
||||
assume es:_DATA
|
||||
mov si, offset _score_lebcd[SCORE_DIGITS - 1]
|
||||
mov di, offset _hiscore_lebcd[SCORE_DIGITS - 1]
|
||||
xor dl, dl
|
||||
mov cx, SCORE_DIGITS
|
||||
cmp _is_hiscore, 0
|
||||
jnz short loc_11786
|
||||
|
||||
loc_1177A:
|
||||
mov al, [si]
|
||||
cmp [di], al
|
||||
ja short loc_1178C
|
||||
jb short loc_11786
|
||||
dec di
|
||||
dec si
|
||||
loop loc_1177A
|
||||
|
||||
loc_11786:
|
||||
std
|
||||
rep movsb
|
||||
cld
|
||||
inc dl
|
||||
|
||||
loc_1178C:
|
||||
mov al, dl
|
||||
pop di
|
||||
pop si
|
||||
jmp loc_116FD
|
||||
score_update_and_render endp
|
||||
main_01_TEXT ends
|
||||
|
||||
HUD_SCORE_PUT procdesc near
|
||||
SCORE_UPDATE_AND_RENDER procdesc near
|
||||
|
||||
main_011_TEXT segment byte public 'CODE' use16
|
||||
assume cs:main_01
|
||||
|
||||
|
@ -40873,34 +40725,8 @@ aVivavvvvilcvb@ db '
|
|||
aPnpcuyszlB@bCa db '<27><EFBFBD>—ãY‘z‹È<E280B9>@<40>` Capriccio ',0
|
||||
include th04/formats/bb_txt_load[data].asm
|
||||
word_231F2 dw 10h
|
||||
db 10h
|
||||
db 27h ; '
|
||||
db 0E8h
|
||||
db 3
|
||||
db 64h ; d
|
||||
db 0
|
||||
db 0Ah
|
||||
db 0
|
||||
db 1
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
unk_23206 db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
include th04/scoreupd[data].asm
|
||||
include th04/hud/gaiji_row[data].asm
|
||||
word_23210 dw 0
|
||||
byte_23212 db 0
|
||||
db 0
|
||||
|
|
|
@ -15,7 +15,7 @@ pushstate
|
|||
nosmart
|
||||
lea di, _hud_gaiji_row + (SCORE_DIGITS - 5)
|
||||
movzx edx, [bp+@@val]
|
||||
lea bx, _POWERS_OF_10_LONG + (2 * 4)
|
||||
lea bx, _SEVEN_DIGIT_POWERS_OF_10 + (2 * 4)
|
||||
popstate
|
||||
mov ax, [bp+@@atrb]
|
||||
mov cx, 4
|
||||
|
@ -43,7 +43,7 @@ hud_points_put proc far
|
|||
mov di, offset _hud_gaiji_row
|
||||
mov ax, TX_WHITE
|
||||
mov _hud_gaiji_row[SCORE_DIGITS - 1], gb_0_ ; ("continues used" digit)
|
||||
mov bx, offset _POWERS_OF_10_LONG
|
||||
mov bx, offset _SEVEN_DIGIT_POWERS_OF_10
|
||||
mov cx, SCORE_DIGITS - 2
|
||||
|
||||
hud_digits_put:
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
/* ReC98
|
||||
* -----
|
||||
* Code segment #1 of TH05's MAIN.EXE
|
||||
* 2nd part of code segment #1 of TH05's MAIN.EXE
|
||||
*/
|
||||
|
||||
#pragma codeseg main_01_TEXT
|
||||
|
||||
extern "C" {
|
||||
#include "th05/th05.hpp"
|
||||
|
175
th05_main.asm
175
th05_main.asm
|
@ -1112,7 +1112,7 @@ sub_B55A proc near
|
|||
call sub_16D67
|
||||
call sub_C473
|
||||
call sparks_init
|
||||
call sub_143CA
|
||||
call hud_score_put
|
||||
call sub_C29E
|
||||
nopcall sub_106F3
|
||||
mov fp_23F5A, offset tiles_render_all
|
||||
|
@ -8896,7 +8896,7 @@ loc_FBB5:
|
|||
nopcall sub_104BB
|
||||
inc _continues_used
|
||||
call sub_10398
|
||||
call sub_143CA
|
||||
call hud_score_put
|
||||
mov al, 0
|
||||
jmp short loc_FBF7
|
||||
; ---------------------------------------------------------------------------
|
||||
|
@ -9481,7 +9481,7 @@ loc_103E9:
|
|||
jg short loc_103A4
|
||||
mov _score_delta, 0
|
||||
mov _score_delta_frame, 0
|
||||
mov _is_hiscore, 0
|
||||
mov _hiscore_popup_shown, 0
|
||||
pop si
|
||||
pop bp
|
||||
retn
|
||||
|
@ -9865,7 +9865,7 @@ sub_106F3 proc far
|
|||
mov bp, sp
|
||||
call gaiji_putsa pascal, (60 shl 16) + 3, ds offset gsHISCORE, TX_YELLOW
|
||||
call gaiji_putsa pascal, (61 shl 16) + 5, ds offset gsSCORE, TX_YELLOW
|
||||
call sub_143CA
|
||||
call hud_score_put
|
||||
mov al, playchar
|
||||
mov ah, 0
|
||||
mov bx, ax
|
||||
|
@ -17712,156 +17712,8 @@ loc_143C1:
|
|||
retn 6
|
||||
sub_1437E endp
|
||||
|
||||
|
||||
; =============== S U B R O U T I N E =======================================
|
||||
|
||||
|
||||
sub_143CA proc near
|
||||
push si
|
||||
push di
|
||||
mov si, offset _hiscore_lebcd[SCORE_DIGITS - 1]
|
||||
mov di, 4
|
||||
|
||||
loc_143D2:
|
||||
mov cx, HUD_TRAM_W
|
||||
mov bx, offset _hud_gaiji_row
|
||||
|
||||
loc_143D8:
|
||||
mov al, [si]
|
||||
add al, 0A0h
|
||||
mov [bx], al
|
||||
inc bx
|
||||
dec si
|
||||
loop loc_143D8
|
||||
call gaiji_putsa pascal, 56, di, ds, offset _hud_gaiji_row, TX_WHITE
|
||||
add di, 2
|
||||
cmp di, 6
|
||||
jz short loc_143D2
|
||||
pop si
|
||||
pop di
|
||||
retn
|
||||
sub_143CA endp
|
||||
|
||||
|
||||
; =============== S U B R O U T I N E =======================================
|
||||
;uth05win:CStage::StepScore()
|
||||
;;_score_delta==curDelta=m_curScore-m_drawScore
|
||||
public SCORE_UPDATE_AND_RENDER
|
||||
score_update_and_render proc near
|
||||
mov eax, _score_delta
|
||||
or eax, eax ;if (eax==0)
|
||||
jz short locret_1445C ; goto locret_1445C
|
||||
cmp _score_delta_frame, eax ;if (m_drawScoreDelta<=m_curScore-m_drawScore)
|
||||
jbe short loc_1440F ; goto loc_1440F
|
||||
mov word ptr _score_delta_frame, ax;m_drawScoreDelta=curDelta;
|
||||
|
||||
loc_1440F:
|
||||
shr eax, 5 ;curDelta/=32
|
||||
or eax, eax ;if (curDelta!=0)
|
||||
jnz short loc_1441B ; goto loc_1441B
|
||||
inc ax ;curDelta=1
|
||||
jmp short loc_14426 ;goto loc_14426
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
loc_1441B:
|
||||
cmp eax, SCORE_DELTA_FRAME_LIMIT
|
||||
jbe short loc_14426 ; goto loc_14426
|
||||
mov ax, SCORE_DELTA_FRAME_LIMIT
|
||||
|
||||
loc_14426:
|
||||
cmp word ptr _score_delta_frame, ax
|
||||
jnb short loc_1442F
|
||||
mov word ptr _score_delta_frame, ax
|
||||
|
||||
loc_1442F:
|
||||
mov dx, word ptr _score_delta_frame
|
||||
jmp short loc_1445E
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
loc_14435:
|
||||
cmp _is_hiscore, 0
|
||||
jnz short loc_14450
|
||||
or al, al
|
||||
jz short loc_14450
|
||||
mov _is_hiscore, 1
|
||||
mov _popup_id_new, POPUP_ID_HISCORE_ENTRY
|
||||
mov _popup_fp, offset popup_update_and_render
|
||||
|
||||
loc_14450:
|
||||
mov eax, _score_delta_frame
|
||||
sub _score_delta, eax
|
||||
call sub_143CA
|
||||
|
||||
locret_1445C:
|
||||
retn
|
||||
; ---------------------------------------------------------------------------
|
||||
nop
|
||||
|
||||
loc_1445E:
|
||||
push si
|
||||
push di
|
||||
push ds
|
||||
pop es
|
||||
mov dword ptr _hud_gaiji_row[4], 0
|
||||
mov di, offset _hud_gaiji_row[4]
|
||||
mov bx, 1FBCh
|
||||
mov cx, 4
|
||||
|
||||
loc_14474:
|
||||
mov ax, dx
|
||||
xor dx, dx
|
||||
div word ptr [bx]
|
||||
add bx, 2
|
||||
mov [di], al
|
||||
dec di
|
||||
loop loc_14474
|
||||
mov [di], dl
|
||||
mov si, offset _score_lebcd[1]
|
||||
mov cx, SCORE_DIGITS - 2
|
||||
xor ah, ah
|
||||
|
||||
loc_1448C:
|
||||
movzx ax, byte ptr [di]
|
||||
add al, [si]
|
||||
aaa
|
||||
mov [si], al
|
||||
inc di
|
||||
inc si
|
||||
add [si], ah
|
||||
loop loc_1448C
|
||||
mov al, [di]
|
||||
add [si], al
|
||||
mov si, offset _score_lebcd[SCORE_DIGITS - 1]
|
||||
mov di, offset _hiscore_lebcd[SCORE_DIGITS - 1]
|
||||
xor dl, dl
|
||||
mov cx, SCORE_DIGITS
|
||||
cmp _is_hiscore, 0
|
||||
jnz short loc_144BC
|
||||
|
||||
loc_144B0:
|
||||
mov al, [si]
|
||||
cmp [di], al
|
||||
ja short loc_144C4
|
||||
jb short loc_144BC
|
||||
dec di
|
||||
dec si
|
||||
loop loc_144B0
|
||||
|
||||
loc_144BC:
|
||||
cli
|
||||
std
|
||||
rep movsb
|
||||
cld
|
||||
sti
|
||||
inc dl
|
||||
|
||||
loc_144C4:
|
||||
mov al, dl
|
||||
pop di
|
||||
pop si
|
||||
jmp loc_14435
|
||||
score_update_and_render endp
|
||||
|
||||
HUD_SCORE_PUT procdesc near
|
||||
SCORE_UPDATE_AND_RENDER procdesc near
|
||||
BOSS_RESET procdesc near
|
||||
BB_STAGE_LOAD procdesc near
|
||||
BB_STAGE_FREE procdesc near
|
||||
|
@ -38280,18 +38132,9 @@ SHOT_FUNCS label word
|
|||
dw shot_yuuka_l9
|
||||
byte_2297E db 0
|
||||
db 0
|
||||
include th02/hud/number_put[data].asm
|
||||
db 10h
|
||||
db 27h ; '
|
||||
db 0E8h
|
||||
db 3
|
||||
db 64h ; d
|
||||
db 0
|
||||
db 0Ah
|
||||
db 0
|
||||
db 1
|
||||
db 0
|
||||
include th05/hud/gaiji_row[data].asm
|
||||
include th02/hud/score_put[data].asm
|
||||
include th04/scoreupd[data].asm
|
||||
include th04/hud/gaiji_row[data].asm
|
||||
db 0
|
||||
db 0
|
||||
db 3
|
||||
|
|
Loading…
Reference in New Issue