[Decompilation] [th04] Player character and shot type selection menu

Significantly more complex than the single menu in TH05!

Completes P0124, funded by [Anonymous] and Blue Bolt.
This commit is contained in:
nmlgc 2020-10-27 18:04:29 +01:00
parent f1c63ab3a1
commit 056b1c77c1
11 changed files with 554 additions and 949 deletions

View File

@ -117,8 +117,8 @@ bin\th04\res_huma.com: th04\res_huma.cpp
$**
| masters.lib
bin\th04\op.exe: bin\th04\op.obj th04\op_01.cpp bin\frmdely2.obj
$(CC) $(CFLAGS) -ml -DGAME=4 -DBINARY='O' -nbin\th04\ -eOP.EXE @&&|
bin\th04\op.exe: bin\th04\op.obj th04\m_char.cpp bin\frmdely2.obj
$(CC) $(CFLAGS) -ml -DGAME=4 -DBINARY='O' -3 -Z -d -nbin\th04\ -eOP.EXE @&&|
$**
|

View File

@ -10,4 +10,9 @@ typedef enum {
SHOTTYPE_COUNT,
} shottype_t;
// Used way too often...
inline playchars_t playchar_other(playchars_t playchar) {
return static_cast<playchars_t>(PLAYCHAR_MARISA - playchar);
}
extern playchars_t playchar;

494
th04/m_char.cpp Normal file
View File

