jabyengine/examples/PoolBox/application/src/Overlay/ScreenCenter/screen_center.cpp

208 lines
7.1 KiB
C++

#include "../../../include/shared.hpp"
#include "include/frame.hpp"
#include <FontWriter/fonts.hpp>
#include <PSX/GPU/gpu.hpp>
#include <PSX/GPU/make_gpu_primitives.hpp>
#include <PSX/Periphery/periphery.hpp>
#include <PSX/Timer/frame_timer.hpp>
namespace ScreenCenter {
using namespace JabyEngine;
using GenericButton = Periphery::GenericController::Button;
struct ButtonPulser {
static constexpr auto StartTime = 2500_ms;
static constexpr auto PulseTime = 100_ms;
enum struct State {
WentDown,
Pulse,
Unkown
};
SimpleTimer<uint8_t> timer;
uint8_t pulse_time;
void setup() {
this->timer.reset();
this->pulse_time = StartTime;
}
void reset() {
ButtonPulser::setup();
}
State check(GenericButton button) {
const auto controller = Periphery::get_primary_controller_as<Periphery::GenericController>();
if(!controller.button.was_down(button)) {
ButtonPulser::reset();
if(controller.button.went_down(button)) {
return State::WentDown;
}
}
if(this->timer.is_expired_for(this->pulse_time)) {
this->pulse_time = PulseTime;
this->timer.reset();
return State::Pulse;
}
return State::Unkown;
}
};
#ifdef JABYENGINE_PAL
static const char TVModeStr[] = "PAL";
static constexpr uint16_t ScanlinesV = 288;
#else
static const char TVModeStr[] = "NTSC";
static constexpr uint16_t ScanlinesV = 240;
#endif //JABYENGINE_PAL
namespace PSYQ {
static const char*const Name = "PSYQ";
static void set_offset(uint16_t x, uint16_t y) {
GPU::Display::set_offset(x, y);
}
}
struct Formular {
const char* name;
void (*function)(uint16_t, uint16_t);
};
static const Formular ScreenFormulars[] = {
Formular{.name = PSYQ::Name, .function = PSYQ::set_offset}
};
static constexpr const GPU::VRAM2VRAM background_img[] = { // TODO: Shouldn't current_id 0 be 0 and not 256?
GPU::VRAM2VRAM::create(Make::AreaU16(384, 240, 256, 240), Make::PositionU16(32, GPU::Display::Height)),
GPU::VRAM2VRAM::create(Make::AreaU16(384, 240, 256, 240), Make::PositionU16(32, 0)),
};
static auto frame = Frame::create();
static ButtonPulser button_pulse[4];
static void (*update)() = nullptr;
static int16_t offset_x = 0;
static int16_t offset_y = 0;
static uint8_t formular_sel = 0;
static void update_interactive();
static void reset_screen();
static void update_enter_state() {
static const char IntroductionTest[] = "Press START to begin with\n";
static constexpr auto IntroductionTestLength = BIOSFont::Info.estimate_str_render_length(IntroductionTest);
static constexpr auto CenterPoint = Make::PositionI16((GPU::Display::Width - IntroductionTestLength)/2, (GPU::Display::Height - (2*16))/2);
const auto controller = Periphery::get_primary_controller_as<Periphery::GenericController>();
if(controller.button.went_up(GenericButton::R1) || controller.button.went_up(GenericButton::L1)) {
// Only one mode supported
//formular_sel ^= 1;
}
if(controller.button.went_down(GenericButton::ST)) {
update = update_interactive;
}
auto cursor = FontWriter::update(CenterPoint);
FontWriter::bios_font_writer.write(cursor, IntroductionTest, GPU::Color24::White());
FontWriter::bios_font_writer.write(cursor, ScreenFormulars[formular_sel].name, GPU::Color24::White());
}
static void update_interactive() {
static const auto handle_button = [](ButtonPulser& button_pulse, GenericButton button, int16_t &dst, const int16_t mlp) {
switch(button_pulse.check(button)) {
case ButtonPulser::State::WentDown:
dst += (1*mlp);
break;
case ButtonPulser::State::Pulse:
dst += (2*mlp);
break;
}
};
static const char*const ModeStr = "TV-Mode: %s\n";
static const char*const FormularStr = "<<%s>>\n";
static const char OffsetStr[] = "Offset: %i, %i";
static constexpr auto CenterLength = FontWriter::BIOSFont::Info.estimate_str_render_length(OffsetStr);
static constexpr auto CenterPoint = Make::PositionI16((GPU::Display::Width - CenterLength)/2, (GPU::Display::Height - 3*16)/2);
const auto& screen_formular = ScreenFormulars[formular_sel];
const auto controller = Periphery::get_primary_controller_as<Periphery::GenericController>();
handle_button(button_pulse[0], GenericButton::Left, offset_x, -1);
handle_button(button_pulse[1], GenericButton::Right, offset_x, 1);
handle_button(button_pulse[2], GenericButton::Up, offset_y, -1);
handle_button(button_pulse[3], GenericButton::Down, offset_y, 1);
if(controller.button.is_down(GenericButton::R1) && controller.button.is_down(GenericButton::L1)) {
for(auto& pulse : button_pulse) {
pulse.setup();
}
reset_screen();
}
auto cursor = FontWriter::update(CenterPoint.move(-offset_x, -offset_y));
FontWriter::bios_font_writer.write(cursor, ModeStr, GPU::Color24::White(), TVModeStr);
FontWriter::bios_font_writer.write(cursor, FormularStr, GPU::Color24::White(), screen_formular.name);
FontWriter::bios_font_writer.write(cursor, OffsetStr, GPU::Color24::White(), offset_x, offset_y);
screen_formular.function(offset_x, offset_y);
}
static void reset_screen() {
PSYQ::set_offset(0, 0);
offset_x = 0;
offset_y = 0;
}
static void setup() {
Shared::back_menu.reset();
frame.setup();
for(auto& pulse : button_pulse) {
pulse.setup();
}
update = update_enter_state;
formular_sel = 0;
offset_x = 0;
offset_y = 0;
}
static bool update_or_exit() {
Periphery::query_controller();
if(Shared::back_menu.update(Make::PositionI16(0, GPU::Display::Height - 32))) {
return true;
}
update();
return false;
}
static void render() {
GPU::render(background_img[GPU::Display::current_id]);
frame.render();
Shared::back_menu.render();
}
void main() {
setup();
while(true) {
if(update_or_exit()) {
reset_screen();
break;
}
GPU::swap_buffers_vsync(1);
render();
}
}
}