#include #include #include #include #include "DefaultHardware.h" #include "DrawContext.h" #include "IDisplay.h" #include "TimeSource.h" #include "Timer.h" #include "app/DesktopApp.h" #include "ui/GameLauncher.h" #ifdef TARGET_IMX #include "FBDisplay.h" #endif #ifdef TARGET_PC #include "SDLDisplay.h" #endif namespace { const int32_t ScreenWidth = 1024; const int32_t ScreenHeight = 600; const int32_t RestoreRetryCount = 5; const uint32_t RestoreRetryDelayMs = 300; static Platform::IDisplay* CreateDisplay() { #ifdef TARGET_IMX return new Platform::FBDisplay(); #endif #ifdef TARGET_PC return new Platform::SDLDisplay(); #endif } static void SleepRemainingFrameTime(const Core::Timer& timer, const Platform::ITimeSource& timeSource) { const uint32_t sleepMs = timer.remaining_frame_ms(timeSource.get_time_ms()); if (sleepMs > 0u) { std::this_thread::sleep_for(std::chrono::milliseconds(sleepMs)); } } static bool RestoreDesktopHardware( Platform::IDisplay* display, Platform::DefaultPointerInput& pointerInput) { for (int32_t attempt = 1; attempt <= RestoreRetryCount; ++attempt) { if (display->init(ScreenWidth, ScreenHeight)) { if (!pointerInput.init("", ScreenWidth, ScreenHeight)) { std::cerr << "[WARN] Pointer input restore failed; desktop touch is disabled." << std::endl; } return true; } std::cerr << "[WARN] Failed to restore desktop display, retry " << attempt << "/" << RestoreRetryCount << "." << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(RestoreRetryDelayMs)); } std::cerr << "[ERROR] Failed to restore desktop display after retries." << std::endl; return false; } static bool LaunchGameAndRestoreDesktop( const Desktop::GameEntry& game, Desktop::GameLauncher& launcher, Platform::IDisplay* display, Platform::DefaultPointerInput& pointerInput) { pointerInput.shutdown(); display->shutdown(); const bool launched = launcher.launch_and_wait(game); if (!launched) { std::cerr << "[WARN] Game launch failed: " << (game.title ? game.title : "(unnamed)") << std::endl; } return RestoreDesktopHardware(display, pointerInput); } } int main(int argc, char* argv[]) { (void)argc; (void)argv; Platform::IDisplay* display = CreateDisplay(); if (!display->init(ScreenWidth, ScreenHeight)) { delete display; return -1; } Platform::DefaultPointerInput pointerInput; if (!pointerInput.init("", ScreenWidth, ScreenHeight)) { std::cerr << "[WARN] Pointer input init failed; desktop touch is disabled." << std::endl; } Core::DrawContext ctx(ScreenWidth, ScreenHeight); Core::Timer timer(30); Platform::SteadyTimeSource timeSource; Desktop::DesktopApp app(ScreenWidth, ScreenHeight, &pointerInput); Desktop::GameLauncher launcher; std::cout << "[INFO] Desktop started. Target FPS: " << timer.target_fps() << std::endl; bool isRunning = true; while (isRunning) { timer.begin_frame(timeSource.get_time_ms()); bool shouldQuit = false; display->poll_events(shouldQuit); if (shouldQuit) { isRunning = false; } app.update(timer.fixed_delta_ms()); const Desktop::GameEntry* launchGame = app.consume_pending_launch(); if (launchGame != nullptr) { if (!LaunchGameAndRestoreDesktop(*launchGame, launcher, display, pointerInput)) { isRunning = false; break; } timer.begin_frame(timeSource.get_time_ms()); } app.draw(ctx); ctx.present(display); SleepRemainingFrameTime(timer, timeSource); } pointerInput.shutdown(); display->shutdown(); delete display; return 0; }