ReC98/th01/main/boss/defeat.cpp

244 lines
5.9 KiB
C++

#include <stddef.h>
#include "platform.h"
#include "pc98.h"
#include "planar.h"
#include "th01/common.h"
#include "th01/resident.hpp"
#include "th01/v_colors.hpp"
#include "th01/math/area.hpp"
#include "th01/main/playfld.hpp"
extern "C" {
#include "th01/formats/pf.hpp"
}
#include "th01/formats/ptn.hpp"
#include "th01/hardware/egc.h"
extern "C" {
#include "th01/hardware/frmdelay.h"
#include "th01/hardware/graph.h"
#include "th01/hardware/input.hpp"
}
#include "th01/hardware/grp2xscs.hpp"
extern "C" {
#include "th01/hardware/palette.h"
}
#include "th01/hardware/scrollup.hpp"
extern "C" {
#include "th01/snd/mdrv2.h"
}
#include "th01/main/player/orb.hpp"
#include "th01/main/player/player.hpp"
#include "th01/shiftjis/routesel.hpp"
#include "th01/main/boss/boss.hpp"
#include "th01/main/boss/entity_a.hpp"
#include "th01/main/boss/defeat.hpp"
#include "th01/main/stage/stages.hpp"
void grcg_whiteline(screen_y_t y)
{
vram_offset_t vo = vram_offset_muldiv(0, y);
grcg_setcolor_rmw(V_WHITE);
for(vram_word_amount_t x = 0; x < (ROW_SIZE / sizeof(dots16_t)); x++) {
grcg_put(vo, 0xFFFF, 16);
vo += static_cast<vram_offset_t>(sizeof(dots16_t));
}
grcg_off();
}
struct defeat_anim_t {
int frame;
int components_done;
screen_y_t bottom;
screen_y_t top;
};
#define defeat_animate( \
start_y, line_distance, whiteout_interval, whitein_interval \
) \
int col; \
int comp; \
screen_y_t top; \
screen_y_t bottom; \
int components_done; \
int frame = 0; \
\
z_vsync_wait_and_scrollup(0); \
\
top = start_y; \
bottom = start_y; \
\
while(1) { \
if(top >= 0) { \
grcg_whiteline(top); \
} \
if(bottom <= (RES_Y - 1)) { \
grcg_whiteline(bottom); \
} \
top -= line_distance; \
bottom += line_distance; \
frame++; \
if((top < 0) && (bottom > (RES_Y - 1))) { \
break; \
} \
if((frame % whiteout_interval) == 0) { \
z_palette_white_out_step(col, comp); \
} \
frame_delay(1); \
} \
\
/* Aww? No ramping loop? */ \
frame = 0; \
z_palette_set_white(col, comp); \
\
/* Unblit all white lines and return to the regular stage background */ \
graph_accesspage_func(1); \
graph_copy_accessed_page_to_other(); \
graph_accesspage_func(0); \
\
/* Reimu might not have been standing still, after all. */ \
ptn_put_8(player_left, player_top, PTN_MIKO_L); \
\
/* Fade to [boss_post_defeat_palette] */ \
while(1) { \
frame++; \
components_done = 0; \
if((frame % whitein_interval) == 0) { \
z_Palettes_set_func_and_show(col, comp, { \
if( \
z_Palettes[col].v[comp] > \
boss_post_defeat_palette[col].v[comp] \
) { \
z_Palettes[col].v[comp]--; \
} else { \
components_done++; \
} \
}); \
} \
if(components_done >= (COLOR_COUNT * COMPONENT_COUNT)) { \
break; \
} \
frame_delay(1); \
}
void singyoku_defeat_animate_and_select_route(void)
{
defeat_animate(
(boss_entities[0].cur_top + (SINGYOKU_H / 2)), 1, 15, 15
);
palette_foreach(col, comp, {
if(z_Palettes[col].v[comp] > 0) {
// Relies on the clamping behavior of z_palette_set_show().
// (The >0 check wouldn't even have been necessary.)
z_Palettes[col].v[comp] = (z_Palettes[col].v[comp] - 0x4);
}
});
z_Palettes[V_WHITE].set(RGB4::max(), RGB4::max(), RGB4::max());
z_palette_set_all_show(z_Palettes);
// Route selection
enum {
MAKAI_TOP = 250,
JIGOKU_TOP = 300,
CURSOR_LEFT = 128,
};
struct {
int v; // route_t
void render(int col_sel, int col_other) {
z_palette_set_show(col_sel, RGB4::max(), RGB4::max(), RGB4::max());
z_palette_set_show(col_other, 0x9, 0x9, 0x9);
}
} route_sel;
#undef ROUTE_SEL_1
#undef ROUTE_SEL_2
#undef ROUTE_SEL_3
#undef ROUTE_SEL_4
#undef ROUTE_SEL_5
extern const char ROUTE_SEL_1[];
extern const char ROUTE_SEL_2[];
extern const char ROUTE_SEL_3[];
extern const char ROUTE_SEL_4[];
extern const char ROUTE_SEL_5[];
graph_accesspage_func(1);
z_graph_clear(); // redundant
graph_glyphrow_put(0, V_WHITE, ROUTE_SEL_1);
graph_glyphrow_put(2, V_WHITE, ROUTE_SEL_2);
graph_glyphrow_put(4, V_WHITE, ROUTE_SEL_3);
graph_glyphrow_put(6, COL_MAKAI, ROUTE_SEL_4);
graph_glyphrow_put(8, COL_JIGOKU, ROUTE_SEL_5);
graph_accesspage_func(0);
route_sel.render(COL_MAKAI, COL_JIGOKU);
// Re-#define the literals...
#include "th01/shiftjis/routesel.hpp"
graph_glyphrow_2xscale_1_to_0(64, 64, 0, shiftjis_w(ROUTE_SEL_1));
graph_glyphrow_2xscale_1_to_0(32, 96, 2, shiftjis_w(ROUTE_SEL_2));
graph_glyphrow_2xscale_1_to_0(32, 180, 4, shiftjis_w(ROUTE_SEL_3));
graph_glyphrow_2xscale_1_to_0(256, MAKAI_TOP, 6, shiftjis_w(ROUTE_SEL_4));
graph_glyphrow_2xscale_1_to_0(256, JIGOKU_TOP, 8, shiftjis_w(ROUTE_SEL_5));
graph_copy_accessed_page_to_other();
ptn_put_8(CURSOR_LEFT, MAKAI_TOP, PTN_ORB);
route_sel.v = ROUTE_MAKAI;
input_shot = false;
input_ok = false;
input_reset_sense();
bool16 holding_up = false;
bool16 holding_down = false;
frame_delay(50);
while(1) {
input_sense(false);
if((input_up && !holding_up) || (input_down && !holding_down)) {
if(route_sel.v == ROUTE_MAKAI) {
egc_copy_rect_1_to_0_16(CURSOR_LEFT, MAKAI_TOP, ORB_W, ORB_H);
ptn_put_8(CURSOR_LEFT, JIGOKU_TOP, PTN_ORB);
route_sel.render(COL_JIGOKU, COL_MAKAI);
route_sel.v = ROUTE_JIGOKU;
} else {
egc_copy_rect_1_to_0_16(CURSOR_LEFT, JIGOKU_TOP, ORB_W, ORB_H);
ptn_put_8(CURSOR_LEFT, MAKAI_TOP, PTN_ORB);
route_sel.render(COL_MAKAI, COL_JIGOKU);
route_sel.v = ROUTE_MAKAI;
}
}
if(!input_up) {
holding_up = false;
}
if(!input_down) {
holding_down = false;
}
if(input_up) {
holding_up = true;
}
if(input_down) {
holding_down = true;
}
if((input_shot == true) || (input_ok == true)) {
mdrv2_se_play(4);
break;
}
frame_delay(5);
}
if(route_sel.v == ROUTE_MAKAI) {
scene_init_and_load(1);
} else {
scene_init_and_load(2);
}
route = static_cast<route_t>(route_sel.v);
stage_cleared = true;
done = true;
}
void boss_defeat_animate(void)
{
defeat_animate((orb_cur_top + (ORB_H / 2)), 2, 7, 5);
stage_cleared = true;
done = true;
}