[Decompilation] [th04/th05] MAINE.EXE: main()

So anticlimactic, again…
Also, note how renaming the `end_sequence_t` constants to better match
their usage also simplifies the explanatory comment for TH04's
not-quirk.

Part of P0265, funded by [Anonymous] and iruleatgames.
This commit is contained in:
nmlgc 2024-01-21 13:55:07 +01:00
parent 1de8585136
commit fd0c95dcd1
9 changed files with 132 additions and 226 deletions

View File

@ -1,6 +1,6 @@
typedef enum {
ES_1CC = 0xFF,
ES_CONTINUED = 0xFE,
ES_GOOD = 0xFF,
ES_BAD = 0xFE,
ES_EXTRA = 0xFD,
ES_INGAME = 0x37,
ES_SCORE = 0,

View File

@ -1,5 +1,5 @@
ES_1CC = 0FFh
ES_CONTINUED = 0FEh
ES_GOOD = 0FFh
ES_BAD = 0FEh
ES_EXTRA = 0FDh
ES_INGAME = 037h
ES_SCORE = 0

View File

@ -4,20 +4,38 @@
#include "pc98.h"
#include "planar.h"
#include "master.hpp"
#include "libs/kaja/kaja.h"
#include "th01/rank.h"
#include "th02/hardware/frmdelay.h"
extern "C" {
#include "th03/formats/cdg.h"
#if (GAME == 4)
#include "th03/formats/pi.hpp"
#include "th04/hardware/input.h"
#endif
}
#include "th03/formats/cfg_impl.hpp"
#include "th03/core/initexit.h"
#include "th03/cutscene/cutscene.hpp"
#include "th04/score.h"
extern "C" {
#include "th04/snd/snd.h"
}
#include "th04/end/end.h"
#include "th04/end/staff.hpp"
#include "th04/end/verdict.hpp"
#include "th04/hiscore/regist.hpp"
#if (GAME == 5)
#include "th04/shiftjis/fnshared.hpp"
#include "th05/mem.h"
#include "th05/resident.hpp"
#include "th05/shiftjis/fns.hpp"
#include "th05/end/allcast.hpp"
#else
#include "th03/shiftjis/fnshared.hpp"
#include "th04/mem.h"
#include "th04/resident.hpp"
#include "th04/shiftjis/fns.hpp"
#endif
resident_t far* resident;
@ -44,8 +62,8 @@ void pascal near game_exit_and_exec(char* fn)
void near end_animate(void)
{
#if (GAME == 5)
static char* SCRIPT_FN = "_ED00.TXT\0" OP_AND_END_PF_FN "\0" SE_FN;
if(resident->end_sequence == ES_CONTINUED) {
static char* SCRIPT_FN = "_ED00.TXT";
if(resident->end_sequence == ES_BAD) {
SCRIPT_FN[3] = '0';
} else if(resident->end_sequence == ES_EXTRA) {
SCRIPT_FN[3] = '2';
@ -63,3 +81,101 @@ void near end_animate(void)
cutscene_animate();
cutscene_script_free();
}
#define congratulations_animate(pic_fn) { \
/* \
* ZUN bloat: The hardware palette is entirely black when we get here, and \
* we don't flip any pages, so the picture could have been just blitted to \
* VRAM page #0. \
* (Would have also been nice to add a palette_black() call here, as an \
* assert() of sorts.) \
*/ \
graph_accesspage(1); \
pi_load_put_8_free(0, pic_fn); \
graph_copy_page(0); \
\
palette_black_in(1); \
input_wait_for_change(0); \
palette_black_out(4); \
}
inline void delay_then_regist_menu(void) {
#if (GAME == 4)
frame_delay(100);
#endif
regist_menu();
}
void main(void)
{
#if (GAME == 4)
char* congratulations_pic_fn = "CONG00.pi";
#endif
if(!cfg_load_resident_ptr()) {
return;
}
#if (GAME == 4)
congratulations_pic_fn[4] = resident->playchar_ascii;
#endif
mem_assign_paras = MEM_ASSIGN_PARAS_MAINE;
game_init_main(OP_AND_END_PF_FN);
#if (GAME == 4)
gaiji_backup();
gaiji_entry_bfnt(GAIJI_FN);
#endif
snd_determine_modes(resident->bgm_mode, resident->se_mode);
#if (GAME == 5)
snd_load(SE_FN, SND_LOAD_SE);
graph_show();
random_seed = resident->rand;
frame_delay(100);
#else
graph_show();
#endif
static_assert(ES_GOOD > ES_BAD);
if(resident->end_sequence >= ES_BAD) {
end_animate();
staffroll_animate();
#if (GAME == 4)
verdict_animate();
// The rank condition causes the congratulation image to be shown
// for the enforced Bad Ending after clearing Stage 5 on Easy Mode,
// regardless of whether the player continued or not. You might
// consider it a quirk to show 「EASY ALL CLEAR!!」 for a ≥2CC, but
// 「Try to Normal Rank!!」 could very well be ZUN's roundabout way
// of implying "because this is how you avoid the Bad Ending".
if(
(resident->end_sequence == ES_GOOD) ||
(resident->rank == RANK_EASY)
) {
congratulations_pic_fn[5] += resident->rank;
congratulations_animate(congratulations_pic_fn);
}
snd_kaja_func(KAJA_SONG_FADE, 4);
#endif
delay_then_regist_menu();
} else if(resident->end_sequence == ES_EXTRA) {
#if (GAME == 5)
end_animate();
allcast_animate();
verdict_animate();
delay_then_regist_menu();
#else
delay_then_regist_menu();
congratulations_pic_fn[5] = ('0' + RANK_EXTRA);
palette_black();
congratulations_animate(congratulations_pic_fn);
verdict_animate();
#endif
} else { // resident->end_sequence == ES_SCORE
delay_then_regist_menu();
verdict_animate();
}
snd_kaja_func(KAJA_SONG_FADE, 4);
game_exit_and_exec(BINARY_OP);
}

View File

@ -1,6 +1,5 @@
; Various memory sizes of external TH04 files.
MEM_ASSIGN_PARAS_OP equ (336000 shr 4)
MEM_ASSIGN_PARAS_MAIN equ (320000 shr 4)
MEM_ASSIGN_PARAS_MAINE equ (336000 shr 4)
DEMO_N = 4000 ; ZUN symbol [MAGNet2010]

View File

@ -1038,7 +1038,7 @@ public @end_game_good$qv
push bp
mov bp, sp
les bx, _resident
mov es:[bx+resident_t.end_sequence], ES_1CC
mov es:[bx+resident_t.end_sequence], ES_GOOD
mov es:[bx+resident_t.end_type_ascii], '0'
kajacall KAJA_SONG_FADE, 4
push 10h
@ -1059,7 +1059,7 @@ public @end_game_bad$qv
push bp
mov bp, sp
les bx, _resident
mov es:[bx+resident_t.end_sequence], ES_CONTINUED
mov es:[bx+resident_t.end_sequence], ES_BAD
mov es:[bx+resident_t.end_type_ascii], '1'
kajacall KAJA_SONG_FADE, 4
push 10h

View File

@ -147,130 +147,11 @@ _TEXT ends
; ===========================================================================
MAINE_E_TEXT segment byte public 'CODE' use16
@cfg_load_resident_ptr$qv procdesc near
@GAME_EXIT_AND_EXEC$QNC procdesc pascal near \
fn_off:word, fn_seg:word
@end_animate$qv procdesc near
MAINE_E_TEXT ends
; Segment type: Pure code
CUTSCENE_TEXT segment byte public 'CODE' use16
assume cs:group_01
;org 9
assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
; int __cdecl main(int argc, const char **argv, const char **envp)
public _main
_main proc far
@@cong_fn = dword ptr -4
enter 4, 0
mov word ptr [bp+@@cong_fn+2], ds
mov word ptr [bp+@@cong_fn], offset _CongFN
call @cfg_load_resident_ptr$qv
or ax, ax
jz locret_A290
les bx, _resident
mov al, es:[bx+resident_t.playchar_ascii]
les bx, [bp+@@cong_fn]
mov es:[bx+4], al
mov _mem_assign_paras, MEM_ASSIGN_PARAS_MAINE
call @game_init_main$qnxuc pascal, ds, offset aMSzlEd_dat
call gaiji_backup
push ds
push offset aGameft_bft ; "GAMEFT.bft"
call gaiji_entry_bfnt
les bx, _resident
mov al, es:[bx+resident_t.bgm_mode]
mov ah, 0
push ax
mov al, es:[bx+resident_t.se_mode]
mov ah, 0
push ax
call snd_determine_modes
call graph_show
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_CONTINUED
jb loc_A1FE
call @end_animate$qv
call @staffroll_animate$qv
call @verdict_animate$qv
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_1CC
jz short loc_A187
cmp es:[bx+resident_t.rank], RANK_EASY
jnz short loc_A1E9
loc_A187:
les bx, [bp+@@cong_fn]
mov al, es:[bx+5]
les bx, _resident
add al, es:[bx+resident_t.rank]
les bx, [bp+@@cong_fn]
mov es:[bx+5], al
graph_accesspage 1
call pi_load pascal, 0, word ptr [bp+@@cong_fn+2], bx
call pi_palette_apply pascal, 0
call pi_put_8 pascal, large 0, 0
freePISlotLarge 0
call graph_copy_page pascal, 0
push 1
call palette_black_in
call input_wait_for_change pascal, 0
push 4
call palette_black_out
loc_A1E9:
kajacall KAJA_SONG_FADE, 4
call @frame_delay$qi pascal, 100
call @regist_menu$qv
jmp loc_A281
; ---------------------------------------------------------------------------
loc_A1FE:
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_EXTRA
jnz short loc_A274
call @frame_delay$qi pascal, 100
call @regist_menu$qv
les bx, [bp+@@cong_fn]
mov byte ptr es:[bx+5], '4'
mov PaletteTone, 0
call far ptr palette_show
graph_accesspage 1
call pi_load pascal, 0, large [bp+@@cong_fn]
call pi_palette_apply pascal, 0
call pi_put_8 pascal, large 0, 0
freePISlotLarge 0
call graph_copy_page pascal, 0
push 1
call palette_black_in
call input_wait_for_change pascal, 0
push 4
call palette_black_out
jmp short loc_A27E
; ---------------------------------------------------------------------------
loc_A274:
call @frame_delay$qi pascal, 100
call @regist_menu$qv
loc_A27E:
call @verdict_animate$qv
loc_A281:
kajacall KAJA_SONG_FADE, 4
call @game_exit_and_exec$qnc pascal, ds, offset arg0 ; "op"
locret_A290:
leave
retf
_main endp
CUTSCENE_TEXT ends
maine_01_TEXT segment byte public 'CODE' use16
@ -1519,7 +1400,7 @@ loc_BC79:
les bx, _resident
cmp es:[bx+resident_t.stage], STAGE_EXTRA
jz short loc_BD0A
cmp es:[bx+resident_t.end_sequence], ES_1CC
cmp es:[bx+resident_t.end_sequence], ES_GOOD
jnz short loc_BCFF
mov es:[bx+resident_t.std_frames], 44000
@ -1748,7 +1629,7 @@ loc_BF96:
loc_BFA1:
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_CONTINUED
cmp es:[bx+resident_t.end_sequence], ES_BAD
jnz short loc_BFB4
sub [bp+var_4], 100000
@ -2703,7 +2584,7 @@ loc_C8D9:
loc_C909:
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_1CC
cmp es:[bx+resident_t.end_sequence], ES_GOOD
jz short loc_C922
cmp es:[bx+resident_t.end_sequence], ES_EXTRA
jz short loc_C922
@ -3131,7 +3012,6 @@ include th02/snd/snd.inc
extern INPUT_WAIT_FOR_CHANGE:proc
extern @POLAR$QIII:proc
extern SND_KAJA_INTERRUPT:proc
extern SND_DETERMINE_MODES:proc
extern SND_DELAY_UNTIL_MEASURE:proc
extern CDG_PUT_PLANE:proc
extern SND_LOAD:proc
@ -3143,7 +3023,6 @@ SHARED_ segment word public 'CODE' use16
include th04/hardware/grppsafx.asm
extern CDG_PUT_8:proc
extern @GAME_INIT_MAIN$QNXUC:proc
extern _input_reset_sense:proc
extern _input_sense:proc
extern _bgimage_snap:proc
@ -3157,13 +3036,6 @@ SHARED_ ends
.data
public _CongFN
_CongFN db 'CONG00.pi',0
aMSzlEd_dat db 'Œ¶z½ed.dat',0
aGameft_bft db 'GAMEFT.bft',0
; char arg0[]
arg0 db 'op',0
db 0
include libs/master.lib/atrtcmod[data].asm
include libs/master.lib/bfnt_id[data].asm
include libs/master.lib/clip[data].asm

View File

@ -1,6 +1,5 @@
; Various memory sizes of external TH05 files.
MEM_ASSIGN_PARAS_OP equ (336000 shr 4)
MEM_ASSIGN_PARAS_MAIN equ (291200 shr 4)
MEM_ASSIGN_PARAS_MAINE equ (336000 shr 4)
DEMO_N = 5000 ; ZUN symbol [MAGNet2010]

View File

@ -2782,13 +2782,13 @@ public @end_game$qv
jz short loc_E45D
les bx, _resident
assume es:nothing
mov es:[bx+resident_t.end_sequence], ES_CONTINUED
mov es:[bx+resident_t.end_sequence], ES_BAD
jmp short loc_E466
; ---------------------------------------------------------------------------
loc_E45D:
les bx, _resident
mov es:[bx+resident_t.end_sequence], ES_1CC
mov es:[bx+resident_t.end_sequence], ES_GOOD
loc_E466:
kajacall KAJA_SONG_FADE, 4

View File

@ -154,84 +154,11 @@ _TEXT ends
; ===========================================================================
MAINE_E_TEXT segment byte public 'CODE' use16
@cfg_load_resident_ptr$qv procdesc near
@GAME_EXIT_AND_EXEC$QNC procdesc pascal near \
fn_off:word, fn_seg:word
@end_animate$qv procdesc near
MAINE_E_TEXT ends
; Segment type: Pure code
CUTSCENE_TEXT segment byte public 'CODE' use16
assume cs:group_01
;org 5
assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
; int __cdecl main(int argc, const char **argv, const char **envp)
public _main
_main proc far
_argc = word ptr 6
_argv = dword ptr 8
_envp = dword ptr 0Ch
push bp
mov bp, sp
call @cfg_load_resident_ptr$qv
or ax, ax
jz loc_A693
mov _mem_assign_paras, MEM_ASSIGN_PARAS_MAINE
call @game_init_main$qnxuc pascal, ds, offset aKaikidan1_dat
les bx, _resident
mov al, es:[bx+resident_t.bgm_mode]
mov ah, 0
push ax
mov al, es:[bx+resident_t.se_mode]
mov ah, 0
push ax
call snd_determine_modes
call snd_load pascal, ds, offset aMiko, SND_LOAD_SE
call graph_show
les bx, _resident
mov eax, es:[bx+resident_t.rand]
mov random_seed, eax
call @frame_delay$qi pascal, 100
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_CONTINUED
jb short loc_A665
call @end_animate$qv
call @staffroll_animate$qv
jmp short loc_A679
; ---------------------------------------------------------------------------
loc_A665:
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_EXTRA
jnz short loc_A67E
call @end_animate$qv
call @allcast_animate$qv
call @verdict_animate$qv
loc_A679:
call @regist_menu$qv
jmp short loc_A684
; ---------------------------------------------------------------------------
loc_A67E:
call @regist_menu$qv
call @verdict_animate$qv
loc_A684:
kajacall KAJA_SONG_FADE, 4
call @game_exit_and_exec$qnc pascal, ds, offset arg0 ; "op"
loc_A693:
pop bp
retf
_main endp
CUTSCENE_TEXT ends
maine_01_TEXT segment byte public 'CODE' use16
@ -2995,7 +2922,7 @@ sub_CA02 proc near
push bp
mov bp, sp
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_1CC
cmp es:[bx+resident_t.end_sequence], ES_GOOD
jz short loc_CA17
cmp es:[bx+resident_t.end_sequence], ES_EXTRA
jnz short loc_CA57
@ -3044,7 +2971,7 @@ loc_CA53:
loc_CA57:
les bx, _resident
cmp es:[bx+resident_t.end_sequence], ES_CONTINUED
cmp es:[bx+resident_t.end_sequence], ES_BAD
jnz short loc_CA66
mov al, 2
pop bp
@ -3269,7 +3196,7 @@ loc_CBE3:
les bx, _resident
cmp es:[bx+resident_t.stage], STAGE_EXTRA
jz short loc_CCC6
cmp es:[bx+resident_t.end_sequence], ES_CONTINUED
cmp es:[bx+resident_t.end_sequence], ES_BAD
jb short loc_CCB3
mov es:[bx+resident_t.std_frames], 46000
@ -6237,7 +6164,6 @@ maine_01__TEXT ends
; Segment type: Pure code
SHARED segment word public 'CODE' use16
extern SND_DETERMINE_MODES:proc
SHARED ends
SHARED_ segment word public 'CODE' use16
@ -6263,7 +6189,6 @@ include th04/hardware/grppsafx.asm
extern PI_PUT_QUARTER_8:proc
extern PI_PALETTE_APPLY:proc
extern PI_FREE:proc
extern @GAME_INIT_MAIN$QNXUC:proc
extern _input_reset_sense_held:proc
extern INPUT_WAIT_FOR_CHANGE:proc
extern _snd_bgm_measure:proc
@ -6274,11 +6199,6 @@ SHARED_ ends
.data
aKaikidan1_dat = ($ - 17)
aMiko = ($ - 5)
; char arg0[]
arg0 db 'op',0
db 0
include libs/master.lib/atan8[data].asm
include libs/master.lib/atrtcmod[data].asm
include libs/master.lib/bfnt_id[data].asm