/* * Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. */ #include #include #include #include using namespace nostalgia; static int spriteX{}; static int spriteY{}; static bool s_paused = false; [[maybe_unused]] static int testUpdateHandler(turbine::Context &tctx) noexcept { auto &cctx = *turbine::applicationData(tctx); constexpr auto sleepTime = 16; if (s_paused) { return sleepTime; } int xmod = 0; int ymod = 0; if (buttonDown(tctx, turbine::Alpha_D) || buttonDown(tctx, turbine::GamePad_Right)) { xmod = 2; } else if (buttonDown(tctx, turbine::Alpha_A) || buttonDown(tctx, turbine::GamePad_Left)) { xmod = -2; } if (buttonDown(tctx, turbine::Alpha_S) || buttonDown(tctx, turbine::GamePad_Down)) { ymod = 2; } else if (buttonDown(tctx, turbine::Alpha_W) || buttonDown(tctx, turbine::GamePad_Up)) { ymod = -2; } if (!xmod && !ymod) { spriteX += 1; } spriteX += xmod; spriteY += ymod; constexpr ox::StringView sprites = "nostalgia"; for (unsigned i = 0; i < sprites.len(); ++i) { auto const c = static_cast(sprites[i] - ('a' - 1)); core::setSprite(cctx, i, { .enabled = true, .x = spriteX + 8 * (static_cast(i) + 1), .y = spriteY, .tileIdx = c, .priority = 1, }); } return sleepTime; } [[maybe_unused]] static void testKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool down) noexcept { if (down) { if (key == turbine::Key::Alpha_Q) { turbine::requestShutdown(tctx); } else if (key == turbine::Key::Alpha_P) { s_paused = !s_paused; } } } [[maybe_unused]] static ox::Error runTest(turbine::Context &tctx) { constexpr ox::StringView TileSheetAddr{"/TileSheets/Charset.ng"}; constexpr ox::StringView PaletteAddr{"/Palettes/Chester.npal"}; oxRequireM(cctx, core::init(tctx)); turbine::setApplicationData(tctx, cctx.get()); oxRequire(tsStat, turbine::rom(tctx)->stat(PaletteAddr)); oxReturnError(core::loadSpriteTileSheet(*cctx, TileSheetAddr)); oxReturnError(core::loadSpritePalette(*cctx, PaletteAddr)); oxReturnError(core::initConsole(*cctx)); core::puts(*cctx, 10, 9, "DOPENESS!!!"); turbine::setUpdateHandler(tctx, testUpdateHandler); turbine::setKeyEventHandler(tctx, testKeyEventHandler); return turbine::run(tctx); } [[maybe_unused]] static ox::Error runTileSheetSetTest(turbine::Context &tctx) { // this should make the screen display 'ABCDB', with the A being upside down // and the first B being backwards constexpr ox::StringView PaletteAddr{"/Palettes/Charset.npal"}; oxRequireM(cctx, core::init(tctx)); turbine::setApplicationData(tctx, cctx.get()); oxRequire(tsStat, turbine::rom(tctx)->stat(PaletteAddr)); core::TileSheetSet const set{ .bpp = 4, .entries = { { .tilesheet = ox::StringLiteral{"/TileSheets/Chester.ng"}, .sections{{.begin = 0, .tiles = 1}} }, { .tilesheet = ox::StringLiteral{"/TileSheets/AB.ng"}, .sections{{.begin = 0, .tiles = 2}} }, { .tilesheet = ox::StringLiteral{"/TileSheets/CD.ng"}, .sections{{.begin = 0, .tiles = 2}} }, { .tilesheet = ox::StringLiteral{"/TileSheets/AB.ng"}, .sections{{.begin = 1, .tiles = 1}} }, }, }; constexpr auto bgPalBank = 1; oxReturnError(core::loadBgTileSheet(*cctx, 0, set)); oxReturnError(core::loadSpriteTileSheet(*cctx, set)); oxReturnError(core::loadBgPalette(*cctx, bgPalBank, PaletteAddr)); oxReturnError(core::loadBgPalette(*cctx, 0, PaletteAddr)); oxReturnError(core::loadSpritePalette(*cctx, PaletteAddr)); core::setBgStatus(*cctx, 0, true); core::setBgTile(*cctx, 0, 10, 9, { .tileIdx = 1, .palBank = bgPalBank, .flipX = 0, .flipY = 1 }); core::setBgTile(*cctx, 0, 11, 9, { .tileIdx = 2, .palBank = bgPalBank, .flipX = 1, .flipY = 0 }); core::setBgTile(*cctx, 0, 13, 9, { .tileIdx = 4, .palBank = bgPalBank, .flipX = 0, .flipY = 0 }); core::setSprite(*cctx, 16, { .enabled = true, .x = 12 * 8, .y = 9 * 8, .tileIdx = 3, .bpp = static_cast(set.bpp), }); core::setSprite(*cctx, 17, { .enabled = true, .x = 14 * 8, .y = 9 * 8, .tileIdx = 5, .bpp = static_cast(set.bpp), }); turbine::setKeyEventHandler(tctx, testKeyEventHandler); return turbine::run(tctx); } static int sceneUpdateHandler(turbine::Context&) noexcept { constexpr auto sleepTime = 16; if (s_paused) { return sleepTime; } // do stuff return sleepTime; } static void sceneKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool down) noexcept { if (down) { if (key == turbine::Key::Alpha_Q) { turbine::requestShutdown(tctx); } else if (key == turbine::Key::Alpha_P) { s_paused = !s_paused; } } } [[maybe_unused]] static ox::Error runScene(turbine::Context &tctx) { constexpr ox::StringView SceneAddr{"/Scenes/Chester.nscn"}; oxRequireM(cctx, core::init(tctx)); oxRequire(scn, keel::readObj(keelCtx(tctx), SceneAddr)); turbine::setUpdateHandler(tctx, sceneUpdateHandler); turbine::setKeyEventHandler(tctx, sceneKeyEventHandler); scene::Scene const scene(*scn); oxReturnError(scene.setupDisplay(*cctx)); return turbine::run(tctx); } namespace olympic { ox::Error run( [[maybe_unused]] ox::StringView project, [[maybe_unused]] ox::StringView appName, [[maybe_unused]] ox::StringView projectDataDir, ox::SpanView args) noexcept { if (args.size() < 2) { return OxError(1, "Please provide path to project directory or OxFS file."); } auto const path = args[1]; oxRequireM(fs, keel::loadRomFs(path)); oxRequireM(tctx, turbine::init(std::move(fs), project)); return runTileSheetSetTest(*tctx); } }