Repository: RetroAchievements/RAIntegration
Pull request #928 (2022-10-16 15:52:32)

don't add indirect notes to code notes window


Patch:
diff --git a/src/data/models/CodeNotesModel.hh b/src/data/models/CodeNotesModel.hh
index caeb3055..126b6ed9 100644
--- a/src/data/models/CodeNotesModel.hh
+++ b/src/data/models/CodeNotesModel.hh
@@ -139,7 +139,7 @@ public:
     void SetCodeNote(ra::ByteAddress nAddress, const std::wstring& sNote);
 
     /// <summary>
-    /// Returns the number of known code notes
+    /// Returns the number of known code notes (not including indirect notes).
     /// </summary>
     size_t CodeNoteCount() const noexcept { return m_mCodeNotes.size(); }
 
diff --git a/src/ui/viewmodels/CodeNotesViewModel.cpp b/src/ui/viewmodels/CodeNotesViewModel.cpp
index bcef93a1..7b7a1257 100644
--- a/src/ui/viewmodels/CodeNotesViewModel.cpp
+++ b/src/ui/viewmodels/CodeNotesViewModel.cpp
@@ -148,7 +148,7 @@ void CodeNotesViewModel::OnCodeNoteChanged(ra::ByteAddress nAddress, const std::
         return;
 
     const auto* pCodeNotes = pGameContext.Assets().FindCodeNotes();
-    if (pCodeNotes == nullptr)
+    if (pCodeNotes == nullptr || pCodeNotes->GetIndirectSource(nAddress) != 0xFFFFFFFF)
         return;
 
     m_nUnfilteredNotesCount = pCodeNotes->CodeNoteCount();


Test patch:
diff --git a/tests/data/models/CodeNotesModel_Tests.cpp b/tests/data/models/CodeNotesModel_Tests.cpp
index 3e156aa5..6a54e504 100644
--- a/tests/data/models/CodeNotesModel_Tests.cpp
+++ b/tests/data/models/CodeNotesModel_Tests.cpp
@@ -662,6 +662,104 @@ public:
         Assert::AreEqual(std::wstring(), notes.FindCodeNote(18, MemSize::SixteenBit));
     }
 
