diff --git a/Runtime/CDvdFile.cpp b/Runtime/CDvdFile.cpp index 7e9ec6a65..5cba6cd05 100644 --- a/Runtime/CDvdFile.cpp +++ b/Runtime/CDvdFile.cpp @@ -220,4 +220,16 @@ void CDvdFile::Shutdown() { m_RequestQueue.clear(); } +SDiscInfo CDvdFile::DiscInfo() { + SDiscInfo out{}; + if (!m_DvdRoot) { + return out; + } + const auto& header = m_DvdRoot->getHeader(); + std::memcpy(out.gameId.data(), header.m_gameID, sizeof(header.m_gameID)); + out.version = header.m_discVersion; + out.gameTitle = header.m_gameTitle; + return out; +} + } // namespace metaforce diff --git a/Runtime/CDvdFile.hpp b/Runtime/CDvdFile.hpp index f4f72c4ee..b828eb6e5 100644 --- a/Runtime/CDvdFile.hpp +++ b/Runtime/CDvdFile.hpp @@ -22,6 +22,12 @@ enum class ESeekOrigin { Begin = 0, Cur = 1, End = 2 }; struct DVDFileInfo; class IDvdRequest; +struct SDiscInfo { + std::array gameId; + uint8_t version; + std::string gameTitle; +}; + class CDvdFile { friend class CResLoader; friend class CFileDvdRequest; @@ -45,6 +51,7 @@ class CDvdFile { public: static bool Initialize(const std::string_view& path); + static SDiscInfo DiscInfo(); static void Shutdown(); CDvdFile(std::string_view path); diff --git a/Runtime/CMain.cpp b/Runtime/CMain.cpp index 5b8123ddd..f517dc1a7 100644 --- a/Runtime/CMain.cpp +++ b/Runtime/CMain.cpp @@ -464,8 +464,6 @@ public: g_mainMP1->Shutdown(); } g_mainMP1.reset(); - // m_renderTex.reset(); - // m_pipelineConv.reset(); m_cvarManager.serialize(); m_voiceEngine.reset(); m_amuseAllocWrapper.reset(); @@ -473,13 +471,11 @@ public: } void onCharKeyDown(uint8_t code, aurora::ModifierKey mods, bool isRepeat) noexcept override { - // if (!ImGuiWindowCallback::m_keyboardCaptured && g_mainMP1) { if (g_mainMP1) { if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) { as->charKeyDown(code, mods, isRepeat); } } - // } } void onCharKeyUp(uint8_t code, aurora::ModifierKey mods) noexcept override { diff --git a/Runtime/IMain.hpp b/Runtime/IMain.hpp index a56725873..04c8a4520 100644 --- a/Runtime/IMain.hpp +++ b/Runtime/IMain.hpp @@ -10,19 +10,19 @@ namespace metaforce { class Console; class CVarManager; -enum class ERegion { Invalid = -1, NTSC_U = 'E', PAL = 'P', NTSC_J = 'J' }; +enum class ERegion { USA, JPN, PAL, KOR }; enum class EGame { Invalid = 0, MetroidPrime1, MetroidPrime2, MetroidPrime3, + MetroidPrimeTrilogy, }; struct MetaforceVersionInfo { std::string version; ERegion region; EGame game; - bool isTrilogy; }; class CStopwatch; @@ -45,6 +45,7 @@ public: virtual bool IsPAL() const = 0; virtual bool IsJapanese() const = 0; virtual bool IsUSA() const = 0; + virtual bool IsKorean() const = 0; virtual bool IsTrilogy() const = 0; virtual std::string_view GetVersionString() const = 0; virtual void Quit() = 0; diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index e6179f152..f97e7426c 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -72,6 +72,8 @@ #include "Runtime/MP1/CCredits.hpp" +#include + #ifdef ENABLE_DISCORD #include #endif @@ -100,6 +102,8 @@ inline void* memmem(const void* haystack, size_t hlen, const void* needle, size_ #endif namespace metaforce::MP1 { +static logvisor::Module Log{"MP1"}; + namespace { struct AudioGroupInfo { const char* name; @@ -574,47 +578,61 @@ void CMain::HandleDiscordErrored(int errorCode, const char* message) { DiscordLog.report(logvisor::Error, FMT_STRING("Discord Error: {}"), message); } -void CMain::Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, - boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) { +void CMain::Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, boo::IAudioVoiceEngine* voiceEngine, + amuse::IBackendVoiceAllocator& backend) { InitializeDiscord(); m_cvarMgr = cvarMgr; m_cvarCommons = std::make_unique(*m_cvarMgr); - bool loadedVersion = false; -#if 0 - if (CDvdFile::FileExists("version.yaml")) { - CDvdFile file("version.yaml"); - if (file) { - std::unique_ptr buf = std::make_unique(file.Length()); - u32 readLen = file.SyncRead(buf.get(), file.Length()); - if (readLen == file.Length()) { - CMemoryInStream memoryInStream(buf.get(), file.Length()); - athena::io::FromYAMLStream(m_version, memoryInStream); - loadedVersion = true; - MainLog.report(logvisor::Level::Info, FMT_STRING("Loaded version info")); - } + const auto discInfo = CDvdFile::DiscInfo(); + if (discInfo.gameId[4] != '0' || discInfo.gameId[5] != '1') { + Log.report(logvisor::Fatal, FMT_STRING("Unknown game ID {}"), std::string_view{discInfo.gameId.data(), 6}); + } + if (strncmp(discInfo.gameId.data(), "GM8", 3) == 0 || strncmp(discInfo.gameId.data(), "R3I", 3) == 0) { + m_version.game = EGame::MetroidPrime1; + } else if (strncmp(discInfo.gameId.data(), "G2M", 3) == 0 || strncmp(discInfo.gameId.data(), "R32", 3) == 0) { + m_version.game = EGame::MetroidPrime2; + } else if (strncmp(discInfo.gameId.data(), "R3M", 3) == 0) { + m_version.game = EGame::MetroidPrime3; + } else if (strncmp(discInfo.gameId.data(), "RM3", 3) == 0) { + m_version.game = EGame::MetroidPrimeTrilogy; + } else { + Log.report(logvisor::Fatal, FMT_STRING("Unknown game ID {}"), std::string_view{discInfo.gameId.data(), 6}); + } + switch (discInfo.gameId[3]) { + case 'E': + if (m_version.game == EGame::MetroidPrime1 && discInfo.version == 48) { + m_version.region = ERegion::KOR; + } else { + m_version.region = ERegion::USA; } - } else -#endif - if (CDvdFile::FileExists("default.dol")) { + break; + case 'J': + m_version.region = ERegion::JPN; + break; + case 'P': + m_version.region = ERegion::PAL; + break; + default: + Log.report(logvisor::Fatal, FMT_STRING("Unknown region {}"), discInfo.gameId[3]); + } + + if (m_version.game != EGame::MetroidPrime1 && m_version.game != EGame::MetroidPrimeTrilogy) { + Log.report(logvisor::Fatal, FMT_STRING("Unsupported game {}"), magic_enum::enum_name(m_version.game)); + } + + { CDvdFile file("default.dol"); - if (file) { - std::unique_ptr buf = std::make_unique(file.Length()); - u32 readLen = file.SyncRead(buf.get(), file.Length()); - const char* buildInfo = - static_cast(memmem(buf.get(), readLen, "MetroidBuildInfo", 16)) + 19; - if (buildInfo != nullptr) { - // TODO - m_version = MetaforceVersionInfo{ - .version = std::string(buildInfo), - .region = ERegion::NTSC_U, - .game = EGame::MetroidPrime1, - .isTrilogy = false, - }; - loadedVersion = true; - MainLog.report(logvisor::Level::Info, FMT_STRING("Loaded version info")); - } + if (!file) { + Log.report(logvisor::Fatal, FMT_STRING("Failed to open default.dol")); } + std::unique_ptr buf = std::make_unique(file.Length()); + u32 readLen = file.SyncRead(buf.get(), file.Length()); + const char* buildInfo = static_cast(memmem(buf.get(), readLen, "MetroidBuildInfo", 16)) + 19; + if (buildInfo == nullptr) { + Log.report(logvisor::Fatal, FMT_STRING("Failed to locate MetroidBuildInfo")); + } + m_version.version = buildInfo; } InitializeSubsystems(); @@ -624,16 +642,8 @@ void CMain::Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, x70_tweaks.RegisterResourceTweaks(m_cvarMgr); AddWorldPaks(); - if (loadedVersion) { - if (GetGame() != EGame::MetroidPrime1) { - MainLog.report(logvisor::Level::Fatal, - FMT_STRING("Attempted to initialize URDE in MP1 mode with non-MP1 data!!!!")); - } - MainLog.report(logvisor::Level::Info, FMT_STRING("Loading data from Metroid Prime version {} from region {}{}"), - GetVersionString(), GetRegion(), IsTrilogy() ? " from trilogy" : ""); - } else { - MainLog.report(logvisor::Level::Fatal, FMT_STRING("Unable to load version info")); - } + MainLog.report(logvisor::Level::Info, FMT_STRING("Loading data from {} version {} from region {}"), + magic_enum::enum_name(GetGame()), GetVersionString(), magic_enum::enum_name(GetRegion())); auto args = aurora::get_args(); for (auto it = args.begin(); it != args.end(); ++it) { diff --git a/Runtime/MP1/MP1.hpp b/Runtime/MP1/MP1.hpp index 49a397ae2..efebe2f8c 100644 --- a/Runtime/MP1/MP1.hpp +++ b/Runtime/MP1/MP1.hpp @@ -287,9 +287,10 @@ public: size_t GetExpectedIdSize() const override { return sizeof(u32); } bool IsPAL() const override { return m_version.region == ERegion::PAL; } - bool IsJapanese() const override { return m_version.region == ERegion::NTSC_J; } - bool IsUSA() const override { return m_version.region == ERegion::NTSC_U; } - bool IsTrilogy() const override { return m_version.isTrilogy; } + bool IsJapanese() const override { return m_version.region == ERegion::JPN; } + bool IsUSA() const override { return m_version.region == ERegion::USA; } + bool IsKorean() const override { return m_version.region == ERegion::KOR; } + bool IsTrilogy() const override { return m_version.game == EGame::MetroidPrimeTrilogy; } ERegion GetRegion() const override { return m_version.region; } EGame GetGame() const override { return m_version.game; } std::string_view GetVersionString() const override { return m_version.version; }