diff --git a/src/data/context/ConsoleContext.cpp b/src/data/context/ConsoleContext.cpp index ae4e4b5f3..c4fbdab44 100644 --- a/src/data/context/ConsoleContext.cpp +++ b/src/data/context/ConsoleContext.cpp @@ -93,10 +93,60 @@ ra::ByteAddress ConsoleContext::ByteAddressFromRealAddress(ra::ByteAddress nReal } } + // additional mirror/shadow ram mappings not directly exposed by rc_console_memory_regions + switch (m_nId) + { + case ConsoleID::Dreamcast: + // http://archiv.sega-dc.de/munkeechuff/hardware/Memory.html + if (nRealAddress >= 0x8C000000 && nRealAddress <= 0x8CFFFFFF) // System Memory (MMU enabled) + return ByteAddressFromRealAddress(nRealAddress & 0x0FFFFFFF); + if (nRealAddress >= 0xAC000000 && nRealAddress <= 0xACFFFFFF) // System Memory (cache enabled) + return ByteAddressFromRealAddress(nRealAddress & 0x0FFFFFFF); + break; + + case ConsoleID::GameCube: + // https://wiibrew.org/wiki/Memory_map + if (nRealAddress >= 0xC0000000 && nRealAddress <= 0xC17FFFFF) // System Memory (uncached) + return ByteAddressFromRealAddress(nRealAddress - (0xC0000000-0x80000000)); + break; + + case ConsoleID::DSi: + // https://problemkaputt.de/gbatek.htm#dsiiomap + if (nRealAddress >= 0x0C000000 && nRealAddress <= 0x0CFFFFFF) // Mirror of Main RAM + return ByteAddressFromRealAddress(nRealAddress - (0x0C000000-0x02000000)); + break; + + case ConsoleID::PlayStation: + // https://www.raphnet.net/electronique/psx_adaptor/Playstation.txt + if (nRealAddress >= 0x80000000 && nRealAddress <= 0x801FFFFF) // Kernel and User Memory Mirror (cached) + return ByteAddressFromRealAddress(nRealAddress & 0x001FFFFF); + if (nRealAddress >= 0xA0000000 && nRealAddress <= 0xA01FFFFF) // Kernel and User Memory Mirror (uncached) + return ByteAddressFromRealAddress(nRealAddress & 0x001FFFFF); + break; + + case ConsoleID::PlayStation2: + // https://psi-rockin.github.io/ps2tek/ + if (nRealAddress >= 0x20000000 && nRealAddress <= 0x21FFFFFF) // Main RAM Mirror (uncached) + return ByteAddressFromRealAddress(nRealAddress & 0x01FFFFFF); + if (nRealAddress >= 0x30100000 && nRealAddress <= 0x31FFFFFF) // Main RAM Mirror (uncached and accelerated) + return ByteAddressFromRealAddress(nRealAddress & 0x01FFFFFF); + break; + + case ConsoleID::WII: + // https://wiibrew.org/wiki/Memory_map + if (nRealAddress >= 0xC0000000 && nRealAddress <= 0xC17FFFFF) // System Memory (uncached) + return ByteAddressFromRealAddress(nRealAddress - (0xC0000000 - 0x80000000)); + if (nRealAddress >= 0xD0000000 && nRealAddress <= 0xD3FFFFFF) // System Memory (uncached) + return ByteAddressFromRealAddress(nRealAddress - (0xD0000000 - 0x90000000)); + break; + + default: + break; + } + return 0xFFFFFFFF; } - } // namespace context } // namespace data } // namespace ra diff --git a/tests/data/context/ConsoleContext_Tests.cpp b/tests/data/context/ConsoleContext_Tests.cpp index 9c9e60095..53ad8e1d6 100644 --- a/tests/data/context/ConsoleContext_Tests.cpp +++ b/tests/data/context/ConsoleContext_Tests.cpp @@ -30,7 +30,7 @@ TEST_CLASS(ConsoleContext_Tests) } public: - TEST_METHOD(TestAtari2600) + TEST_METHOD(TestInitializeAtari2600) { ConsoleContext context(ConsoleID::Atari2600); @@ -54,7 +54,7 @@ TEST_CLASS(ConsoleContext_Tests) Assert::AreEqual(0xFFFFFFFFU, context.ByteAddressFromRealAddress(0x14U)); } - TEST_METHOD(TestGameboyAdvance) + TEST_METHOD(TestInitializeGameboyAdvance) { ConsoleContext context(ConsoleID::GBA); @@ -91,7 +91,7 @@ TEST_CLASS(ConsoleContext_Tests) Assert::AreEqual(0x00019234U, context.ByteAddressFromRealAddress(0x02011234U)); } - TEST_METHOD(TestPlayStationPortable) + TEST_METHOD(TestInitializePlayStationPortable) { ConsoleContext context(ConsoleID::PSP); @@ -120,6 +120,71 @@ TEST_CLASS(ConsoleContext_Tests) Assert::AreEqual(0x01123456U, context.ByteAddressFromRealAddress(0x09123456U)); } + + TEST_METHOD(TestByteAddressFromRealAddressDreamcast) + { + ConsoleContext context(ConsoleID::Dreamcast); + + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x0C001234U)); + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x8C001234U)); + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0xAC001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x9C001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x00001234U)); + } + + TEST_METHOD(TestByteAddressFromRealAddressGameCube) + { + ConsoleContext context(ConsoleID::GameCube); + + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x80001234U)); + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0xC0001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0xA0001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x00001234U)); + } + + TEST_METHOD(TestByteAddressFromRealAddressDSi) + { + ConsoleContext context(ConsoleID::DSi); + + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x02001234U)); + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x0C001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x0A001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x00001234U)); + } + + TEST_METHOD(TestByteAddressFromRealAddressPlayStation) + { + ConsoleContext context(ConsoleID::PlayStation); + + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x00001234U)); + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x80001234U)); + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0xA0001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x90001234U)); + } + + TEST_METHOD(TestByteAddressFromRealAddressPlayStation2) + { + ConsoleContext context(ConsoleID::PlayStation2); + + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x00001234U)); + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x20001234U)); + Assert::AreEqual({ 0x00101234 }, context.ByteAddressFromRealAddress(0x30101234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x30001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x80001234U)); + } + + TEST_METHOD(TestByteAddressFromRealAddressWII) + { + ConsoleContext context(ConsoleID::WII); + + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0x80001234U)); + Assert::AreEqual({ 0x00001234 }, context.ByteAddressFromRealAddress(0xC0001234U)); + Assert::AreEqual({ 0x01801234 }, context.ByteAddressFromRealAddress(0x90001234U)); + Assert::AreEqual({ 0x01801234 }, context.ByteAddressFromRealAddress(0xD0001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0xA0001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0xB0001234U)); + Assert::AreEqual({ 0xFFFFFFFF }, context.ByteAddressFromRealAddress(0x00001234U)); + } }; } // namespace tests