+    TEST_METHOD(TestEnumerateCodeNotes)
+    {
+        CodeNotesModelHarness notes;
+        const std::wstring sPointerNote =
+            L"Pointer\n"
+            L"+8 = Unknown\n"
+            L"+16 = Small (8-bit)";
+        notes.AddCodeNote(1234, "Author", sPointerNote);
+        notes.AddCodeNote(20, "Author", L"After [32-bit]");
+        notes.AddCodeNote(4, "Author", L"Before");
+        notes.AddCodeNote(12, "Author", L"In the middle");
+
+        int i = 0;
+        notes.EnumerateCodeNotes([&i, &sPointerNote](ra::ByteAddress nAddress, unsigned nBytes, const std::wstring& sNote) {
+            switch (i++)
+            {
+                case 0:
+                    Assert::AreEqual({4U}, nAddress);
+                    Assert::AreEqual(1U, nBytes);
+                    Assert::AreEqual(std::wstring(L"Before"), sNote);
+                    break;
+                case 1:
+                    Assert::AreEqual({12U}, nAddress);
+                    Assert::AreEqual(1U, nBytes);
+                    Assert::AreEqual(std::wstring(L"In the middle"), sNote);
+                    break;
+                case 2:
+                    Assert::AreEqual({20U}, nAddress);
+                    Assert::AreEqual(4U, nBytes);
+                    Assert::AreEqual(std::wstring(L"After [32-bit]"), sNote);
+                    break;
+                case 3:
+                    Assert::AreEqual({1234U}, nAddress);
+                    Assert::AreEqual(4U, nBytes); // unspecified size on pointer assumed to be 32-bit
+                    Assert::AreEqual(sPointerNote, sNote);
+                    break;
+                case 4:
+                    Assert::Fail(L"Too many notes");
+                    break;
+            }
+            return true;
+        }, false);
+    }
+
+    TEST_METHOD(TestEnumerateCodeNotesWithIndirect)
+    {
+        CodeNotesModelHarness notes;
+        const std::wstring sPointerNote =
+            L"Pointer\n"
+            L"+8 = Unknown\n"
+            L"+16 = Small (16-bit)";
+        notes.AddCodeNote(1234, "Author", sPointerNote);
+        notes.AddCodeNote(20, "Author", L"After [32-bit]");
+        notes.AddCodeNote(4, "Author", L"Before");
+        notes.AddCodeNote(12, "Author", L"In the middle");
+
+        int i = 0;
+        notes.EnumerateCodeNotes([&i, &sPointerNote](ra::ByteAddress nAddress, unsigned nBytes, const std::wstring& sNote) {
+            switch (i++)
+            {
+                case 0:
+                    Assert::AreEqual({4U}, nAddress);
+                    Assert::AreEqual(1U, nBytes);
+                    Assert::AreEqual(std::wstring(L"Before"), sNote);
+                    break;
+                case 1:
+                    Assert::AreEqual({8U}, nAddress);
+                    Assert::AreEqual(1U, nBytes);
+                    Assert::AreEqual(std::wstring(L"Unknown"), sNote);
+                    break;
+                case 2:
+                    Assert::AreEqual({12U}, nAddress);
+                    Assert::AreEqual(1U, nBytes);
+                    Assert::AreEqual(std::wstring(L"In the middle"), sNote);
+                    break;
+                case 3:
+                    Assert::AreEqual({16U}, nAddress);
+                    Assert::AreEqual(2U, nBytes);
+                    Assert::AreEqual(std::wstring(L"Small (16-bit)"), sNote);
+                    break;
+                case 4:
+                    Assert::AreEqual({20U}, nAddress);
+                    Assert::AreEqual(4U, nBytes);
+                    Assert::AreEqual(std::wstring(L"After [32-bit]"), sNote);
+                    break;
+                case 5:
+                    Assert::AreEqual({1234U}, nAddress);
+                    Assert::AreEqual(4U, nBytes); // unspecified size on pointer assumed to be 32-bit
+                    Assert::AreEqual(sPointerNote, sNote);
+                    break;
+                case 6:
+                    Assert::Fail(L"Too many notes");
+                    break;
+            }
+            return true;
+        }, true);
+    }
+
     TEST_METHOD(TestDoFrame)
     {
         CodeNotesModelHarness notes;
diff --git a/tests/ui/viewmodels/CodeNotesViewModel_Tests.cpp b/tests/ui/viewmodels/CodeNotesViewModel_Tests.cpp
index 2451c032..2e3b6c50 100644
--- a/tests/ui/viewmodels/CodeNotesViewModel_Tests.cpp
+++ b/tests/ui/viewmodels/CodeNotesViewModel_Tests.cpp
@@ -249,6 +249,40 @@ public:
         AssertRow(notes, 8, 0x0030, L"0x0030", L"Item 1 Quantity");
     }
 
+    TEST_METHOD(TestUpdateNoteIndirectUnfiltered)
+    {
+        CodeNotesViewModelHarness notes;
+        notes.PopulateNotes();
+        Assert::AreEqual({ 0U }, notes.Notes().Count());
+
+        const wchar_t* sPointerNote =
+            L"Pointer\n"
+            L"+8 = Unknown\n"        // no note at $0008
+            L"+16 = Small (16-bit)"; // note would exist at $0010
+
+        notes.SetIsVisible(true);
+        Assert::AreEqual({ 14U }, notes.Notes().Count());
+        Assert::AreEqual(std::wstring(L""), notes.GetFilterValue());
+        Assert::AreEqual(std::wstring(L"14/14"), notes.GetResultCount());
+
+        // This creates an indirect note at $0008, which would bring the total
+        // note count to 15. Make sure it's not added to the list.
+        notes.mockGameContext.SetCodeNote(0x0022, sPointerNote);
+
+        Assert::AreEqual({ 14U }, notes.Notes().Count());
+        Assert::AreEqual(std::wstring(L""), notes.GetFilterValue());
+        Assert::AreEqual(std::wstring(L"14/14"), notes.GetResultCount());
+
+        // indirect 0+8 = 8, would be first element.
+        // indirect 0+16 would be $0010.
+        // this one assert ensures the first item is not the indirect 8, or the note from the indirect 16
+        AssertRow(notes, 0, 0x0010, L"0x0010", L"Score X000");
+
+        // also validate the pointer note itself and that it wasn't duplicated
+        AssertRow(notes, 7, 0x0022, L"0x0022", sPointerNote);
+        AssertRow(notes, 8, 0x0030, L"0x0030", L"Item 1 Quantity");
+    }
+
     TEST_METHOD(TestUpdateNoteFilterStillApplies)
     {
         CodeNotesViewModelHarness notes;