@ -0,0 +1,494 @@
/* ReC98
* -----
* TH04 player character selection menu
*/
#pragma codeseg op_01_TEXT
extern "C" {
#include <stddef.h>
#include <dos.h>
#include "platform.h"
#include "pc98.h"
#include "planar.h"
#include "master.hpp"
#include "th01/ranks.h"
#include "th02/hardware/frmdelay.h"
#include "th03/formats/pi.h"
#include "th04/common.h"
#include "th04/chars.h"
#include "th04/formats/scoredat.h"
#include "th04/resident.hpp"
#include "th04/hardware/input.h"
#include "th04/hardware/grppsafx.h"
#include "th04/formats/cdg.h"
#include "th04/snd/snd.h"
#include "th04/sprites/op_cdg.h"
#include "th04/op/op.h"
#include "th04/strings/m_char.c"
static const pixel_t PIC_W = 256;
static const pixel_t PIC_H = 244;
static const int COL_SELECTED = 15;
static const int COL_NOT_SELECTED = 3;
static const int COL_BOX = 2;
static const int COL_SHADOW = 1;
// Raised edge
// -----------
static const pixel_t RAISE_W = 8;
static const pixel_t RAISE_H = 8;
static const vram_byte_amount_t RAISE_BG_SIZE = (
(((PIC_W * RAISE_H) + (RAISE_W * PIC_H)) / BYTE_DOTS) * PL_COUNT
);
inline vram_offset_t raise(vram_offset_t vram_offset) {
return (vram_offset - vram_offset_shift(RAISE_W, RAISE_H));
}
inline void dropshadow_put(screen_x_t raised_left, vram_y_t raised_top) {
grcg_setcolor(GC_RMW, COL_SHADOW);
grcg_boxfill_8(
(raised_left + PIC_W),
(raised_top + RAISE_W),
(raised_left + PIC_W),
(raised_top + PIC_H - 1)
);
grcg_boxfill_8(
(raised_left + RAISE_W),
(raised_top + PIC_H),
(raised_left + PIC_W),
(raised_top + PIC_H + RAISE_H - 1)
);
grcg_off();
}
// -----------
// Boxes
// -----
static const pixel_t SHADOW_DISTANCE = 8;
static const pixel_t BOX_ROUND = 8;
#define box_put(left, top, w, h, padding_y) \
grcg_round_boxfill( \
(left), (top), (left + w), (top + (padding_y * 2) + h), BOX_ROUND \
)
#define box_shadow_put(left, top, w, h, padding_y) \
box_put((SHADOW_DISTANCE + left), (SHADOW_DISTANCE + top), w, h, padding_y)
// -----
// Player character selection
// --------------------------
static const screen_x_t REIMU_LEFT = 48;
static const vram_y_t REIMU_TOP = 52;
static const screen_x_t MARISA_LEFT = 336;
static const vram_y_t MARISA_TOP = 52;
inline screen_x_t playchar_title_left(screen_x_t playchar_left) {
return (playchar_left + 32);
}
static const vram_y_t PLAYCHAR_TITLE_TOP = 312;
static const pixel_t PLAYCHAR_TITLE_W = (PLAYCHAR_TITLE_LEN * GLYPH_HALF_W);
static const pixel_t PLAYCHAR_TITLE_H = ((PLAYCHAR_TITLE_LINES + 1) * GLYPH_H);
// --------------------------
// Shot type selection
// -------------------
static const screen_x_t SHOTTYPE_PIC_LEFT = 184;
static const vram_y_t SHOTTYPE_PIC_TOP = 44;
static const vram_y_t SHOTTYPE_BOX_TOP = 312;
static const pixel_t SHOTTYPE_BOX_PADDING_Y = 4;
static const screen_x_t SHOTTYPE_CHOOSE_LEFT = 128;
static const pixel_t SHOTTYPE_CHOOSE_PADDING_LEFT = (3 * GLYPH_HALF_W);
static const screen_x_t SHOTTYPE_TITLE_LEFT = 320;
static const pixel_t SHOTTYPE_CHOOSE_W = (
(SHOTTYPE_CHOOSE_LEN * GLYPH_HALF_W) + SHOTTYPE_CHOOSE_PADDING_LEFT
);
static const pixel_t SHOTTYPE_TITLE_W = (SHOTTYPE_TITLE_LEN * GLYPH_HALF_W);
inline vram_y_t shottype_title_top(shottype_t shottype) {
return (SHOTTYPE_BOX_TOP + (
shottype * (GLYPH_H + (SHOTTYPE_BOX_PADDING_Y * 2))
));
}
// -------------------
// State
// -----
extern unsigned char playchar_menu_sel;
extern unsigned char shottype_menu_sel;
bool selectable_with[PLAYCHAR_COUNT][SHOTTYPE_COUNT];
// -----
void near raise_bg_allocate_and_snap(void)
;
void near pascal raise_bg_put(playchars_t playchar_lowered)
;
void near raise_bg_free(void)
;
#include "th04/op/darken.cpp"
void near pascal pic_darken(playchars_t playchar)
{
vram_offset_t vo;
vram_byte_amount_t x;
pixel_t y;
if(playchar == PLAYCHAR_REIMU) {
vo = vram_offset_shift(REIMU_LEFT, REIMU_TOP);
} else {
vo = vram_offset_shift(MARISA_LEFT, MARISA_TOP);
}
darken(vo, x, y, PIC_W, PIC_H, 1);
}
#define playchar_title_left_for(left, playchar) \
switch(playchar) { \
case PLAYCHAR_REIMU: left = playchar_title_left(REIMU_LEFT); break; \
case PLAYCHAR_MARISA: left = playchar_title_left(MARISA_LEFT); break; \
}
void near pascal playchar_title_put(int playchar_sel)
{
int playchar = playchar_sel;
screen_x_t left;
vram_y_t top;
#define put(left, top, col, playchar) \
graph_putsa_fx( \
(left + BOX_ROUND), \
(top + BOX_ROUND), \
col, \
PLAYCHAR_TITLE[playchar][0] \
); \
graph_putsa_fx( \
(left + BOX_ROUND), \
((top + BOX_ROUND) + (GLYPH_H * 2)), \
col, \
PLAYCHAR_TITLE[playchar][1] \
);
// Selected character
playchar_title_left_for(left, playchar);
top = PLAYCHAR_TITLE_TOP;
put(left, top, COL_SELECTED, playchar);
// Other character
playchar = (PLAYCHAR_MARISA - playchar);
playchar_title_left_for(left, playchar);
put(left, top, COL_NOT_SELECTED, playchar);
#undef put
}
void near pascal playchar_title_box_put(int playchar)
{
screen_x_t left;
vram_y_t top;
playchar_title_left_for(left, playchar);
top = PLAYCHAR_TITLE_TOP;
grcg_setcolor(GC_RMW, COL_SHADOW);
box_shadow_put(left, top, PLAYCHAR_TITLE_W, PLAYCHAR_TITLE_H, BOX_ROUND);
grcg_setcolor(GC_RMW, COL_BOX);
box_put(left, top, PLAYCHAR_TITLE_W, PLAYCHAR_TITLE_H, BOX_ROUND);
grcg_off();
}
inline void pic_put_for(
playchars_t playchar_sel,
screen_x_t sel_left,
vram_y_t sel_top,
screen_x_t other_left,
vram_y_t other_top
) {
cdg_put_noalpha_8(
(sel_left - RAISE_W), (sel_top - RAISE_H), (CDG_PIC + playchar_sel)
);
raise_bg_put(playchar_other(playchar_sel));
cdg_put_noalpha_8(
other_left, other_top, (CDG_PIC + playchar_other(playchar_sel))
);
pic_darken(playchar_other(playchar_sel));
dropshadow_put((sel_left - RAISE_W), (sel_top - RAISE_H));
playchar_title_put(playchar_sel);
}
void near pic_put(void)
{
if(playchar_menu_sel == PLAYCHAR_REIMU) {
pic_put_for(
PLAYCHAR_REIMU, REIMU_LEFT, REIMU_TOP, MARISA_LEFT, MARISA_TOP
);
} else {
pic_put_for(
PLAYCHAR_MARISA, MARISA_LEFT, MARISA_TOP, REIMU_LEFT, REIMU_TOP
);
}
}
#define shottype_title_top_and_clearflag_for(top, clearflag, shottype) \
switch(shottype) { \
case SHOTTYPE_A: \
top = shottype_title_top(SHOTTYPE_A); \
clearflag = SCOREDAT_CLEARED_A; \
break; \
case SHOTTYPE_B: \
top = shottype_title_top(SHOTTYPE_B); \
clearflag = SCOREDAT_CLEARED_B; \
break; \
}
void near pascal shottype_title_put(int shottype_sel)
{
vram_y_t top;
int shottype = shottype_sel;
screen_x_t left;
int rank;
uint8_t clearflag;
rank = (resident->stage == STAGE_EXTRA)
? static_cast<int>(RANK_EXTRA)
: resident->rank;
#define put(top, clearflag, rank, col) \
if(cleared_with[playchar_menu_sel][rank] & clearflag) { \
graph_putsa_fx_func = FX_WEIGHT_NORMAL; \
graph_putsa_fx( \
(left - GLYPH_HALF_W), \
(top + SHOTTYPE_BOX_PADDING_Y), \
COL_SELECTED, \
SHOTTYPE_CLEARED \
); \
graph_putsa_fx_func = FX_WEIGHT_BOLD; \
} \
graph_putsa_fx( \
(left + GLYPH_HALF_W), \
(top + SHOTTYPE_BOX_PADDING_Y), \
col, \
SHOTTYPE_TITLE[playchar_menu_sel][shottype] \
);
// Selected shot type
shottype_title_top_and_clearflag_for(top, clearflag, shottype);
left = SHOTTYPE_TITLE_LEFT;
put(top, clearflag, rank, COL_SELECTED);
// Other shot type
shottype = (SHOTTYPE_B - shottype);
shottype_title_top_and_clearflag_for(top, clearflag, shottype);
put(top, clearflag, rank, COL_NOT_SELECTED);
#undef put
}
void near shottype_title_box_put(void)
{
vram_y_t top = SHOTTYPE_BOX_TOP;
screen_x_t left = SHOTTYPE_TITLE_LEFT;
#define box_top(top, i) \
(top + (i * (GLYPH_H + (SHOTTYPE_BOX_PADDING_Y * 2))))
#define put(func, left, top, w) \
func(left, top, w, (GLYPH_H - 1), SHOTTYPE_BOX_PADDING_Y)
grcg_setcolor(GC_RMW, COL_SHADOW);
put(box_shadow_put, left, box_top(top, 0), (SHOTTYPE_TITLE_W - 1));
put(box_shadow_put, left, box_top(top, 1), (SHOTTYPE_TITLE_W - 1));
put(box_shadow_put, SHOTTYPE_CHOOSE_LEFT, top, (SHOTTYPE_CHOOSE_W - 1));
grcg_setcolor(GC_RMW, COL_BOX);
put(box_put, left, box_top(top, 0), SHOTTYPE_TITLE_W);
put(box_put, left, box_top(top, 1), SHOTTYPE_TITLE_W);
put(box_put, SHOTTYPE_CHOOSE_LEFT, top, (SHOTTYPE_CHOOSE_W - 1));
grcg_off();
graph_putsa_fx(
(SHOTTYPE_CHOOSE_LEFT + SHOTTYPE_CHOOSE_PADDING_LEFT),
(top + SHOTTYPE_BOX_PADDING_Y),
COL_NOT_SELECTED,
SHOTTYPE_CHOOSE
);
#undef put
#undef box_top
}
void near shottype_menu_put_initial(void)
{
if(playchar_menu_sel == PLAYCHAR_REIMU) {
cdg_put_noalpha_8(
SHOTTYPE_PIC_LEFT, SHOTTYPE_PIC_TOP, (CDG_PIC + PLAYCHAR_REIMU)
);
} else {
cdg_put_noalpha_8(
SHOTTYPE_PIC_LEFT, SHOTTYPE_PIC_TOP, (CDG_PIC + PLAYCHAR_MARISA)
);
}
dropshadow_put(SHOTTYPE_PIC_LEFT, SHOTTYPE_PIC_TOP);
shottype_title_box_put();
shottype_title_put(shottype_menu_sel);
}
void near playchar_menu_put_initial(void)
{
palette_black();
pi_load(0, "slb1.pi");
graph_accesspage(1);
graph_showpage(0);
pi_palette_apply(0);
pi_put_8(0, 0, 0);
raise_bg_allocate_and_snap();
playchar_title_box_put(PLAYCHAR_REIMU);
playchar_title_box_put(PLAYCHAR_MARISA);
pic_put();
graph_copy_page(0);
palette_black_in(1);
}
inline bool16 near playchar_menu_leave(bool16 retval) {
palette_black_out(1);
raise_bg_free();
pi_free(0);
return retval;
}
bool16 near playchar_menu(void)
{
int rank;
int playchar;
uint8_t input_prev;
bool extra_unlocked;
if(resident->stage == STAGE_EXTRA) {
for(playchar = PLAYCHAR_REIMU; playchar < PLAYCHAR_COUNT; playchar++) {
#define set_selectable_with(playchar, shottype, flag) \
extra_unlocked = false; \
for(rank = RANK_NORMAL; rank < RANK_EXTRA; rank++) { \
extra_unlocked |= cleared_with[playchar][rank] & flag; \
} \
selectable_with[playchar][shottype] = (extra_unlocked) != false;
set_selectable_with(playchar, SHOTTYPE_A, SCOREDAT_CLEARED_A);
set_selectable_with(playchar, SHOTTYPE_B, SCOREDAT_CLEARED_B);
#undef set_selectable_with
}
} else {
selectable_with[PLAYCHAR_REIMU][SHOTTYPE_A] = true;
selectable_with[PLAYCHAR_REIMU][SHOTTYPE_B] = true;
selectable_with[PLAYCHAR_MARISA][SHOTTYPE_A] = true;
selectable_with[PLAYCHAR_MARISA][SHOTTYPE_B] = true;
}
playchar_menu_sel = (
selectable_with[PLAYCHAR_REIMU][SHOTTYPE_A] ||
selectable_with[PLAYCHAR_REIMU][SHOTTYPE_B]
)
? PLAYCHAR_REIMU
: PLAYCHAR_MARISA;
while(1) {
playchar_menu_put_initial();
// Character
while(1) {
input_reset_sense();
if(input_prev == INPUT_NONE) {
if((key_det & INPUT_LEFT) || (key_det & INPUT_RIGHT)) {
snd_se_play_force(1);
playchar_menu_sel = (1 - playchar_menu_sel);
if(
!selectable_with[playchar_menu_sel][SHOTTYPE_A] &&
!selectable_with[playchar_menu_sel][SHOTTYPE_B]
) {
playchar_menu_sel = (1 - playchar_menu_sel);
}
graph_accesspage(1);
pic_put();
sync_pages_and_delay();
}
if((key_det & INPUT_OK) || (key_det & INPUT_SHOT)) {
snd_se_play_force(11);
shottype_menu_sel = (
selectable_with[playchar_menu_sel][SHOTTYPE_A]
)
? SHOTTYPE_A
: SHOTTYPE_B;
graph_accesspage(1);
palette_white();
pi_put_8(0, 0, 0);
shottype_menu_put_initial();
graph_copy_page(0);
palette_white_in(1);
break;
}
if(key_det & INPUT_CANCEL) {
return playchar_menu_leave(true);
}
input_prev = key_det;
} else {
if(key_det == INPUT_NONE) {
input_prev = INPUT_NONE;
}
}
frame_delay(1);
}
// Shot type
while(1) {
input_reset_sense();
if(input_prev == INPUT_NONE) {
if((key_det & INPUT_UP) || (key_det & INPUT_DOWN)) {
shottype_menu_sel = (1 - shottype_menu_sel);
if(!selectable_with[playchar_menu_sel][shottype_menu_sel]) {
shottype_menu_sel = (1 - shottype_menu_sel);
}
graph_accesspage(1);
shottype_title_put(shottype_menu_sel);
sync_pages_and_delay();
snd_se_play_force(1);
}
if((key_det & INPUT_OK) || (key_det & INPUT_SHOT)) {
snd_se_play_force(11);
resident->shottype = shottype_menu_sel;
resident->playchar_ascii = (playchar_menu_sel + '0');
return playchar_menu_leave(false);
}
if(key_det & INPUT_CANCEL) {
raise_bg_free();
pi_free(0);
break;
}
input_prev = key_det;
} else {
if(key_det == INPUT_NONE) {
input_prev = INPUT_NONE;
}
}
frame_delay(1);
}
}
}
}

