#include "../../../include/shared.hpp" #include "include/frame.hpp" #include #include #include #include #include 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 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(); 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(); 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(); 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(); } } }