#include "../include/asset_mgr.hpp" #include "include/font_writer.hpp" #include "include/menu.hpp" #include "include/paco.hpp" #include "Overlay/Overlays.hpp" #include #include #include #include #include #include using namespace JabyEngine; using DigitalButton = Periphery::GenericController::Button; struct CDPlayer { static constexpr auto MaxChannels = 2; uint8_t channel; bool is_xa; static constexpr CDPlayer create() { return CDPlayer{.channel = 0, .is_xa = true}; } void play() { if(this->is_xa) { Assets::XAAudio::play_mix(); } else { const auto [first_track, last_track] = CDDA::get_tracks(); CDDA::play(first_track); } } void stop() { if(this->is_xa) { CDXA::stop(); } else { CDDA::stop(); } } void change_channel(int8_t step) { if(this->is_xa) { this->channel = static_cast((this->channel + step))%MaxChannels; CDXA::set_channel(this->channel); } } void change_audio() { CDPlayer::stop(); this->is_xa = !this->is_xa; CDPlayer::play(); } void push() { if(this->is_xa) { CDXA::push_play(); } else { CDDA::push_play(); } } void pop() { if(this->is_xa) { CDXA::pop_play(); } else { CDDA::pop_play(); } } }; struct StateChange { void (*asset_load)(); void (*main)(); static constexpr StateChange empty() { return StateChange{.asset_load = nullptr, .main = nullptr}; } void clear() { this->asset_load = nullptr; this->main = nullptr; } bool contains_state() const { return this->main; } auto operator<=>(const StateChange&) const = default; }; static const Menu::SimpleMenu::Entry MenuEntries[] = { {"Controller Test"}, {"GPU Test"}, {"GTE Test"}, {"Font Cycler"}, {"Screen Center"}, {"BIOS Information"} }; static const auto doener_fish = Make::SPRT( Make::AreaI16(Make::PositionI16(8, GPU::Display::Height - Assets::Main::DoenerFishInfo.size.height), Assets::Main::DoenerFishInfo.size), // v this needs to be nicer! Has to be Make::OffsetPageWithClut(Assets::Main::DoenerFishInfo.tim.get_page_offset_clut4(), Make::PageClut(Assets::Main::DoenerFishInfo.tim.get_clut_position())), GPU::Color24::Grey() ); static CDPlayer cd_player = CDPlayer::create(); static object::Paco paco; static Menu::SimpleMenu menu; static StateChange state_changer; static StateChange old_state_changer; namespace Shared { Menu::BackMenu back_menu; JabyEngine::GPU::POLY_G4 background = Make::POLY_G4( Make::AreaI16(0, 0, GPU::Display::Width, GPU::Display::Height), {GPU::Color24::Red(0xA0), GPU::Color24::Green(0xA0), GPU::Color24::Blue(0xA0), GPU::Color24::Black()} ); bool load_test = false; } static void setup() { Assets::Main::load(); FontWriter::setup(); paco.setup(); Shared::back_menu.setup(&FontWriter::bios_font_writer); menu.setup([](uint32_t selection) { switch(selection) { case 0: state_changer.asset_load = Assets::Overlay::load_controller_test; state_changer.main = ControllerTest::main; break; case 1: state_changer.asset_load = Assets::Overlay::load_gpu_test; state_changer.main = GPUTest::main; break; case 2: state_changer.asset_load = Assets::Overlay::load_gte_test; state_changer.main = GTETest::main; break; case 3: state_changer.asset_load = Assets::Overlay::load_font_cycler; state_changer.main = FontCycler::main; break; case 4: state_changer.asset_load = Assets::Overlay::load_screen_center; state_changer.main = ScreenCenter::main; break; case 5: state_changer.asset_load = Assets::Overlay::load_bios_info; state_changer.main = BIOSInfo::main; break; } },MenuEntries); cd_player.play(); } namespace NormalScene { static void update() { static const char Title[] = ">> Pool Box <<"; static const char Version[] = "Ver. 0.9.0"; static constexpr auto TitleLength = DefaultFont::Info.estimate_str_render_length(Title); static constexpr auto VersionLength = DefaultFont::Info.estimate_str_render_length(Version); Periphery::query_controller(); const auto& controller = Periphery::get_primary_controller_as(); if(controller.is_connected()) { if(controller.button.went_down(DigitalButton::SEL)) { cd_player.change_audio(); } if(controller.button.went_down(DigitalButton::R1)) { cd_player.change_channel(1); } if(controller.button.went_down(DigitalButton::L1)) { cd_player.change_channel(-1); } // Trigger load test if(controller.button.is_down(DigitalButton::R2) && controller.button.is_down(DigitalButton::L2) && controller.button.is_down(DigitalButton::ST)) { Shared::load_test = true; } } auto cursor = FontWriter::update(Make::PositionI16((GPU::Display::Width-TitleLength)/2, 16)); paco.update(); FontWriter::new_font_writer.write(cursor, Title, GPU::Color24::Yellow(0xD0), &FontWriter::wiggle); FontWriter::new_font_writer.write(cursor.change_position(Make::PositionI16((GPU::Display::Width-VersionLength)/2, 16 + DefaultFont::Info.get_kern_size().height)), Version, GPU::Color24::Green(0xD0), &FontWriter::wiggle); menu.update(FontWriter::bios_font_writer, cursor, Make::PositionI16(8, 64)); cursor.change_position(Make::PositionI16(doener_fish.position.x + doener_fish.size.width, GPU::Display::Height - 32)); FontWriter::bios_font_writer.write(cursor, "Audio:\n%s", cd_player.is_xa ? "CD-XA" : "CD-DA"); if(Shared::load_test) { // Force state change if we are in the load_test state state_changer.asset_load = Assets::Overlay::load_large_gpu_test; state_changer.main = GPUTest::main; } } static void render() { GPU::render(Shared::background); FontWriter::new_font_writer.render(); FontWriter::bios_font_writer.render(); paco.render(); GPU::render(doener_fish); } static void run() { update(); GPU::swap_buffers_vsync(1); render(); } } namespace LoadingScene { static SimpleTimer jaby_timer; static uint8_t jaby_frame_offset; static void update() { jaby_timer.reset(); jaby_frame_offset = 0; } static void vsync_render() { static constexpr auto StartPosition = Make::PositionI16(24, 64); const auto load_font = Make::SPRT( Make::AreaI16(StartPosition.move(Assets::Main::JabyLoader::JabyFrame.size.width + 8, 0), Assets::Main::JabyLoader::FontFrame.size), Make::OffsetPageWithClut(Assets::Main::JabyLoader::TIMLoaction.get_page_offset_clut4().move(Assets::Main::JabyLoader::FontFrame.position.x, Assets::Main::JabyLoader::FontFrame.position.y), Make::PageClut(Assets::Main::JabyLoader::TIMLoaction.get_clut_position())), GPU::Color24::Grey() ); auto jaby_sprt = Make::SPRT( Make::AreaI16(StartPosition, Assets::Main::JabyLoader::JabyFrame.size), Make::OffsetPageWithClut(Assets::Main::JabyLoader::TIMLoaction.get_page_offset_clut4(), Make::PageClut(Assets::Main::JabyLoader::TIMLoaction.get_clut_position())), GPU::Color24::Grey() ); if(jaby_timer.is_expired_for(500_ms)) { jaby_frame_offset = jaby_frame_offset ? 0 : 32; jaby_timer.reset(); } jaby_sprt.tex_offset.add(jaby_frame_offset, 0); GPU::swap_buffers(!Shared::load_test); GPU::render(jaby_sprt); GPU::render(load_font); jaby_sprt.position.move(Assets::Main::JabyLoader::FontFrame.size.width + Assets::Main::JabyLoader::JabyFrame.size.width + 8, 0); GPU::render(jaby_sprt); } static void run() { if(Shared::load_test || old_state_changer != state_changer) { GPU::set_vsync_callback(vsync_render); cd_player.push(); state_changer.asset_load(); old_state_changer = state_changer; cd_player.pop(); GPU::set_vsync_callback(nullptr); } state_changer.main(); state_changer.clear(); } } void main() { const auto& controller = Periphery::get_primary_controller_as(); setup(); while(true) { if(state_changer.contains_state()) { LoadingScene::run(); } else { NormalScene::run(); } } }