View File

@ -2,7 +2,7 @@
// alternating dot pattern in the given [col]. [x] and [y] store the currently
// iterated position.
#define darken(vram_offset, x, y, w, h, col) \
grcg_setcolor(GC_RMW, 1); \
grcg_setcolor(GC_RMW, col); \
dots32_t pattern = 0xAAAAAAAA; \
\
y = 0; \

View File

@ -24,3 +24,15 @@ void near cleardata_and_regist_view_sprites_load(void);
// selection to [resident]. Returns whether to start the game (false) or
// return to the main menu (true).
bool16 near playchar_menu(void);
// Synchronizes both VRAM pages within a 2-frame delay.
#define sync_pages_and_delay() \
vsync_reset1(); \
frame_delay(1); \
\
graph_showpage(1); \
graph_copy_page(0); \
vsync_reset1(); \
frame_delay(1); \
\
graph_showpage(0);

View File

@ -1,13 +0,0 @@
/* ReC98
* -----
* Code segment #1 of TH04's OP.EXE
*/
extern "C" {
#include "platform.h"
#include "th04/chars.h"
bool selectable_with[PLAYCHAR_COUNT][SHOTTYPE_COUNT];
}

View File

@ -54,3 +54,5 @@ typedef struct {
unsigned char turbo_mode;
int8_t unused_5[182];
} resident_t;
extern resident_t *resident;

