From 8bbb847a1bb37e81bb684ed742d63951183ce468 Mon Sep 17 00:00:00 2001 From: 1165565692-lang <1165565692@qq.com> Date: Tue, 9 Jun 2026 01:13:07 +0800 Subject: [PATCH] Fix Switch startup save path --- .../include/frostbite2D/core/application.h | 5 +++ .../include/frostbite2D/resource/asset.h | 1 + .../src/frostbite2D/core/application.cpp | 41 ++++++++++++++----- .../src/frostbite2D/resource/asset.cpp | 19 ++++++++- game/src/main.cpp | 29 +++++++++++++ 5 files changed, 83 insertions(+), 12 deletions(-) diff --git a/Frostbite2D/include/frostbite2D/core/application.h b/Frostbite2D/include/frostbite2D/core/application.h index 22ea1d3..77c7592 100644 --- a/Frostbite2D/include/frostbite2D/core/application.h +++ b/Frostbite2D/include/frostbite2D/core/application.h @@ -253,6 +253,11 @@ private: bool running_ = false; bool paused_ = false; bool shouldQuit_ = false; + bool sdlInitialized_ = false; +#ifdef __SWITCH__ + bool switchPlatformInitialized_ = false; + bool switchRomfsMounted_ = false; +#endif bool textInputEnabled_ = false; bool immEnabled_ = false; int textInputRequestCount_ = 0; diff --git a/Frostbite2D/include/frostbite2D/resource/asset.h b/Frostbite2D/include/frostbite2D/resource/asset.h index 24f3b81..cc67b38 100644 --- a/Frostbite2D/include/frostbite2D/resource/asset.h +++ b/Frostbite2D/include/frostbite2D/resource/asset.h @@ -389,6 +389,7 @@ private: fs::path toPath(const std::string &path) const; std::string fromPath(const fs::path &path) const; std::string resolveFullPath(const std::string &path) const; + bool isDevicePath(const std::string &path) const; std::string workingDirectory_; std::string assetRoot_; diff --git a/Frostbite2D/src/frostbite2D/core/application.cpp b/Frostbite2D/src/frostbite2D/core/application.cpp index a7c155b..7723d3a 100644 --- a/Frostbite2D/src/frostbite2D/core/application.cpp +++ b/Frostbite2D/src/frostbite2D/core/application.cpp @@ -58,6 +58,7 @@ bool Application::init(const AppConfig& config) { { ScopedStartupTrace stageTrace("switchInit"); switchInit(); + switchPlatformInitialized_ = true; } #endif @@ -80,7 +81,11 @@ bool Application::init(const AppConfig& config) { } void Application::shutdown() { - if (!initialized_) + if (!initialized_ && !sdlInitialized_ +#ifdef __SWITCH__ + && !switchPlatformInitialized_ && !switchRomfsMounted_ +#endif + ) return; running_ = false; @@ -115,17 +120,25 @@ void Application::shutdown() { window_ = nullptr; } + if (sdlInitialized_) { + SDL_Quit(); + sdlInitialized_ = false; + } + +#ifdef __SWITCH__ + if (switchRomfsMounted_) { + romfsExit(); + switchRomfsMounted_ = false; + } +#endif + // 平台相关清理 #ifdef __SWITCH__ - switchShutdown(); - #endif - - // 退出 SDL(添加重复调用保护) - static bool sdlQuitCalled = false; - if (!sdlQuitCalled) { - SDL_Quit(); - sdlQuitCalled = true; + if (switchPlatformInitialized_) { + switchShutdown(); + switchPlatformInitialized_ = false; } + #endif ObjectRegistry::get().clear(); @@ -153,7 +166,8 @@ bool Application::initCoreModules() { SDL_Log("Asset working directory: %s", workingDir.c_str()); } #else - if (R_SUCCEEDED(romfsInit())) { + if (!switchRomfsMounted_ && R_SUCCEEDED(romfsInit())) { + switchRomfsMounted_ = true; asset.setWorkingDirectory("romfs:/"); } else { asset.setWorkingDirectory("/switch/Frostbite2D/" + config_.appName); @@ -163,7 +177,11 @@ bool Application::initCoreModules() { { ScopedStartupTrace stageTrace("SaveSystem::init"); - if (!SaveSystem::get().init()) { + SaveSystemConfig saveConfig; +#ifdef __SWITCH__ + saveConfig.saveRoot = "sdmc:/switch/NSUnknownGame/save"; +#endif + if (!SaveSystem::get().init(saveConfig)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize save system"); return false; } @@ -175,6 +193,7 @@ bool Application::initCoreModules() { SDL_Log("Failed to initialize SDL: %s", SDL_GetError()); return false; } + sdlInitialized_ = true; } // Disable text input by default. UI widgets should enable it explicitly. diff --git a/Frostbite2D/src/frostbite2D/resource/asset.cpp b/Frostbite2D/src/frostbite2D/resource/asset.cpp index d6331ff..3df6cd0 100644 --- a/Frostbite2D/src/frostbite2D/resource/asset.cpp +++ b/Frostbite2D/src/frostbite2D/resource/asset.cpp @@ -12,6 +12,23 @@ Asset &Asset::get() { return instance; } +bool Asset::isDevicePath(const std::string &path) const { + auto colon = path.find(':'); + if (colon == std::string::npos || colon == 0) { + return false; + } + + for (size_t i = 0; i < colon; ++i) { + unsigned char ch = static_cast(path[i]); + if (!std::isalnum(ch) && ch != '_' && ch != '-') { + return false; + } + } + + return colon + 1 < path.size() && + (path[colon + 1] == '/' || path[colon + 1] == '\\'); +} + fs::path Asset::toPath(const std::string &path) const { #ifdef _WIN32 return fs::u8path(path); @@ -34,7 +51,7 @@ std::string Asset::resolveFullPath(const std::string &path) const { } fs::path p = toPath(path); - if (p.is_absolute()) { + if (p.is_absolute() || isDevicePath(path)) { return path; } diff --git a/game/src/main.cpp b/game/src/main.cpp index 551f790..88b2105 100644 --- a/game/src/main.cpp +++ b/game/src/main.cpp @@ -12,6 +12,34 @@ #include #include +#ifdef __SWITCH__ +namespace { +void showSwitchInitFailure() { + consoleInit(nullptr); + + PadState pad; + padInitializeDefault(&pad); + + std::puts("NS Unknown Game"); + std::puts(""); + std::puts("Switch init failed."); + std::puts("Check nxlink/Ryujinx logs for the failed init stage."); + std::puts(""); + std::puts("Press + to exit."); + + while (appletMainLoop()) { + padUpdate(&pad); + if (padGetButtonsDown(&pad) & HidNpadButton_Plus) { + break; + } + consoleUpdate(nullptr); + } + + consoleExit(nullptr); +} +} // namespace +#endif + int main(int argc, char** argv) { (void)argc; (void)argv; @@ -45,6 +73,7 @@ int main(int argc, char** argv) { if (!app.init(config)) { #ifdef __SWITCH__ std::puts("NS Unknown Game Switch init failed."); + showSwitchInitFailure(); #else std::puts("NS Unknown Game init failed."); #endif