Repository: RetroAchievements/RAIntegration
Pull request #970 (2023-02-01 17:38:32)

split DSi from DS
Allows loading DS games in DSi context, which provides the following path forward:
1) build a DLL with these changes and distribute to #dsi-rollout
    - DSi games will continue to load as DS games in DS context
2) update BizHawk to pass DSi console ID
    - DSi games will continue to load as DS games in DSi context
3) change console ID for server records
    - DSi games will load as DSi games in DSi context
    - DS games can still be loaded in DSi context to enable any potential DSi enhancements (which mostly consist of using the camera, so may not really matter for achievements)


Patch:
diff --git a/RAInterface b/RAInterface
index d1443922..f3a14127 160000
--- a/RAInterface
+++ b/RAInterface
@@ -1,1 +1,1 @@
-Subproject commit d1443922a4d5400aadf608a6a34fc988bd7d2a8b
+Subproject commit f3a14127b87c398fc19553bdfe2536e300f4cc48
diff --git a/rcheevos b/rcheevos
index a5dc2b2e..286f2305 160000
--- a/rcheevos
+++ b/rcheevos
@@ -1,1 +1,1 @@
-Subproject commit a5dc2b2e6fbaad0f586161e8cf9d05de0546fa80
+Subproject commit 286f230586004615ac0eb001b3ff352623c94f04
diff --git a/src/data/context/GameContext.cpp b/src/data/context/GameContext.cpp
index 3f5af4ee..7bee3813 100644
--- a/src/data/context/GameContext.cpp
+++ b/src/data/context/GameContext.cpp
@@ -125,6 +125,11 @@ void GameContext::LoadGame(unsigned int nGameId, Mode nMode)
             // GB memory map is just a subset of GBC, and GBC runs GB games, so allow loading a
             // GB game in GBC context.
         }
+        else if (nServerConsoleId == ConsoleID::DS && pConsoleContext.Id() == ConsoleID::DSi)
+        {
+            // DS memory map is just a subset of DSi, and DSi runs DS games, so allow loading a
+            // DS game in DSi context.
+        }
         else if (ra::etoi(nServerConsoleId) == RC_CONSOLE_EVENTS)
         {
             // Hashes for Events are generated by modifying an existing ROM in a very specific manner


Test patch:
diff --git a/tests/data/context/GameContext_Tests.cpp b/tests/data/context/GameContext_Tests.cpp
index fbd98765..a417b7d9 100644
--- a/tests/data/context/GameContext_Tests.cpp
+++ b/tests/data/context/GameContext_Tests.cpp
@@ -317,6 +317,43 @@ public:
         Assert::IsFalse(bDialogShown);
     }
 
+    TEST_METHOD(TestLoadGameTitleConsoleMismatchDSvDSi)
+    {
+        GameContextHarness game;
+        game.mockServer.HandleRequest<ra::api::FetchGameData>([](const ra::api::FetchGameData::Request& request, ra::api::FetchGameData::Response& response)
+        {
+            Assert::AreEqual(1U, request.GameId);
+
+            response.Title = L"Game";
+            response.ConsoleId = ra::etoi(ConsoleID::DS);
+            response.ImageIcon = "9743";
+            return true;
+        });
+
+        game.mockConsoleContext.SetId(ConsoleID::DSi);
+        game.mockConsoleContext.SetName(L"Nintendo DSi");
+
+        bool bDialogShown = false;
+        game.mockDesktop.ExpectWindow<ra::ui::viewmodels::MessageBoxViewModel>([&bDialogShown](ra::ui::viewmodels::MessageBoxViewModel&)
+        {
+            bDialogShown = true;
+            return ra::ui::DialogResult::OK;
+        });
+
+        game.LoadGame(1U);
+
+        Assert::IsTrue(game.mockAudioSystem.WasAudioFilePlayed(std::wstring(L"Overlay\\info.wav")));
+
+        const auto* pPopup = game.mockOverlayManager.GetMessage(1);
+        Expects(pPopup != nullptr);
+        Assert::IsNotNull(pPopup);
+        Assert::AreEqual(std::wstring(L"Loaded Game"), pPopup->GetTitle());
+        Assert::AreEqual(std::wstring(L"0 achievements, 0 points"), pPopup->GetDescription());
+        Assert::AreEqual(std::string("9743"), pPopup->GetImage().Name());
+
+        Assert::IsFalse(bDialogShown);
+    }
+
     TEST_METHOD(TestLoadGameTitleConsoleMismatchNESvEvent)
     {
         GameContextHarness game;