5
th04/sprites/op_cdg.h Normal file
View File

@ -0,0 +1,5 @@
/// CDG slots for TH05's OP.EXE
typedef enum {
CDG_PIC = 40,
CDG_PIC_last = (CDG_PIC + PLAYCHAR_COUNT - 1)
} op_cdg_slot_t;

17
th04/strings/m_char.c Normal file
View File

@ -0,0 +1,17 @@
static const int PLAYCHAR_TITLE_LEN = 24;
static const int PLAYCHAR_TITLE_LINES = 2;
static const int SHOTTYPE_TITLE_LEN = 24;
static const int SHOTTYPE_CHOOSE_LEN = 21;
const unsigned char *PLAYCHAR_TITLE[PLAYCHAR_COUNT][PLAYCHAR_TITLE_LINES] = {
{ " 博麗靈夢(巫女さん) ", " 広範囲攻撃型  " },
{ " 霧雨魔理沙(魔法使い)", " 攻撃力重視型 " },
};
const unsigned char *SHOTTYPE_TITLE[PLAYCHAR_COUNT][SHOTTYPE_COUNT] = {
{ "  サーチショット  ", " ワイドショット " },
{ "イリュージョンレーザー", " ラピッドショット " },
};
#define SHOTTYPE_CLEARED "☆"
#define SHOTTYPE_CHOOSE "サブウェポンの選択"

View File

