From 191a3497d8d3469c0fb6e9069950fc09507f7848 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Fri, 12 Aug 2022 16:41:02 +0200 Subject: [PATCH] [Decompilation] [th01] Pause menu Part of P0214, funded by Ember2528. --- th01/hardware/input.hpp | 7 ++ th01/main/hud/menu.cpp | 157 ++++++++++++++++++++++++++++ th01/main/hud/menu.hpp | 2 + th01/main_010.cpp | 4 + th01/math/clamp.hpp | 4 + th01/resident.hpp | 8 +- th01/shiftjis/hud.hpp | 25 +++++ th01_reiiden.asm | 224 +--------------------------------------- 8 files changed, 208 insertions(+), 223 deletions(-) create mode 100644 th01/main/hud/menu.cpp create mode 100644 th01/main/hud/menu.hpp create mode 100644 th01/shiftjis/hud.hpp diff --git a/th01/hardware/input.hpp b/th01/hardware/input.hpp index c460f747..05040289 100644 --- a/th01/hardware/input.hpp +++ b/th01/hardware/input.hpp @@ -35,6 +35,13 @@ void input_sense(bool16 reset_repeat); // keyboard state. void input_reset_sense(void); +// Resets just menu-related inputs. +inline void input_reset_menu_related(void) { + input_lr = INPUT_NONE; + input_shot = false; + input_ok = false; +} + #define input_func_flag(var, flag) { var |= flag; } else { var &= ~flag; } #define input_onchange(prev_slot, cur_sensed, if_pressed) \ diff --git a/th01/main/hud/menu.cpp b/th01/main/hud/menu.cpp new file mode 100644 index 00000000..502a2a41 --- /dev/null +++ b/th01/main/hud/menu.cpp @@ -0,0 +1,157 @@ +#include "th01/math/clamp.hpp" +#include "th01/main/hud/menu.hpp" +#include "th01/shiftjis/hud.hpp" + +// Pause menu +// ---------- + +// Not quite the center. +static const screen_x_t PAUSE_CENTER_X = (PLAYFIELD_CENTER_X - GLYPH_HALF_W); + +inline screen_y_t pause_top(int line) { + return (PLAYFIELD_TOP + ((PLAYFIELD_H / 21) * 4) + (line * GLYPH_H)); +} + +void z_palette_settone_but_keep_white(int tone) +{ + int col; + int comp; + + for(col = 0; col < COLOR_COUNT; col++) { + if(col == V_WHITE) { + continue; + } + for(comp = 0; comp < COMPONENT_COUNT; comp++) { + z_Palettes[col].v[comp] = ((z_Palettes[col].v[comp]) * tone / 100); + + // ZUN bloat: Already done by z_palette_set_all_show(). + if(z_Palettes[col].v[comp] < 0x0) { + z_Palettes[col].v[comp] = 0x0; + } + + if(z_Palettes[col].v[comp] > 0xF) { + z_Palettes[col].v[comp] = 0xF; + } + } + } + z_palette_set_all_show(z_Palettes); +} + +inline void pause_cursor_unput(screen_x_t left) { + egc_copy_rect_1_to_0_16( + left, pause_top(1), shiftjis_w(PAUSE_CURSOR), GLYPH_H + ); +} + +inline void pause_cursor_put(screen_x_t left, const shiftjis_t* str) { + graph_putsa_fx(left, pause_top(1), V_WHITE, str); +} + +inline void pause_str_put(screen_x_t left, int line, const shiftjis_t* str) { + graph_putsa_fx(left, pause_top(line), (V_WHITE | FX_WEIGHT_BLACK), str); +} + +#define pause_select_loop(ret, sel_0_left, sel_1_left) { \ + while(paused) { \ + input_sense(false); \ + /** + * ZUN bloat: Just replace with \ + * \ + * ((input_shot == true) && (input_ok == true)) \ + * \ + * No need to complicate input handling and abuse this variable. \ + * (And yes, you *can* trigger this one instead of the `break` case \ + * below. \ + */ \ + if(player_is_hit == true) { \ + return true; \ + } \ + if(input_lr == INPUT_LEFT) { \ + pause_cursor_unput(sel_1_left); \ + pause_cursor_put(sel_0_left, PAUSE_CURSOR); \ + sel = 0; \ + } \ + if(input_lr == INPUT_RIGHT) { \ + pause_cursor_unput(sel_0_left); \ + pause_cursor_put(sel_1_left, PAUSE_CURSOR); \ + sel = 1; \ + } \ + if(input_shot || input_ok) { \ + break; \ + } \ + frame_delay(1); \ + } \ +} + +bool16 pause_menu(void) +{ + enum { + PAUSE_TITLE_W = shiftjis_w(PAUSE_TITLE), + PAUSE_CHOICES_W = shiftjis_w(PAUSE_CHOICES), + PAUSE_TITLE_LEFT = (PAUSE_CENTER_X - (PAUSE_TITLE_W / 2)), + PAUSE_CHOICES_LEFT = (PAUSE_CENTER_X - (PAUSE_CHOICES_W / 2)), + PAUSE_CHOICE_0_LEFT = PAUSE_CHOICES_LEFT, + PAUSE_CHOICE_1_LEFT = ( + PAUSE_CHOICE_0_LEFT + shiftjis_w(PAUSE_CHOICE_0) + ), + + QUIT_TITLE_W = shiftjis_w(QUIT_TITLE), + QUIT_CHOICES_W = shiftjis_w(QUIT_CHOICES), + QUIT_TITLE_LEFT = (PAUSE_CENTER_X - (QUIT_TITLE_W / 2)), + QUIT_CHOICES_LEFT = (PAUSE_CENTER_X - (QUIT_CHOICES_W / 2)), + QUIT_CHOICE_0_LEFT = QUIT_CHOICES_LEFT, + QUIT_CHOICE_1_LEFT = (QUIT_CHOICE_0_LEFT + shiftjis_w(QUIT_CHOICE_0)), + + TITLE_W = max_macro(PAUSE_TITLE_W, QUIT_TITLE_W), + OPTIONS_W = max_macro(PAUSE_CHOICES_W, QUIT_CHOICES_W), + MENU_W = max_macro(TITLE_W, OPTIONS_W), + }; + + int8_t sel = 0; + + pause_str_put(PAUSE_TITLE_LEFT, 0, PAUSE_TITLE); + pause_str_put(PAUSE_CHOICES_LEFT, 1, PAUSE_CHOICES); + pause_cursor_put(PAUSE_CHOICE_0_LEFT, PAUSE_CURSOR_INITIAL); + z_palette_settone_but_keep_white(40); + + input_reset_menu_related(); + pause_select_loop(sel, PAUSE_CHOICE_0_LEFT, PAUSE_CHOICE_1_LEFT); + + // ZUN bug: Wrong left coordinate. Thankfully doesn't matter due to that + // function's word alignment. + egc_copy_rect_1_to_0_16( + (PAUSE_TITLE_LEFT + 4), pause_top(0), shiftjis_w(PAUSE_TITLE), GLYPH_H + ); + egc_copy_rect_1_to_0_16( + PAUSE_CHOICES_LEFT, pause_top(1), shiftjis_w(PAUSE_CHOICES), GLYPH_H + ); + + frame_delay(20); + input_reset_menu_related(); + if((sel != 0) && paused) { + pause_str_put(QUIT_TITLE_LEFT, 0, QUIT_TITLE); + pause_str_put(QUIT_CHOICES_LEFT, 1, QUIT_CHOICES); + pause_cursor_put(QUIT_CHOICE_0_LEFT, PAUSE_CURSOR); + sel = 0; + pause_select_loop(sel, QUIT_CHOICE_0_LEFT, QUIT_CHOICE_1_LEFT); + + if(sel != 0) { + resident_continue_use(); + return true; + } + } + + z_palette_set_all_show(stage_palette); + input_reset_sense(); + + // ZUN bug: Same as above. + egc_copy_rect_1_to_0_16( + ((PAUSE_CENTER_X - (MENU_W / 2)) + 8), + pause_top(0), + MENU_W, + (pause_top(2) - pause_top(0)) + ); + + return false; +} +// ----------- diff --git a/th01/main/hud/menu.hpp b/th01/main/hud/menu.hpp new file mode 100644 index 00000000..599ffa1c --- /dev/null +++ b/th01/main/hud/menu.hpp @@ -0,0 +1,2 @@ +// Shows the pause menu, and returns `true` if the player selected to quit. +bool16 pause_menu(void); diff --git a/th01/main_010.cpp b/th01/main_010.cpp index 41b1fd99..dfe06da0 100644 --- a/th01/main_010.cpp +++ b/th01/main_010.cpp @@ -14,11 +14,14 @@ #include "master.hpp" #include "pc98kbd.h" #include "shiftjis.hpp" +#include "th01/common.h" +#include "th01/resident.hpp" #include "th01/v_colors.hpp" #include "th01/math/subpixel.hpp" #include "th01/hardware/egc.h" #include "th01/hardware/frmdelay.h" #include "th01/hardware/graph.h" +#include "th01/hardware/grppsafx.h" #include "th01/hardware/input.hpp" #include "th01/hardware/palette.h" #include "th01/hardware/text.h" @@ -295,3 +298,4 @@ void stage_entrance(int stage_id, const char* bg_fn, bool16 clear_vram_page_0) #include "th01/main/stage/palette.cpp" #include "th01/main/player/inv_spr.cpp" #include "th01/main/player/orb.cpp" +#include "th01/main/hud/menu.cpp" diff --git a/th01/math/clamp.hpp b/th01/math/clamp.hpp index 7b0d9af4..ba527a1d 100644 --- a/th01/math/clamp.hpp +++ b/th01/math/clamp.hpp @@ -1,3 +1,7 @@ +#define max_macro(a, b) ( \ + (a > b) ? a : b \ +) + // Yes, these are exactly what every tutorial presents as a bad example of C // macros, especially if they are nested within each other. // MODDERS: Turn into template functions. diff --git a/th01/resident.hpp b/th01/resident.hpp index 7e2a6ff4..cc620a1f 100644 --- a/th01/resident.hpp +++ b/th01/resident.hpp @@ -54,7 +54,7 @@ typedef struct { // of the current scene, without the boss stage long bonus_per_stage[STAGES_PER_SCENE - 1]; - int stage_id; + unsigned int stage_id; unsigned long hiscore; long score_highest; // among all continues uint16_t point_value; @@ -64,3 +64,9 @@ extern long continues_total; extern route_t route; extern resident_t far *resident; + +inline void resident_continue_use(void) { + resident->continues_total++; + continues_total++; + resident->continues_per_scene[resident->stage_id / STAGES_PER_SCENE]++; +} diff --git a/th01/shiftjis/hud.hpp b/th01/shiftjis/hud.hpp new file mode 100644 index 00000000..d3f4c2f6 --- /dev/null +++ b/th01/shiftjis/hud.hpp @@ -0,0 +1,25 @@ +// Pause menu +// ---------- + +#define PAUSE_TITLE "PAUSE" +#define PAUSE_CHOICE_RESUME "再開" +#define PAUSE_CHOICE_QUIT "終了" + +#define QUIT_TITLE "本当に終了しちゃうの?" +#define QUIT_CHOICE_NO "うそですぅ" +#define QUIT_CHOICE_YES "はいっ" + +// ZUN bloat: Does this mean that this menu used to be shown in text RAM? +#define PAUSE_CURSOR_INITIAL "●      " + +#define PAUSE_CURSOR "●" + +// Leaving one fullwidth space for the cursor in front of each, and another +// one to right-pad the first option. +#define PAUSE_CHOICE_0 " " PAUSE_CHOICE_RESUME " " +#define PAUSE_CHOICE_1 " " PAUSE_CHOICE_QUIT +#define QUIT_CHOICE_0 " " QUIT_CHOICE_NO " " +#define QUIT_CHOICE_1 " " QUIT_CHOICE_YES +#define PAUSE_CHOICES PAUSE_CHOICE_0 PAUSE_CHOICE_1 +#define QUIT_CHOICES QUIT_CHOICE_0 QUIT_CHOICE_1 +// ---------- diff --git a/th01_reiiden.asm b/th01_reiiden.asm index ca7db107..9e96102f 100644 --- a/th01_reiiden.asm +++ b/th01_reiiden.asm @@ -104,217 +104,7 @@ main_010_TEXT ends main_012_TEXT segment byte public 'CODE' use16 extern @invincibility_sprites_update_and$qi:proc extern @ORB_AND_PELLETS_AND_STAGE_UNPUT_$QI:proc - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_C8C7 proc far - -arg_0 = word ptr 6 - - push bp - mov bp, sp - push si - push di - xor si, si - jmp short loc_C92D -; --------------------------------------------------------------------------- - -loc_C8D0: - cmp si, 7 - jz short loc_C92C - xor di, di - jmp short loc_C927 -; --------------------------------------------------------------------------- - -loc_C8D9: - mov bx, si - imul bx, 3 - mov al, _z_Palettes[bx+di] - cbw - imul [bp+arg_0] - mov bx, 100 - cwd - idiv bx - mov bx, si - imul bx, 3 - mov _z_Palettes[bx+di], al - mov bx, si - imul bx, 3 - mov al, _z_Palettes[bx+di] - cbw - or ax, ax - jge short loc_C90D - mov bx, si - imul bx, 3 - mov byte ptr _z_Palettes[bx+di], 0 - -loc_C90D: - mov bx, si - imul bx, 3 - mov al, _z_Palettes[bx+di] - cbw - cmp ax, 0Fh - jle short loc_C926 - mov bx, si - imul bx, 3 - mov byte ptr _z_Palettes[bx+di], 0Fh - -loc_C926: - inc di - -loc_C927: - cmp di, 3 - jl short loc_C8D9 - -loc_C92C: - inc si - -loc_C92D: - cmp si, 10h - jl short loc_C8D0 - call @z_palette_set_all_show$qmx27%Palette$t14%RGB$tc$ii$16%% c, offset _z_Palettes, ds - pop di - pop si - pop bp - retf -sub_C8C7 endp - - -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_C942 proc far - -var_1 = byte ptr -1 - - enter 2, 0 - mov [bp+var_1], 0 - call @graph_putsa_fx$qiiinxuc c, 272, large ((7 or FX_WEIGHT_BLACK) shl 16) or 128, offset aVovVtvrvd, ds ; "PAUSE" - call @graph_putsa_fx$qiiinxuc c, 256, large ((7 or FX_WEIGHT_BLACK) shl 16) or 144, offset aB@nKjb@b@pic, ds ; " 再開  終了" - call @graph_putsa_fx$qiiinxuc c, 256, large (7 shl 16) or 144, offset aBB@b@b@b@b@b@, ds ; "●      " - push 28h ; '(' - call sub_C8C7 - pop cx - mov _input_lr, 0 - mov _input_shot, 0 - mov _input_ok, 0 - jmp loc_CA30 -; --------------------------------------------------------------------------- - -loc_C9A2: - call @input_sense$qi stdcall, 0 - pop cx - cmp _player_is_hit, 1 - jz loc_CB91 - cmp _input_lr, INPUT_LEFT - jnz short loc_C9E6 - call @egc_copy_rect_1_to_0_16$qiiii c, large (144 shl 16) or 320, large (16 shl 16) or 16 - call @graph_putsa_fx$qiiinxuc c, 256, large (7 shl 16) or 144, offset aB, ds ; "●" - mov [bp+var_1], 0 - -loc_C9E6: - cmp _input_lr, INPUT_RIGHT - jnz short loc_CA1A - call @egc_copy_rect_1_to_0_16$qiiii c, large (144 shl 16) or 256, large (16 shl 16) or 16 - call @graph_putsa_fx$qiiinxuc c, 320, large (7 shl 16) or 144, offset aB, ds ; "●" - mov [bp+var_1], 1 - -loc_CA1A: - cmp _input_shot, 0 - jnz short loc_CA39 - cmp _input_ok, 0 - jnz short loc_CA39 - push 1 - call @frame_delay$qui - pop cx - -loc_CA30: - cmp _paused, 0 - jnz loc_C9A2 - -loc_CA39: - call @egc_copy_rect_1_to_0_16$qiiii c, large (128 shl 16) or 276, large (16 shl 16) or 80 - call @egc_copy_rect_1_to_0_16$qiiii c, large (144 shl 16) or 256, large (16 shl 16) or 112 - push 14h - call @frame_delay$qui - pop cx - mov _input_lr, 0 - mov _input_shot, 0 - mov _input_ok, 0 - cmp [bp+var_1], 0 - jz loc_CB96 - cmp _paused, 0 - jz loc_CB96 - call @graph_putsa_fx$qiiinxuc c, 224, large ((7 or FX_WEIGHT_BLACK) shl 16) or 128, offset aCUcvPicVVVsvdv, ds ; "本当に終了しちゃうの?" - call @graph_putsa_fx$qiiinxuc c, 224, large ((7 or FX_WEIGHT_BLACK) shl 16) or 144, offset aB@vdvVVVgb@b@v, ds ; " うそですぅ  はいっ" - call @graph_putsa_fx$qiiinxuc c, 224, large (7 shl 16) or 144, offset aB, ds ; "●" - mov [bp+var_1], 0 - jmp loc_CB5D -; --------------------------------------------------------------------------- - -loc_CACF: - call @input_sense$qi stdcall, 0 - pop cx - cmp _player_is_hit, 1 - jz loc_CB91 - cmp _input_lr, INPUT_LEFT - jnz short loc_CB13 - call @egc_copy_rect_1_to_0_16$qiiii c, large (144 shl 16) or 336, large (16 shl 16) or 16 - call @graph_putsa_fx$qiiinxuc c, 224, large (7 shl 16) or 144, offset aB, ds ; "●" - mov [bp+var_1], 0 - -loc_CB13: - cmp _input_lr, INPUT_RIGHT - jnz short loc_CB47 - call @egc_copy_rect_1_to_0_16$qiiii c, large (144 shl 16) or 224, large (16 shl 16) or 16 - call @graph_putsa_fx$qiiinxuc c, 336, large (7 shl 16) or 144, offset aB, ds ; "●" - mov [bp+var_1], 1 - -loc_CB47: - cmp _input_shot, 0 - jnz short loc_CB66 - cmp _input_ok, 0 - jnz short loc_CB66 - push 1 - call @frame_delay$qui - pop cx - -loc_CB5D: - cmp _paused, 0 - jnz loc_CACF - -loc_CB66: - cmp [bp+var_1], 0 - jz short loc_CB96 - les bx, _resident - inc es:[bx+reiidenconfig_t.continues_total] - inc _continues_total - mov ax, es:[bx+reiidenconfig_t.stage] - mov bx, 5 - xor dx, dx - div bx - add ax, ax - mov bx, word ptr _resident - add bx, ax - inc es:[bx+reiidenconfig_t.continues_per_scene] - -loc_CB91: - mov ax, 1 - leave - retf -; --------------------------------------------------------------------------- - -loc_CB96: - call @z_palette_set_all_show$qmx27%Palette$t14%RGB$tc$ii$16%% c, offset _stage_palette, ds - call @input_reset_sense$qv - call @egc_copy_rect_1_to_0_16$qiiii c, large (128 shl 16) or 232, large (32 shl 16) or 176 - xor ax, ax - leave - retf -sub_C942 endp + extern @pause_menu$qv:proc main_012_TEXT ends main_013_TEXT segment byte public 'CODE' use16 @@ -2137,7 +1927,7 @@ loc_DD6B: call @orb_and_pellets_and_stage_unput_$qi stdcall, [bp+@@stage] cmp _paused, 1 jnz short loc_DDF8 - call sub_C942 + call @pause_menu$qv mov [bp+var_4], ax loc_DDF8: @@ -2876,12 +2666,6 @@ main_38_TEXT ends .data -aVovVtvrvd db 'PAUSE',0 -aB@nKjb@b@pic db ' 再開  終了',0 -aBB@b@b@b@b@b@ db '●      ',0 -aB db '●',0 -aCUcvPicVVVsvdv db '本当に終了しちゃうの?',0 -aB@vdvVVVgb@b@v db ' うそですぅ  はいっ',0 aVgvpvovfvivovx db 'continue?    ',0 aVxvevub@b@B@ db 'Yes    ',0 aVmvpb@b@B@ db 'No     ',0 @@ -3004,8 +2788,6 @@ include th01/hiscore/routes[data].asm ; char aOp[3] aOp db 'op',0 -INPUT_RIGHT = 01h -INPUT_LEFT = 02h BOMB_DOUBLETAP_WINDOW = 20 OVX_4_LEFT = 1 @@ -3055,7 +2837,6 @@ OVX_4_LEFT = 1 extern byte_34AD5:byte extern byte_34ADF:byte - extern _z_Palettes:byte:(size rgb_t * COLOR_COUNT) PTN_SLOT_COUNT = 8 extern _ptn_image_count:byte:PTN_SLOT_COUNT @@ -3227,7 +3008,6 @@ CObstacles ends extern _resident:dword extern _shootout_lasers:byte - extern _stage_palette:palette_t extern _hud_bg:dword extern _hud_bg_size:word extern _stage_timer:word