ReC98/th05/m_char.cpp

260 lines
5.9 KiB
C++

/* ReC98
* -----
* TH05 player character selection menu
*/
#pragma option -zCop_01_TEXT
#include "platform.h"
#include "x86real.h"
#include "pc98.h"
#include "planar.h"
#include "master.hpp"
#include "th01/rank.h"
extern "C" {
#include "th02/hardware/frmdelay.h"
#include "th04/formats/cdg.h"
#include "th04/hardware/bgimage.hpp"
#include "th04/score.h"
#include "th04/common.h"
#include "th05/playchar.h"
#include "th05/resident.hpp"
#include "th05/op/op.hpp"
#include "th05/sprites/op_cdg.h"
#include "th05/snd/snd.h"
#include "th05/hardware/input.h"
#include "th05/formats/pi.hpp"
#pragma option -a2
static const pixel_t PIC_W = 224;
static const pixel_t PIC_H = 160;
static const pixel_t CLEARED_W = 64;
static const pixel_t CLEARED_H = 16;
static const pixel_t RAISE_W = 8;
static const pixel_t RAISE_H = 8;
static const screen_x_t REIMU_LEFT = 16;
static const vram_y_t REIMU_TOP = 48;
static const screen_x_t MARISA_LEFT = 272;
static const vram_y_t MARISA_TOP = 48;
static const screen_x_t MIMA_LEFT = 160;
static const vram_y_t MIMA_TOP = 224;
static const screen_x_t YUUKA_LEFT = 400;
static const vram_y_t YUUKA_TOP = 224;
unsigned char playchar_menu_sel;
static uint8_t unused_1;
unsigned char playchar_menu_rank;
static uint8_t unused_0[4];
bool extra_playable_with[PLAYCHAR_COUNT];
bool selectable_with[PLAYCHAR_COUNT];
#include "th04/op/darken.cpp"
void pascal near pic_darken(unsigned char playchar)
{
vram_offset_t vram_offset;
switch(playchar) {
case PLAYCHAR_REIMU:
vram_offset = vram_offset_shift(REIMU_LEFT, REIMU_TOP);
break;
case PLAYCHAR_MARISA:
vram_offset = vram_offset_shift(MARISA_LEFT, MARISA_TOP);
break;
case PLAYCHAR_MIMA:
vram_offset = vram_offset_shift(MIMA_LEFT, MIMA_TOP);
break;
case PLAYCHAR_YUUKA:
vram_offset = vram_offset_shift(YUUKA_LEFT, YUUKA_TOP);
break;
}
darken(vram_offset, PIC_W, PIC_H, 1);
}
void pascal near pic_put(bool16 darkened)
{
screen_x_t pic_left;
vram_y_t pic_top;
screen_x_t cleared_left;
vram_y_t cleared_top;
#define set_coords(left, top) \
pic_left = left; \
pic_top = top; \
cleared_left = (left + (PIC_W - CLEARED_W)); \
cleared_top = (top + (PIC_H - CLEARED_H));
switch(playchar_menu_sel) {
case PLAYCHAR_REIMU: set_coords(REIMU_LEFT, REIMU_TOP); break;
case PLAYCHAR_MARISA: set_coords(MARISA_LEFT, MARISA_TOP); break;
case PLAYCHAR_MIMA: set_coords(MIMA_LEFT, MIMA_TOP); break;
case PLAYCHAR_YUUKA: set_coords(YUUKA_LEFT, YUUKA_TOP); break;
}
#define pic_raised_left (pic_left - RAISE_W)
#define pic_raised_top (pic_top - RAISE_H)
if(!darkened) {
// Pic
if(selectable_with[playchar_menu_sel]) {
cdg_put_noalpha_8(
pic_raised_left, pic_raised_top, (CDG_PIC + playchar_menu_sel)
);
} else {
cdg_put_noalpha_8(
pic_raised_left, pic_raised_top, CDG_PIC_NOT_CLEARED
);
}
// Drop shadow
grcg_setcolor(GC_RMW, 1);
grcg_boxfill_8(
(pic_raised_left + PIC_W),
pic_top,
(pic_left + PIC_W - 1),
(pic_raised_top + PIC_H - 1)
);
grcg_boxfill_8(
pic_left,
(pic_raised_top + PIC_H),
(pic_left + PIC_W - 1),
(pic_top + PIC_H - 1)
);
grcg_off();
// "Cleared!!" sprite
if(cleared_with[playchar_menu_sel][playchar_menu_rank]) {
cdg_put_8(
(cleared_left - RAISE_W), (cleared_top - RAISE_H), CDG_CLEARED
);
}
} else {
// Raised area of the highlighted pic
bgimage_put_rect(pic_raised_left, pic_raised_top, PIC_W, RAISE_H);
bgimage_put_rect(pic_raised_left, pic_top, RAISE_W, PIC_H);
// Pic
if(selectable_with[playchar_menu_sel]) {
cdg_put_noalpha_8(pic_left, pic_top, (CDG_PIC + playchar_menu_sel));
} else {
cdg_put_noalpha_8(pic_left, pic_top, CDG_PIC_NOT_CLEARED);
}
// "Cleared!!" sprite
if(cleared_with[playchar_menu_sel][playchar_menu_rank]) {
cdg_put_8(cleared_left, cleared_top, CDG_CLEARED);
}
pic_darken(playchar_menu_sel);
}
#undef set_coords
#undef pic_raised_top
#undef pic_raised_left
}
void near playchar_menu_put_initial(void)
{
int selected = playchar_menu_sel;
palette_settone(0);
graph_accesspage(1);
pi_load_put_8_free(0, "slb1.pi");
graph_copy_page(0);
bgimage_snap();
graph_accesspage(1);
graph_showpage(0);
int i = PLAYCHAR_REIMU;
playchar_menu_sel = PLAYCHAR_REIMU;
while(i < PLAYCHAR_COUNT) {
pic_put(playchar_menu_sel != selected ? true : false);
i++;
playchar_menu_sel++;
}
playchar_menu_sel = selected;
graph_copy_page(0);
palette_black_in(1);
}
inline void near on_directional_input(uint8_t sel_xorval) {
snd_se_play_force(1);
graph_accesspage(1);
pic_put(true);
playchar_menu_sel ^= sel_xorval;
pic_put(false);
sync_pages_and_delay();
}
bool16 near playchar_menu(void)
{
uint8_t input_prev;
int i;
for(i = PLAYCHAR_REIMU; i < PLAYCHAR_COUNT; i++) {
selectable_with[i] = extra_playable_with[i];
}
if(resident->stage == STAGE_EXTRA) {
playchar_menu_rank = RANK_EXTRA;
playchar_menu_sel = 0xFF;
for(i = PLAYCHAR_REIMU; i < PLAYCHAR_COUNT; i++) {
if(playchar_menu_sel == 0xFF) {
if(selectable_with[i]) {
playchar_menu_sel = i;
}
}
}
} else {
for(i = PLAYCHAR_REIMU; i < PLAYCHAR_COUNT; i++) {
selectable_with[i] = true;
}
playchar_menu_rank = resident->rank;
playchar_menu_sel = PLAYCHAR_REIMU;
}
playchar_menu_put_initial();
while(1) {
input_reset_sense_held();
if(input_prev == INPUT_NONE) {
if((key_det & INPUT_LEFT) || (key_det & INPUT_RIGHT)) {
on_directional_input(1); // 0<->1, 2<->3
}
if((key_det & INPUT_UP) || (key_det & INPUT_DOWN)) {
on_directional_input(2); // 0<->2, 1<->3
}
if((key_det & INPUT_OK) || (key_det & INPUT_SHOT)) {
if(selectable_with[playchar_menu_sel]) {
snd_se_play_force(11);
resident->playchar = playchar_menu_sel;
palette_black_out(1);
bgimage_free();
return false;
}
}
if(key_det & INPUT_CANCEL) {
palette_black_out(1);
bgimage_free();
return true;
}
input_prev = key_det;
} else {
if(key_det == INPUT_NONE) {
input_prev = INPUT_NONE;
}
}
frame_delay(1);
}
}
}