@ -177,7 +177,7 @@ _start_game proc near
mov es:[bx+resident_t.credit_bombs], al
mov es:[bx+resident_t.playchar_ascii], '0' + PLAYCHAR_REIMU
mov es:[bx+resident_t.stage_ascii], '0'
call playchar_menu
call _playchar_menu
or ax, ax
jnz short loc_A96A
les bx, _resident
@ -228,7 +228,7 @@ _start_extra proc near
mov es:[bx+resident_t.credit_bombs], 2
mov es:[bx+resident_t.playchar_ascii], '0' + PLAYCHAR_REIMU
mov es:[bx+resident_t.stage_ascii], '6'
call playchar_menu
call _playchar_menu
or ax, ax
jnz short loc_A9C7
les bx, _resident
@ -2631,8 +2631,8 @@ _op_animate endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_CF5E proc near
public _raise_bg_allocate_and_snap
_raise_bg_allocate_and_snap proc near
var_A = word ptr -0Ah
var_8 = word ptr -8
@ -2783,14 +2783,14 @@ loc_D0F2:
pop si
leave
retn
sub_CF5E endp
_raise_bg_allocate_and_snap endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_D0FF proc near
public RAISE_BG_PUT
raise_bg_put proc near
var_6 = dword ptr -6
var_2 = word ptr -2
@ -2914,14 +2914,14 @@ loc_D1E7:
pop si
leave
retn 2
sub_D0FF endp
raise_bg_put endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_D1F3 proc near
public _raise_bg_free
_raise_bg_free proc near
push bp
mov bp, sp
push word ptr dword_132BA+2
@ -2930,896 +2930,9 @@ sub_D1F3 proc near
call hmem_free
pop bp
retn
sub_D1F3 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
darken_pic proc near
var_6 = dword ptr -6
var_2 = word ptr -2
arg_0 = byte ptr 4
enter 6, 0
push si
push di
cmp [bp+arg_0], 0
jnz short loc_D21B
mov si, (52 * ROW_SIZE) + ( 48 / 8)
jmp short loc_D21E
; ---------------------------------------------------------------------------
loc_D21B:
mov si, (52 * ROW_SIZE) + (336 / 8)
loc_D21E:
call grcg_setcolor pascal, (GC_RMW shl 16) + 1
mov [bp+var_6], 0AAAAAAAAh
xor di, di
jmp short loc_D273
; ---------------------------------------------------------------------------
loc_D235:
test di, 1
jnz short loc_D243
mov eax, 0AAAAAAAAh
jmp short loc_D249
; ---------------------------------------------------------------------------
loc_D243:
mov eax, 55555555h
loc_D249:
mov [bp+var_6], eax
mov [bp+var_2], 0
jmp short loc_D269
; ---------------------------------------------------------------------------
loc_D254:
les bx, _VRAM_PLANE_B
add bx, si
mov eax, [bp+var_6]
mov es:[bx], eax
add [bp+var_2], 4
add si, 4
loc_D269:
cmp [bp+var_2], (256 / 8)
jl short loc_D254
inc di
add si, ROW_SIZE - (256 / 8)
loc_D273:
cmp di, 244
jl short loc_D235
GRCG_OFF_CLOBBERING dx
pop di
pop si
leave
retn 2
darken_pic endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_D285 proc near
var_2 = word ptr -2
arg_0 = word ptr 4
enter 2, 0
push si
push di
mov si, [bp+arg_0]
mov ax, si
or ax, ax
jz short loc_D29B
cmp ax, 1
jz short loc_D2A0
jmp short loc_D2A3
; ---------------------------------------------------------------------------
loc_D29B:
mov di, 80
jmp short loc_D2A3
; ---------------------------------------------------------------------------
loc_D2A0:
mov di, 368
loc_D2A3:
mov [bp+var_2], 312
lea ax, [di+8]
push ax
mov ax, [bp+var_2]
add ax, 8
push ax
push 0Fh
mov bx, si
shl bx, 3
pushd aPLAYCHAR_NAME_AND_TITLE[bx]
call graph_putsa_fx
lea ax, [di+8]
push ax
mov ax, [bp+var_2]
add ax, 40
push ax
push 0Fh
mov bx, si
shl bx, 3
pushd aPLAYCHAR_TYPE[bx]
call graph_putsa_fx
mov ax, 1
sub ax, si
mov si, ax
or ax, ax
jz short loc_D2F2
cmp ax, 1
jz short loc_D2F7
jmp short loc_D2FA
; ---------------------------------------------------------------------------
loc_D2F2:
mov di, 80
jmp short loc_D2FA
; ---------------------------------------------------------------------------
loc_D2F7:
mov di, 368
loc_D2FA:
lea ax, [di+8]
push ax
mov ax, [bp+var_2]
add ax, 8
push ax
push 3
mov bx, si
shl bx, 3
pushd aPLAYCHAR_NAME_AND_TITLE[bx]
call graph_putsa_fx
lea ax, [di+8]
push ax
mov ax, [bp+var_2]
add ax, 40
push ax
push 3
mov bx, si
shl bx, 3
pushd aPLAYCHAR_TYPE[bx]
call graph_putsa_fx
pop di
pop si
leave
retn 2
sub_D285 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_D338 proc near
arg_0 = word ptr 4
push bp
mov bp, sp
push si
push di
mov ax, [bp+arg_0]
or ax, ax
jz short loc_D34B
cmp ax, 1
jz short loc_D350
jmp short loc_D353
; ---------------------------------------------------------------------------
loc_D34B:
mov si, 80
jmp short loc_D353
; ---------------------------------------------------------------------------
loc_D350:
mov si, 368
loc_D353:
mov di, 312
call grcg_setcolor pascal, (GC_RMW shl 16) + 1
lea ax, [si+8]
push ax
lea ax, [di+8]
push ax
lea ax, [si+200]
push ax
lea ax, [di+72]
push ax
push 8
call grcg_round_boxfill
call grcg_setcolor pascal, (GC_RMW shl 16) + 2
push si
push di
lea ax, [si+192]
push ax
lea ax, [di+64]
push ax
push 8
call grcg_round_boxfill
GRCG_OFF_CLOBBERING dx
pop di
pop si
pop bp
retn 2
sub_D338 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_D3A2 proc near
push bp
mov bp, sp
cmp playchar_132B8, PLAYCHAR_REIMU
jnz short loc_D407
call cdg_put_noalpha_8 pascal, large (40 shl 16) or 44, 40
push 1
call sub_D0FF
call cdg_put_noalpha_8 pascal, large (336 shl 16) or 52, 41
push 1
call darken_pic
call grcg_setcolor pascal, (GC_RMW shl 16) + 1
call grcg_byteboxfill_x pascal, ((296 / 8) shl 16) or 52, ((296 / 8) shl 16) or 287
call grcg_byteboxfill_x pascal, (( 48 / 8) shl 16) or 288, ((296 / 8) shl 16) or 295
GRCG_OFF_CLOBBERING dx
push 0
jmp short loc_D460
; ---------------------------------------------------------------------------
loc_D407:
call cdg_put_noalpha_8 pascal, large (328 shl 16) or 44, 41
push 0
call sub_D0FF
call cdg_put_noalpha_8 pascal, large (48 shl 16) or 52, 40
push 0
call darken_pic
call grcg_setcolor pascal, (GC_RMW shl 16) + 1
call grcg_byteboxfill_x pascal, ((584 / 8) shl 16) or 52, ((584 / 8) shl 16) or 287
call grcg_byteboxfill_x pascal, ((336 / 8) shl 16) or 288, ((584 / 8) shl 16) or 295
GRCG_OFF_CLOBBERING dx
push 1
loc_D460:
call sub_D285
pop bp
retn
sub_D3A2 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_D465 proc near
var_5 = byte ptr -5
var_4 = word ptr -4
var_2 = word ptr -2
arg_0 = word ptr 4
enter 6, 0
push si
push di
mov di, [bp+arg_0]
les bx, _resident
cmp es:[bx+resident_t.stage], STAGE_EXTRA
jnz short loc_D47E
mov ax, RANK_EXTRA
jmp short loc_D488
; ---------------------------------------------------------------------------
loc_D47E:
les bx, _resident
mov al, es:[bx+resident_t.rank]
mov ah, 0
loc_D488:
mov [bp+var_4], ax
mov ax, di
or ax, ax
jz short loc_D498
cmp ax, 1
jz short loc_D4A1
jmp short loc_D4A8
; ---------------------------------------------------------------------------
loc_D498:
mov si, 312
mov [bp+var_5], SCOREDAT_CLEARED_A
jmp short loc_D4A8
; ---------------------------------------------------------------------------
loc_D4A1:
mov si, 336
mov [bp+var_5], SCOREDAT_CLEARED_B
loc_D4A8:
mov [bp+var_2], 320
mov al, playchar_132B8
mov ah, 0
imul ax, RANK_COUNT
add ax, [bp+var_4]
mov dl, [bp+var_5]
mov bx, ax
test _cleared_with[bx], dl
jz short loc_D4E5
mov _graph_putsa_fx_func, 0
mov ax, [bp+var_2]
add ax, -8
push ax
lea ax, [si+4]
push ax
push 15
push ds
push offset aStar
call graph_putsa_fx
mov _graph_putsa_fx_func, 2
loc_D4E5:
mov ax, [bp+var_2]
add ax, 8
push ax
lea ax, [si+4]
push ax
push 15
mov al, playchar_132B8
mov ah, 0
shl ax, 3
mov dx, di
shl dx, 2
add ax, dx
mov bx, ax
pushd aPLAYCHAR_SHOT[bx]
call graph_putsa_fx
mov ax, 1
sub ax, di
mov di, ax
or ax, ax
jz short loc_D51F
cmp ax, 1
jz short loc_D528
jmp short loc_D52F
; ---------------------------------------------------------------------------
loc_D51F:
mov si, 312
mov [bp+var_5], SCOREDAT_CLEARED_A
jmp short loc_D52F
; ---------------------------------------------------------------------------
loc_D528:
mov si, 336
mov [bp+var_5], SCOREDAT_CLEARED_B
loc_D52F:
mov al, playchar_132B8
mov ah, 0
imul ax, RANK_COUNT
add ax, [bp+var_4]
mov dl, [bp+var_5]
mov bx, ax
test _cleared_with[bx], dl
jz short loc_D567
mov _graph_putsa_fx_func, 0
mov ax, [bp+var_2]
add ax, -8
push ax
lea ax, [si+4]
push ax
push 15
push ds
push offset aStar
call graph_putsa_fx
mov _graph_putsa_fx_func, 2
loc_D567:
mov ax, [bp+var_2]
add ax, 8
push ax
lea ax, [si+4]
push ax
push 3
mov al, playchar_132B8
mov ah, 0
shl ax, 3
mov dx, di
shl dx, 2
add ax, dx
mov bx, ax
pushd aPLAYCHAR_SHOT[bx]
call graph_putsa_fx
pop di
pop si
leave
retn 2
sub_D465 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_D595 proc near
push bp
mov bp, sp
push si
push di
mov si, 312
mov di, 320
call grcg_setcolor pascal, (GC_RMW shl 16) + 1
lea ax, [di+8]
push ax
lea ax, [si+8]
push ax
lea ax, [di+199]
push ax
lea ax, [si+31]
push ax
push 8
call grcg_round_boxfill
lea ax, [di+8]
push ax
lea ax, [si+32]
push ax
lea ax, [di+199]
push ax
lea ax, [si+55]
push ax
push 8
call grcg_round_boxfill
push 136
lea ax, [si+8]
push ax
push 327
lea ax, [si+31]
push ax
push 8
call grcg_round_boxfill
call grcg_setcolor pascal, (GC_RMW shl 16) + 2
push di
push si
lea ax, [di+192]
push ax
lea ax, [si+23]
push ax
push 8
call grcg_round_boxfill
push di
lea ax, [si+24]
push ax
lea ax, [di+192]
push ax
lea ax, [si+47]
push ax
push 8
call grcg_round_boxfill
push 128
push si
push 319
lea ax, [si+23]
push ax
push 8
call grcg_round_boxfill
GRCG_OFF_CLOBBERING dx
push 152
lea ax, [si+4]
push ax
push 3
push ds
push offset aGtgugegfgGuvSi ; "サブウェポンの選択"
call graph_putsa_fx
pop di
pop si
pop bp
retn
sub_D595 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_D650 proc near
push bp
mov bp, sp
cmp playchar_132B8, PLAYCHAR_REIMU
jnz short loc_D664
push (184 shl 16) or 44
push 40
jmp short loc_D66C
; ---------------------------------------------------------------------------
loc_D664:
push (184 shl 16) or 44
push 41
loc_D66C:
call cdg_put_noalpha_8
call grcg_setcolor pascal, (GC_RMW shl 16) + 1
call grcg_byteboxfill_x pascal, ((440 / 8) shl 16) or 52, ((440 / 8) shl 16) or 287
call grcg_byteboxfill_x pascal, ((192 / 8) shl 16) or 288, ((440 / 8) shl 16) or 295
GRCG_OFF_CLOBBERING dx
call sub_D595
mov al, byte_132B9
mov ah, 0
push ax
call sub_D465
pop bp
retn
sub_D650 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
playchar_menu_init proc near
push bp
mov bp, sp
mov PaletteTone, 0
call far ptr palette_show
call pi_load pascal, 0, ds, offset aSlb1_pi
graph_accesspage 1
graph_showpage 0
call pi_palette_apply pascal, 0
call pi_put_8 pascal, large 0, 0
call sub_CF5E
push 0
call sub_D338
push 1
call sub_D338
call sub_D3A2
call graph_copy_page pascal, 0
push 1
call palette_black_in
pop bp
retn
playchar_menu_init endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
playchar_menu proc near
var_2 = byte ptr -2
@@input_locked = byte ptr -1
enter 2, 0
push si
push di
les bx, _resident
cmp es:[bx+resident_t.stage], STAGE_EXTRA
jnz short loc_D78D
xor di, di
jmp short loc_D786
; ---------------------------------------------------------------------------
loc_D71D:
mov [bp+var_2], 0
mov si, RANK_NORMAL
jmp short loc_D735
; ---------------------------------------------------------------------------
loc_D726:
mov bx, di
imul bx, RANK_COUNT
mov al, _cleared_with[bx+si]
and al, 1
or [bp+var_2], al
inc si
loc_D735:
cmp si, RANK_EXTRA
jl short loc_D726
mov bx, di
add bx, bx
push bx
cmp [bp+var_2], 0
jz short loc_D74A
mov ax, 1
jmp short loc_D74C
; ---------------------------------------------------------------------------
loc_D74A:
xor ax, ax
loc_D74C:
pop bx
mov _selectable_with[SHOTTYPE_A][bx], al
mov [bp+var_2], 0
mov si, RANK_NORMAL
jmp short loc_D769
; ---------------------------------------------------------------------------
loc_D75A:
mov bx, di
imul bx, RANK_COUNT
mov al, _cleared_with[bx+si]
and al, 2
or [bp+var_2], al
inc si
loc_D769:
cmp si, RANK_EXTRA
jl short loc_D75A
mov bx, di
add bx, bx
push bx
cmp [bp+var_2], 0
jz short loc_D77E
mov ax, 1
jmp short loc_D780
; ---------------------------------------------------------------------------
loc_D77E:
xor ax, ax
loc_D780:
pop bx
mov _selectable_with[SHOTTYPE_B][bx], al
inc di
loc_D786:
cmp di, PLAYCHAR_COUNT
jl short loc_D71D
jmp short loc_D7A1
; ---------------------------------------------------------------------------
loc_D78D:
mov _selectable_with[PLAYCHAR_REIMU * PLAYCHAR_COUNT][SHOTTYPE_A], 1
mov _selectable_with[PLAYCHAR_REIMU * PLAYCHAR_COUNT][SHOTTYPE_B], 1
mov _selectable_with[PLAYCHAR_MARISA * PLAYCHAR_COUNT][SHOTTYPE_A], 1
mov _selectable_with[PLAYCHAR_MARISA * PLAYCHAR_COUNT][SHOTTYPE_B], 1
loc_D7A1:
cmp _selectable_with[PLAYCHAR_REIMU * PLAYCHAR_COUNT][SHOTTYPE_A], 0
jnz short loc_D7AF
cmp _selectable_with[PLAYCHAR_REIMU * PLAYCHAR_COUNT][SHOTTYPE_B], 0
jz short loc_D7B3
loc_D7AF:
mov al, PLAYCHAR_REIMU
jmp short loc_D7B5
; ---------------------------------------------------------------------------
loc_D7B3:
mov al, PLAYCHAR_MARISA
loc_D7B5:
mov playchar_132B8, al
loc_D7B8:
call playchar_menu_init
loc_D7BB:
call far ptr _input_reset_sense
cmp [bp+@@input_locked], 0
jnz loc_D8DF
test _key_det.lo, low INPUT_LEFT
jnz short loc_D7D6
test _key_det.lo, low INPUT_RIGHT
jz short loc_D84C
loc_D7D6:
call _snd_se_reset
call snd_se_play pascal, 1
call _snd_se_update
mov al, 1
sub al, playchar_132B8
mov playchar_132B8, al
mov ah, 0
add ax, ax
mov bx, ax
cmp _selectable_with[SHOTTYPE_A][bx], 0
jnz short loc_D816
mov al, playchar_132B8
mov ah, 0
add ax, ax
mov bx, ax
cmp _selectable_with[SHOTTYPE_B][bx], 0
jnz short loc_D816
mov al, 1
sub al, playchar_132B8
mov playchar_132B8, al
loc_D816:
graph_accesspage 1
call sub_D3A2
mov vsync_Count1, 0
push 1
call frame_delay
graph_showpage 1
call graph_copy_page pascal, 0
mov vsync_Count1, 0
push 1
call frame_delay
graph_showpage 0
loc_D84C:
test _key_det.hi, high INPUT_OK
jnz short loc_D85A
test _key_det.lo, low INPUT_SHOT
jz short loc_D8B2
loc_D85A:
call _snd_se_reset
call snd_se_play pascal, 11
call _snd_se_update
mov al, playchar_132B8
mov ah, 0
add ax, ax
mov bx, ax
cmp _selectable_with[bx], 0
jz short loc_D87F
mov al, 0
jmp short loc_D881
; ---------------------------------------------------------------------------
loc_D87F:
mov al, 1
loc_D881:
mov byte_132B9, al
graph_accesspage 1
mov PaletteTone, 200
call far ptr palette_show
call pi_put_8 pascal, large 0, 0
call sub_D650
call graph_copy_page pascal, 0
push 1
call palette_white_in
loc_D8B0:
jmp short loc_D8F4
; ---------------------------------------------------------------------------
loc_D8B2:
test _key_det.hi, high INPUT_CANCEL
jz short loc_D8D7
push 1
call palette_black_out
call sub_D1F3
freePISlotLarge 0
mov ax, 1
jmp loc_DA0D
; ---------------------------------------------------------------------------
loc_D8D7:
mov al, _key_det.lo
mov [bp+@@input_locked], al
jmp short loc_D8EA
; ---------------------------------------------------------------------------
loc_D8DF:
cmp _key_det, INPUT_NONE
jnz short loc_D8EA
mov [bp+@@input_locked], 0
loc_D8EA:
push 1
call frame_delay
jmp loc_D7BB
; ---------------------------------------------------------------------------
loc_D8F4:
call far ptr _input_reset_sense
cmp [bp+@@input_locked], 0
jnz loc_D9F8
test _key_det.lo, low INPUT_UP
jnz short loc_D90F
test _key_det.lo, low INPUT_DOWN
jz short loc_D986
loc_D90F:
mov al, 1
sub al, byte_132B9
mov byte_132B9, al
mov al, playchar_132B8
mov ah, 0
add ax, ax
mov dl, byte_132B9
mov dh, 0
add ax, dx
mov bx, ax
cmp _selectable_with[bx], 0
jnz short loc_D939
mov al, 1
sub al, byte_132B9
mov byte_132B9, al
loc_D939:
graph_accesspage 1
mov al, byte_132B9
mov ah, 0
push ax
call sub_D465
mov vsync_Count1, 0
push 1
call frame_delay
graph_showpage 1
call graph_copy_page pascal, 0
mov vsync_Count1, 0
push 1
call frame_delay
graph_showpage 0
call _snd_se_reset
call snd_se_play pascal, 1
call _snd_se_update
loc_D986:
test _key_det.hi, high INPUT_OK
jnz short @@z_pressed
test _key_det.lo, low INPUT_SHOT
jz short loc_D9D5
@@z_pressed:
call _snd_se_reset
call snd_se_play pascal, 11
call _snd_se_update
les bx, _resident
mov al, byte_132B9
mov es:[bx+resident_t.shottype], al
mov al, playchar_132B8
add al, '0'
mov es:[bx+resident_t.playchar_ascii], al
push 1
call palette_black_out
call sub_D1F3
freePISlotLarge 0
xor ax, ax
jmp short loc_DA0D
; ---------------------------------------------------------------------------
loc_D9D5:
test _key_det.hi, high INPUT_CANCEL
jz short loc_D9F0
call sub_D1F3
freePISlotLarge 0
jmp loc_D7B8
; ---------------------------------------------------------------------------
loc_D9F0:
mov al, _key_det.lo
mov [bp+@@input_locked], al
jmp short loc_DA03
; ---------------------------------------------------------------------------
loc_D9F8:
cmp _key_det, INPUT_NONE
jnz short loc_DA03
mov [bp+@@input_locked], 0
loc_DA03:
push 1
call frame_delay
jmp loc_D8B0
; ---------------------------------------------------------------------------
loc_DA0D:
pop di
pop si
leave
retn
playchar_menu endp
db 0
_raise_bg_free endp
_playchar_menu procdesc near
op_01_TEXT ends
; ===========================================================================
@ -4097,29 +3210,6 @@ aOp1b_pi db 'op1b.pi',0
aOp0b_pi db 'op0b.pi',0
aOp_1 db 'op',0
aOp1_pi_1 db 'op1.pi',0
db 0
aPLAYCHAR_NAME_AND_TITLE label dword
dd aB@focasCBiiPcv ; " 博麗靈夢(巫女さん) "
aPLAYCHAR_TYPE label dword
dd aNlfINumvmB@ ; " 広範囲攻撃型  "
dd aCIjcvcanBicvc@ ; " 霧雨魔理沙(魔法使い)"
dd aNumvcPdolm ; " 攻撃力重視型 "
aPLAYCHAR_SHOT label dword
dd aB@GtbGGvgzgbgg ; "  サーチショット  "
dd aGpgcghgvgzgbgg ; " ワイドショット "
dd aGcgkgebGwgzgug ; "イリュージョンレーザー"
dd aGigsgbghgvgzgb ; " ラピッドショット "
aB@focasCBiiPcv db ' 博麗靈夢(巫女さん) ',0
aNlfINumvmB@ db ' 広範囲攻撃型  ',0
aCIjcvcanBicvc@ db ' 霧雨魔理沙(魔法使い)',0
aNumvcPdolm db ' 攻撃力重視型 ',0
aB@GtbGGvgzgbgg db '  サーチショット  ',0
aGpgcghgvgzgbgg db ' ワイドショット ',0
aGcgkgebGwgzgug db 'イリュージョンレーザー',0
aGigsgbghgvgzgb db ' ラピッドショット ',0
aStar db '☆',0
aGtgugegfgGuvSi db 'サブウェポンの選択',0
aSlb1_pi db 'slb1.pi',0
.data?
@ -4166,8 +3256,9 @@ _cleared_with_reimu db RANK_COUNT dup (?)
_cleared_with_marisa db RANK_COUNT dup (?)
_extra_unlocked db ?
db 49 dup(?)
playchar_132B8 db ?
byte_132B9 db ?
public _playchar_menu_sel, _shottype_menu_sel
_playchar_menu_sel db ?
_shottype_menu_sel db ?
dword_132BA dd ?
dword_132BE dd ?
extern _selectable_with:byte

View File

@ -193,15 +193,7 @@ inline void near on_directional_input(uint8_t sel_xorval) {
pic_put(true);
playchar_menu_sel ^= sel_xorval;
pic_put(false);
vsync_reset1();
frame_delay(1);
graph_showpage(1);
graph_copy_page(0);
vsync_reset1();
frame_delay(1);
graph_showpage(0);
sync_pages_and_delay();
}
bool16 near playchar_menu(void)