diff --git a/src/Exports.cpp b/src/Exports.cpp index 03ad55e4c..44446d365 100644 --- a/src/Exports.cpp +++ b/src/Exports.cpp @@ -11,6 +11,7 @@ #include "context\IConsoleContext.hh" #include "context\IRcClient.hh" #include "context\impl\ConsoleContext.hh" +#include "context\impl\EmulatorMemoryContext.hh" #include "data\context\EmulatorContext.hh" #include "data\context\GameContext.hh" @@ -428,20 +429,30 @@ API void CCONV _RA_SetUserAgentDetail(const char* sDetail) API void CCONV _RA_InstallMemoryBank(int nBankID, void* pReader, void* pWriter, int nBankSize) { - ra::services::ServiceLocator::GetMutable().AddMemoryBlock(nBankID, nBankSize, - static_cast(pReader), - static_cast(pWriter)); + auto* pEmulatorMemoryContext = dynamic_cast(&ra::services::ServiceLocator::GetMutable()); + if (pEmulatorMemoryContext) + { + pEmulatorMemoryContext->AddMemoryBlock(nBankID, nBankSize, + static_cast(pReader), + static_cast(pWriter)); + } } API void CCONV _RA_InstallMemoryBankBlockReader(int nBankID, void* pReader) { - ra::services::ServiceLocator::GetMutable().AddMemoryBlockReader( - nBankID, static_cast(pReader)); + auto* pEmulatorMemoryContext = dynamic_cast(&ra::services::ServiceLocator::GetMutable()); + if (pEmulatorMemoryContext) + { + pEmulatorMemoryContext->AddMemoryBlockReader( + nBankID, static_cast(pReader)); + } } API void CCONV _RA_ClearMemoryBanks() { - ra::services::ServiceLocator::GetMutable().ClearMemoryBlocks(); + auto* pEmulatorMemoryContext = dynamic_cast(&ra::services::ServiceLocator::GetMutable()); + if (pEmulatorMemoryContext) + pEmulatorMemoryContext->ClearMemoryBlocks();; } API unsigned int CCONV _RA_IdentifyRom(const BYTE* pROM, unsigned int nROMSize) diff --git a/src/RA_Defs.cpp b/src/RA_Defs.cpp index 1ef1a6c2e..e5e4a94ff 100644 --- a/src/RA_Defs.cpp +++ b/src/RA_Defs.cpp @@ -1,9 +1,10 @@ #include "RA_Defs.h" -#include "util\Strings.hh" -#include "services\ServiceLocator.hh" +#include "context/IEmulatorMemoryContext.hh" -#include "data\context\EmulatorContext.hh" +#include "services/ServiceLocator.hh" + +#include "util/Strings.hh" #include @@ -13,8 +14,8 @@ _Use_decl_annotations_ std::string ByteAddressToString(ra::data::ByteAddress nAddr) { #ifndef RA_UTEST - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - return pEmulatorContext.FormatAddress(nAddr); + const auto& pEmulatorMemoryContext = ra::services::ServiceLocator::Get(); + return pEmulatorMemoryContext.FormatAddress(nAddr); #else return ra::StringPrintf("0x%04x", nAddr); #endif diff --git a/src/RA_Integration.vcxproj b/src/RA_Integration.vcxproj index 1b3f1580c..a130f44ed 100644 --- a/src/RA_Integration.vcxproj +++ b/src/RA_Integration.vcxproj @@ -92,7 +92,6 @@ - Create @@ -111,6 +110,7 @@ + @@ -234,7 +234,6 @@ - @@ -255,7 +254,6 @@ - @@ -264,9 +262,9 @@ - + diff --git a/src/RA_Integration.vcxproj.filters b/src/RA_Integration.vcxproj.filters index f87f1e472..0a856bc75 100644 --- a/src/RA_Integration.vcxproj.filters +++ b/src/RA_Integration.vcxproj.filters @@ -52,9 +52,6 @@ {e978c08c-fedb-4ead-af63-0420b26291bb} - - {94064815-198f-4ee6-bdea-3a44f8b79d2d} - @@ -399,9 +396,6 @@ Services\Search - - Data\Search - UI\ViewModels @@ -420,6 +414,9 @@ Services\Impl + + Services\Impl + @@ -476,12 +473,6 @@ Services\Impl - - Services - - - Services\Impl - Services\Impl @@ -1010,9 +1001,6 @@ Services\Search - - Data\Search - UI\ViewModels @@ -1034,6 +1022,9 @@ Services\Impl + + Services\Impl + diff --git a/src/data/context/EmulatorContext.cpp b/src/data/context/EmulatorContext.cpp index baf12f82c..e29c561f2 100644 --- a/src/data/context/EmulatorContext.cpp +++ b/src/data/context/EmulatorContext.cpp @@ -34,40 +34,9 @@ namespace ra { namespace data { namespace context { -static std::string FormatAddressLarge(ra::data::ByteAddress nAddress) -{ - std::string sAddress; - sAddress.resize(10); - sprintf_s(sAddress.data(), 11, "0x%08x", nAddress); - return sAddress; -} - -static std::string FormatAddressMedium(ra::data::ByteAddress nAddress) -{ - if (nAddress & 0xFF000000) - return FormatAddressLarge(nAddress); - - std::string sAddress; - sAddress.resize(8); - sprintf_s(sAddress.data(), 9, "0x%06x", nAddress); - return sAddress; -} - -static std::string FormatAddressSmall(ra::data::ByteAddress nAddress) -{ - if (nAddress & 0xFFFF0000) - return FormatAddressMedium(nAddress); - - std::string sAddress; - sAddress.resize(6); - sprintf_s(sAddress.data(), 7, "0x%04x", nAddress); - return sAddress; -} - void EmulatorContext::Initialize(EmulatorID nEmulatorId, const char* sClientName) { m_nEmulatorId = nEmulatorId; - m_fFormatAddress = FormatAddressSmall; switch (nEmulatorId) { @@ -625,578 +594,6 @@ std::string EmulatorContext::GetGameTitle() const return std::string(buffer.data()); } -void EmulatorContext::ClearMemoryBlocks() -{ - m_vMemoryBlocks.clear(); - - if (m_nTotalMemorySize != 0U) - { - m_nTotalMemorySize = 0U; - OnTotalMemorySizeChanged(); - } -} - -void EmulatorContext::AddMemoryBlock(gsl::index nIndex, size_t nBytes, - EmulatorContext::MemoryReadFunction pReader, EmulatorContext::MemoryWriteFunction pWriter) -{ - while (m_vMemoryBlocks.size() <= ra::to_unsigned(nIndex)) - m_vMemoryBlocks.emplace_back(); - - MemoryBlock& pBlock = m_vMemoryBlocks.at(nIndex); - if (pBlock.size == 0) - { - pBlock.size = nBytes; - pBlock.read = pReader; - pBlock.write = pWriter; - pBlock.readBlock = nullptr; - - m_nTotalMemorySize += nBytes; - - OnTotalMemorySizeChanged(); - } -} - -void EmulatorContext::AddMemoryBlockReader(gsl::index nIndex, - EmulatorContext::MemoryReadBlockFunction pReader) -{ - if (nIndex < gsl::narrow_cast(m_vMemoryBlocks.size())) - m_vMemoryBlocks.at(nIndex).readBlock = pReader; -} - -void EmulatorContext::OnTotalMemorySizeChanged() -{ - if (m_nTotalMemorySize <= 0x10000) - m_fFormatAddress = FormatAddressSmall; - else if (m_nTotalMemorySize <= 0x1000000) - m_fFormatAddress = FormatAddressMedium; - else - m_fFormatAddress = FormatAddressLarge; - - if (m_vNotifyTargets.LockIfNotEmpty()) - { - for (auto& target : m_vNotifyTargets.Targets()) - target.OnTotalMemorySizeChanged(); - - m_vNotifyTargets.Unlock(); - } -} - -bool EmulatorContext::HasInvalidRegions() const noexcept -{ - for (const auto& pBlock : m_vMemoryBlocks) - { - if (!pBlock.read) - return true; - } - - return false; -} - -bool EmulatorContext::IsValidAddress(ra::data::ByteAddress nAddress) const noexcept -{ - for (const auto& pBlock : m_vMemoryBlocks) - { - if (nAddress < pBlock.size) - { - if (pBlock.read) - return true; - - break; - } - - nAddress -= gsl::narrow_cast(pBlock.size); - } - - return false; -} - -void EmulatorContext::AssertIsOnDoFrameThread() const -{ -#if RA_INTEGRATION_VERSION_REVISION != 0 - #if !defined(RA_UTEST) - const auto* pClient = ra::services::ServiceLocator::Get().GetClient(); - const auto& pRuntime = ra::services::ServiceLocator::Get(); - if (!pClient->state.allow_background_memory_reads && - !pRuntime.IsOnDoFrameThread()) - { - const auto& pGameContext = ra::services::ServiceLocator::Get(); - if (pGameContext.GameId() != 0 && !pGameContext.IsGameLoading()) - { - ra::ui::viewmodels::MessageBoxViewModel::ShowWarningMessage( - L"Memory Read on Background Thread", - L"Memory is being read on a thread other than the thread that last called rc_client_do_frame and the " - L"client has specified that should not be allowed. Please notify a RetroAchievements engineer what you " - L"were doing when this occurred."); - } - } - #endif -#endif -} - -uint8_t EmulatorContext::ReadMemoryByte(ra::data::ByteAddress nAddress) const -{ - AssertIsOnDoFrameThread(); - - for (const auto& pBlock : m_vMemoryBlocks) - { - if (nAddress < pBlock.size) - { - if (pBlock.read) - return pBlock.read(nAddress); - - break; - } - - nAddress -= gsl::narrow_cast(pBlock.size); - } - - return 0; -} - -uint32_t EmulatorContext::ReadMemory(ra::data::ByteAddress nAddress, uint8_t pBuffer[], size_t nCount, - const EmulatorContext::MemoryBlock& pBlock) -{ - Expects(pBuffer != nullptr); - - if (pBlock.readBlock) - { - const size_t nRead = pBlock.readBlock(nAddress, pBuffer, gsl::narrow_cast(nCount)); - if (nRead < nCount) - memset(pBuffer + nRead, 0, nCount - nRead); - - return gsl::narrow_cast(nRead); - } - - if (!pBlock.read) - { - memset(pBuffer, 0, nCount); - return 0; - } - - auto nRemaining = nCount; - while (nRemaining >= 8) // unrolled loop to read 8-byte chunks - { - *pBuffer++ = pBlock.read(nAddress++); - *pBuffer++ = pBlock.read(nAddress++); - *pBuffer++ = pBlock.read(nAddress++); - *pBuffer++ = pBlock.read(nAddress++); - *pBuffer++ = pBlock.read(nAddress++); - *pBuffer++ = pBlock.read(nAddress++); - *pBuffer++ = pBlock.read(nAddress++); - *pBuffer++ = pBlock.read(nAddress++); - nRemaining -= 8; - } - - switch (nRemaining) // partial Duff's device to read remaining bytes - { - case 7: - *pBuffer++ = pBlock.read(nAddress++); - _FALLTHROUGH; - case 6: - *pBuffer++ = pBlock.read(nAddress++); - _FALLTHROUGH; - case 5: - *pBuffer++ = pBlock.read(nAddress++); - _FALLTHROUGH; - case 4: - *pBuffer++ = pBlock.read(nAddress++); - _FALLTHROUGH; - case 3: - *pBuffer++ = pBlock.read(nAddress++); - _FALLTHROUGH; - case 2: - *pBuffer++ = pBlock.read(nAddress++); - _FALLTHROUGH; - case 1: - *pBuffer++ = pBlock.read(nAddress++); - _FALLTHROUGH; - default: - break; - } - - return gsl::narrow_cast(nCount); -} - -_Use_decl_annotations_ -uint32_t EmulatorContext::ReadMemory(ra::data::ByteAddress nAddress, uint8_t pBuffer[], size_t nCount) const -{ - AssertIsOnDoFrameThread(); - - uint32_t nBytesRead = 0; - Expects(pBuffer != nullptr); - - for (const auto& pBlock : m_vMemoryBlocks) - { - if (nAddress >= pBlock.size) - { - nAddress -= gsl::narrow_cast(pBlock.size); - continue; - } - - const size_t nBlockRemaining = pBlock.size - nAddress; - size_t nToRead = std::min(nCount, nBlockRemaining); - - nBytesRead += ReadMemory(nAddress, pBuffer, nToRead, pBlock); - - pBuffer += nToRead; - nCount -= nToRead; - - if (nCount == 0) - return nBytesRead; - - nAddress = 0; - } - - if (nCount > 0) - memset(pBuffer, 0, nCount); - - return nBytesRead; -} - -uint32_t EmulatorContext::ReadMemory(ra::data::ByteAddress nAddress, Memory::Size nSize) const -{ - switch (nSize) - { - case Memory::Size::Bit0: - return (ReadMemoryByte(nAddress) & 0x01); - case Memory::Size::Bit1: - return (ReadMemoryByte(nAddress) & 0x02) ? 1 : 0; - case Memory::Size::Bit2: - return (ReadMemoryByte(nAddress) & 0x04) ? 1 : 0; - case Memory::Size::Bit3: - return (ReadMemoryByte(nAddress) & 0x08) ? 1 : 0; - case Memory::Size::Bit4: - return (ReadMemoryByte(nAddress) & 0x10) ? 1 : 0; - case Memory::Size::Bit5: - return (ReadMemoryByte(nAddress) & 0x20) ? 1 : 0; - case Memory::Size::Bit6: - return (ReadMemoryByte(nAddress) & 0x40) ? 1 : 0; - case Memory::Size::Bit7: - return (ReadMemoryByte(nAddress) & 0x80) ? 1 : 0; - case Memory::Size::NibbleLower: - return (ReadMemoryByte(nAddress) & 0x0F); - case Memory::Size::NibbleUpper: - return ((ReadMemoryByte(nAddress) >> 4) & 0x0F); - case Memory::Size::EightBit: - return ReadMemoryByte(nAddress); - default: - case Memory::Size::SixteenBit: - { - uint8_t buffer[2]; - ReadMemory(nAddress, buffer, 2); - return buffer[0] | (buffer[1] << 8); - } - case Memory::Size::TwentyFourBit: - { - uint8_t buffer[3]; - ReadMemory(nAddress, buffer, 3); - return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16); - } - case Memory::Size::Float: - case Memory::Size::FloatBigEndian: - case Memory::Size::Double32: - case Memory::Size::Double32BigEndian: - case Memory::Size::MBF32: - case Memory::Size::MBF32LE: - case Memory::Size::ThirtyTwoBit: - { - uint8_t buffer[4]; - ReadMemory(nAddress, buffer, 4); - return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24); - } - case Memory::Size::SixteenBitBigEndian: - { - uint8_t buffer[2]; - ReadMemory(nAddress, buffer, 2); - return buffer[1] | (buffer[0] << 8); - } - case Memory::Size::TwentyFourBitBigEndian: - { - uint8_t buffer[3]; - ReadMemory(nAddress, buffer, 3); - return buffer[2] | (buffer[1] << 8) | (buffer[0] << 16); - } - case Memory::Size::ThirtyTwoBitBigEndian: - { - uint8_t buffer[4]; - ReadMemory(nAddress, buffer, 4); - return buffer[3] | (buffer[2] << 8) | (buffer[1] << 16) | (buffer[0] << 24); - } - case Memory::Size::BitCount: - { - const uint8_t nValue = ReadMemoryByte(nAddress); - static const std::array nBitsSet = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; - return nBitsSet.at(nValue & 0x0F) + nBitsSet.at((nValue >> 4) & 0x0F); - } - } -} - -void EmulatorContext::WriteMemory(ra::data::ByteAddress nAddress, const uint8_t* pBytes, size_t nBytes) const -{ - Expects(pBytes != nullptr); - size_t nBytesWritten = 0; - auto nBlockAddress = nAddress; - - for (const auto& pBlock : m_vMemoryBlocks) - { - if (nBlockAddress < pBlock.size) - { - if (!pBlock.write) - break; - - m_bMemoryModified = true; - - if (nBytes == 1) - { - pBlock.write(nBlockAddress, pBytes[0]); - nBytesWritten = 1; - break; - } - else - { - do - { - pBlock.write(nBlockAddress++, pBytes[nBytesWritten++]); - } while (nBytesWritten < nBytes && nBlockAddress < pBlock.size); - - if (nBytesWritten == nBytes) - break; - } - } - - nBlockAddress -= gsl::narrow_cast(pBlock.size); - } - - if (nBytesWritten > 0) - { - if (m_vNotifyTargets.LockIfNotEmpty()) - { - for (auto& target : m_vNotifyTargets.Targets()) - { - for (unsigned nIndex = 0; nIndex < nBytesWritten; ++nIndex) - target.OnByteWritten(nAddress + nIndex, pBytes[nIndex]); - } - - m_vNotifyTargets.Unlock(); - } - } -} - -void EmulatorContext::WriteMemoryByte(ra::data::ByteAddress nAddress, uint8_t nValue) const -{ - WriteMemory(nAddress, &nValue, 1); -} - -void EmulatorContext::WriteMemory(ra::data::ByteAddress nAddress, Memory::Size nSize, uint32_t nValue) const -{ - union - { - uint32_t u32; - uint8_t u8[4]; - } u; - u.u32 = nValue; - - switch (nSize) - { - case Memory::Size::EightBit: - WriteMemory(nAddress, u.u8, 1); - break; - - case Memory::Size::SixteenBit: - WriteMemory(nAddress, u.u8, 2); - break; - - case Memory::Size::TwentyFourBit: - WriteMemory(nAddress, u.u8, 3); - break; - - case Memory::Size::ThirtyTwoBit: - // already little endian - WriteMemory(nAddress, u.u8, 4); - break; - - case Memory::Size::Float: - case Memory::Size::FloatBigEndian: - case Memory::Size::Double32: - case Memory::Size::Double32BigEndian: - case Memory::Size::MBF32: - case Memory::Size::MBF32LE: - // assume the value has already been encoded into a 32-bit little endian value - WriteMemory(nAddress, u.u8, 4); - break; - - case Memory::Size::SixteenBitBigEndian: - u.u8[3] = u.u8[0]; - u.u8[2] = u.u8[1]; - WriteMemory(nAddress, &u.u8[2], 2); - break; - - case Memory::Size::TwentyFourBitBigEndian: - u.u8[3] = u.u8[0]; - u.u8[0] = u.u8[2]; - u.u8[2] = u.u8[3]; - WriteMemory(nAddress, u.u8, 3); - break; - - case Memory::Size::ThirtyTwoBitBigEndian: - u.u32 = ra::data::Memory::ReverseBytes(nValue); - WriteMemory(nAddress, u.u8, 4); - break; - - case Memory::Size::Bit0: - u.u32 = (ReadMemoryByte(nAddress) & ~0x01) | (nValue & 1); - WriteMemory(nAddress, u.u8, 1); - break; - case Memory::Size::Bit1: - u.u32 = (ReadMemoryByte(nAddress) & ~0x02) | ((nValue & 1) << 1); - WriteMemory(nAddress, u.u8, 1); - break; - case Memory::Size::Bit2: - u.u32 = (ReadMemoryByte(nAddress) & ~0x04) | ((nValue & 1) << 2); - WriteMemory(nAddress, u.u8, 1); - break; - case Memory::Size::Bit3: - u.u32 = (ReadMemoryByte(nAddress) & ~0x08) | ((nValue & 1) << 3); - WriteMemory(nAddress, u.u8, 1); - break; - case Memory::Size::Bit4: - u.u32 = (ReadMemoryByte(nAddress) & ~0x10) | ((nValue & 1) << 4); - WriteMemory(nAddress, u.u8, 1); - break; - case Memory::Size::Bit5: - u.u32 = (ReadMemoryByte(nAddress) & ~0x20) | ((nValue & 1) << 5); - WriteMemory(nAddress, u.u8, 1); - break; - case Memory::Size::Bit6: - u.u32 = (ReadMemoryByte(nAddress) & ~0x40) | ((nValue & 1) << 6); - WriteMemory(nAddress, u.u8, 1); - break; - case Memory::Size::Bit7: - u.u32 = (ReadMemoryByte(nAddress) & ~0x80) | ((nValue & 1) << 7); - WriteMemory(nAddress, u.u8, 1); - break; - - case Memory::Size::NibbleLower: - u.u32 = (ReadMemoryByte(nAddress) & ~0x0F) | (nValue & 0x0F); - WriteMemory(nAddress, u.u8, 1); - break; - case Memory::Size::NibbleUpper: - u.u32 = (ReadMemoryByte(nAddress) & ~0xF0) | ((nValue & 0x0F) << 4); - WriteMemory(nAddress, u.u8, 1); - break; - - default: - break; - } -} - -void EmulatorContext::ResetMemoryModified() -{ - m_bMemoryModified = false; - - if (m_bMemoryInsecure) - { - // memory was insecure, immediately do a check - const auto& pDesktop = ra::services::ServiceLocator::Get(); - m_bMemoryInsecure = pDesktop.IsDebuggerPresent(); - - const auto& pClock = ra::services::ServiceLocator::Get(); - m_tLastInsecureCheck = pClock.UpTime(); - } -} - -bool EmulatorContext::IsMemoryInsecure() const -{ - if (m_bMemoryInsecure) - return true; - - // limit checks to once every 10 seconds - const auto& pClock = ra::services::ServiceLocator::Get(); - const auto tNow = pClock.UpTime(); - const auto tElapsed = tNow - m_tLastInsecureCheck; - if (tElapsed > std::chrono::seconds(10)) - { - const auto& pDesktop = ra::services::ServiceLocator::Get(); - m_bMemoryInsecure = pDesktop.IsDebuggerPresent(); - m_tLastInsecureCheck = tNow; - } - - return m_bMemoryInsecure; -} - -_CONSTANT_VAR MAX_BLOCK_SIZE = 256U * 1024; // 256K - -void EmulatorContext::CaptureMemory(std::vector& vBlocks, ra::data::ByteAddress nAddress, uint32_t nCount, uint32_t nPadding) const -{ - ra::data::ByteAddress nAdjustedAddress = nAddress; - for (const auto& pMemoryBlock : m_vMemoryBlocks) - { - if (nAdjustedAddress >= pMemoryBlock.size) - { - nAdjustedAddress -= gsl::narrow_cast(pMemoryBlock.size); - continue; - } - - if (!pMemoryBlock.read && !pMemoryBlock.readBlock) - { - nCount -= gsl::narrow_cast(pMemoryBlock.size); - nAddress += gsl::narrow_cast(pMemoryBlock.size); - nAdjustedAddress = 0; - continue; - } - - const uint32_t nBlockRemaining = gsl::narrow_cast(pMemoryBlock.size) - nAdjustedAddress; - uint32_t nToRead = std::min(nCount, nBlockRemaining); - nCount -= nToRead; - - while (nToRead > 0) - { - ra::data::search::MemBlock* pBlock = nullptr; - - const uint32_t nBlockSize = std::min(nToRead, MAX_BLOCK_SIZE); - const bool bIsLastBlock = (nCount == 0 && nBlockSize == nToRead); - if (!bIsLastBlock) - { - // capture nPadding overlapping bytes so we don't have to stitch multiple - // blocks together if a read occurs at the block boundary - pBlock = &vBlocks.emplace_back(nAddress, nBlockSize + nPadding, nBlockSize); - } - else - { - pBlock = &vBlocks.emplace_back(nAddress, nBlockSize, nBlockSize); - } - - Expects(pBlock != nullptr); - ReadMemory(nAdjustedAddress, pBlock->GetBytes(), nBlockSize, pMemoryBlock); - pBlock->OptimizeMemory(vBlocks); - - nAddress += nBlockSize; - nAdjustedAddress += nBlockSize; - nToRead -= nBlockSize; - } - - if (nCount == 0) - break; - - nAdjustedAddress = 0; - } - - if (nPadding) - { - // copy the first four bytes of each block to the last four bytes of the previous - // block to cover the overlap - for (size_t i = 1; i < vBlocks.size(); ++i) - { - auto& pDstBlock = vBlocks.at(i - 1); - // ASSERT: pDstBlock->GetBytes() is a size that's a multiple of 4 even if - // pDstBlock->GetBytesSize() is not. - auto* pDstBytes = pDstBlock.GetBytes() + (pDstBlock.GetBytesSize() & ~3); - const auto* pSrcBytes = vBlocks.at(i).GetBytes(); - memcpy(pDstBytes, pSrcBytes, 4); - } - } -} - void EmulatorContext::UpdateMenuState(int nMenuItemId) const { SyncClientExternalRAIntegrationMenuItem(nMenuItemId); diff --git a/src/data/context/EmulatorContext.hh b/src/data/context/EmulatorContext.hh index 5cba48d43..318031835 100644 --- a/src/data/context/EmulatorContext.hh +++ b/src/data/context/EmulatorContext.hh @@ -9,7 +9,7 @@ #include #include "data\NotifyTargetSet.hh" -#include "data\search\MemBlock.hh" +#include "data\CapturedMemoryBlock.hh" namespace ra { namespace data { @@ -178,128 +178,15 @@ public: /// const wchar_t* GetCancelButtonText() const noexcept { return m_sCancelButtonText; } - typedef uint8_t(MemoryReadFunction)(uint32_t nAddress); - typedef uint32_t(MemoryReadBlockFunction)(uint32_t nAddress, uint8_t* pBuffer, uint32_t nBytes); - typedef void (MemoryWriteFunction)(uint32_t nAddress, uint8_t nValue); - - /// - /// Specifies functions to read and write memory in the emulator. - /// - void AddMemoryBlock(gsl::index nIndex, size_t nBytes, MemoryReadFunction pReader, MemoryWriteFunction pWriter); - - /// - /// Specifies functions to read chunks of memory in the emulator. - /// - void AddMemoryBlockReader(gsl::index nIndex, MemoryReadBlockFunction pReader); - - /// - /// Clears all registered memory blocks so they can be rebuilt. - /// - void ClearMemoryBlocks(); - - /// - /// Gets the total amount of emulator-exposed memory. - /// - size_t TotalMemorySize() const noexcept { return m_nTotalMemorySize; } - - /// - /// Determines if any invalid regions were registered. - /// - bool HasInvalidRegions() const noexcept; - - /// - /// Determines if the specified address is valid. - /// - bool IsValidAddress(ra::data::ByteAddress nAddress) const noexcept; - - /// - /// Reads memory from the emulator. - /// - uint32_t ReadMemory(ra::data::ByteAddress nAddress, Memory::Size nSize) const; - - /// - /// Reads memory from the emulator. - /// - uint8_t ReadMemoryByte(ra::data::ByteAddress nAddress) const; - - /// - /// Reads memory from the emulator. - /// - uint32_t ReadMemory(ra::data::ByteAddress nAddress, _Out_writes_(nCount) uint8_t pBuffer[], size_t nCount) const; - - /// - /// Writes memory to the emulator. - /// - void WriteMemoryByte(ra::data::ByteAddress nAddress, uint8_t nValue) const; - - /// - /// Writes memory to the emulator. - /// - void WriteMemory(ra::data::ByteAddress nAddress, Memory::Size nSize, uint32_t nValue) const; - class DispatchesReadMemory { protected: static void DispatchMemoryRead(std::function&& fFunction); }; - /// - /// Captures the current state of memory - /// - void CaptureMemory(std::vector& vMemBlocks, ra::data::ByteAddress nAddress, uint32_t nCount, uint32_t nPadding) const; - - /// - /// Converts an address to a displayable string. - /// - std::string FormatAddress(ra::data::ByteAddress nAddress) const { return m_fFormatAddress(nAddress); } - - /// - /// Gets whether or not memory has been modified. - /// - bool WasMemoryModified() const noexcept { return m_bMemoryModified; } - - /// - /// Sets the memory modified flag. - /// - void SetMemoryModified() noexcept { m_bMemoryModified = true; } - - /// - /// Resets the memory modified flag. - /// - void ResetMemoryModified(); - - /// - /// Determines if the memory is considered secure. - /// - virtual bool IsMemoryInsecure() const; - - class NotifyTarget - { - public: - NotifyTarget() noexcept = default; - virtual ~NotifyTarget() noexcept = default; - NotifyTarget(const NotifyTarget&) noexcept = delete; - NotifyTarget& operator=(const NotifyTarget&) noexcept = delete; - NotifyTarget(NotifyTarget&&) noexcept = default; - NotifyTarget& operator=(NotifyTarget&&) noexcept = default; - - virtual void OnTotalMemorySizeChanged() noexcept(false) {} - virtual void OnByteWritten(ra::data::ByteAddress, uint8_t) noexcept(false) {} - }; - - void AddNotifyTarget(NotifyTarget& pTarget) noexcept { m_vNotifyTargets.Add(pTarget); } - void RemoveNotifyTarget(NotifyTarget& pTarget) noexcept { m_vNotifyTargets.Remove(pTarget); } - -private: - mutable ra::data::NotifyTargetSet m_vNotifyTargets; - - void WriteMemory(ra::data::ByteAddress nAddress, const uint8_t* pBytes, size_t nByteCount) const; - protected: void UpdateUserAgent(); - void OnTotalMemorySizeChanged(); virtual bool ValidateClientVersion(bool& bHardcore); - void AssertIsOnDoFrameThread() const noexcept(false); EmulatorID m_nEmulatorId = EmulatorID::UnknownEmulator; std::string m_sVersion; @@ -316,23 +203,6 @@ protected: std::function m_fUnpauseEmulator; std::function m_fGetGameTitle; std::function m_fRebuildMenu; - - std::function m_fFormatAddress; - - struct MemoryBlock - { - size_t size; - MemoryReadFunction* read; - MemoryWriteFunction* write; - MemoryReadBlockFunction* readBlock; - }; - static uint32_t ReadMemory(ra::data::ByteAddress nAddress, uint8_t pBuffer[], size_t nCount, const MemoryBlock& pBlock); - - std::vector m_vMemoryBlocks; - size_t m_nTotalMemorySize = 0U; - mutable bool m_bMemoryModified = false; - mutable bool m_bMemoryInsecure = false; - mutable std::chrono::steady_clock::time_point m_tLastInsecureCheck{}; }; } // namespace context diff --git a/src/data/context/SessionTracker.cpp b/src/data/context/SessionTracker.cpp index 48ae824a1..b7263193e 100644 --- a/src/data/context/SessionTracker.cpp +++ b/src/data/context/SessionTracker.cpp @@ -5,6 +5,8 @@ #include "util\Log.hh" #include "util\Strings.hh" +#include "context\IEmulatorMemoryContext.hh" + #include "data\context\GameContext.hh" #include "services\AchievementRuntime.hh" @@ -162,8 +164,8 @@ void SessionTracker::UpdateSession(time_t tSessionStart) const auto& pConfiguration = ra::services::ServiceLocator::Get(); if (pConfiguration.IsFeatureEnabled(ra::services::Feature::Hardcore)) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - pEmulatorContext.IsMemoryInsecure(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + pMemoryContext.IsMemoryInsecure(); } } diff --git a/src/data/models/CodeNoteModel.cpp b/src/data/models/CodeNoteModel.cpp index 75aa56a2e..92ff8a819 100644 --- a/src/data/models/CodeNoteModel.cpp +++ b/src/data/models/CodeNoteModel.cpp @@ -2,8 +2,6 @@ #include "context\IConsoleContext.hh" -#include "data\context\EmulatorContext.hh" - #include "services\ServiceLocator.hh" #include "util\Strings.hh" @@ -92,7 +90,7 @@ static ra::data::ByteAddress ConvertPointer(ra::data::ByteAddress nAddress) return nAddress; } -void CodeNoteModel::UpdateRawPointerValue(ra::data::ByteAddress nAddress, const ra::data::context::EmulatorContext& pEmulatorContext, +void CodeNoteModel::UpdateRawPointerValue(ra::data::ByteAddress nAddress, const ra::context::IEmulatorMemoryContext& pMemoryContext, NoteMovedFunction fNoteMovedCallback) { if (m_pPointerData == nullptr) @@ -100,7 +98,7 @@ void CodeNoteModel::UpdateRawPointerValue(ra::data::ByteAddress nAddress, const m_pPointerData->PointerRead = true; - const uint32_t nValue = pEmulatorContext.ReadMemory(nAddress, GetMemSize()); + const uint32_t nValue = pMemoryContext.ReadMemory(nAddress, GetMemSize()); if (nValue != m_pPointerData->RawPointerValue) { m_pPointerData->RawPointerValue = nValue; @@ -130,7 +128,7 @@ void CodeNoteModel::UpdateRawPointerValue(ra::data::ByteAddress nAddress, const if (pNote.IsPointer()) { pNote.UpdateRawPointerValue(m_pPointerData->PointerAddress + pNote.GetAddress(), - pEmulatorContext, fNoteMovedCallback); + pMemoryContext, fNoteMovedCallback); } } } @@ -1130,8 +1128,8 @@ void CodeNoteModel::ProcessIndirectNotes(const std::wstring& sNote, size_t nInde // flag it to be converted to an RA address when evaluating indirect notes in DoFrame() if (m_nMemSize == Memory::Size::ThirtyTwoBit || m_nMemSize == Memory::Size::ThirtyTwoBitBigEndian) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - const auto nMaxAddress = pEmulatorContext.TotalMemorySize(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nMaxAddress = pMemoryContext.TotalMemorySize(); const auto nUnderflowMinAddress = 0xFFFFFFFF - nMaxAddress + 1; pointerData->OffsetType = PointerData::OffsetType::Converted; diff --git a/src/data/models/CodeNoteModel.hh b/src/data/models/CodeNoteModel.hh index 2ff8e3dca..2c1af74b6 100644 --- a/src/data/models/CodeNoteModel.hh +++ b/src/data/models/CodeNoteModel.hh @@ -4,7 +4,7 @@ #include "data/Types.hh" -#include "data/context/EmulatorContext.hh" +#include "context/IEmulatorMemoryContext.hh" namespace ra { namespace data { @@ -45,7 +45,7 @@ public: virtual bool GetPointerChain(std::vector& vChain, const CodeNoteModel& pRootNote) const; typedef std::function NoteMovedFunction; - void UpdateRawPointerValue(ra::data::ByteAddress nAddress, const ra::data::context::EmulatorContext& pEmulatorContext, NoteMovedFunction fNoteMovedCallback); + void UpdateRawPointerValue(ra::data::ByteAddress nAddress, const ra::context::IEmulatorMemoryContext& pMemoryContext, NoteMovedFunction fNoteMovedCallback); bool GetPreviousAddress(ra::data::ByteAddress nBeforeAddress, ra::data::ByteAddress& nPreviousAddress) const; bool GetNextAddress(ra::data::ByteAddress nAfterAddress, ra::data::ByteAddress& nNextAddress) const; diff --git a/src/data/models/CodeNotesModel.cpp b/src/data/models/CodeNotesModel.cpp index 183e41a77..f362b19a3 100644 --- a/src/data/models/CodeNotesModel.cpp +++ b/src/data/models/CodeNotesModel.cpp @@ -510,7 +510,7 @@ void CodeNotesModel::DoFrame() if (!m_bHasPointers) return; - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); for (auto& pCodeNote : m_vCodeNotes) { @@ -518,11 +518,11 @@ void CodeNotesModel::DoFrame() { if (!m_fCodeNoteMoved) { - pCodeNote->UpdateRawPointerValue(pCodeNote->GetAddress(), pEmulatorContext, nullptr); + pCodeNote->UpdateRawPointerValue(pCodeNote->GetAddress(), pMemoryContext, nullptr); } else if (pCodeNote->HasRawPointerValue()) { - pCodeNote->UpdateRawPointerValue(pCodeNote->GetAddress(), pEmulatorContext, + pCodeNote->UpdateRawPointerValue(pCodeNote->GetAddress(), pMemoryContext, [this](ra::data::ByteAddress nOldAddress, ra::data::ByteAddress nNewAddress, const CodeNoteModel& pOffsetNote) { m_fCodeNoteMoved(nOldAddress, nNewAddress, pOffsetNote.GetNote()); }); @@ -530,7 +530,7 @@ void CodeNotesModel::DoFrame() else { // pointer hasn't been read before, provide dummy previous address - pCodeNote->UpdateRawPointerValue(pCodeNote->GetAddress(), pEmulatorContext, + pCodeNote->UpdateRawPointerValue(pCodeNote->GetAddress(), pMemoryContext, [this](ra::data::ByteAddress, ra::data::ByteAddress nNewAddress, const CodeNoteModel& pOffsetNote) { m_fCodeNoteMoved(0xFFFFFFFF, nNewAddress, pOffsetNote.GetNote()); }); diff --git a/src/data/models/MemoryRegionsModel.cpp b/src/data/models/MemoryRegionsModel.cpp index cd14984fb..3b5ad1168 100644 --- a/src/data/models/MemoryRegionsModel.cpp +++ b/src/data/models/MemoryRegionsModel.cpp @@ -2,7 +2,7 @@ #include "RA_Defs.h" -#include "data/context/EmulatorContext.hh" +#include "context/IEmulatorMemoryContext.hh" #include "services/ServiceLocator.hh" @@ -129,8 +129,8 @@ static bool ParseAddress(const wchar_t** pointer, ra::data::ByteAddress& address bool MemoryRegionsModel::ParseFilterRange(const std::wstring& sRange, _Out_ ra::data::ByteAddress& nStart, _Out_ ra::data::ByteAddress& nEnd) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - const auto nMax = gsl::narrow_cast(pEmulatorContext.TotalMemorySize()) - 1; + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nMax = gsl::narrow_cast(pMemoryContext.TotalMemorySize()) - 1; if (sRange.empty()) { diff --git a/src/data/models/TriggerValidation.cpp b/src/data/models/TriggerValidation.cpp index a94873f0f..50ae79e22 100644 --- a/src/data/models/TriggerValidation.cpp +++ b/src/data/models/TriggerValidation.cpp @@ -235,8 +235,8 @@ bool TriggerValidation::Validate(const std::string& sTrigger, std::wstring& sErr if (nMaxAddress == 0) { // if console definition doesn't specify the max address, see how much was exposed by the emulator - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - nMaxAddress = gsl::narrow_cast(pEmulatorContext.TotalMemorySize()) - 1; + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + nMaxAddress = gsl::narrow_cast(pMemoryContext.TotalMemorySize()) - 1; nResult = rc_validate_trigger(&trigger->trigger, sErrorBuffer, sizeof(sErrorBuffer), nMaxAddress); } diff --git a/src/data/search/MemBlock.hh b/src/data/search/MemBlock.hh deleted file mode 100644 index acd38be14..000000000 --- a/src/data/search/MemBlock.hh +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef SEARCH_MEMBLOCK_H -#define SEARCH_MEMBLOCK_H -#pragma once - -#include "data\Memory.hh" - -namespace ra { -namespace data { -namespace search { - -class MemBlock -{ -private: - struct AllocatedMemory - { - uint32_t nReferenceCount; - uint32_t nHash; - uint8_t pBytes[16]; - }; - -public: - explicit MemBlock(_In_ uint32_t nAddress, _In_ uint32_t nSize, _In_ uint32_t nMaxAddresses) : - m_nFirstAddress(nAddress), - m_nBytesSize(nSize), - m_nMatchingAddresses(nMaxAddresses), - m_nMaxAddresses(nMaxAddresses) - { - if (IsBytesAllocated()) - { - const auto nAllocSize = sizeof(AllocatedMemory) - sizeof(m_pAllocatedMemory->pBytes) + - ((gsl::narrow_cast(nSize) + 3) & ~3); - m_pAllocatedMemory = static_cast(malloc(nAllocSize)); - Expects(m_pAllocatedMemory != nullptr); - m_pAllocatedMemory->nReferenceCount = 1; - m_pAllocatedMemory->nHash = 0; - } - } - - MemBlock(const MemBlock& other) noexcept; - MemBlock& operator=(const MemBlock&) noexcept = delete; - MemBlock(MemBlock&& other) noexcept; - MemBlock& operator=(MemBlock&&) noexcept = delete; - - ~MemBlock() noexcept; - - uint8_t* GetBytes() noexcept - { - return IsBytesAllocated() ? &m_pAllocatedMemory->pBytes[0] : &m_vBytes[0]; - } - const uint8_t* GetBytes() const noexcept - { - return IsBytesAllocated() ? &m_pAllocatedMemory->pBytes[0] : &m_vBytes[0]; - } - - void SetFirstAddress(ra::data::ByteAddress nAddress) noexcept { m_nFirstAddress = nAddress; } - ra::data::ByteAddress GetFirstAddress() const noexcept { return m_nFirstAddress; } - uint32_t GetBytesSize() const noexcept { return m_nBytesSize & 0x00FFFFFF; } - bool IsBytesAllocated() const noexcept { return GetBytesSize() > sizeof(m_vBytes); } - void SetMaxAddresses(uint32_t nMaxAddresses) noexcept { m_nMaxAddresses = nMaxAddresses; } - uint32_t GetMaxAddresses() const noexcept { return m_nMaxAddresses; } - - bool ContainsAddress(ra::data::ByteAddress nAddress) const noexcept; - - void SetMatchingAddresses(std::vector& vAddresses, gsl::index nFirstIndex, gsl::index nLastIndex); - void CopyMatchingAddresses(const MemBlock& pSource); - void ExcludeMatchingAddress(ra::data::ByteAddress nAddress); - bool ContainsMatchingAddress(ra::data::ByteAddress nAddress) const; - - void SetMatchingAddressCount(uint32_t nCount) noexcept { m_nMatchingAddresses = nCount; } - uint32_t GetMatchingAddressCount() const noexcept { return m_nMatchingAddresses; } - ra::data::ByteAddress GetMatchingAddress(gsl::index nIndex) const noexcept; - bool AreAllAddressesMatching() const noexcept { return m_nMatchingAddresses == m_nMaxAddresses; } - - const uint8_t* GetMatchingAddressPointer() const noexcept - { - if (AreAllAddressesMatching()) - return nullptr; - - const auto nAddressesSize = (m_nMaxAddresses + 7) / 8; - return (nAddressesSize > sizeof(m_vAddresses)) ? m_pAddresses : &m_vAddresses[0]; - } - - bool HasMatchingAddress(const uint8_t* pMatchingAddresses, ra::data::ByteAddress nAddress) const noexcept - { - if (!pMatchingAddresses) - return true; - - const auto nIndex = nAddress - m_nFirstAddress; - if (nIndex >= m_nMaxAddresses) - return false; - - const auto nBit = 1 << (nIndex & 7); - return (pMatchingAddresses[nIndex >> 3] & nBit); - } - - void ShareMemory(const std::vector& vBlocks, uint32_t nHash) noexcept; - void OptimizeMemory(const std::vector& vBlocks) noexcept; - -private: - uint8_t* AllocateMatchingAddresses() noexcept; - void SetRepeat(uint32_t nCount, uint32_t nValue) noexcept; - - ra::data::ByteAddress m_nFirstAddress; // 4 bytes - uint32_t m_nBytesSize; // 4 bytes - - union // 8 bytes - { - uint8_t m_vBytes[8]{}; - AllocatedMemory* m_pAllocatedMemory; - }; - - union // 8 bytes - { - uint8_t m_vAddresses[8]{}; - uint8_t* m_pAddresses; - }; - - uint32_t m_nMatchingAddresses; // 4 bytes - uint32_t m_nMaxAddresses; // 4 bytes -}; -static_assert(sizeof(MemBlock) <= 32, "sizeof(MemBlock) is incorrect"); - -} // namespace search -} // namespace services -} // namespace ra - -#endif /* !SEARCH_MEMBLOCK_H */ diff --git a/src/devkit/RADevKit.vcxproj b/src/devkit/RADevKit.vcxproj index 47a914585..8813c0c32 100644 --- a/src/devkit/RADevKit.vcxproj +++ b/src/devkit/RADevKit.vcxproj @@ -58,7 +58,9 @@ + + @@ -70,10 +72,13 @@ + + + @@ -84,10 +89,13 @@ + + + diff --git a/src/devkit/RADevKit.vcxproj.filters b/src/devkit/RADevKit.vcxproj.filters index f6d63ddcd..7a5d8cb93 100644 --- a/src/devkit/RADevKit.vcxproj.filters +++ b/src/devkit/RADevKit.vcxproj.filters @@ -126,6 +126,24 @@ data + + data + + + context\impl + + + context + + + services\impl + + + services + + + services + @@ -164,5 +182,11 @@ context\impl + + data + + + context\impl + \ No newline at end of file diff --git a/src/devkit/context/IEmulatorMemoryContext.hh b/src/devkit/context/IEmulatorMemoryContext.hh new file mode 100644 index 000000000..20f925d49 --- /dev/null +++ b/src/devkit/context/IEmulatorMemoryContext.hh @@ -0,0 +1,120 @@ +#ifndef RA_CONTEXT_IEMULATORMEMORYCONTEXT_HH +#define RA_CONTEXT_IEMULATORMEMORYCONTEXT_HH +#pragma once + +#include "data/Memory.hh" + +#include + +#include "data/CapturedMemoryBlock.hh" +#include "data/NotifyTargetSet.hh" + +namespace ra { +namespace context { + +class IEmulatorMemoryContext +{ +public: + virtual ~IEmulatorMemoryContext() noexcept = default; + IEmulatorMemoryContext(const IEmulatorMemoryContext&) noexcept = delete; + IEmulatorMemoryContext& operator=(const IEmulatorMemoryContext&) noexcept = delete; + IEmulatorMemoryContext(IEmulatorMemoryContext&&) noexcept = delete; + IEmulatorMemoryContext& operator=(IEmulatorMemoryContext&&) noexcept = delete; + + /// + /// Gets the total amount of emulator-exposed memory. + /// + virtual size_t TotalMemorySize() const noexcept = 0; + + /// + /// Determines if any invalid regions were registered. + /// + virtual bool HasInvalidRegions() const noexcept = 0; + + /// + /// Determines if the specified address is valid. + /// + virtual bool IsValidAddress(ra::data::ByteAddress nAddress) const noexcept = 0; + + /// + /// Reads memory from the emulator. + /// + virtual uint32_t ReadMemory(ra::data::ByteAddress nAddress, ra::data::Memory::Size nSize) const = 0; + + /// + /// Reads memory from the emulator. + /// + virtual uint8_t ReadMemoryByte(ra::data::ByteAddress nAddress) const = 0; + + /// + /// Reads memory from the emulator. + /// + virtual uint32_t ReadMemory(ra::data::ByteAddress nAddress, uint8_t pBuffer[], size_t nCount) const = 0; + + /// + /// Writes memory to the emulator. + /// + virtual void WriteMemoryByte(ra::data::ByteAddress nAddress, uint8_t nValue) const = 0; + + /// + /// Writes memory to the emulator. + /// + virtual void WriteMemory(ra::data::ByteAddress nAddress, ra::data::Memory::Size nSize, uint32_t nValue) const = 0; + + /// + /// Captures the current state of memory + /// + virtual void CaptureMemory(std::vector& vMemBlocks, ra::data::ByteAddress nAddress, uint32_t nCount, uint32_t nPadding) const = 0; + + /// + /// Converts an address to a displayable string. + /// + virtual std::string FormatAddress(ra::data::ByteAddress nAddress) const = 0; + + /// + /// Gets whether or not memory has been modified. + /// + virtual bool WasMemoryModified() const noexcept = 0; + + /// + /// Sets the memory modified flag. + /// + virtual void SetMemoryModified() noexcept = 0; + + /// + /// Resets the memory modified flag. + /// + virtual void ResetMemoryModified() = 0; + + /// + /// Determines if the memory is considered secure. + /// + virtual bool IsMemoryInsecure() const = 0; + + class NotifyTarget + { + public: + NotifyTarget() noexcept = default; + virtual ~NotifyTarget() noexcept = default; + NotifyTarget(const NotifyTarget&) noexcept = delete; + NotifyTarget& operator=(const NotifyTarget&) noexcept = delete; + NotifyTarget(NotifyTarget&&) noexcept = default; + NotifyTarget& operator=(NotifyTarget&&) noexcept = default; + + virtual void OnTotalMemorySizeChanged() noexcept(false) {} + virtual void OnByteWritten(ra::data::ByteAddress, uint8_t) noexcept(false) {} + }; + + void AddNotifyTarget(NotifyTarget& pTarget) noexcept { m_vNotifyTargets.Add(pTarget); } + void RemoveNotifyTarget(NotifyTarget& pTarget) noexcept { m_vNotifyTargets.Remove(pTarget); } + +protected: + IEmulatorMemoryContext() noexcept = default; + + mutable ra::data::NotifyTargetSet m_vNotifyTargets; +}; + +} // namespace context +} // namespace ra + +#endif // !RA_CONTEXT_IEMULATORMEMORYCONTEXT_HH diff --git a/src/devkit/context/impl/EmulatorMemoryContext.cpp b/src/devkit/context/impl/EmulatorMemoryContext.cpp new file mode 100644 index 000000000..ceab3490c --- /dev/null +++ b/src/devkit/context/impl/EmulatorMemoryContext.cpp @@ -0,0 +1,623 @@ +#include "EmulatorMemoryContext.hh" + +#include "services/IClock.hh" +#include "services/IDebuggerDetector.hh" +#include "services/ServiceLocator.hh" + +#include "util/Compat.hh" +#include "util/TypeCasts.hh" + +namespace ra { +namespace context { +namespace impl { + +static std::string FormatAddressLarge(ra::data::ByteAddress nAddress) +{ + std::string sAddress; + sAddress.resize(10); + sprintf_s(sAddress.data(), 11, "0x%08x", nAddress); + return sAddress; +} + +static std::string FormatAddressMedium(ra::data::ByteAddress nAddress) +{ + if (nAddress & 0xFF000000) + return FormatAddressLarge(nAddress); + + std::string sAddress; + sAddress.resize(8); + sprintf_s(sAddress.data(), 9, "0x%06x", nAddress); + return sAddress; +} + +static std::string FormatAddressSmall(ra::data::ByteAddress nAddress) +{ + if (nAddress & 0xFFFF0000) + return FormatAddressMedium(nAddress); + + std::string sAddress; + sAddress.resize(6); + sprintf_s(sAddress.data(), 7, "0x%04x", nAddress); + return sAddress; +} + +GSL_SUPPRESS_F6 +EmulatorMemoryContext::EmulatorMemoryContext() noexcept +{ + m_fFormatAddress = FormatAddressSmall; +} + +void EmulatorMemoryContext::ClearMemoryBlocks() +{ + m_vMemoryBlocks.clear(); + + if (m_nTotalMemorySize != 0U) + { + m_nTotalMemorySize = 0U; + OnTotalMemorySizeChanged(); + } +} + +void EmulatorMemoryContext::AddMemoryBlock(gsl::index nIndex, size_t nBytes, + EmulatorMemoryContext::MemoryReadFunction pReader, EmulatorMemoryContext::MemoryWriteFunction pWriter) +{ + while (m_vMemoryBlocks.size() <= ra::to_unsigned(nIndex)) + m_vMemoryBlocks.emplace_back(); + + MemoryBlock& pBlock = m_vMemoryBlocks.at(nIndex); + if (pBlock.size == 0) + { + pBlock.size = nBytes; + pBlock.read = pReader; + pBlock.write = pWriter; + pBlock.readBlock = nullptr; + + m_nTotalMemorySize += nBytes; + + OnTotalMemorySizeChanged(); + } +} + +void EmulatorMemoryContext::AddMemoryBlockReader(gsl::index nIndex, + EmulatorMemoryContext::MemoryReadBlockFunction pReader) +{ + if (nIndex < gsl::narrow_cast(m_vMemoryBlocks.size())) + m_vMemoryBlocks.at(nIndex).readBlock = pReader; +} + +void EmulatorMemoryContext::OnTotalMemorySizeChanged() +{ + if (m_nTotalMemorySize <= 0x10000) + m_fFormatAddress = FormatAddressSmall; + else if (m_nTotalMemorySize <= 0x1000000) + m_fFormatAddress = FormatAddressMedium; + else + m_fFormatAddress = FormatAddressLarge; + + if (m_vNotifyTargets.LockIfNotEmpty()) + { + for (auto& target : m_vNotifyTargets.Targets()) + target.OnTotalMemorySizeChanged(); + + m_vNotifyTargets.Unlock(); + } +} + +bool EmulatorMemoryContext::HasInvalidRegions() const noexcept +{ + for (const auto& pBlock : m_vMemoryBlocks) + { + if (!pBlock.read) + return true; + } + + return false; +} + +bool EmulatorMemoryContext::IsValidAddress(ra::data::ByteAddress nAddress) const noexcept +{ + for (const auto& pBlock : m_vMemoryBlocks) + { + if (nAddress < pBlock.size) + { + if (pBlock.read) + return true; + + break; + } + + nAddress -= gsl::narrow_cast(pBlock.size); + } + + return false; +} + +void EmulatorMemoryContext::AssertIsOnDoFrameThread() const +{ +#if RA_INTEGRATION_VERSION_REVISION != 0 + #if !defined(RA_UTEST) + const auto* pClient = ra::services::ServiceLocator::Get().GetClient(); + const auto& pRuntime = ra::services::ServiceLocator::Get(); + if (!pClient->state.allow_background_memory_reads && + !pRuntime.IsOnDoFrameThread()) + { + const auto& pGameContext = ra::services::ServiceLocator::Get(); + if (pGameContext.GameId() != 0 && !pGameContext.IsGameLoading()) + { + ra::ui::viewmodels::MessageBoxViewModel::ShowWarningMessage( + L"Memory Read on Background Thread", + L"Memory is being read on a thread other than the thread that last called rc_client_do_frame and the " + L"client has specified that should not be allowed. Please notify a RetroAchievements engineer what you " + L"were doing when this occurred."); + } + } + #endif +#endif +} + +uint8_t EmulatorMemoryContext::ReadMemoryByte(ra::data::ByteAddress nAddress) const +{ + AssertIsOnDoFrameThread(); + + for (const auto& pBlock : m_vMemoryBlocks) + { + if (nAddress < pBlock.size) + { + if (pBlock.read) + return pBlock.read(nAddress); + + break; + } + + nAddress -= gsl::narrow_cast(pBlock.size); + } + + return 0; +} + +uint32_t EmulatorMemoryContext::ReadMemory(ra::data::ByteAddress nAddress, uint8_t pBuffer[], size_t nCount, + const EmulatorMemoryContext::MemoryBlock& pBlock) +{ + Expects(pBuffer != nullptr); + + if (pBlock.readBlock) + { + const size_t nRead = pBlock.readBlock(nAddress, pBuffer, gsl::narrow_cast(nCount)); + if (nRead < nCount) + memset(pBuffer + nRead, 0, nCount - nRead); + + return gsl::narrow_cast(nRead); + } + + if (!pBlock.read) + { + memset(pBuffer, 0, nCount); + return 0; + } + + auto nRemaining = nCount; + while (nRemaining >= 8) // unrolled loop to read 8-byte chunks + { + *pBuffer++ = pBlock.read(nAddress++); + *pBuffer++ = pBlock.read(nAddress++); + *pBuffer++ = pBlock.read(nAddress++); + *pBuffer++ = pBlock.read(nAddress++); + *pBuffer++ = pBlock.read(nAddress++); + *pBuffer++ = pBlock.read(nAddress++); + *pBuffer++ = pBlock.read(nAddress++); + *pBuffer++ = pBlock.read(nAddress++); + nRemaining -= 8; + } + + switch (nRemaining) // partial Duff's device to read remaining bytes + { + case 7: + *pBuffer++ = pBlock.read(nAddress++); + _FALLTHROUGH; + case 6: + *pBuffer++ = pBlock.read(nAddress++); + _FALLTHROUGH; + case 5: + *pBuffer++ = pBlock.read(nAddress++); + _FALLTHROUGH; + case 4: + *pBuffer++ = pBlock.read(nAddress++); + _FALLTHROUGH; + case 3: + *pBuffer++ = pBlock.read(nAddress++); + _FALLTHROUGH; + case 2: + *pBuffer++ = pBlock.read(nAddress++); + _FALLTHROUGH; + case 1: + *pBuffer++ = pBlock.read(nAddress++); + _FALLTHROUGH; + default: + break; + } + + return gsl::narrow_cast(nCount); +} + +uint32_t EmulatorMemoryContext::ReadMemory(ra::data::ByteAddress nAddress, uint8_t pBuffer[], size_t nCount) const +{ + AssertIsOnDoFrameThread(); + + uint32_t nBytesRead = 0; + Expects(pBuffer != nullptr); + + for (const auto& pBlock : m_vMemoryBlocks) + { + if (nAddress >= pBlock.size) + { + nAddress -= gsl::narrow_cast(pBlock.size); + continue; + } + + const size_t nBlockRemaining = pBlock.size - nAddress; + size_t nToRead = std::min(nCount, nBlockRemaining); + + nBytesRead += ReadMemory(nAddress, pBuffer, nToRead, pBlock); + + pBuffer += nToRead; + nCount -= nToRead; + + if (nCount == 0) + return nBytesRead; + + nAddress = 0; + } + + if (nCount > 0) + memset(pBuffer, 0, nCount); + + return nBytesRead; +} + +uint32_t EmulatorMemoryContext::ReadMemory(ra::data::ByteAddress nAddress, ra::data::Memory::Size nSize) const +{ + switch (nSize) + { + case ra::data::Memory::Size::Bit0: + return (ReadMemoryByte(nAddress) & 0x01); + case ra::data::Memory::Size::Bit1: + return (ReadMemoryByte(nAddress) & 0x02) ? 1 : 0; + case ra::data::Memory::Size::Bit2: + return (ReadMemoryByte(nAddress) & 0x04) ? 1 : 0; + case ra::data::Memory::Size::Bit3: + return (ReadMemoryByte(nAddress) & 0x08) ? 1 : 0; + case ra::data::Memory::Size::Bit4: + return (ReadMemoryByte(nAddress) & 0x10) ? 1 : 0; + case ra::data::Memory::Size::Bit5: + return (ReadMemoryByte(nAddress) & 0x20) ? 1 : 0; + case ra::data::Memory::Size::Bit6: + return (ReadMemoryByte(nAddress) & 0x40) ? 1 : 0; + case ra::data::Memory::Size::Bit7: + return (ReadMemoryByte(nAddress) & 0x80) ? 1 : 0; + case ra::data::Memory::Size::NibbleLower: + return (ReadMemoryByte(nAddress) & 0x0F); + case ra::data::Memory::Size::NibbleUpper: + return ((ReadMemoryByte(nAddress) >> 4) & 0x0F); + case ra::data::Memory::Size::EightBit: + return ReadMemoryByte(nAddress); + default: + case ra::data::Memory::Size::SixteenBit: + { + uint8_t buffer[2]; + ReadMemory(nAddress, buffer, 2); + return buffer[0] | (buffer[1] << 8); + } + case ra::data::Memory::Size::TwentyFourBit: + { + uint8_t buffer[3]; + ReadMemory(nAddress, buffer, 3); + return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16); + } + case ra::data::Memory::Size::Float: + case ra::data::Memory::Size::FloatBigEndian: + case ra::data::Memory::Size::Double32: + case ra::data::Memory::Size::Double32BigEndian: + case ra::data::Memory::Size::MBF32: + case ra::data::Memory::Size::MBF32LE: + case ra::data::Memory::Size::ThirtyTwoBit: + { + uint8_t buffer[4]; + ReadMemory(nAddress, buffer, 4); + return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24); + } + case ra::data::Memory::Size::SixteenBitBigEndian: + { + uint8_t buffer[2]; + ReadMemory(nAddress, buffer, 2); + return buffer[1] | (buffer[0] << 8); + } + case ra::data::Memory::Size::TwentyFourBitBigEndian: + { + uint8_t buffer[3]; + ReadMemory(nAddress, buffer, 3); + return buffer[2] | (buffer[1] << 8) | (buffer[0] << 16); + } + case ra::data::Memory::Size::ThirtyTwoBitBigEndian: + { + uint8_t buffer[4]; + ReadMemory(nAddress, buffer, 4); + return buffer[3] | (buffer[2] << 8) | (buffer[1] << 16) | (buffer[0] << 24); + } + case ra::data::Memory::Size::BitCount: + { + const uint8_t nValue = ReadMemoryByte(nAddress); + static const std::array nBitsSet = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; + return nBitsSet.at(nValue & 0x0F) + nBitsSet.at((nValue >> 4) & 0x0F); + } + } +} + +void EmulatorMemoryContext::WriteMemory(ra::data::ByteAddress nAddress, const uint8_t* pBytes, size_t nBytes) const +{ + Expects(pBytes != nullptr); + size_t nBytesWritten = 0; + auto nBlockAddress = nAddress; + + for (const auto& pBlock : m_vMemoryBlocks) + { + if (nBlockAddress < pBlock.size) + { + if (!pBlock.write) + break; + + m_bMemoryModified = true; + + if (nBytes == 1) + { + pBlock.write(nBlockAddress, pBytes[0]); + nBytesWritten = 1; + break; + } + else + { + do + { + pBlock.write(nBlockAddress++, pBytes[nBytesWritten++]); + } while (nBytesWritten < nBytes && nBlockAddress < pBlock.size); + + if (nBytesWritten == nBytes) + break; + } + } + + nBlockAddress -= gsl::narrow_cast(pBlock.size); + } + + if (nBytesWritten > 0) + { + if (m_vNotifyTargets.LockIfNotEmpty()) + { + for (auto& target : m_vNotifyTargets.Targets()) + { + for (unsigned nIndex = 0; nIndex < nBytesWritten; ++nIndex) + target.OnByteWritten(nAddress + nIndex, pBytes[nIndex]); + } + + m_vNotifyTargets.Unlock(); + } + } +} + +void EmulatorMemoryContext::WriteMemoryByte(ra::data::ByteAddress nAddress, uint8_t nValue) const +{ + WriteMemory(nAddress, &nValue, 1); +} + +void EmulatorMemoryContext::WriteMemory(ra::data::ByteAddress nAddress, ra::data::Memory::Size nSize, uint32_t nValue) const +{ + union + { + uint32_t u32; + uint8_t u8[4]; + } u; + u.u32 = nValue; + + switch (nSize) + { + case ra::data::Memory::Size::EightBit: + WriteMemory(nAddress, u.u8, 1); + break; + + case ra::data::Memory::Size::SixteenBit: + WriteMemory(nAddress, u.u8, 2); + break; + + case ra::data::Memory::Size::TwentyFourBit: + WriteMemory(nAddress, u.u8, 3); + break; + + case ra::data::Memory::Size::ThirtyTwoBit: + // already little endian + WriteMemory(nAddress, u.u8, 4); + break; + + case ra::data::Memory::Size::Float: + case ra::data::Memory::Size::FloatBigEndian: + case ra::data::Memory::Size::Double32: + case ra::data::Memory::Size::Double32BigEndian: + case ra::data::Memory::Size::MBF32: + case ra::data::Memory::Size::MBF32LE: + // assume the value has already been encoded into a 32-bit little endian value + WriteMemory(nAddress, u.u8, 4); + break; + + case ra::data::Memory::Size::SixteenBitBigEndian: + u.u8[3] = u.u8[0]; + u.u8[2] = u.u8[1]; + WriteMemory(nAddress, &u.u8[2], 2); + break; + + case ra::data::Memory::Size::TwentyFourBitBigEndian: + u.u8[3] = u.u8[0]; + u.u8[0] = u.u8[2]; + u.u8[2] = u.u8[3]; + WriteMemory(nAddress, u.u8, 3); + break; + + case ra::data::Memory::Size::ThirtyTwoBitBigEndian: + u.u32 = ra::data::Memory::ReverseBytes(nValue); + WriteMemory(nAddress, u.u8, 4); + break; + + case ra::data::Memory::Size::Bit0: + u.u32 = (ReadMemoryByte(nAddress) & ~0x01) | (nValue & 1); + WriteMemory(nAddress, u.u8, 1); + break; + case ra::data::Memory::Size::Bit1: + u.u32 = (ReadMemoryByte(nAddress) & ~0x02) | ((nValue & 1) << 1); + WriteMemory(nAddress, u.u8, 1); + break; + case ra::data::Memory::Size::Bit2: + u.u32 = (ReadMemoryByte(nAddress) & ~0x04) | ((nValue & 1) << 2); + WriteMemory(nAddress, u.u8, 1); + break; + case ra::data::Memory::Size::Bit3: + u.u32 = (ReadMemoryByte(nAddress) & ~0x08) | ((nValue & 1) << 3); + WriteMemory(nAddress, u.u8, 1); + break; + case ra::data::Memory::Size::Bit4: + u.u32 = (ReadMemoryByte(nAddress) & ~0x10) | ((nValue & 1) << 4); + WriteMemory(nAddress, u.u8, 1); + break; + case ra::data::Memory::Size::Bit5: + u.u32 = (ReadMemoryByte(nAddress) & ~0x20) | ((nValue & 1) << 5); + WriteMemory(nAddress, u.u8, 1); + break; + case ra::data::Memory::Size::Bit6: + u.u32 = (ReadMemoryByte(nAddress) & ~0x40) | ((nValue & 1) << 6); + WriteMemory(nAddress, u.u8, 1); + break; + case ra::data::Memory::Size::Bit7: + u.u32 = (ReadMemoryByte(nAddress) & ~0x80) | ((nValue & 1) << 7); + WriteMemory(nAddress, u.u8, 1); + break; + + case ra::data::Memory::Size::NibbleLower: + u.u32 = (ReadMemoryByte(nAddress) & ~0x0F) | (nValue & 0x0F); + WriteMemory(nAddress, u.u8, 1); + break; + case ra::data::Memory::Size::NibbleUpper: + u.u32 = (ReadMemoryByte(nAddress) & ~0xF0) | ((nValue & 0x0F) << 4); + WriteMemory(nAddress, u.u8, 1); + break; + + default: + break; + } +} + +void EmulatorMemoryContext::ResetMemoryModified() +{ + m_bMemoryModified = false; + + if (m_bMemoryInsecure) + { + // memory was insecure, immediately do a check + const auto& pDesktop = ra::services::ServiceLocator::Get(); + m_bMemoryInsecure = pDesktop.IsDebuggerPresent(); + + const auto& pClock = ra::services::ServiceLocator::Get(); + m_tLastInsecureCheck = pClock.UpTime(); + } +} + +bool EmulatorMemoryContext::IsMemoryInsecure() const +{ + if (m_bMemoryInsecure) + return true; + + // limit checks to once every 10 seconds + const auto& pClock = ra::services::ServiceLocator::Get(); + const auto tNow = pClock.UpTime(); + const auto tElapsed = tNow - m_tLastInsecureCheck; + if (tElapsed > std::chrono::seconds(10)) + { + const auto& pDesktop = ra::services::ServiceLocator::Get(); + m_bMemoryInsecure = pDesktop.IsDebuggerPresent(); + m_tLastInsecureCheck = tNow; + } + + return m_bMemoryInsecure; +} + +_CONSTANT_VAR MAX_BLOCK_SIZE = 256U * 1024; // 256K + +void EmulatorMemoryContext::CaptureMemory(std::vector& vBlocks, ra::data::ByteAddress nAddress, uint32_t nCount, uint32_t nPadding) const +{ + ra::data::ByteAddress nAdjustedAddress = nAddress; + for (const auto& pMemoryBlock : m_vMemoryBlocks) + { + if (nAdjustedAddress >= pMemoryBlock.size) + { + nAdjustedAddress -= gsl::narrow_cast(pMemoryBlock.size); + continue; + } + + if (!pMemoryBlock.read && !pMemoryBlock.readBlock) + { + nCount -= gsl::narrow_cast(pMemoryBlock.size); + nAddress += gsl::narrow_cast(pMemoryBlock.size); + nAdjustedAddress = 0; + continue; + } + + const uint32_t nBlockRemaining = gsl::narrow_cast(pMemoryBlock.size) - nAdjustedAddress; + uint32_t nToRead = std::min(nCount, nBlockRemaining); + nCount -= nToRead; + + while (nToRead > 0) + { + ra::data::CapturedMemoryBlock* pBlock = nullptr; + + const uint32_t nBlockSize = std::min(nToRead, MAX_BLOCK_SIZE); + const bool bIsLastBlock = (nCount == 0 && nBlockSize == nToRead); + if (!bIsLastBlock) + { + // capture nPadding overlapping bytes so we don't have to stitch multiple + // blocks together if a read occurs at the block boundary + pBlock = &vBlocks.emplace_back(nAddress, nBlockSize + nPadding, nBlockSize); + } + else + { + pBlock = &vBlocks.emplace_back(nAddress, nBlockSize, nBlockSize); + } + + Expects(pBlock != nullptr); + ReadMemory(nAdjustedAddress, pBlock->GetBytes(), nBlockSize, pMemoryBlock); + pBlock->OptimizeMemory(vBlocks); + + nAddress += nBlockSize; + nAdjustedAddress += nBlockSize; + nToRead -= nBlockSize; + } + + if (nCount == 0) + break; + + nAdjustedAddress = 0; + } + + if (nPadding) + { + // copy the first four bytes of each block to the last four bytes of the previous + // block to cover the overlap + for (size_t i = 1; i < vBlocks.size(); ++i) + { + auto& pDstBlock = vBlocks.at(i - 1); + // ASSERT: pDstBlock->GetBytes() is a size that's a multiple of 4 even if + // pDstBlock->GetBytesSize() is not. + auto* pDstBytes = pDstBlock.GetBytes() + (pDstBlock.GetBytesSize() & ~3); + const auto* pSrcBytes = vBlocks.at(i).GetBytes(); + memcpy(pDstBytes, pSrcBytes, 4); + } + } +} + +} // namespace impl +} // namespace context +} // namespace ra diff --git a/src/devkit/context/impl/EmulatorMemoryContext.hh b/src/devkit/context/impl/EmulatorMemoryContext.hh new file mode 100644 index 000000000..98cd3b525 --- /dev/null +++ b/src/devkit/context/impl/EmulatorMemoryContext.hh @@ -0,0 +1,139 @@ +#ifndef RA_CONTEXT_IMPL_EMULATORMEMORYCONTEXT_HH +#define RA_CONTEXT_IMPL_EMULATORMEMORYCONTEXT_HH +#pragma once + +#include "context/IEmulatorMemoryContext.hh" + +namespace ra { +namespace context { +namespace impl { + +class EmulatorMemoryContext : public IEmulatorMemoryContext +{ +public: + EmulatorMemoryContext() noexcept; + virtual ~EmulatorMemoryContext() noexcept = default; + EmulatorMemoryContext(const EmulatorMemoryContext&) noexcept = delete; + EmulatorMemoryContext& operator=(const EmulatorMemoryContext&) noexcept = delete; + EmulatorMemoryContext(EmulatorMemoryContext&&) noexcept = delete; + EmulatorMemoryContext& operator=(EmulatorMemoryContext&&) noexcept = delete; + + typedef uint8_t(MemoryReadFunction)(uint32_t nAddress); + typedef uint32_t(MemoryReadBlockFunction)(uint32_t nAddress, uint8_t* pBuffer, uint32_t nBytes); + typedef void (MemoryWriteFunction)(uint32_t nAddress, uint8_t nValue); + + /// + /// Specifies functions to read and write memory in the emulator. + /// + void AddMemoryBlock(gsl::index nIndex, size_t nBytes, MemoryReadFunction pReader, MemoryWriteFunction pWriter); + + /// + /// Specifies functions to read chunks of memory in the emulator. + /// + void AddMemoryBlockReader(gsl::index nIndex, MemoryReadBlockFunction pReader); + + /// + /// Clears all registered memory blocks so they can be rebuilt. + /// + void ClearMemoryBlocks(); + + /// + /// Gets the total amount of emulator-exposed memory. + /// + size_t TotalMemorySize() const noexcept override { return m_nTotalMemorySize; } + + /// + /// Determines if any invalid regions were registered. + /// + bool HasInvalidRegions() const noexcept override; + + /// + /// Determines if the specified address is valid. + /// + bool IsValidAddress(ra::data::ByteAddress nAddress) const noexcept override; + + /// + /// Reads memory from the emulator. + /// + uint32_t ReadMemory(ra::data::ByteAddress nAddress, ra::data::Memory::Size nSize) const override; + + /// + /// Reads memory from the emulator. + /// + uint8_t ReadMemoryByte(ra::data::ByteAddress nAddress) const override; + + /// + /// Reads memory from the emulator. + /// + uint32_t ReadMemory(ra::data::ByteAddress nAddress, uint8_t pBuffer[], size_t nCount) const override; + + /// + /// Writes memory to the emulator. + /// + void WriteMemoryByte(ra::data::ByteAddress nAddress, uint8_t nValue) const override; + + /// + /// Writes memory to the emulator. + /// + void WriteMemory(ra::data::ByteAddress nAddress, ra::data::Memory::Size nSize, uint32_t nValue) const override; + + /// + /// Captures the current state of memory + /// + void CaptureMemory(std::vector& vMemBlocks, ra::data::ByteAddress nAddress, uint32_t nCount, uint32_t nPadding) const override; + + /// + /// Converts an address to a displayable string. + /// + std::string FormatAddress(ra::data::ByteAddress nAddress) const override { return m_fFormatAddress(nAddress); } + + /// + /// Gets whether or not memory has been modified. + /// + bool WasMemoryModified() const noexcept override { return m_bMemoryModified; } + + /// + /// Sets the memory modified flag. + /// + void SetMemoryModified() noexcept override { m_bMemoryModified = true; } + + /// + /// Resets the memory modified flag. + /// + void ResetMemoryModified() override; + + /// + /// Determines if the memory is considered secure. + /// + bool IsMemoryInsecure() const override; + +private: + void WriteMemory(ra::data::ByteAddress nAddress, const uint8_t* pBytes, size_t nByteCount) const; + +protected: + void OnTotalMemorySizeChanged(); + void AssertIsOnDoFrameThread() const noexcept(false); + + std::function m_fFormatAddress; + + struct MemoryBlock + { + size_t size; + MemoryReadFunction* read; + MemoryWriteFunction* write; + MemoryReadBlockFunction* readBlock; + }; + static uint32_t ReadMemory(ra::data::ByteAddress nAddress, uint8_t pBuffer[], size_t nCount, const MemoryBlock& pBlock); + + std::vector m_vMemoryBlocks; + size_t m_nTotalMemorySize = 0U; + mutable bool m_bMemoryModified = false; + mutable bool m_bMemoryInsecure = false; + mutable std::chrono::steady_clock::time_point m_tLastInsecureCheck{}; +}; + +} // namespace impl +} // namespace context +} // namespace ra + +#endif // !RA_CONTEXT_IMPL_EMULATORMEMORYCONTEXT_HH diff --git a/src/data/search/MemBlock.cpp b/src/devkit/data/CapturedMemoryBlock.cpp similarity index 52% rename from src/data/search/MemBlock.cpp rename to src/devkit/data/CapturedMemoryBlock.cpp index fdb7f82af..2f00b39d4 100644 --- a/src/data/search/MemBlock.cpp +++ b/src/devkit/data/CapturedMemoryBlock.cpp @@ -1,16 +1,13 @@ -#include "MemBlock.hh" - -#include "util\GSL.hh" +#include "CapturedMemoryBlock.hh" namespace ra { namespace data { -namespace search { -MemBlock::MemBlock(const MemBlock& other) noexcept : +CapturedMemoryBlock::CapturedMemoryBlock(const CapturedMemoryBlock& other) noexcept : m_nFirstAddress(other.m_nFirstAddress), m_nBytesSize(other.m_nBytesSize), - m_nMatchingAddresses(other.m_nMatchingAddresses), - m_nMaxAddresses(other.m_nMaxAddresses) + m_nMatchingAddressCount(other.m_nMatchingAddressCount), + m_nAddressCount(other.m_nAddressCount) { if (IsBytesAllocated()) { @@ -22,14 +19,14 @@ MemBlock::MemBlock(const MemBlock& other) noexcept : std::memcpy(m_vBytes, other.m_vBytes, sizeof(m_vBytes)); } - m_nMatchingAddresses = other.m_nMatchingAddresses; + m_nMatchingAddressCount = other.m_nMatchingAddressCount; if (!AreAllAddressesMatching()) { - if ((m_nMatchingAddresses + 7) / 8 > sizeof(m_vAddresses)) + if ((m_nMatchingAddressCount + 7) / 8 > sizeof(m_vAddresses)) { auto* pAddresses = AllocateMatchingAddresses(); if (pAddresses != nullptr) - std::memcpy(pAddresses, other.m_pAddresses, (m_nMatchingAddresses + 7) / 8); + std::memcpy(pAddresses, other.m_pAddresses, (m_nMatchingAddressCount + 7) / 8); } else { @@ -38,11 +35,11 @@ MemBlock::MemBlock(const MemBlock& other) noexcept : } } -MemBlock::MemBlock(MemBlock&& other) noexcept : +CapturedMemoryBlock::CapturedMemoryBlock(CapturedMemoryBlock&& other) noexcept : m_nFirstAddress(other.m_nFirstAddress), m_nBytesSize(other.m_nBytesSize), - m_nMatchingAddresses(other.m_nMatchingAddresses), - m_nMaxAddresses(other.m_nMaxAddresses) + m_nMatchingAddressCount(other.m_nMatchingAddressCount), + m_nAddressCount(other.m_nAddressCount) { if (other.IsBytesAllocated()) { @@ -57,11 +54,11 @@ MemBlock::MemBlock(MemBlock&& other) noexcept : if (!AreAllAddressesMatching()) { - if ((m_nMatchingAddresses + 7) / 8 > sizeof(m_vAddresses)) + if ((m_nMatchingAddressCount + 7) / 8 > sizeof(m_vAddresses)) { m_pAddresses = other.m_pAddresses; other.m_pAddresses = nullptr; - other.m_nMatchingAddresses = 0; + other.m_nMatchingAddressCount = 0; } else { @@ -70,7 +67,7 @@ MemBlock::MemBlock(MemBlock&& other) noexcept : } } -MemBlock::~MemBlock() noexcept +CapturedMemoryBlock::~CapturedMemoryBlock() noexcept { if (IsBytesAllocated()) { @@ -79,11 +76,11 @@ MemBlock::~MemBlock() noexcept free(m_pAllocatedMemory); } - if (!AreAllAddressesMatching() && (m_nMatchingAddresses + 7) / 8 > sizeof(m_vAddresses)) + if (!AreAllAddressesMatching() && (m_nMatchingAddressCount + 7) / 8 > sizeof(m_vAddresses)) delete[] m_pAddresses; } -void MemBlock::ShareMemory(const std::vector& vBlocks, uint32_t nHash) noexcept +void CapturedMemoryBlock::ShareMemory(const std::vector& vBlocks, uint32_t nHash) noexcept { if (IsBytesAllocated()) { @@ -111,14 +108,14 @@ void MemBlock::ShareMemory(const std::vector& vBlocks, uint32_t nHash) } } -void MemBlock::SetRepeat(uint32_t nCount, uint32_t nValue) noexcept -{ - m_nBytesSize = (nCount * sizeof(uint32_t)) | 0x01000000; - memcpy(m_vBytes, &nValue, 4); - memcpy(&m_vBytes[4], &nValue, 4); -} +//void CapturedMemoryBlock::SetRepeat(uint32_t nCount, uint32_t nValue) noexcept +//{ +// m_nBytesSize = (nCount * sizeof(uint32_t)) | 0x01000000; +// memcpy(m_vBytes, &nValue, 4); +// memcpy(&m_vBytes[4], &nValue, 4); +//} -void MemBlock::OptimizeMemory(const std::vector& vBlocks) noexcept +void CapturedMemoryBlock::OptimizeMemory(const std::vector& vBlocks) noexcept { if (!IsBytesAllocated()) return; @@ -135,12 +132,18 @@ void MemBlock::OptimizeMemory(const std::vector& vBl GSL_SUPPRESS_TYPE1 const auto* pStop = reinterpret_cast(pBytes + GetBytesSize()); - //const auto* pUniqueStart = pScan; + +#ifdef COLLAPSE_FILLED + // TODO: this attempts to identify large chunks of repeated data to avoid + // allocating AllocatedMemory for them. However, that breaks anything + // trying to read from the GetBytes() pointer, so its unfeasible at this time. + + const auto* pUniqueStart = pScan; uint32_t nHash = *pScan++; uint32_t nLast = nHash; uint32_t nRepeat = 1; - //bool bWasSplit = false; - //uint32_t nAddress = GetFirstAddress(); + bool bWasSplit = false; + uint32_t nAddress = GetFirstAddress(); while (pScan < pStop) { @@ -151,26 +154,26 @@ void MemBlock::OptimizeMemory(const std::vector& vBl } else { - //if (nRepeat >= 64 / 4) // 64 bytes of repeated data - //{ - // const auto* pRepeatStart = pScan - nRepeat - 1; - // const auto nUniqueSize = (pRepeatStart - pUniqueStart) * sizeof(uint32_t); - // if (nUniqueSize) - // { - // auto& pUniqueBlock = vBlocks.emplace_back(nAddress, nUniqueSize, nUniqueSize); - // memcpy(pUniqueBlock.GetBytes(), pUniqueStart, nUniqueSize); - // pUniqueBlock.ShareMemory(vBlocks, nHash); - // nAddress += nUniqueSize; - // } - - // auto& pRepeatBlock = vBlocks.emplace_back(nAddress, 0, 0); - // pRepeatBlock.SetRepeat(nRepeat, nLast); - // nAddress += nRepeat * sizeof(uint32_t); - - // pUniqueStart = pScan - 1; - // bWasSplit = true; - // nHash = 0; - //} + if (nRepeat >= 64 / 4) // 64 bytes of repeated data + { + const auto* pRepeatStart = pScan - nRepeat - 1; + const auto nUniqueSize = (pRepeatStart - pUniqueStart) * sizeof(uint32_t); + if (nUniqueSize) + { + auto& pUniqueBlock = vBlocks.emplace_back(nAddress, nUniqueSize, nUniqueSize); + memcpy(pUniqueBlock.GetBytes(), pUniqueStart, nUniqueSize); + pUniqueBlock.ShareMemory(vBlocks, nHash); + nAddress += nUniqueSize; + } + + auto& pRepeatBlock = vBlocks.emplace_back(nAddress, 0, 0); + pRepeatBlock.SetRepeat(nRepeat, nLast); + nAddress += nRepeat * sizeof(uint32_t); + + pUniqueStart = pScan - 1; + bWasSplit = true; + nHash = 0; + } // branchless version of "if (nRepeat & 1) nHash ^= nScan" nHash ^= (nScan * (nRepeat & 1)); @@ -180,46 +183,51 @@ void MemBlock::OptimizeMemory(const std::vector& vBl } } - //if (nRepeat >= 64 / 4) // 64 bytes of repeated data - //{ - // const auto* pRepeatStart = pScan - nRepeat - 1; - // const auto nUniqueSize = (pRepeatStart - pUniqueStart) * sizeof(uint32_t); - // if (nUniqueSize) - // { - // auto& pUniqueBlock = vBlocks.emplace_back(nAddress, nUniqueSize, nUniqueSize); - // memcpy(pUniqueBlock.GetBytes(), pUniqueStart, nUniqueSize); - // pUniqueBlock.ShareMemory(vBlocks, nHash); - // nAddress += nUniqueSize; - // } - - // auto& pRepeatBlock = vBlocks.emplace_back(nAddress, 0, 0); - // pRepeatBlock.SetRepeat(nRepeat, nLast); - // nAddress += nRepeat * sizeof(uint32_t); - - // pUniqueStart = pScan; - //} - - //if (bWasSplit) - //{ - // // copy last block - // const auto nUniqueSize = (pScan - pUniqueStart) * sizeof(uint32_t); - // if (nUniqueSize) - // { - // auto& pUniqueBlock = vBlocks.emplace_back(nAddress, nUniqueSize, nUniqueSize); - // memcpy(pUniqueBlock.GetBytes(), pUniqueStart, nUniqueSize); - // pUniqueBlock.ShareMemory(vBlocks, nHash); - // } - - // vBlocks.erase(this); - // return; - //} + if (nRepeat >= 64 / 4) // 64 bytes of repeated data + { + const auto* pRepeatStart = pScan - nRepeat - 1; + const auto nUniqueSize = (pRepeatStart - pUniqueStart) * sizeof(uint32_t); + if (nUniqueSize) + { + auto& pUniqueBlock = vBlocks.emplace_back(nAddress, nUniqueSize, nUniqueSize); + memcpy(pUniqueBlock.GetBytes(), pUniqueStart, nUniqueSize); + pUniqueBlock.ShareMemory(vBlocks, nHash); + nAddress += nUniqueSize; + } + + auto& pRepeatBlock = vBlocks.emplace_back(nAddress, 0, 0); + pRepeatBlock.SetRepeat(nRepeat, nLast); + nAddress += nRepeat * sizeof(uint32_t); + + pUniqueStart = pScan; + } + + if (bWasSplit) + { + // copy last block + const auto nUniqueSize = (pScan - pUniqueStart) * sizeof(uint32_t); + if (nUniqueSize) + { + auto& pUniqueBlock = vBlocks.emplace_back(nAddress, nUniqueSize, nUniqueSize); + memcpy(pUniqueBlock.GetBytes(), pUniqueStart, nUniqueSize); + pUniqueBlock.ShareMemory(vBlocks, nHash); + } + + vBlocks.erase(this); + return; + } +#else + uint32_t nHash = *pScan++; + while (pScan < pStop) + nHash ^= *pScan++; +#endif ShareMemory(vBlocks, nHash); } -uint8_t* MemBlock::AllocateMatchingAddresses() noexcept +uint8_t* CapturedMemoryBlock::AllocateMatchingAddresses() noexcept { - const auto nAddressesSize = (m_nMaxAddresses + 7) / 8; + const auto nAddressesSize = (m_nAddressCount + 7) / 8; if (nAddressesSize > sizeof(m_vAddresses)) { if (m_pAddresses == nullptr) @@ -231,13 +239,13 @@ uint8_t* MemBlock::AllocateMatchingAddresses() noexcept return &m_vAddresses[0]; } -void MemBlock::SetMatchingAddresses(std::vector& vAddresses, gsl::index nFirstIndex, gsl::index nLastIndex) +void CapturedMemoryBlock::SetMatchingAddresses(std::vector& vAddresses, gsl::index nFirstIndex, gsl::index nLastIndex) { - m_nMatchingAddresses = gsl::narrow_cast(nLastIndex - nFirstIndex) + 1; + m_nMatchingAddressCount = gsl::narrow_cast(nLastIndex - nFirstIndex) + 1; - if (m_nMatchingAddresses != m_nMaxAddresses) + if (m_nMatchingAddressCount != m_nAddressCount) { - const auto nAddressesSize = (m_nMaxAddresses + 7) / 8; + const auto nAddressesSize = (m_nAddressCount + 7) / 8; unsigned char* pAddresses = AllocateMatchingAddresses(); Expects(pAddresses != nullptr); @@ -245,31 +253,34 @@ void MemBlock::SetMatchingAddresses(std::vector& vAddress for (gsl::index nIndex = nFirstIndex; nIndex <= nLastIndex; ++nIndex) { const auto nOffset = vAddresses.at(nIndex) - m_nFirstAddress; - const auto nBit = 1 << (nOffset & 7); - pAddresses[nOffset >> 3] |= nBit; + if (nOffset < m_nAddressCount) + { + const auto nBit = 1 << (nOffset & 7); + pAddresses[nOffset >> 3] |= nBit; + } } } } -void MemBlock::CopyMatchingAddresses(const MemBlock& pSource) +void CapturedMemoryBlock::CopyMatchingAddresses(const CapturedMemoryBlock& pSource) { - Expects(pSource.m_nMaxAddresses == m_nMaxAddresses); + Expects(pSource.m_nAddressCount == m_nAddressCount); if (pSource.AreAllAddressesMatching()) { - m_nMatchingAddresses = m_nMaxAddresses; + m_nMatchingAddressCount = m_nAddressCount; } else { - const auto nAddressesSize = (m_nMaxAddresses + 7) / 8; + const auto nAddressesSize = (m_nAddressCount + 7) / 8; unsigned char* pAddresses = AllocateMatchingAddresses(); memcpy(pAddresses, pSource.GetMatchingAddressPointer(), nAddressesSize); - m_nMatchingAddresses = pSource.m_nMatchingAddresses; + m_nMatchingAddressCount = pSource.m_nMatchingAddressCount; } } -void MemBlock::ExcludeMatchingAddress(ra::data::ByteAddress nAddress) +void CapturedMemoryBlock::ExcludeMatchingAddress(ra::data::ByteAddress nAddress) { - const auto nAddressesSize = (m_nMaxAddresses + 7) / 8; + const auto nAddressesSize = (m_nAddressCount + 7) / 8; unsigned char* pAddresses = nullptr; const auto nIndex = nAddress - m_nFirstAddress; const auto nBit = 1 << (nIndex & 7); @@ -289,25 +300,25 @@ void MemBlock::ExcludeMatchingAddress(ra::data::ByteAddress nAddress) } pAddresses[nIndex >> 3] &= ~nBit; - --m_nMatchingAddresses; + --m_nMatchingAddressCount; } -bool MemBlock::ContainsAddress(ra::data::ByteAddress nAddress) const noexcept +bool CapturedMemoryBlock::ContainsAddress(ra::data::ByteAddress nAddress) const noexcept { if (nAddress < m_nFirstAddress) return false; nAddress -= m_nFirstAddress; - return (nAddress < m_nMaxAddresses); + return (nAddress < m_nAddressCount); } -bool MemBlock::ContainsMatchingAddress(ra::data::ByteAddress nAddress) const +bool CapturedMemoryBlock::ContainsMatchingAddress(ra::data::ByteAddress nAddress) const { if (nAddress < m_nFirstAddress) return false; const auto nIndex = nAddress - m_nFirstAddress; - if (nIndex >= m_nMaxAddresses) + if (nIndex >= m_nAddressCount) return false; if (AreAllAddressesMatching()) @@ -319,15 +330,15 @@ bool MemBlock::ContainsMatchingAddress(ra::data::ByteAddress nAddress) const return (pAddresses[nIndex >> 3] & nBit); } -ra::data::ByteAddress MemBlock::GetMatchingAddress(gsl::index nIndex) const noexcept +ra::data::ByteAddress CapturedMemoryBlock::GetMatchingAddress(gsl::index nIndex) const noexcept { if (AreAllAddressesMatching()) return m_nFirstAddress + gsl::narrow_cast(nIndex); - const auto nAddressesSize = (m_nMaxAddresses + 7) / 8; + const auto nAddressesSize = (m_nAddressCount + 7) / 8; const uint8_t* pAddresses = (nAddressesSize > sizeof(m_vAddresses)) ? m_pAddresses : &m_vAddresses[0]; ra::data::ByteAddress nAddress = m_nFirstAddress; - const ra::data::ByteAddress nStop = m_nFirstAddress + m_nMaxAddresses; + const ra::data::ByteAddress nStop = m_nFirstAddress + m_nAddressCount; uint8_t nMask = 0x01; if (pAddresses != nullptr) @@ -366,6 +377,5 @@ ra::data::ByteAddress MemBlock::GetMatchingAddress(gsl::index nIndex) const noex return 0; } -} // namespace search -} // namespace services +} // namespace data } // namespace ra diff --git a/src/devkit/data/CapturedMemoryBlock.hh b/src/devkit/data/CapturedMemoryBlock.hh new file mode 100644 index 000000000..31c86634e --- /dev/null +++ b/src/devkit/data/CapturedMemoryBlock.hh @@ -0,0 +1,207 @@ +#ifndef RA_DATA_CAPTUREDMEMORYBLOCK_HH +#define RA_DATA_CAPTUREDMEMORYBLOCK_HH +#pragma once + +#include "Memory.hh" + +#include "util/GSL.hh" + +namespace ra { +namespace data { + +class CapturedMemoryBlock +{ +private: + struct AllocatedMemory + { + uint32_t nReferenceCount; + uint32_t nHash; + uint8_t pBytes[16]; // this will actually be sized by the allocation code. + }; + +public: + explicit CapturedMemoryBlock(uint32_t nAddress, uint32_t nSize, uint32_t nMaxAddresses) : + m_nFirstAddress(nAddress), + m_nBytesSize(nSize), + m_nMatchingAddressCount(nMaxAddresses), + m_nAddressCount(nMaxAddresses) + { + if (IsBytesAllocated()) // not actually allocated yet, but about to be. + { + const auto nAllocSize = sizeof(AllocatedMemory) - sizeof(m_pAllocatedMemory->pBytes) + + ((gsl::narrow_cast(nSize) + 3) & ~3); + m_pAllocatedMemory = static_cast(malloc(nAllocSize)); + Expects(m_pAllocatedMemory != nullptr); + m_pAllocatedMemory->nReferenceCount = 1; + m_pAllocatedMemory->nHash = 0; + } + } + + ~CapturedMemoryBlock() noexcept; + + CapturedMemoryBlock(const CapturedMemoryBlock& other) noexcept; + CapturedMemoryBlock& operator=(const CapturedMemoryBlock&) noexcept = delete; + CapturedMemoryBlock(CapturedMemoryBlock&& other) noexcept; + CapturedMemoryBlock& operator=(CapturedMemoryBlock&&) noexcept = delete; + + /// + /// Gets the raw bytes that were captured. + /// + uint8_t* GetBytes() noexcept + { + return IsBytesAllocated() ? &m_pAllocatedMemory->pBytes[0] : &m_vBytes[0]; + } + + /// + /// Gets the raw bytes that were captured. + /// + const uint8_t* GetBytes() const noexcept + { + return IsBytesAllocated() ? &m_pAllocatedMemory->pBytes[0] : &m_vBytes[0]; + } + + /// + /// Gets the number of captured bytes. + /// + uint32_t GetBytesSize() const noexcept { return m_nBytesSize; } + + /// + /// Gets the first address of the captured memory. + /// + /// + /// May be virtualized as addresses represent indices into the captured memory. + /// + ByteAddress GetFirstAddress() const noexcept { return m_nFirstAddress; } + + /// + /// Sets the first address of the captured memory. + /// + void SetFirstAddress(ByteAddress nAddress) noexcept { m_nFirstAddress = nAddress; } + + /// + /// Gets the number of addresses associated to the captured memory. + /// + /// + /// This is specifed by the capturing code to indicate how many whole records are availble + /// in the captured memory depending on the captured size. For example, 75 bytes of memory + /// holds 18 whole 32-bit records, so the caller would set this to 18. + /// + uint32_t GetAddressCount() const noexcept { return m_nAddressCount; } + + /// + /// Sets the number of addresses associated to the captured memory. + /// + void SetAddressCount(uint32_t nAddressCount) noexcept + { + m_nAddressCount = nAddressCount; + m_nMatchingAddressCount = nAddressCount; + } + + /// + /// Determines whether the specified address is valid within this CapturedMemoryBlock. + /// + bool ContainsAddress(ByteAddress nAddress) const noexcept; + + /// + /// Gets the number of addresses associated to the captured memory that have been flagged as matching. + /// + uint32_t GetMatchingAddressCount() const noexcept { return m_nMatchingAddressCount; } + + /// + /// Gets the Nth matching address. + /// + ByteAddress GetMatchingAddress(gsl::index nIndex) const noexcept; + + /// + /// Determines whether the specified address is marked as matching. + /// + bool ContainsMatchingAddress(ByteAddress nAddress) const; + + /// + /// Specifies which addresses are matching from a slice of an address list. + /// + void SetMatchingAddresses(std::vector& vAddresses, gsl::index nFirstIndex, gsl::index nLastIndex); + + /// + /// Marks an address as no longer matching. + /// + void ExcludeMatchingAddress(ByteAddress nAddress); + + /// + /// Copies the matching addresses from another CapturedMemoryBlock. + /// + void CopyMatchingAddresses(const CapturedMemoryBlock& pSource); + + /// + /// Gets the raw pointer to the matching address data to pass to . + /// + /// + /// Exposed for performance. Do not call unnecessarily. + /// + const uint8_t* GetMatchingAddressPointer() const noexcept + { + if (AreAllAddressesMatching()) + return nullptr; + + const auto nAddressesSize = (m_nAddressCount + 7) / 8; + return (nAddressesSize > sizeof(m_vAddresses)) ? m_pAddresses : &m_vAddresses[0]; + } + + /// + /// Determines whether the specified address is marked as matching. + /// + /// + /// Exposed for performance. Call for general use. + /// + bool HasMatchingAddress(const uint8_t* pMatchingAddresses, ByteAddress nAddress) const noexcept + { + if (!pMatchingAddresses) + return true; + + const auto nIndex = nAddress - m_nFirstAddress; + if (nIndex >= m_nAddressCount) + return false; + + const auto nBit = 1 << (nIndex & 7); + return (pMatchingAddresses[nIndex >> 3] & nBit); + } + + /// + /// Attempts to minimize memory allocations by detecting and sharing large blocks of repeated data. + /// + /// A collection of previously captured memory blocks that could be shared. + void OptimizeMemory(const std::vector& vBlocks) noexcept; + +private: + bool IsBytesAllocated() const noexcept { return GetBytesSize() > sizeof(m_vBytes); } + + void ShareMemory(const std::vector& vBlocks, uint32_t nHash) noexcept; + //void SetRepeat(uint32_t nCount, uint32_t nValue) noexcept; + + uint8_t* AllocateMatchingAddresses() noexcept; + bool AreAllAddressesMatching() const noexcept { return m_nMatchingAddressCount == m_nAddressCount; } + + ByteAddress m_nFirstAddress; // 4 bytes + uint32_t m_nBytesSize; // 4 bytes + + union // 8 bytes + { + uint8_t m_vBytes[8]{}; + AllocatedMemory* m_pAllocatedMemory; + }; + + union // 8 bytes + { + uint8_t m_vAddresses[8]{}; + uint8_t* m_pAddresses; + }; + + uint32_t m_nMatchingAddressCount;// 4 bytes + uint32_t m_nAddressCount; // 4 bytes +}; +static_assert(sizeof(CapturedMemoryBlock) <= 32, "sizeof(CapturedMemoryBlock) is incorrect"); + +} // namespace data +} // namespace ra + +#endif /* !RA_DATA_CAPTUREDMEMORYBLOCK_HH */ diff --git a/src/services/IClock.hh b/src/devkit/services/IClock.hh similarity index 94% rename from src/services/IClock.hh rename to src/devkit/services/IClock.hh index 2f351b4bb..639d56842 100644 --- a/src/services/IClock.hh +++ b/src/devkit/services/IClock.hh @@ -2,6 +2,8 @@ #define RA_SERVICES_ICLOCK_HH #pragma once +#include + namespace ra { namespace services { @@ -33,4 +35,4 @@ protected: } // namespace services } // namespace ra -#endif // !RA_SERVICES_ILOGGER_HH +#endif // !RA_SERVICES_ICLOCK_HH diff --git a/src/devkit/services/IDebuggerDetector.hh b/src/devkit/services/IDebuggerDetector.hh new file mode 100644 index 000000000..644a7f7ef --- /dev/null +++ b/src/devkit/services/IDebuggerDetector.hh @@ -0,0 +1,29 @@ +#ifndef RA_SERVICES_IDEBUGGERDETECTOR_HH +#define RA_SERVICES_IDEBUGGERDETECTOR_HH +#pragma once + +namespace ra { +namespace services { + +class IDebuggerDetector +{ +public: + virtual ~IDebuggerDetector() noexcept = default; + IDebuggerDetector(const IDebuggerDetector&) noexcept = delete; + IDebuggerDetector& operator=(const IDebuggerDetector&) noexcept = delete; + IDebuggerDetector(IDebuggerDetector&&) noexcept = delete; + IDebuggerDetector& operator=(IDebuggerDetector&&) noexcept = delete; + + /// + /// Determines if the process is running in a debugger. + /// + virtual bool IsDebuggerPresent() const = 0; + +protected: + IDebuggerDetector() noexcept = default; +}; + +} // namespace services +} // namespace ra + +#endif // !RA_SERVICES_IDEBUGGERDETECTOR_HH diff --git a/src/services/impl/Clock.hh b/src/devkit/services/impl/Clock.hh similarity index 100% rename from src/services/impl/Clock.hh rename to src/devkit/services/impl/Clock.hh diff --git a/src/services/AchievementRuntime.cpp b/src/services/AchievementRuntime.cpp index 2ff6cd441..bfd72b2f2 100644 --- a/src/services/AchievementRuntime.cpp +++ b/src/services/AchievementRuntime.cpp @@ -12,6 +12,7 @@ #include "RA_md5factory.h" #include "context\IConsoleContext.hh" +#include "context\IEmulatorMemoryContext.hh" #include "context\IRcClient.hh" #include "data\context\EmulatorContext.hh" @@ -61,11 +62,11 @@ static int CanSubmit() if (pConfiguration.IsFeatureEnabled(ra::services::Feature::Offline)) return 0; - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - if (pEmulatorContext.WasMemoryModified()) + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + if (pMemoryContext.WasMemoryModified()) return 0; - if (_RA_HardcoreModeIsActive() && pEmulatorContext.IsMemoryInsecure()) + if (_RA_HardcoreModeIsActive() && pMemoryContext.IsMemoryInsecure()) return 0; return 1; @@ -235,8 +236,8 @@ AchievementRuntime::~AchievementRuntime() uint32_t AchievementRuntime::ReadMemory(uint32_t nAddress, uint8_t* pBuffer, uint32_t nBytes, rc_client_t*) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - return pEmulatorContext.ReadMemory(nAddress, pBuffer, nBytes); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + return pMemoryContext.ReadMemory(nAddress, pBuffer, nBytes); } typedef struct QueueMemoryReadData @@ -1639,8 +1640,8 @@ static void HandleAchievementTriggeredEvent(const rc_client_achievement_t& pAchi bSubmit = false; } - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - if (bSubmit && pEmulatorContext.WasMemoryModified()) + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + if (bSubmit && pMemoryContext.WasMemoryModified()) { vmPopup->SetTitle(L"Achievement Unlocked LOCALLY"); vmPopup->SetErrorDetail(L"Error: RAM tampered with"); @@ -1650,7 +1651,7 @@ static void HandleAchievementTriggeredEvent(const rc_client_achievement_t& pAchi bSubmit = false; } - if (bSubmit && _RA_HardcoreModeIsActive() && pEmulatorContext.IsMemoryInsecure()) + if (bSubmit && _RA_HardcoreModeIsActive() && pMemoryContext.IsMemoryInsecure()) { vmPopup->SetTitle(L"Achievement Unlocked LOCALLY"); vmPopup->SetErrorDetail(L"Error: RAM insecure"); @@ -1969,8 +1970,8 @@ static void HandleLeaderboardSubmittedEvent(const rc_client_leaderboard_t& pLead bSubmit = false; } - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - if (bSubmit && pEmulatorContext.WasMemoryModified()) + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + if (bSubmit && pMemoryContext.WasMemoryModified()) { vmPopup->SetErrorDetail(L"Error: RAM tampered with"); bSubmit = false; @@ -1983,7 +1984,7 @@ static void HandleLeaderboardSubmittedEvent(const rc_client_leaderboard_t& pLead vmPopup->SetErrorDetail(L"Submission requires Hardcore mode"); bSubmit = false; } - else if (pEmulatorContext.IsMemoryInsecure()) + else if (pMemoryContext.IsMemoryInsecure()) { vmPopup->SetErrorDetail(L"Error: RAM insecure"); bSubmit = false; @@ -2702,15 +2703,15 @@ int AchievementRuntime::SaveProgressToBuffer(uint8_t* pBuffer, int nBufferSize) extern "C" unsigned int rc_peek_callback(unsigned int nAddress, unsigned int nBytes, _UNUSED void* pData) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); switch (nBytes) { case 1: - return pEmulatorContext.ReadMemoryByte(nAddress); + return pMemoryContext.ReadMemoryByte(nAddress); case 2: - return pEmulatorContext.ReadMemory(nAddress, ra::data::Memory::Size::SixteenBit); + return pMemoryContext.ReadMemory(nAddress, ra::data::Memory::Size::SixteenBit); case 4: - return pEmulatorContext.ReadMemory(nAddress, ra::data::Memory::Size::ThirtyTwoBit); + return pMemoryContext.ReadMemory(nAddress, ra::data::Memory::Size::ThirtyTwoBit); default: return 0U; } diff --git a/src/services/AchievementRuntimeExports.cpp b/src/services/AchievementRuntimeExports.cpp index 6c21c3569..860b6aefe 100644 --- a/src/services/AchievementRuntimeExports.cpp +++ b/src/services/AchievementRuntimeExports.cpp @@ -5,7 +5,9 @@ #include "RA_Resource.h" #include "context\IConsoleContext.hh" +#include "context\IEmulatorMemoryContext.hh" #include "context\IRcClient.hh" +#include "context\impl\EmulatorMemoryContext.hh" #include "data\context\GameContext.hh" @@ -71,9 +73,9 @@ class AchievementRuntimeExports : private AchievementRuntime typedef struct MemoryBlockWrapper { ra::data::ByteAddress nOffset; - ra::data::context::EmulatorContext::MemoryReadFunction* fReadByte; - ra::data::context::EmulatorContext::MemoryWriteFunction* fWriteByte; - ra::data::context::EmulatorContext::MemoryReadBlockFunction* fReadBlock; + ra::context::impl::EmulatorMemoryContext::MemoryReadFunction* fReadByte; + ra::context::impl::EmulatorMemoryContext::MemoryWriteFunction* fWriteByte; + ra::context::impl::EmulatorMemoryContext::MemoryReadBlockFunction* fReadBlock; } MemoryBlockWrapper; static std::array s_memoryBlockWrappers; @@ -83,8 +85,11 @@ class AchievementRuntimeExports : private AchievementRuntime { const auto& pConsoleContext = ra::services::ServiceLocator::Get(); - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.ClearMemoryBlocks(); + auto* pEmulatorMemoryContext = dynamic_cast(&ra::services::ServiceLocator::GetMutable()); + if (!pEmulatorMemoryContext) + return; + + pEmulatorMemoryContext->ClearMemoryBlocks(); gsl::index nIndex = 0; uint32_t nBytes = 0; @@ -96,10 +101,10 @@ class AchievementRuntimeExports : private AchievementRuntime { if (nBytes > 0) { - pEmulatorContext.AddMemoryBlock(nIndex, nBytes, + pEmulatorMemoryContext->AddMemoryBlock(nIndex, nBytes, s_memoryBlockWrappers.at(nIndex).fReadByte, s_memoryBlockWrappers.at(nIndex).fWriteByte); - pEmulatorContext.AddMemoryBlockReader(nIndex, + pEmulatorMemoryContext->AddMemoryBlockReader(nIndex, s_memoryBlockWrappers.at(nIndex).fReadBlock); nBytes = 0; @@ -107,7 +112,7 @@ class AchievementRuntimeExports : private AchievementRuntime s_memoryBlockWrappers.at(nIndex).nOffset = pRegion.GetStartAddress(); } - pEmulatorContext.AddMemoryBlock(nIndex++, nSize, nullptr, nullptr); + pEmulatorMemoryContext->AddMemoryBlock(nIndex++, nSize, nullptr, nullptr); Expects(gsl::narrow_cast(nIndex) < s_memoryBlockWrappers.size()); s_memoryBlockWrappers.at(nIndex).nOffset = pRegion.GetEndAddress() + 1; @@ -120,10 +125,10 @@ class AchievementRuntimeExports : private AchievementRuntime if (nBytes > 0) { - pEmulatorContext.AddMemoryBlock(nIndex, nBytes, + pEmulatorMemoryContext->AddMemoryBlock(nIndex, nBytes, s_memoryBlockWrappers.at(nIndex).fReadByte, s_memoryBlockWrappers.at(nIndex).fWriteByte); - pEmulatorContext.AddMemoryBlockReader(nIndex, + pEmulatorMemoryContext->AddMemoryBlockReader(nIndex, s_memoryBlockWrappers.at(nIndex).fReadBlock); } } @@ -586,11 +591,11 @@ class AchievementRuntimeExports : private AchievementRuntime pAchievement->GetChanges() != ra::data::models::AssetChanges::None) // unpublished changes return RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_MODIFIED; - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - if (pEmulatorContext.WasMemoryModified()) + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + if (pMemoryContext.WasMemoryModified()) return RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_INSECURE; - if (_RA_HardcoreModeIsActive() && pEmulatorContext.IsMemoryInsecure()) + if (_RA_HardcoreModeIsActive() && pMemoryContext.IsMemoryInsecure()) return RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_INSECURE; return RC_CLIENT_RAINTEGRATION_ACHIEVEMENT_STATE_PUBLISHED; diff --git a/src/services/GameIdentifier.cpp b/src/services/GameIdentifier.cpp index e9f304003..f18c415d7 100644 --- a/src/services/GameIdentifier.cpp +++ b/src/services/GameIdentifier.cpp @@ -8,6 +8,7 @@ #include "api\ResolveHash.hh" #include "context\IConsoleContext.hh" +#include "context\IEmulatorMemoryContext.hh" #include "data\context\EmulatorContext.hh" #include "data\context\GameContext.hh" @@ -218,7 +219,7 @@ void GameIdentifier::ActivateGame(unsigned int nGameId) pGameContext.SetGameHash((m_nPendingGameId == 0) ? m_sPendingHash : ""); } - ra::services::ServiceLocator::GetMutable().ResetMemoryModified(); + ra::services::ServiceLocator::GetMutable().ResetMemoryModified(); } void GameIdentifier::IdentifyAndActivateGame(const BYTE* pROM, size_t nROMSize) diff --git a/src/services/Initialization.cpp b/src/services/Initialization.cpp index f9e5ee542..1640f985e 100644 --- a/src/services/Initialization.cpp +++ b/src/services/Initialization.cpp @@ -3,6 +3,7 @@ #include "api\impl\DisconnectedServer.hh" #include "context\impl\ConsoleContext.hh" +#include "context\impl\EmulatorMemoryContext.hh" #include "context\impl\RcClient.hh" #include "data\context\EmulatorContext.hh" @@ -23,6 +24,7 @@ #include "services\impl\WindowsAudioSystem.hh" #include "services\impl\WindowsClipboard.hh" #include "services\impl\WindowsDebuggerFileLogger.hh" +#include "services\impl\WindowsDebuggerDetector.hh" #include "services\impl\WindowsFileSystem.hh" #include "services\impl\WindowsHttpRequester.hh" @@ -161,6 +163,12 @@ void Initialization::RegisterServices(EmulatorID nEmulatorId, const char* sClien auto pRcClient = std::make_unique(); ra::services::ServiceLocator::Provide(std::move(pRcClient)); + auto pEmulatorMemoryContext = std::make_unique(); + ra::services::ServiceLocator::Provide(std::move(pEmulatorMemoryContext)); + + auto pDebuggerDetector = std::make_unique(); + ra::services::ServiceLocator::Provide(std::move(pDebuggerDetector)); + auto pAchievementRuntime = std::make_unique(); ra::services::ServiceLocator::Provide(std::move(pAchievementRuntime)); @@ -235,9 +243,9 @@ void Initialization::Shutdown() // explicitly deregister it to prevent exceptions when closing down the application. ra::services::ServiceLocator::Provide(nullptr); - // GridBinding subclass destructors may try to use the EmulatorContext if they think it still exists. + // GridBinding subclass destructors may try to use the EmulatorMemoryContext if they think it still exists. // explicitly deregister it to prevent exceptions when closing down the application. - ra::services::ServiceLocator::Provide(nullptr); + ra::services::ServiceLocator::Provide(nullptr); // clear out the IThreadPool and IConfiguration services to indicate things have been de-initialized ra::services::ServiceLocator::Provide(nullptr); diff --git a/src/services/Search/SearchImpl.cpp b/src/services/Search/SearchImpl.cpp index 382ab018e..34ae0b919 100644 --- a/src/services/Search/SearchImpl.cpp +++ b/src/services/Search/SearchImpl.cpp @@ -156,7 +156,7 @@ bool SearchImpl::GetMatchingAddress(const SearchResults& srResults, gsl::index n if (nIndex < gsl::narrow_cast(pBlock.GetMatchingAddressCount())) { result.nAddress = pBlock.GetMatchingAddress(nIndex); - return GetValueFromMemBlock(pBlock, result); + return GetValueFromCapturedMemoryBlock(pBlock, result); } nIndex -= pBlock.GetMatchingAddressCount(); @@ -181,7 +181,7 @@ size_t SearchImpl::GetIndexOfBlockForVirtualAddress(const SearchResults& srResul } const uint32_t nOffset = nAddress - pBlockMid.GetFirstAddress(); - if (nOffset >= pBlockMid.GetMaxAddresses()) + if (nOffset >= pBlockMid.GetAddressCount()) { nIndexLow = nIndexMid + 1; continue; @@ -199,7 +199,7 @@ bool SearchImpl::GetValueAtVirtualAddress(const SearchResults& srResults, Search const auto nIndex = GetIndexOfBlockForVirtualAddress(srResults, result.nAddress); if (nIndex < srResults.m_vBlocks.size()) { - if (GetValueFromMemBlock(srResults.m_vBlocks.at(nIndex), result)) + if (GetValueFromCapturedMemoryBlock(srResults.m_vBlocks.at(nIndex), result)) return true; } @@ -223,10 +223,10 @@ std::wstring SearchImpl::GetFormattedValue(const SearchResults& pResults, ra::da } bool SearchImpl::UpdateValue(const SearchResults& pResults, SearchResult& pResult, - _Out_ std::wstring* sFormattedValue, const ra::data::context::EmulatorContext& pEmulatorContext) const + _Out_ std::wstring* sFormattedValue, const ra::context::IEmulatorMemoryContext& pMemoryContext) const { const uint32_t nPreviousValue = pResult.nValue; - pResult.nValue = pEmulatorContext.ReadMemory(pResult.nAddress, pResult.nSize); + pResult.nValue = pMemoryContext.ReadMemory(pResult.nAddress, pResult.nSize); if (sFormattedValue) *sFormattedValue = GetFormattedValue(pResults, pResult); @@ -272,7 +272,7 @@ bool SearchImpl::MatchesFilter(const SearchResults& pResults, const SearchResult } void SearchImpl::ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const { const auto nBlockAddress = pPreviousBlock.GetFirstAddress(); @@ -293,7 +293,7 @@ void SearchImpl::ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pByte } void SearchImpl::ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const { const auto* pBlockBytes = pPreviousBlock.GetBytes(); @@ -315,7 +315,7 @@ void SearchImpl::ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytes } } -bool SearchImpl::GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept +bool SearchImpl::GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept { if (result.nAddress < block.GetFirstAddress()) return false; @@ -357,7 +357,7 @@ void SearchImpl::AddBlocks(SearchResults& srNew, std::vector /// Determines if the provided search result would appear in pResults if it were freshly populated from @@ -106,12 +106,12 @@ public: protected: // generic implementation for less used search types - virtual void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, const MemBlock& pPreviousBlock, + virtual void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const; // generic implementation for less used search types - virtual void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, const MemBlock& pPreviousBlock, + virtual void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const; @@ -144,7 +144,7 @@ protected: #pragma warning(disable : 5045) template void ApplyCompareFilterLittleEndian(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, unsigned nAdjustment, std::vector& vMatches) const { const auto* pScan = pBytes; @@ -225,7 +225,7 @@ protected: /// against [out] The list of matching addresses template void ApplyCompareFilterLittleEndian(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const { switch (nComparison) @@ -256,7 +256,7 @@ protected: #else // #ifndef DISABLE_TEMPLATED_SEARCH template void ApplyCompareFilterLittleEndian(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const { if (TIsConstantFilter) @@ -281,7 +281,7 @@ protected: return srResults.m_vBlocks.front().GetFirstAddress(); } - static const std::vector& GetBlocks(const SearchResults& srResults) noexcept + static const std::vector& GetBlocks(const SearchResults& srResults) noexcept { return srResults.m_vBlocks; } @@ -304,14 +304,14 @@ protected: /// true if the memory was available in the block, false if not. /// Sets result.nValue to the value from the captured memory, and changes result.nAddress to a real /// address - virtual bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept; + virtual bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept; // Gets the index of the block in srResults containing the provided virtual address. static size_t GetIndexOfBlockForVirtualAddress(const SearchResults& srResults, uint32_t nAddress); virtual uint32_t BuildValue(const uint8_t* ptr) const noexcept; - static MemBlock& AddBlock(SearchResults& srResults, ra::data::ByteAddress nAddress, uint32_t nSize, + static CapturedMemoryBlock& AddBlock(SearchResults& srResults, ra::data::ByteAddress nAddress, uint32_t nSize, uint32_t nMaxAddresses) { return srResults.m_vBlocks.emplace_back(nAddress, nSize, nMaxAddresses); diff --git a/src/services/Search/SearchImpl_16bit.hh b/src/services/Search/SearchImpl_16bit.hh index 122e7c475..52c09e741 100644 --- a/src/services/Search/SearchImpl_16bit.hh +++ b/src/services/Search/SearchImpl_16bit.hh @@ -25,7 +25,7 @@ public: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, @@ -33,7 +33,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, diff --git a/src/services/Search/SearchImpl_16bit_aligned.hh b/src/services/Search/SearchImpl_16bit_aligned.hh index fb972ced3..91401ea4c 100644 --- a/src/services/Search/SearchImpl_16bit_aligned.hh +++ b/src/services/Search/SearchImpl_16bit_aligned.hh @@ -30,7 +30,7 @@ public: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, @@ -38,7 +38,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, @@ -46,7 +46,7 @@ protected: } - bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept override + bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept override { const unsigned int nOffset = (result.nAddress - block.GetFirstAddress()) * 2; if (nOffset + 1 >= block.GetBytesSize()) diff --git a/src/services/Search/SearchImpl_16bit_be.hh b/src/services/Search/SearchImpl_16bit_be.hh index adc65db7b..82138c02a 100644 --- a/src/services/Search/SearchImpl_16bit_be.hh +++ b/src/services/Search/SearchImpl_16bit_be.hh @@ -24,7 +24,7 @@ protected: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { SearchImpl::ApplyConstantFilter(pBytes, pBytesStop, @@ -32,7 +32,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { SearchImpl::ApplyCompareFilter(pBytes, pBytesStop, diff --git a/src/services/Search/SearchImpl_16bit_be_aligned.hh b/src/services/Search/SearchImpl_16bit_be_aligned.hh index 2846de42d..03034f89b 100644 --- a/src/services/Search/SearchImpl_16bit_be_aligned.hh +++ b/src/services/Search/SearchImpl_16bit_be_aligned.hh @@ -24,7 +24,7 @@ protected: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { SearchImpl::ApplyConstantFilter(pBytes, pBytesStop, @@ -32,7 +32,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { SearchImpl::ApplyCompareFilter(pBytes, pBytesStop, diff --git a/src/services/Search/SearchImpl_32bit.hh b/src/services/Search/SearchImpl_32bit.hh index 7b1f5b963..6c53756e7 100644 --- a/src/services/Search/SearchImpl_32bit.hh +++ b/src/services/Search/SearchImpl_32bit.hh @@ -25,7 +25,7 @@ public: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, @@ -33,7 +33,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, diff --git a/src/services/Search/SearchImpl_32bit_aligned.hh b/src/services/Search/SearchImpl_32bit_aligned.hh index 6c6c02692..5ac0fd9e5 100644 --- a/src/services/Search/SearchImpl_32bit_aligned.hh +++ b/src/services/Search/SearchImpl_32bit_aligned.hh @@ -30,7 +30,7 @@ public: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, @@ -38,7 +38,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, @@ -46,7 +46,7 @@ protected: } - bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept override + bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept override { const unsigned int nOffset = (result.nAddress - block.GetFirstAddress()) * 4; if (nOffset + 3 >= block.GetBytesSize()) diff --git a/src/services/Search/SearchImpl_32bit_be.hh b/src/services/Search/SearchImpl_32bit_be.hh index b7cd80604..7a172c54d 100644 --- a/src/services/Search/SearchImpl_32bit_be.hh +++ b/src/services/Search/SearchImpl_32bit_be.hh @@ -22,7 +22,7 @@ class ThirtyTwoBitBigEndianSearchImpl : public ThirtyTwoBitSearchImpl protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { SearchImpl::ApplyConstantFilter(pBytes, pBytesStop, @@ -30,7 +30,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { SearchImpl::ApplyCompareFilter(pBytes, pBytesStop, diff --git a/src/services/Search/SearchImpl_32bit_be_aligned.hh b/src/services/Search/SearchImpl_32bit_be_aligned.hh index ea77997b8..e6d53a483 100644 --- a/src/services/Search/SearchImpl_32bit_be_aligned.hh +++ b/src/services/Search/SearchImpl_32bit_be_aligned.hh @@ -22,7 +22,7 @@ class ThirtyTwoBitBigEndianAlignedSearchImpl : public ThirtyTwoBitAlignedSearchI protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { SearchImpl::ApplyConstantFilter(pBytes, pBytesStop, @@ -30,7 +30,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { SearchImpl::ApplyCompareFilter(pBytes, pBytesStop, diff --git a/src/services/Search/SearchImpl_4bit.hh b/src/services/Search/SearchImpl_4bit.hh index 5809b47e3..30950d044 100644 --- a/src/services/Search/SearchImpl_4bit.hh +++ b/src/services/Search/SearchImpl_4bit.hh @@ -50,7 +50,7 @@ class FourBitSearchImpl : public SearchImpl } void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { const auto nBlockAddress = pPreviousBlock.GetFirstAddress(); @@ -78,7 +78,7 @@ class FourBitSearchImpl : public SearchImpl } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { const auto* pBlockBytes = pPreviousBlock.GetBytes(); @@ -110,7 +110,7 @@ class FourBitSearchImpl : public SearchImpl } protected: - bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept override + bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept override { if (result.nAddress & 1) result.nSize = ra::data::Memory::Size::NibbleUpper; diff --git a/src/services/Search/SearchImpl_8bit.hh b/src/services/Search/SearchImpl_8bit.hh index b4356b415..abf07cd3c 100644 --- a/src/services/Search/SearchImpl_8bit.hh +++ b/src/services/Search/SearchImpl_8bit.hh @@ -12,7 +12,7 @@ class EightBitSearchImpl : public SearchImpl { protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, @@ -20,7 +20,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { ApplyCompareFilterLittleEndian(pBytes, pBytesStop, diff --git a/src/services/Search/SearchImpl_asciitext.hh b/src/services/Search/SearchImpl_asciitext.hh index 4bc57f33f..05175c181 100644 --- a/src/services/Search/SearchImpl_asciitext.hh +++ b/src/services/Search/SearchImpl_asciitext.hh @@ -163,10 +163,10 @@ public: } bool UpdateValue(const SearchResults&, SearchResult& pResult, - _Out_ std::wstring* sFormattedValue, const ra::data::context::EmulatorContext& pEmulatorContext) const override + _Out_ std::wstring* sFormattedValue, const ra::context::IEmulatorMemoryContext& pMemoryContext) const override { std::array pBuffer; - pEmulatorContext.ReadMemory(pResult.nAddress, &pBuffer.at(0), pBuffer.size()); + pMemoryContext.ReadMemory(pResult.nAddress, &pBuffer.at(0), pBuffer.size()); std::wstring sText; GetASCIIText(sText, pBuffer.data(), pBuffer.size()); diff --git a/src/services/Search/SearchImpl_bitcount.hh b/src/services/Search/SearchImpl_bitcount.hh index e060ed87d..8f73bbf83 100644 --- a/src/services/Search/SearchImpl_bitcount.hh +++ b/src/services/Search/SearchImpl_bitcount.hh @@ -23,10 +23,10 @@ protected: } bool UpdateValue(const SearchResults& pResults, SearchResult& pResult, - _Out_ std::wstring* sFormattedValue, const ra::data::context::EmulatorContext& pEmulatorContext) const override + _Out_ std::wstring* sFormattedValue, const ra::context::IEmulatorMemoryContext& pMemoryContext) const override { const unsigned int nPreviousValue = pResult.nValue; - pResult.nValue = pEmulatorContext.ReadMemory(pResult.nAddress, ra::data::Memory::Size::EightBit); + pResult.nValue = pMemoryContext.ReadMemory(pResult.nAddress, ra::data::Memory::Size::EightBit); if (sFormattedValue) *sFormattedValue = GetFormattedValue(pResults, pResult); @@ -48,7 +48,7 @@ protected: } private: - bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept override + bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept override { if (result.nAddress < block.GetFirstAddress()) return false; diff --git a/src/services/Search/SearchImpl_double32_aligned.hh b/src/services/Search/SearchImpl_double32_aligned.hh index aa35bbd8c..be93eabbf 100644 --- a/src/services/Search/SearchImpl_double32_aligned.hh +++ b/src/services/Search/SearchImpl_double32_aligned.hh @@ -47,7 +47,7 @@ public: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { pBytes += 4; // we're only looking at the four most significant bytes @@ -68,7 +68,7 @@ protected: GSL_SUPPRESS_TYPE1 void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { // cannot use base implementation because we need to offset pBytes and pBlockBytes @@ -94,7 +94,7 @@ protected: } } - bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept override + bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept override { const unsigned int nOffset = (result.nAddress - block.GetFirstAddress()) * 8; if (nOffset + 7 >= block.GetBytesSize()) diff --git a/src/services/Search/SearchImpl_double32_be_aligned.hh b/src/services/Search/SearchImpl_double32_be_aligned.hh index 9a6cfabe6..ae6ca1c55 100644 --- a/src/services/Search/SearchImpl_double32_be_aligned.hh +++ b/src/services/Search/SearchImpl_double32_be_aligned.hh @@ -32,7 +32,7 @@ public: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { if (nComparison == ComparisonType::Equals || nComparison == ComparisonType::NotEqualTo) @@ -49,7 +49,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { if (nComparison == ComparisonType::Equals || nComparison == ComparisonType::NotEqualTo) @@ -65,7 +65,7 @@ protected: } } - bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept override + bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept override { const unsigned int nOffset = (result.nAddress - block.GetFirstAddress()) * 8; if (nOffset + 3 >= block.GetBytesSize()) diff --git a/src/services/Search/SearchImpl_float.hh b/src/services/Search/SearchImpl_float.hh index 68cd9e212..41f8f9643 100644 --- a/src/services/Search/SearchImpl_float.hh +++ b/src/services/Search/SearchImpl_float.hh @@ -99,7 +99,7 @@ protected: GSL_SUPPRESS_TYPE1 void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { if (nComparison == ComparisonType::Equals || nComparison == ComparisonType::NotEqualTo) @@ -132,7 +132,7 @@ protected: GSL_SUPPRESS_TYPE1 void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { if (nComparison == ComparisonType::Equals || nComparison == ComparisonType::NotEqualTo) diff --git a/src/services/Search/SearchImpl_float_aligned.hh b/src/services/Search/SearchImpl_float_aligned.hh index a6c1a5f53..720340ebe 100644 --- a/src/services/Search/SearchImpl_float_aligned.hh +++ b/src/services/Search/SearchImpl_float_aligned.hh @@ -30,7 +30,7 @@ public: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { if (nComparison == ComparisonType::Equals || nComparison == ComparisonType::NotEqualTo) @@ -47,7 +47,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { if (nComparison == ComparisonType::Equals || nComparison == ComparisonType::NotEqualTo) @@ -63,7 +63,7 @@ protected: } } - bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept override + bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept override { const unsigned int nOffset = (result.nAddress - block.GetFirstAddress()) * 4; if (nOffset + 3 >= block.GetBytesSize()) diff --git a/src/services/Search/SearchImpl_float_be_aligned.hh b/src/services/Search/SearchImpl_float_be_aligned.hh index eaddb2e3d..0987add61 100644 --- a/src/services/Search/SearchImpl_float_be_aligned.hh +++ b/src/services/Search/SearchImpl_float_be_aligned.hh @@ -30,7 +30,7 @@ public: protected: void ApplyConstantFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nConstantValue, std::vector& vMatches) const override { if (nComparison == ComparisonType::Equals || nComparison == ComparisonType::NotEqualTo) @@ -47,7 +47,7 @@ protected: } void ApplyCompareFilter(const uint8_t* pBytes, const uint8_t* pBytesStop, - const MemBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, + const CapturedMemoryBlock& pPreviousBlock, ComparisonType nComparison, unsigned nAdjustment, std::vector& vMatches) const override { if (nComparison == ComparisonType::Equals || nComparison == ComparisonType::NotEqualTo) @@ -63,7 +63,7 @@ protected: } } - bool GetValueFromMemBlock(const MemBlock& block, SearchResult& result) const noexcept override + bool GetValueFromCapturedMemoryBlock(const CapturedMemoryBlock& block, SearchResult& result) const noexcept override { const unsigned int nOffset = (result.nAddress - block.GetFirstAddress()) * 4; if (nOffset + 3 >= block.GetBytesSize()) diff --git a/src/services/SearchResults.cpp b/src/services/SearchResults.cpp index 8e0ecf3e0..e64fd7aa1 100644 --- a/src/services/SearchResults.cpp +++ b/src/services/SearchResults.cpp @@ -3,7 +3,7 @@ #include "RA_Defs.h" #include "util\Log.hh" -#include "data\context\EmulatorContext.hh" +#include "context\IEmulatorMemoryContext.hh" #include "services\ServiceLocator.hh" @@ -115,14 +115,14 @@ static search::SearchImpl* GetSearchImpl(SearchType nType) noexcept } #ifndef RA_UTEST -static size_t CalcSize(const std::vector& vBlocks) +static size_t CalcSize(const std::vector& vBlocks) { std::set vAllocatedMemoryBlocks; - size_t nTotalSize = vBlocks.size() * sizeof(data::search::MemBlock); + size_t nTotalSize = vBlocks.size() * sizeof(ra::data::CapturedMemoryBlock); for (const auto& pBlock : vBlocks) { - if (pBlock.IsBytesAllocated()) + if (pBlock.GetBytesSize() > 8) // IsBytesAllocated { const auto* pBytes = pBlock.GetBytes(); if (vAllocatedMemoryBlocks.find(pBytes) == vAllocatedMemoryBlocks.end()) @@ -147,8 +147,8 @@ void SearchResults::Initialize(ra::data::ByteAddress nAddress, size_t nBytes, Se m_nType = nType; m_pImpl = GetSearchImpl(nType); - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - const auto nTotalMemorySize = pEmulatorContext.TotalMemorySize(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nTotalMemorySize = pMemoryContext.TotalMemorySize(); if (nAddress > nTotalMemorySize) nAddress = 0; if (nBytes + nAddress > nTotalMemorySize) @@ -158,15 +158,14 @@ void SearchResults::Initialize(ra::data::ByteAddress nAddress, size_t nBytes, Se if (nPadding >= nBytes) nBytes = 0; - pEmulatorContext.CaptureMemory(m_vBlocks, nAddress, gsl::narrow_cast(nBytes), nPadding); + pMemoryContext.CaptureMemory(m_vBlocks, nAddress, gsl::narrow_cast(nBytes), nPadding); for (auto& pBlock : m_vBlocks) { pBlock.SetFirstAddress(m_pImpl->ConvertFromRealAddress(pBlock.GetFirstAddress())); const auto nAdjustedAddressCount = m_pImpl->GetAddressCountForBytes(pBlock.GetBytesSize()); - pBlock.SetMaxAddresses(nAdjustedAddressCount); - pBlock.SetMatchingAddressCount(nAdjustedAddressCount); + pBlock.SetAddressCount(nAdjustedAddressCount); } RA_LOG_INFO("Allocated %zu bytes for initial search", CalcSize(m_vBlocks)); @@ -328,9 +327,9 @@ _Use_decl_annotations_ bool SearchResults::Initialize(const SearchResults& srSource, ComparisonType nCompareType, SearchFilterType nFilterType, const std::wstring& sFilterValue) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - auto pReadMemory = [&pEmulatorContext](ra::data::ByteAddress nAddress, uint8_t* pBuffer, size_t nBufferSize) { - pEmulatorContext.ReadMemory(nAddress, pBuffer, nBufferSize); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + auto pReadMemory = [&pMemoryContext](ra::data::ByteAddress nAddress, uint8_t* pBuffer, size_t nBufferSize) { + pMemoryContext.ReadMemory(nAddress, pBuffer, nBufferSize); }; return Initialize(srSource, pReadMemory, nCompareType, nFilterType, sFilterValue); @@ -427,10 +426,10 @@ std::wstring SearchResults::GetFormattedValue(ra::data::ByteAddress nAddress, ra } bool SearchResults::UpdateValue(SearchResult& pResult, - _Out_ std::wstring* sFormattedValue, const ra::data::context::EmulatorContext& pEmulatorContext) const + _Out_ std::wstring* sFormattedValue, const ra::context::IEmulatorMemoryContext& pMemoryContext) const { if (m_pImpl) - return m_pImpl->UpdateValue(*this, pResult, sFormattedValue, pEmulatorContext); + return m_pImpl->UpdateValue(*this, pResult, sFormattedValue, pMemoryContext); if (sFormattedValue) sFormattedValue->clear(); diff --git a/src/services/SearchResults.h b/src/services/SearchResults.h index 314aa8b1c..ebae438fb 100644 --- a/src/services/SearchResults.h +++ b/src/services/SearchResults.h @@ -2,11 +2,10 @@ #define SEARCHRESULTS_H #pragma once -#include "data\Types.hh" +#include "data/CapturedMemoryBlock.hh" +#include "data/Types.hh" -#include "data\context\EmulatorContext.hh" - -#include "data\search\MemBlock.hh" +#include "context/IEmulatorMemoryContext.hh" namespace ra { namespace services { @@ -154,7 +153,7 @@ class SearchResults /// Pointer to a string to populate with a textual representation of the value. [optional] /// true if the value changed, false if not. bool UpdateValue(SearchResult& pResult, _Out_ std::wstring* sFormattedValue, - const ra::data::context::EmulatorContext& pEmulatorContext) const; + const ra::context::IEmulatorMemoryContext& pMemoryContext) const; /// /// Determines if a value compared to its previous value matches the filter. @@ -213,7 +212,7 @@ class SearchResults private: void MergeSearchResults(const SearchResults& srMemory, const SearchResults& srAddresses); - std::vector m_vBlocks; + std::vector m_vBlocks; SearchType m_nType = SearchType::EightBit; friend class search::SearchImpl; diff --git a/src/services/impl/WindowsDebuggerDetector.cpp b/src/services/impl/WindowsDebuggerDetector.cpp new file mode 100644 index 000000000..600b4f8f5 --- /dev/null +++ b/src/services/impl/WindowsDebuggerDetector.cpp @@ -0,0 +1,73 @@ +#include "WindowsDebuggerDetector.hh" + +#include "util/Log.hh" +#include "util/Strings.hh" + +#include + +namespace ra { +namespace services { +namespace impl { + +static bool IsSuspiciousProcessRunning() +{ + bool bFound = false; + + const HANDLE hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot) + { + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(PROCESSENTRY32); + if (Process32First(hSnapshot, &pe32)) + { + do + { + if (tcslen_s(pe32.szExeFile) >= 15) + { + std::string sFilename = ra::Narrow(pe32.szExeFile); + ra::StringMakeLowercase(sFilename); + + // cannot reliably detect injection without ObRegisterCallbacks, which requires Vista, + // instead just look for the default process names (it's better than nothing) + // [Cheat Engine.exe, cheatengine-i386.exe, cheatengine-x86_64.exe] + if (sFilename.find("cheat") != std::string::npos && + sFilename.find("engine") != std::string::npos) + { + RA_LOG_WARN("Cheat Engine detected"); + bFound = true; + break; + } + } + } while (Process32Next(hSnapshot, &pe32)); + } + CloseHandle(hSnapshot); + } + + return bFound; +} + +bool WindowsDebuggerDetector::IsDebuggerPresent() const +{ +#ifdef NDEBUG // allow debugger-limited functionality when using a DEBUG build + if (::IsDebuggerPresent()) + { + RA_LOG_WARN("Debugger detected"); + return true; + } + + BOOL bDebuggerPresent; + if (::CheckRemoteDebuggerPresent(GetCurrentProcess(), &bDebuggerPresent) && bDebuggerPresent) + { + RA_LOG_WARN("Remote debugger detected"); + return true; + } +#endif + + // real cheating tools don't register as debuggers (or intercept and override the call) + // also check for known bad agents and assume that the player is using them to cheat + return IsSuspiciousProcessRunning(); +} + +} // namespace impl +} // namespace services +} // namespace ra diff --git a/src/services/impl/WindowsDebuggerDetector.hh b/src/services/impl/WindowsDebuggerDetector.hh new file mode 100644 index 000000000..ccf0e2b14 --- /dev/null +++ b/src/services/impl/WindowsDebuggerDetector.hh @@ -0,0 +1,20 @@ +#ifndef RA_SERVICES_IMPL_DEBUGGER_DETECTOR +#define RA_SERVICES_IMPL_DEBUGGER_DETECTOR + +#include "services/IDebuggerDetector.hh" + +namespace ra { +namespace services { +namespace impl { + +class WindowsDebuggerDetector : public IDebuggerDetector +{ +public: + bool IsDebuggerPresent() const override; +}; + +} // namespace impl +} // namespace services +} // namespace ra + +#endif // !RA_SERVICES_IMPL_DEBUGGER_DETECTOR diff --git a/src/ui/viewmodels/AssetEditorViewModel.hh b/src/ui/viewmodels/AssetEditorViewModel.hh index 3f4303a4c..63cc13982 100644 --- a/src/ui/viewmodels/AssetEditorViewModel.hh +++ b/src/ui/viewmodels/AssetEditorViewModel.hh @@ -5,6 +5,7 @@ #include "TriggerViewModel.hh" #include "data\Types.hh" +#include "data\context\EmulatorContext.hh" #include "data\models\AchievementModel.hh" #include "data\models\AssetModelBase.hh" diff --git a/src/ui/viewmodels/AssetListViewModel.cpp b/src/ui/viewmodels/AssetListViewModel.cpp index 7c3dce86c..4195d5a2d 100644 --- a/src/ui/viewmodels/AssetListViewModel.cpp +++ b/src/ui/viewmodels/AssetListViewModel.cpp @@ -1,5 +1,7 @@ #include "AssetListViewModel.hh" +#include "context\IEmulatorMemoryContext.hh" + #include "data\context\GameContext.hh" #include "data\context\UserContext.hh" @@ -411,8 +413,8 @@ void AssetListViewModel::OnValueChanged(const BoolModelProperty::ChangeArgs& arg auto& pRuntime = ra::services::ServiceLocator::GetMutable(); pRuntime.SetPaused(!args.tNewValue); - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.SetMemoryModified(); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.SetMemoryModified(); } WindowViewModelBase::OnValueChanged(args); diff --git a/src/ui/viewmodels/MemoryBookmarksViewModel.cpp b/src/ui/viewmodels/MemoryBookmarksViewModel.cpp index 961be8943..66ce282cf 100644 --- a/src/ui/viewmodels/MemoryBookmarksViewModel.cpp +++ b/src/ui/viewmodels/MemoryBookmarksViewModel.cpp @@ -4,8 +4,9 @@ #include "RA_Json.h" #include "util\Strings.hh" +#include "context\IEmulatorMemoryContext.hh" + #include "data\Types.hh" -#include "data\context\EmulatorContext.hh" #include "data\models\TriggerValidation.hh" #include "services\AchievementLogicSerializer.hh" @@ -84,8 +85,8 @@ bool MemoryBookmarksViewModel::MemoryBookmarkViewModel::ChangeValue(uint32_t nNe // value changed. if it's frozen, write the frozen value back into memory if (nBehavior == BookmarkBehavior::Frozen) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - pEmulatorContext.WriteMemory(GetAddress(), GetSize(), GetCurrentValueRaw()); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + pMemoryContext.WriteMemory(GetAddress(), GetSize(), GetCurrentValueRaw()); return false; } diff --git a/src/ui/viewmodels/MemoryInspectorViewModel.cpp b/src/ui/viewmodels/MemoryInspectorViewModel.cpp index 7f30a3094..a4bff2ae2 100644 --- a/src/ui/viewmodels/MemoryInspectorViewModel.cpp +++ b/src/ui/viewmodels/MemoryInspectorViewModel.cpp @@ -54,8 +54,8 @@ void MemoryInspectorViewModel::DoFrame() m_pViewer.DoFrame(); const auto nAddress = GetCurrentAddress(); - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - const auto nValue = pEmulatorContext.ReadMemoryByte(nAddress); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nValue = pMemoryContext.ReadMemoryByte(nAddress); SetValue(CurrentAddressValueProperty, nValue); } @@ -465,8 +465,8 @@ void MemoryInspectorViewModel::ToggleBit(int nBit) nValue ^= (1 << nBit); // push the updated value to the emulator - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - pEmulatorContext.WriteMemoryByte(nAddress, gsl::narrow_cast(nValue)); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + pMemoryContext.WriteMemoryByte(nAddress, gsl::narrow_cast(nValue)); // update the local value, which will cause the bits string to get updated SetValue(CurrentAddressValueProperty, nValue); diff --git a/src/ui/viewmodels/MemorySearchViewModel.cpp b/src/ui/viewmodels/MemorySearchViewModel.cpp index 784c2d57c..ecffe119e 100644 --- a/src/ui/viewmodels/MemorySearchViewModel.cpp +++ b/src/ui/viewmodels/MemorySearchViewModel.cpp @@ -168,8 +168,8 @@ MemorySearchViewModel::MemorySearchViewModel() void MemorySearchViewModel::InitializeNotifyTargets() { - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.AddNotifyTarget(*this); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.AddNotifyTarget(*this); OnTotalMemorySizeChanged(); auto& pGameContext = ra::services::ServiceLocator::GetMutable(); @@ -195,7 +195,8 @@ void MemorySearchViewModel::OnTotalMemorySizeChanged() { RebuildPredefinedFilterRanges(); - const auto nTotalBankSize = gsl::narrow_cast(ra::services::ServiceLocator::Get().TotalMemorySize()); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nTotalBankSize = gsl::narrow_cast(pMemoryContext.TotalMemorySize()); SetValue(CanBeginNewSearchProperty, (nTotalBankSize > 0U)); SetValue(TotalMemorySizeProperty, nTotalBankSize); } @@ -427,7 +428,7 @@ void MemorySearchViewModel::DoFrame() return; } - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); { std::lock_guard lock(m_oMutex); @@ -445,7 +446,7 @@ void MemorySearchViewModel::DoFrame() pCurrentResults.pResults.GetMatchingAddress(nIndex++, pResult); const auto nPreviousValue = pResult.nValue; - UpdateResult(pRow, pCurrentResults.pResults, pResult, false, pEmulatorContext); + UpdateResult(pRow, pCurrentResults.pResults, pResult, false, pMemoryContext); // when updating an existing result, check to see if it's been modified and update the tracker if (!pRow.bHasBeenModified && pResult.nValue != nPreviousValue) @@ -852,7 +853,7 @@ void MemorySearchViewModel::UpdateResults() const auto& vmBookmarks = ra::services::ServiceLocator::Get().MemoryBookmarks; const auto& pGameContext = ra::services::ServiceLocator::Get(); - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); const auto* pCodeNotes = pGameContext.Assets().FindCodeNotes(); m_vResults.RemoveNotifyTarget(*this); @@ -889,7 +890,7 @@ void MemorySearchViewModel::UpdateResults() pRow->SetAddress(ra::Widen(sAddress)); - UpdateResult(*pRow, pCurrentResults.pResults, pResult, true, pEmulatorContext); + UpdateResult(*pRow, pCurrentResults.pResults, pResult, true, pMemoryContext); const auto pCodeNote = (pCodeNotes != nullptr) ? pCodeNotes->FindCodeNote(pResult.nAddress, pResult.nSize) : std::wstring(L""); @@ -913,12 +914,12 @@ void MemorySearchViewModel::UpdateResults() void MemorySearchViewModel::UpdateResult(SearchResultViewModel& vmResult, const ra::services::SearchResults& pResults, ra::services::SearchResult& pResult, - bool bForceFilterCheck, const ra::data::context::EmulatorContext& pEmulatorContext) + bool bForceFilterCheck, const ra::context::IEmulatorMemoryContext& pMemoryContext) { std::wstring sFormattedValue; pResult.nValue = vmResult.nCurrentValue; - if (pResults.UpdateValue(pResult, &sFormattedValue, pEmulatorContext) || bForceFilterCheck) + if (pResults.UpdateValue(pResult, &sFormattedValue, pMemoryContext) || bForceFilterCheck) { if (pResults.GetFilterType() == ra::services::SearchFilterType::InitialValue) vmResult.bMatchesFilter = pResults.MatchesFilter(m_vSearchResults.front()->pResults, pResult); diff --git a/src/ui/viewmodels/MemorySearchViewModel.hh b/src/ui/viewmodels/MemorySearchViewModel.hh index 8e516f7ac..b2037b8d2 100644 --- a/src/ui/viewmodels/MemorySearchViewModel.hh +++ b/src/ui/viewmodels/MemorySearchViewModel.hh @@ -2,6 +2,8 @@ #define RA_UI_MEMORYSEARCHVIEWMODEL_H #pragma once +#include "context\IEmulatorMemoryContext.hh" + #include "data\Types.hh" #include "data\context\EmulatorContext.hh" #include "data\context\GameContext.hh" @@ -20,7 +22,7 @@ namespace viewmodels { class MemorySearchViewModel : public ViewModelBase, protected ViewModelCollectionBase::NotifyTarget, - protected ra::data::context::EmulatorContext::NotifyTarget, + protected ra::context::IEmulatorMemoryContext::NotifyTarget, protected ra::data::context::EmulatorContext::DispatchesReadMemory, protected ra::data::context::GameContext::NotifyTarget { @@ -520,7 +522,7 @@ private: void DoApplyFilter(); void UpdateResult(SearchResultViewModel& pRow, const ra::services::SearchResults& pResults, ra::services::SearchResult& pResult, bool bForceFilterCheck, - const ra::data::context::EmulatorContext& pEmulatorContext); + const ra::context::IEmulatorMemoryContext& pMemoryContext); void OnPredefinedFilterRangeChanged(const IntModelProperty::ChangeArgs& args); void OnFilterRangeChanged(); diff --git a/src/ui/viewmodels/MemoryViewerViewModel.cpp b/src/ui/viewmodels/MemoryViewerViewModel.cpp index 6abecb6f4..d77f6f4ad 100644 --- a/src/ui/viewmodels/MemoryViewerViewModel.cpp +++ b/src/ui/viewmodels/MemoryViewerViewModel.cpp @@ -124,10 +124,10 @@ MemoryViewerViewModel::MemoryViewerViewModel() void MemoryViewerViewModel::InitializeNotifyTargets() { - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.AddNotifyTarget(*this); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.AddNotifyTarget(*this); - m_nTotalMemorySize = gsl::narrow(pEmulatorContext.TotalMemorySize()); + m_nTotalMemorySize = gsl::narrow(pMemoryContext.TotalMemorySize()); auto& pGameContext = ra::services::ServiceLocator::GetMutable(); pGameContext.AddNotifyTarget(*this); @@ -137,8 +137,8 @@ void MemoryViewerViewModel::InitializeNotifyTargets() void MemoryViewerViewModel::InitializeFixedViewer(ra::data::ByteAddress nAddress) { - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - m_nTotalMemorySize = gsl::narrow(pEmulatorContext.TotalMemorySize()); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + m_nTotalMemorySize = gsl::narrow(pMemoryContext.TotalMemorySize()); m_bReadOnly = true; m_bAddressFixed = true; @@ -295,11 +295,11 @@ void MemoryViewerViewModel::UpdateInvalidRegions() const auto nFirstAddress = GetFirstAddress(); const auto nVisibleBytes = std::min(m_nTotalMemorySize - nFirstAddress, nVisibleLines * 16); - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - if (pEmulatorContext.HasInvalidRegions()) + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + if (pMemoryContext.HasInvalidRegions()) { for (unsigned i = 0; i < nVisibleBytes; ++i) - m_pInvalid[i] = pEmulatorContext.IsValidAddress(nFirstAddress + i) ? 0 : 1; + m_pInvalid[i] = pMemoryContext.IsValidAddress(nFirstAddress + i) ? 0 : 1; } else { @@ -468,8 +468,8 @@ void MemoryViewerViewModel::ReadMemory(ra::data::ByteAddress nFirstAddress, int return; } - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - pEmulatorContext.ReadMemory(nFirstAddress, m_pMemory, gsl::narrow_cast(nNumVisibleLines) * 16); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + pMemoryContext.ReadMemory(nFirstAddress, m_pMemory, gsl::narrow_cast(nNumVisibleLines) * 16); UpdateInvalidRegions(); UpdateColors(); @@ -705,8 +705,8 @@ void MemoryViewerViewModel::IncreaseCurrentValue(uint32_t nModifier) DispatchMemoryRead([this, nModifier]() { const auto nAddress = GetAddress(); const auto nSize = GetSize(); - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - auto nMem = pEmulatorContext.ReadMemory(nAddress, nSize); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + auto nMem = pMemoryContext.ReadMemory(nAddress, nSize); auto const nMaxValue = ra::data::Memory::SizeMax(nSize); if (nMem >= nMaxValue) @@ -717,7 +717,7 @@ void MemoryViewerViewModel::IncreaseCurrentValue(uint32_t nModifier) else nMem += nModifier; - pEmulatorContext.WriteMemory(nAddress, nSize, nMem); + pMemoryContext.WriteMemory(nAddress, nSize, nMem); }); } @@ -729,8 +729,8 @@ void MemoryViewerViewModel::DecreaseCurrentValue(uint32_t nModifier) DispatchMemoryRead([this, nModifier]() { const auto nAddress = GetAddress(); const auto nSize = GetSize(); - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - auto nMem = pEmulatorContext.ReadMemory(nAddress, nSize); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + auto nMem = pMemoryContext.ReadMemory(nAddress, nSize); if (nMem == 0) return; @@ -740,7 +740,7 @@ void MemoryViewerViewModel::DecreaseCurrentValue(uint32_t nModifier) else nMem -= nModifier; - pEmulatorContext.WriteMemory(nAddress, nSize, nMem); + pMemoryContext.WriteMemory(nAddress, nSize, nMem); }); } @@ -833,9 +833,9 @@ void MemoryViewerViewModel::OnCodeNoteChanged(ra::data::ByteAddress nAddress, co void MemoryViewerViewModel::OnTotalMemorySizeChanged() { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); const bool bTotalMemorySizeWasZero = (m_nTotalMemorySize == 0); - m_nTotalMemorySize = gsl::narrow_cast(pEmulatorContext.TotalMemorySize()); + m_nTotalMemorySize = gsl::narrow_cast(pMemoryContext.TotalMemorySize()); if (m_nTotalMemorySize == 0) { @@ -1115,8 +1115,8 @@ bool MemoryViewerViewModel::OnChar(char c) m_nNeedsRedraw |= REDRAW_MEMORY; // push the updated value to the emulator - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.WriteMemoryByte(nAddress, nByte); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.WriteMemoryByte(nAddress, nByte); // advance the cursor to the next nibble AdvanceCursor(); @@ -1147,8 +1147,8 @@ void MemoryViewerViewModel::DoFrame() const auto nVisibleLines = GetNumVisibleLines(); Expects(nVisibleLines < MaxLines); - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - pEmulatorContext.ReadMemory(nAddress, pMemory, gsl::narrow_cast(nVisibleLines) * 16); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + pMemoryContext.ReadMemory(nAddress, pMemory, gsl::narrow_cast(nVisibleLines) * 16); constexpr int nStride = 8; for (int nIndex = 0; nIndex < nVisibleLines * 16; nIndex += nStride) diff --git a/src/ui/viewmodels/MemoryViewerViewModel.hh b/src/ui/viewmodels/MemoryViewerViewModel.hh index d4a5cc5e4..4db303a2c 100644 --- a/src/ui/viewmodels/MemoryViewerViewModel.hh +++ b/src/ui/viewmodels/MemoryViewerViewModel.hh @@ -2,6 +2,8 @@ #define RA_UI_MEMORYVIEWERVIEWMODEL_H #pragma once +#include "context\IEmulatorMemoryContext.hh" + #include "data\Types.hh" #include "data\context\EmulatorContext.hh" #include "data\context\GameContext.hh" @@ -18,7 +20,7 @@ namespace viewmodels { class MemoryViewerViewModel : public ViewModelBase, protected ra::data::context::GameContext::NotifyTarget, - protected ra::data::context::EmulatorContext::NotifyTarget, + protected ra::context::IEmulatorMemoryContext::NotifyTarget, protected ra::data::context::EmulatorContext::DispatchesReadMemory { public: diff --git a/src/ui/viewmodels/MemoryWatchListViewModel.cpp b/src/ui/viewmodels/MemoryWatchListViewModel.cpp index de14c331f..a748df864 100644 --- a/src/ui/viewmodels/MemoryWatchListViewModel.cpp +++ b/src/ui/viewmodels/MemoryWatchListViewModel.cpp @@ -63,8 +63,8 @@ void MemoryWatchListViewModel::InitializeNotifyTargets(bool syncNotes) pGameContext.AddNotifyTarget(*this); } - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.AddNotifyTarget(*this); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.AddNotifyTarget(*this); } void MemoryWatchListViewModel::OnCodeNoteMoved(ra::data::ByteAddress nOldAddress, ra::data::ByteAddress nNewAddress, const std::wstring& sNote) @@ -112,15 +112,15 @@ void MemoryWatchListViewModel::OnByteWritten(ra::data::ByteAddress nAddress, uin void MemoryWatchListViewModel::DoFrame() { // don't watch for memory changes while we're processing the list. frozen bookmarks may write memory - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.RemoveNotifyTarget(*this); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.RemoveNotifyTarget(*this); m_vItems.BeginUpdate(); for (auto& pItem : m_vItems) pItem.DoFrame(); m_vItems.EndUpdate(); - pEmulatorContext.AddNotifyTarget(*this); + pMemoryContext.AddNotifyTarget(*this); } void MemoryWatchListViewModel::OnViewModelBoolValueChanged(gsl::index nIndex, const BoolModelProperty::ChangeArgs& args) @@ -132,14 +132,14 @@ void MemoryWatchListViewModel::OnViewModelBoolValueChanged(gsl::index nIndex, co } else if (args.Property == MemoryWatchViewModel::IsWritingMemoryProperty) { - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); if (args.tNewValue) { - pEmulatorContext.RemoveNotifyTarget(*this); + pMemoryContext.RemoveNotifyTarget(*this); } else { - pEmulatorContext.AddNotifyTarget(*this); + pMemoryContext.AddNotifyTarget(*this); const auto* pItem = m_vItems.GetItemAt(nIndex); Expects(pItem != nullptr); diff --git a/src/ui/viewmodels/MemoryWatchListViewModel.hh b/src/ui/viewmodels/MemoryWatchListViewModel.hh index dcfbf2c31..a5b8af9f9 100644 --- a/src/ui/viewmodels/MemoryWatchListViewModel.hh +++ b/src/ui/viewmodels/MemoryWatchListViewModel.hh @@ -2,6 +2,8 @@ #define RA_UI_MEMORYWATCHLISTVIEWMODEL_H #pragma once +#include "context\IEmulatorMemoryContext.hh" + #include "data\Types.hh" #include "data\context\EmulatorContext.hh" #include "data\context\GameContext.hh" @@ -18,7 +20,7 @@ namespace viewmodels { class MemoryWatchListViewModel : public ViewModelBase, protected ra::data::context::GameContext::NotifyTarget, - protected ra::data::context::EmulatorContext::NotifyTarget, + protected ra::context::IEmulatorMemoryContext::NotifyTarget, protected ra::data::context::EmulatorContext::DispatchesReadMemory, protected ra::ui::ViewModelCollectionBase::NotifyTarget { diff --git a/src/ui/viewmodels/MemoryWatchViewModel.cpp b/src/ui/viewmodels/MemoryWatchViewModel.cpp index 5f2d6b43c..0bee09dcc 100644 --- a/src/ui/viewmodels/MemoryWatchViewModel.cpp +++ b/src/ui/viewmodels/MemoryWatchViewModel.cpp @@ -247,12 +247,12 @@ uint32_t MemoryWatchViewModel::ReadValue() // updated, proceeed to logic below to do the special processing. } - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); if (m_nSize == ra::data::Memory::Size::Text) { // only have 32 bits to store the value in. generate a hash for the string std::array pBuffer; - pEmulatorContext.ReadMemory(m_nAddress, &pBuffer.at(0), pBuffer.size() - 1); + pMemoryContext.ReadMemory(m_nAddress, &pBuffer.at(0), pBuffer.size() - 1); pBuffer.at(pBuffer.size() - 1) = '\0'; const char* pText; @@ -262,7 +262,7 @@ uint32_t MemoryWatchViewModel::ReadValue() return ra::StringHash(sText); } - return pEmulatorContext.ReadMemory(m_nAddress, m_nSize); + return pMemoryContext.ReadMemory(m_nAddress, m_nSize); } void MemoryWatchViewModel::EndInitialization() @@ -283,7 +283,7 @@ void MemoryWatchViewModel::EndInitialization() bool MemoryWatchViewModel::SetCurrentValue(const std::wstring& sValue, _Out_ std::wstring& sError) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); const auto nAddress = m_nAddress; unsigned nValue = 0; @@ -317,7 +317,7 @@ bool MemoryWatchViewModel::SetCurrentValue(const std::wstring& sValue, _Out_ std // use the IsWritingMemoryProperty to disable the event handler in the list // while we write the memory so it doesn't try to sync the value back here SetValue(IsWritingMemoryProperty, true); - pEmulatorContext.WriteMemory(nAddress, m_nSize, nValue); + pMemoryContext.WriteMemory(nAddress, m_nSize, nValue); SetValue(IsWritingMemoryProperty, false); // update the fields dependent on m_nValue diff --git a/src/ui/viewmodels/PointerFinderViewModel.cpp b/src/ui/viewmodels/PointerFinderViewModel.cpp index ce9a129e9..07081f3b3 100644 --- a/src/ui/viewmodels/PointerFinderViewModel.cpp +++ b/src/ui/viewmodels/PointerFinderViewModel.cpp @@ -58,7 +58,8 @@ void PointerFinderViewModel::StateViewModel::ToggleCapture() void PointerFinderViewModel::StateViewModel::Capture() { - if (ra::services::ServiceLocator::Get().TotalMemorySize() == 0) + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + if (pMemoryContext.TotalMemorySize() == 0) { ra::ui::viewmodels::MessageBoxViewModel::ShowErrorMessage(L"No game loaded.", L"Cannot capture memory without a loaded game."); return; @@ -89,8 +90,8 @@ void PointerFinderViewModel::StateViewModel::Capture() } DispatchMemoryRead([this]() { - const auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - const auto nMemorySize = gsl::narrow(pEmulatorContext.TotalMemorySize()); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nMemorySize = gsl::narrow(pMemoryContext.TotalMemorySize()); m_pCapture.reset(new ra::services::SearchResults()); m_pCapture->Initialize(0, nMemorySize, m_pOwner->GetSearchType()); diff --git a/src/ui/viewmodels/PointerInspectorViewModel.cpp b/src/ui/viewmodels/PointerInspectorViewModel.cpp index 0aa3eeef8..ba15c49ed 100644 --- a/src/ui/viewmodels/PointerInspectorViewModel.cpp +++ b/src/ui/viewmodels/PointerInspectorViewModel.cpp @@ -3,6 +3,7 @@ #include "RA_Defs.h" #include "context\IConsoleContext.hh" +#include "context\IEmulatorMemoryContext.hh" #include "services\AchievementLogicSerializer.hh" #include "services\IClipboard.hh" @@ -163,16 +164,16 @@ void PointerInspectorViewModel::OnEndGameLoad() m_vPointers.BeginUpdate(); m_vPointers.Clear(); - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); const auto* pCodeNotes = pGameContext.Assets().FindCodeNotes(); if (pCodeNotes != nullptr) { pCodeNotes->EnumerateCodeNotes( - [this, &pEmulatorContext](ra::data::ByteAddress nAddress, const ra::data::models::CodeNoteModel& pNote) { + [this, &pMemoryContext](ra::data::ByteAddress nAddress, const ra::data::models::CodeNoteModel& pNote) { if (pNote.IsPointer()) { m_vPointers.Add(nAddress, - ra::StringPrintf(L"%s | %s", pEmulatorContext.FormatAddress(nAddress), + ra::StringPrintf(L"%s | %s", pMemoryContext.FormatAddress(nAddress), ra::data::models::CodeNoteModel::TrimSize( pNote.GetPointerDescription(), false))); } @@ -238,10 +239,10 @@ void PointerInspectorViewModel::UpdatePointerVisibility(ra::data::ByteAddress nA if (bIsPointerNote) { // valid pointer note not found, insert it - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); m_vPointers.BeginUpdate(); m_vPointers.Add(nAddress, - ra::StringPrintf(L"%s | %s", pEmulatorContext.FormatAddress(nAddress), + ra::StringPrintf(L"%s | %s", pMemoryContext.FormatAddress(nAddress), ra::data::models::CodeNoteModel::TrimSize(pNote->GetPointerDescription(), false))); m_vPointers.MoveItem(nCount, nIndex); m_vPointers.EndUpdate(); @@ -850,8 +851,8 @@ void PointerInspectorViewModel::UpdatePointerChainRowColor(PointerInspectorViewM if (nMemSize == ra::data::Memory::Size::TwentyFourBit) nMemSize = ra::data::Memory::Size::ThirtyTwoBit; - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - const auto nRawPointer = pEmulatorContext.ReadMemory(pPointer.GetAddress(), nMemSize); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nRawPointer = pMemoryContext.ReadMemory(pPointer.GetAddress(), nMemSize); bValid = (pConsoleContext.ByteAddressFromRealAddress(nRawPointer) != 0xFFFFFFFF); } else diff --git a/src/ui/viewmodels/TriggerViewModel.hh b/src/ui/viewmodels/TriggerViewModel.hh index 1a56b82a1..8c2ef4ce9 100644 --- a/src/ui/viewmodels/TriggerViewModel.hh +++ b/src/ui/viewmodels/TriggerViewModel.hh @@ -2,6 +2,8 @@ #define RA_UI_TRIGGERVIEWMODEL_H #pragma once +#include "data\context\EmulatorContext.hh" + #include "data\models\CapturedTriggerHits.hh" #include "ui\ViewModelBase.hh" diff --git a/src/ui/win32/CodeNotesDialog.cpp b/src/ui/win32/CodeNotesDialog.cpp index 41b925b82..d37b8656f 100644 --- a/src/ui/win32/CodeNotesDialog.cpp +++ b/src/ui/win32/CodeNotesDialog.cpp @@ -55,16 +55,16 @@ void CodeNotesDialog::Presenter::OnClosed() noexcept { m_pDialog.reset(); } CodeNotesDialog::CodeNotesGridBinding::CodeNotesGridBinding(ViewModelBase& vmViewModel) : ra::ui::win32::bindings::MultiLineGridBinding(vmViewModel) { - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.AddNotifyTarget(*this); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.AddNotifyTarget(*this); } CodeNotesDialog::CodeNotesGridBinding::~CodeNotesGridBinding() { if (ra::services::ServiceLocator::Exists()) { - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.RemoveNotifyTarget(*this); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.RemoveNotifyTarget(*this); } } diff --git a/src/ui/win32/CodeNotesDialog.hh b/src/ui/win32/CodeNotesDialog.hh index e889ddb39..61296b976 100644 --- a/src/ui/win32/CodeNotesDialog.hh +++ b/src/ui/win32/CodeNotesDialog.hh @@ -2,7 +2,7 @@ #define RA_UI_WIN32_DLG_CODENOTES_H #pragma once -#include "data/context/EmulatorContext.hh" +#include "context/IEmulatorMemoryContext.hh" #include "ui/viewmodels/CodeNotesViewModel.hh" @@ -45,7 +45,7 @@ protected: private: class CodeNotesGridBinding : public ra::ui::win32::bindings::MultiLineGridBinding, - protected ra::data::context::EmulatorContext::NotifyTarget + protected ra::context::IEmulatorMemoryContext::NotifyTarget { public: explicit CodeNotesGridBinding(ViewModelBase& vmViewModel); diff --git a/src/ui/win32/MemoryBookmarksDialog.cpp b/src/ui/win32/MemoryBookmarksDialog.cpp index 33fb16fb1..a3a340b4e 100644 --- a/src/ui/win32/MemoryBookmarksDialog.cpp +++ b/src/ui/win32/MemoryBookmarksDialog.cpp @@ -57,16 +57,16 @@ void MemoryBookmarksDialog::Presenter::OnClosed() noexcept { m_pDialog.reset(); MemoryBookmarksDialog::BookmarksGridBinding::BookmarksGridBinding(ViewModelBase& vmViewModel) : ra::ui::win32::bindings::GridBinding(vmViewModel) { - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.AddNotifyTarget(*this); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.AddNotifyTarget(*this); } MemoryBookmarksDialog::BookmarksGridBinding::~BookmarksGridBinding() { - if (ra::services::ServiceLocator::Exists()) + if (ra::services::ServiceLocator::Exists()) { - auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - pEmulatorContext.RemoveNotifyTarget(*this); + auto& pMemoryContext = ra::services::ServiceLocator::GetMutable(); + pMemoryContext.RemoveNotifyTarget(*this); } } diff --git a/src/ui/win32/MemoryBookmarksDialog.hh b/src/ui/win32/MemoryBookmarksDialog.hh index a118be233..f929fb68b 100644 --- a/src/ui/win32/MemoryBookmarksDialog.hh +++ b/src/ui/win32/MemoryBookmarksDialog.hh @@ -2,7 +2,7 @@ #define RA_UI_WIN32_DLG_MEMORYBOOKMARKS_H #pragma once -#include "data/context/EmulatorContext.hh" +#include "context/IEmulatorMemoryContext.hh" #include "ui/viewmodels/MemoryBookmarksViewModel.hh" #include "ui/win32/bindings/GridBinding.hh" @@ -41,7 +41,7 @@ protected: private: class BookmarksGridBinding : public ra::ui::win32::bindings::GridBinding, - protected ra::data::context::EmulatorContext::NotifyTarget + protected ra::context::IEmulatorMemoryContext::NotifyTarget { public: explicit BookmarksGridBinding(ViewModelBase& vmViewModel); diff --git a/src/ui/win32/MemoryInspectorDialog.cpp b/src/ui/win32/MemoryInspectorDialog.cpp index f5c67806a..c63811822 100644 --- a/src/ui/win32/MemoryInspectorDialog.cpp +++ b/src/ui/win32/MemoryInspectorDialog.cpp @@ -481,9 +481,9 @@ INT_PTR CALLBACK MemoryInspectorDialog::DialogProc(HWND hDlg, UINT uMsg, WPARAM if (wParam != 1) break; - // ignore if memory not avaialble - const auto& pEmulatorContext = ra::services::ServiceLocator::GetMutable(); - if (pEmulatorContext.TotalMemorySize() == 0) + // ignore if memory not available + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + if (pMemoryContext.TotalMemorySize() == 0) break; // ignore if not 8-bit mode diff --git a/src/ui/win32/bindings/GridAddressColumnBinding.cpp b/src/ui/win32/bindings/GridAddressColumnBinding.cpp index 326b8d13e..de7d50f2b 100644 --- a/src/ui/win32/bindings/GridAddressColumnBinding.cpp +++ b/src/ui/win32/bindings/GridAddressColumnBinding.cpp @@ -38,8 +38,8 @@ unsigned GridAddressColumnBinding::CalculateWidth() { unsigned nMaxChars = 6; // 0x1234 - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - const auto nTotalMemorySize = pEmulatorContext.TotalMemorySize(); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nTotalMemorySize = pMemoryContext.TotalMemorySize(); if (nTotalMemorySize > 0x1000000) nMaxChars = 10; // 0x12345678 else if (nTotalMemorySize > 0x10000) diff --git a/src/ui/win32/bindings/MemoryViewerControlBinding.cpp b/src/ui/win32/bindings/MemoryViewerControlBinding.cpp index b95d23d94..035714986 100644 --- a/src/ui/win32/bindings/MemoryViewerControlBinding.cpp +++ b/src/ui/win32/bindings/MemoryViewerControlBinding.cpp @@ -205,8 +205,8 @@ bool MemoryViewerControlBinding::HandleNavigation(UINT nChar) case VK_END: if (bControlHeld) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - const auto nTotalBytes = gsl::narrow(pEmulatorContext.TotalMemorySize()); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + const auto nTotalBytes = gsl::narrow(pMemoryContext.TotalMemorySize()); m_pViewModel.SetFirstAddress(nTotalBytes & ~0x0F); m_pViewModel.SetAddress(nTotalBytes - 1); diff --git a/tests/Exports_Tests.cpp b/tests/Exports_Tests.cpp index 521b273c9..b9c02aeaa 100644 --- a/tests/Exports_Tests.cpp +++ b/tests/Exports_Tests.cpp @@ -7,10 +7,10 @@ #include "RA_Resource.h" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" #include "tests\mocks\MockAudioSystem.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockEmulatorContext.hh" diff --git a/tests/RA_Integration.Tests.vcxproj b/tests/RA_Integration.Tests.vcxproj index c760d7ed3..2b9d68d61 100644 --- a/tests/RA_Integration.Tests.vcxproj +++ b/tests/RA_Integration.Tests.vcxproj @@ -93,7 +93,6 @@ - Create @@ -174,6 +173,7 @@ + diff --git a/tests/RA_Integration.Tests.vcxproj.filters b/tests/RA_Integration.Tests.vcxproj.filters index 18e67caf4..a079cdcaa 100644 --- a/tests/RA_Integration.Tests.vcxproj.filters +++ b/tests/RA_Integration.Tests.vcxproj.filters @@ -438,9 +438,6 @@ Code - - Code - Code @@ -468,6 +465,9 @@ Code + + Code + diff --git a/tests/data/context/EmulatorContext_Tests.cpp b/tests/data/context/EmulatorContext_Tests.cpp index 7841278a0..adc4367b2 100644 --- a/tests/data/context/EmulatorContext_Tests.cpp +++ b/tests/data/context/EmulatorContext_Tests.cpp @@ -5,12 +5,13 @@ #include "tests\data\DataAsserts.hh" #include "tests\ui\UIAsserts.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\devkit\services\mocks\MockHttpRequester.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockGameContext.hh" @@ -34,6 +35,7 @@ TEST_CLASS(EmulatorContext_Tests) { public: ra::api::mocks::MockServer mockServer; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; @@ -89,19 +91,6 @@ TEST_CLASS(EmulatorContext_Tests) ra::services::ServiceLocator::ServiceOverride m_Override; }; - class EmulatorContextNotifyHarness : public EmulatorContext::NotifyTarget - { - public: - void OnByteWritten(ra::data::ByteAddress nAddress, uint8_t nValue) noexcept override - { - nLastByteWrittenAddress = nAddress; - nLastByteWritten = nValue; - } - - ra::data::ByteAddress nLastByteWrittenAddress = 0xFFFFFFFFU; - uint8_t nLastByteWritten = 0xFF; - }; - public: TEST_METHOD(TestClientName) { @@ -1202,527 +1191,6 @@ TEST_CLASS(EmulatorContext_Tests) return nBytes; } - static void WriteMemory0(uint32_t nAddress, uint8_t nValue) noexcept { memory.at(nAddress) = nValue; } - static void WriteMemory1(uint32_t nAddress, uint8_t nValue) noexcept { memory.at(gsl::narrow_cast(nAddress) + 10) = nValue; } - static void WriteMemory2(uint32_t nAddress, uint8_t nValue) noexcept { memory.at(gsl::narrow_cast(nAddress) + 20) = nValue; } - static void WriteMemory3(uint32_t nAddress, uint8_t nValue) noexcept { memory.at(gsl::narrow_cast(nAddress) + 30) = nValue; } - - static void InitializeMemory() - { - for (size_t i = 0; i < memory.size(); ++i) - memory.at(i) = gsl::narrow_cast(i); - } - - TEST_METHOD(TestIsValidAddress) - { - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); - - Assert::IsTrue(emulator.IsValidAddress(12U)); - Assert::IsTrue(emulator.IsValidAddress(25U)); - Assert::IsTrue(emulator.IsValidAddress(29U)); - Assert::IsFalse(emulator.IsValidAddress(30U)); - } - - TEST_METHOD(TestReadMemoryByte) - { - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); - - Assert::AreEqual(12, static_cast(emulator.ReadMemoryByte(12U))); - Assert::AreEqual(25, static_cast(emulator.ReadMemoryByte(25U))); - Assert::AreEqual(4, static_cast(emulator.ReadMemoryByte(4U))); - Assert::AreEqual(29, static_cast(emulator.ReadMemoryByte(29U))); - Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(30U))); - } - - TEST_METHOD(TestAddMemoryBlocksOutOfOrder) - { - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); - - Assert::AreEqual(12, static_cast(emulator.ReadMemoryByte(12U))); - Assert::AreEqual(25, static_cast(emulator.ReadMemoryByte(25U))); - Assert::AreEqual(4, static_cast(emulator.ReadMemoryByte(4U))); - Assert::AreEqual(29, static_cast(emulator.ReadMemoryByte(29U))); - Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(30U))); - } - - TEST_METHOD(TestAddMemoryBlockDoesNotOverwrite) - { - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - emulator.AddMemoryBlock(0, 20, &ReadMemory3, &WriteMemory3); - Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); - - Assert::AreEqual(12, static_cast(emulator.ReadMemoryByte(12U))); - Assert::AreEqual(25, static_cast(emulator.ReadMemoryByte(25U))); - Assert::AreEqual(4, static_cast(emulator.ReadMemoryByte(4U))); - Assert::AreEqual(29, static_cast(emulator.ReadMemoryByte(29U))); - Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(30U))); - } - - TEST_METHOD(TestClearMemoryBlocks) - { - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - emulator.ClearMemoryBlocks(); - emulator.AddMemoryBlock(0, 20, &ReadMemory3, &WriteMemory3); - Assert::AreEqual({ 20U }, emulator.TotalMemorySize()); - - Assert::AreEqual(32, static_cast(emulator.ReadMemoryByte(2U))); - Assert::AreEqual(41, static_cast(emulator.ReadMemoryByte(11U))); - Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(55U))); - } - - TEST_METHOD(TestInvalidMemoryBlock) - { - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, nullptr, nullptr); - emulator.AddMemoryBlock(2, 10, &ReadMemory3, &WriteMemory3); - Assert::AreEqual({ 40U }, emulator.TotalMemorySize()); - - Assert::IsTrue(emulator.IsValidAddress(12U)); - Assert::IsTrue(emulator.IsValidAddress(19U)); - Assert::IsFalse(emulator.IsValidAddress(20U)); - Assert::IsFalse(emulator.IsValidAddress(29U)); - Assert::IsTrue(emulator.IsValidAddress(30U)); - Assert::IsTrue(emulator.IsValidAddress(39U)); - Assert::IsFalse(emulator.IsValidAddress(40U)); - - Assert::AreEqual(12, static_cast(emulator.ReadMemoryByte(12U))); - Assert::AreEqual(19, static_cast(emulator.ReadMemoryByte(19U))); - Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(20U))); - Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(29U))); - Assert::AreEqual(30, static_cast(emulator.ReadMemoryByte(30U))); - Assert::AreEqual(39, static_cast(emulator.ReadMemoryByte(39U))); - Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(40U))); - } - - TEST_METHOD(TestReadMemory) - { - memory.at(4) = 0xA8; - memory.at(5) = 0x00; - memory.at(6) = 0x37; - memory.at(7) = 0x2E; - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - - // ReadMemory calls ReadMemoryByte for small sizes - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit0))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit1))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit2))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit3))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit4))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit5))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit6))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit7))); - Assert::AreEqual(3, static_cast(emulator.ReadMemory(4U, Memory::Size::BitCount))); - Assert::AreEqual(8, static_cast(emulator.ReadMemory(4U, Memory::Size::NibbleLower))); - Assert::AreEqual(10, static_cast(emulator.ReadMemory(4U, Memory::Size::NibbleUpper))); - Assert::AreEqual(0xA8, static_cast(emulator.ReadMemory(4U, Memory::Size::EightBit))); - Assert::AreEqual(0xA8, static_cast(emulator.ReadMemory(4U, Memory::Size::SixteenBit))); - Assert::AreEqual(0x2E37, static_cast(emulator.ReadMemory(6U, Memory::Size::SixteenBit))); - Assert::AreEqual(0x2E3700, static_cast(emulator.ReadMemory(5U, Memory::Size::TwentyFourBit))); - Assert::AreEqual(0x2E3700A8, static_cast(emulator.ReadMemory(4U, Memory::Size::ThirtyTwoBit))); - Assert::AreEqual(0x372E, static_cast(emulator.ReadMemory(6U, Memory::Size::SixteenBitBigEndian))); - Assert::AreEqual(0x00372E, static_cast(emulator.ReadMemory(5U, Memory::Size::TwentyFourBitBigEndian))); - Assert::AreEqual(0xA800372EU, emulator.ReadMemory(4U, Memory::Size::ThirtyTwoBitBigEndian)); - - memory.at(4) ^= 0xFF; // toggle all bits and verify again - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit0))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit1))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit2))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit3))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit4))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit5))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit6))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit7))); - Assert::AreEqual(5, static_cast(emulator.ReadMemory(4U, Memory::Size::BitCount))); - Assert::AreEqual(7, static_cast(emulator.ReadMemory(4U, Memory::Size::NibbleLower))); - Assert::AreEqual(5, static_cast(emulator.ReadMemory(4U, Memory::Size::NibbleUpper))); - Assert::AreEqual(0x57, static_cast(emulator.ReadMemory(4U, Memory::Size::EightBit))); - } - - TEST_METHOD(TestReadMemoryBlock) - { - for (size_t i = 0; i < memory.size(); i++) - memory.at(i) = gsl::narrow_cast(i); - - memory.at(4) = 0xA8; - memory.at(5) = 0x00; - memory.at(6) = 0x37; - memory.at(7) = 0x2E; - - memory.at(14) = 0x57; - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory1, &WriteMemory0); // purposefully use ReadMemory1 to detect using byte reader for non-byte reads - emulator.AddMemoryBlockReader(0, &ReadMemoryBlock0); - - // ReadMemory calls ReadMemoryByte for small sizes - should call ReadMemory1 ($4 => $14) - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit0))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit1))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit2))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit3))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit4))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit5))); - Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit6))); - Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, Memory::Size::Bit7))); - Assert::AreEqual(5, static_cast(emulator.ReadMemory(4U, Memory::Size::BitCount))); - Assert::AreEqual(7, static_cast(emulator.ReadMemory(4U, Memory::Size::NibbleLower))); - Assert::AreEqual(5, static_cast(emulator.ReadMemory(4U, Memory::Size::NibbleUpper))); - Assert::AreEqual(0x57, static_cast(emulator.ReadMemory(4U, Memory::Size::EightBit))); - - // sizes larger than 8 bits should use the block reader ($4 => $4) - Assert::AreEqual(0xA8, static_cast(emulator.ReadMemory(4U, Memory::Size::SixteenBit))); - Assert::AreEqual(0x2E37, static_cast(emulator.ReadMemory(6U, Memory::Size::SixteenBit))); - Assert::AreEqual(0x2E3700, static_cast(emulator.ReadMemory(5U, Memory::Size::TwentyFourBit))); - Assert::AreEqual(0x2E3700A8, static_cast(emulator.ReadMemory(4U, Memory::Size::ThirtyTwoBit))); - Assert::AreEqual(0x372E, static_cast(emulator.ReadMemory(6U, Memory::Size::SixteenBitBigEndian))); - Assert::AreEqual(0x00372E, static_cast(emulator.ReadMemory(5U, Memory::Size::TwentyFourBitBigEndian))); - Assert::AreEqual(0xA800372EU, emulator.ReadMemory(4U, Memory::Size::ThirtyTwoBitBigEndian)); - - // test the block reader directly - uint8_t buffer[16]; - emulator.ReadMemory(0U, buffer, sizeof(buffer)); - for (size_t i = 0; i < sizeof(buffer); i++) - Assert::AreEqual(gsl::at(buffer, i), memory.at(i)); - - emulator.ReadMemory(4U, buffer, 1); - Assert::AreEqual(gsl::at(buffer, 0), memory.at(4)); - Assert::AreEqual(gsl::at(buffer, 1), memory.at(1)); - } - - TEST_METHOD(TestReadMemoryBuffer) - { - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); - - uint8_t buffer[32]; - - // simple read within a block - emulator.ReadMemory(6U, buffer, 12); - Assert::IsTrue(memcmp(buffer, &memory.at(6), 11) == 0); - - // read across block - emulator.ReadMemory(19U, buffer, 4); - Assert::IsTrue(memcmp(buffer, &memory.at(19), 4) == 0); - - // read end of block - emulator.ReadMemory(13U, buffer, 7); - Assert::IsTrue(memcmp(buffer, &memory.at(13), 7) == 0); - - // read start of block - emulator.ReadMemory(20U, buffer, 5); - Assert::IsTrue(memcmp(buffer, &memory.at(20), 5) == 0); - - // read passed end of total memory - emulator.ReadMemory(28U, buffer, 4); - Assert::AreEqual(28, static_cast(buffer[0])); - Assert::AreEqual(29, static_cast(buffer[1])); - Assert::AreEqual(0, static_cast(buffer[2])); - Assert::AreEqual(0, static_cast(buffer[3])); - - // read outside memory - buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xFF; - emulator.ReadMemory(37U, buffer, 4); - Assert::AreEqual(0, static_cast(buffer[0])); - Assert::AreEqual(0, static_cast(buffer[1])); - Assert::AreEqual(0, static_cast(buffer[2])); - Assert::AreEqual(0, static_cast(buffer[3])); - } - - TEST_METHOD(TestReadMemoryBufferInvalidMemoryBlock) - { - constexpr uint8_t zero = 0; - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, nullptr, nullptr); - emulator.AddMemoryBlock(2, 10, &ReadMemory3, &WriteMemory3); - Assert::AreEqual({ 40U }, emulator.TotalMemorySize()); - - uint8_t buffer[32]; - - // simple read within valid block - emulator.ReadMemory(6U, buffer, 12); - Assert::IsTrue(memcmp(buffer, &memory.at(6), 11) == 0); - - // simple read within invalid block - emulator.ReadMemory(22U, buffer, 4); - Assert::AreEqual(zero, buffer[0]); - Assert::AreEqual(zero, buffer[1]); - Assert::AreEqual(zero, buffer[2]); - Assert::AreEqual(zero, buffer[3]); - - // read across block (valid -> invalid) - emulator.ReadMemory(16U, buffer, 8); - Assert::AreEqual(memory.at(16), buffer[0]); - Assert::AreEqual(memory.at(17), buffer[1]); - Assert::AreEqual(memory.at(18), buffer[2]); - Assert::AreEqual(memory.at(19), buffer[3]); - Assert::AreEqual(zero, buffer[4]); - Assert::AreEqual(zero, buffer[5]); - Assert::AreEqual(zero, buffer[6]); - Assert::AreEqual(zero, buffer[7]); - - // read across block (invalid -> valid) - emulator.ReadMemory(26U, buffer, 8); - Assert::AreEqual(zero, buffer[0]); - Assert::AreEqual(zero, buffer[1]); - Assert::AreEqual(zero, buffer[2]); - Assert::AreEqual(zero, buffer[3]); - Assert::AreEqual(memory.at(30), buffer[4]); - Assert::AreEqual(memory.at(31), buffer[5]); - Assert::AreEqual(memory.at(32), buffer[6]); - Assert::AreEqual(memory.at(33), buffer[7]); - } - - TEST_METHOD(TestWriteMemoryByte) - { - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); - - // attempt to write all 64 bytes - for (ra::data::ByteAddress i = 0; i < memory.size(); ++i) - emulator.WriteMemoryByte(i, gsl::narrow_cast(i + 4)); - - // only the 30 mapped bytes should be updated - for (uint8_t i = 0; i < emulator.TotalMemorySize(); ++i) - Assert::AreEqual(static_cast(i + 4), memory.at(i)); - - // the others should have their original values - for (uint8_t i = gsl::narrow_cast(emulator.TotalMemorySize()); i < memory.size(); ++i) - Assert::AreEqual(i, memory.at(i)); - } - - TEST_METHOD(TestWriteMemoryByteEvents) - { - InitializeMemory(); - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); - - EmulatorContextNotifyHarness notify; - emulator.AddNotifyTarget(notify); - - // write to first block - uint8_t nByte = 0xCE; - emulator.WriteMemoryByte(6U, nByte); - Assert::AreEqual(6U, notify.nLastByteWrittenAddress); - Assert::AreEqual(nByte, notify.nLastByteWritten); - - // write to second block - nByte = 0xEE; - emulator.WriteMemoryByte(26U, nByte); - Assert::AreEqual(26U, notify.nLastByteWrittenAddress); - Assert::AreEqual(nByte, notify.nLastByteWritten); - - // write to invalid address - emulator.WriteMemoryByte(36U, nByte + 3); - Assert::AreEqual(26U, notify.nLastByteWrittenAddress); - Assert::AreEqual(nByte, notify.nLastByteWritten); - - // write partial value - nByte = 0xC4; - emulator.WriteMemory(6U, Memory::Size::NibbleLower, 0x04); - Assert::AreEqual(6U, notify.nLastByteWrittenAddress); - Assert::AreEqual(nByte, notify.nLastByteWritten); - } - - TEST_METHOD(TestWriteMemory) - { - memory.at(4) = 0xA8; - memory.at(5) = 0x60; - memory.at(6) = 0x37; - memory.at(7) = 0x2E; - memory.at(8) = 0x04; - - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - - emulator.WriteMemory(4U, Memory::Size::EightBit, 0xFC); - Assert::AreEqual((uint8_t)0xFC, memory.at(4)); - Assert::AreEqual((uint8_t)0x60, memory.at(5)); - - emulator.WriteMemory(4U, Memory::Size::EightBit, 0x12345678); - Assert::AreEqual((uint8_t)0x78, memory.at(4)); - Assert::AreEqual((uint8_t)0x60, memory.at(5)); - - emulator.WriteMemory(4U, Memory::Size::SixteenBit, 0xABCD); - Assert::AreEqual((uint8_t)0xCD, memory.at(4)); - Assert::AreEqual((uint8_t)0xAB, memory.at(5)); - Assert::AreEqual((uint8_t)0x37, memory.at(6)); - - emulator.WriteMemory(4U, Memory::Size::SixteenBit, 0x12345678); - Assert::AreEqual((uint8_t)0x78, memory.at(4)); - Assert::AreEqual((uint8_t)0x56, memory.at(5)); - Assert::AreEqual((uint8_t)0x37, memory.at(6)); - - emulator.WriteMemory(4U, Memory::Size::TwentyFourBit, 0x12345678); - Assert::AreEqual((uint8_t)0x78, memory.at(4)); - Assert::AreEqual((uint8_t)0x56, memory.at(5)); - Assert::AreEqual((uint8_t)0x34, memory.at(6)); - Assert::AreEqual((uint8_t)0x2E, memory.at(7)); - - emulator.WriteMemory(4U, Memory::Size::ThirtyTwoBit, 0x76543210); - Assert::AreEqual((uint8_t)0x10, memory.at(4)); - Assert::AreEqual((uint8_t)0x32, memory.at(5)); - Assert::AreEqual((uint8_t)0x54, memory.at(6)); - Assert::AreEqual((uint8_t)0x76, memory.at(7)); - Assert::AreEqual((uint8_t)0x04, memory.at(8)); - - emulator.WriteMemory(4U, Memory::Size::SixteenBitBigEndian, 0x12345678); - Assert::AreEqual((uint8_t)0x56, memory.at(4)); - Assert::AreEqual((uint8_t)0x78, memory.at(5)); - Assert::AreEqual((uint8_t)0x54, memory.at(6)); - - emulator.WriteMemory(4U, Memory::Size::TwentyFourBitBigEndian, 0x12345678); - Assert::AreEqual((uint8_t)0x34, memory.at(4)); - Assert::AreEqual((uint8_t)0x56, memory.at(5)); - Assert::AreEqual((uint8_t)0x78, memory.at(6)); - Assert::AreEqual((uint8_t)0x76, memory.at(7)); - - emulator.WriteMemory(4U, Memory::Size::ThirtyTwoBitBigEndian, 0x76543210); - Assert::AreEqual((uint8_t)0x76, memory.at(4)); - Assert::AreEqual((uint8_t)0x54, memory.at(5)); - Assert::AreEqual((uint8_t)0x32, memory.at(6)); - Assert::AreEqual((uint8_t)0x10, memory.at(7)); - Assert::AreEqual((uint8_t)0x04, memory.at(8)); - - memory.at(4) = 0xFF; - emulator.WriteMemory(4U, Memory::Size::Bit0, 0x00); - Assert::AreEqual((uint8_t)0xFE, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::Bit0, 0x01); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::Bit1, 0x00); - Assert::AreEqual((uint8_t)0xFD, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::Bit1, 0x01); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::Bit2, 0x00); - Assert::AreEqual((uint8_t)0xFB, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::Bit2, 0x01); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::Bit3, 0x00); - Assert::AreEqual((uint8_t)0xF7, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::Bit3, 0x01); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::Bit4, 0x00); - Assert::AreEqual((uint8_t)0xEF, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::Bit4, 0x01); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::Bit5, 0x00); - Assert::AreEqual((uint8_t)0xDF, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::Bit5, 0x01); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::Bit6, 0x00); - Assert::AreEqual((uint8_t)0xBF, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::Bit6, 0x01); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::Bit7, 0x00); - Assert::AreEqual((uint8_t)0x7F, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::Bit7, 0x01); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::NibbleLower, 0x00); - Assert::AreEqual((uint8_t)0xF0, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::NibbleLower, 0x0F); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::NibbleUpper, 0x00); - Assert::AreEqual((uint8_t)0x0F, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::NibbleUpper, 0x0F); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - - emulator.WriteMemory(4U, Memory::Size::BitCount, 0x00); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - emulator.WriteMemory(4U, Memory::Size::BitCount, 0x02); - Assert::AreEqual((uint8_t)0xFF, memory.at(4)); - } - - TEST_METHOD(TestIsMemoryInsecureCached) - { - EmulatorContextHarness emulator; - Assert::IsFalse(emulator.IsMemoryInsecure()); - - emulator.mockDesktop.SetDebuggerPresent(true); - Assert::IsFalse(emulator.IsMemoryInsecure()); - - emulator.mockClock.AdvanceTime(std::chrono::seconds(5)); - Assert::IsFalse(emulator.IsMemoryInsecure()); - - emulator.mockClock.AdvanceTime(std::chrono::seconds(6)); - Assert::IsTrue(emulator.IsMemoryInsecure()); - } - - TEST_METHOD(TestIsMemoryInsecureRememberedUntilReset) - { - EmulatorContextHarness emulator; - emulator.mockDesktop.SetDebuggerPresent(true); - Assert::IsTrue(emulator.IsMemoryInsecure()); - - emulator.mockDesktop.SetDebuggerPresent(false); - Assert::IsTrue(emulator.IsMemoryInsecure()); - - emulator.mockClock.AdvanceTime(std::chrono::seconds(100)); - Assert::IsTrue(emulator.IsMemoryInsecure()); - - emulator.ResetMemoryModified(); - Assert::IsFalse(emulator.IsMemoryInsecure()); - } - - TEST_METHOD(TestIsMemoryInsecureRecheckedWhenReset) - { - EmulatorContextHarness emulator; - emulator.mockDesktop.SetDebuggerPresent(true); - Assert::IsTrue(emulator.IsMemoryInsecure()); - - emulator.mockClock.AdvanceTime(std::chrono::seconds(100)); - Assert::IsTrue(emulator.IsMemoryInsecure()); - - emulator.ResetMemoryModified(); - Assert::IsTrue(emulator.IsMemoryInsecure()); - } - TEST_METHOD(TestEnableHardcoreModeUnfreezesBookmarks) { EmulatorContextHarness emulator; @@ -1812,182 +1280,8 @@ TEST_CLASS(EmulatorContext_Tests) Assert::AreEqual(ra::data::models::AssetState::Inactive, vmAchievement46->GetState()); Assert::AreEqual(ra::data::models::AssetState::Inactive, vmAchievement47->GetState()); } - - TEST_METHOD(TestFormatAddress) - { - EmulatorContextHarness emulator; - emulator.AddMemoryBlock(0, 0x80, nullptr, nullptr); - - Assert::AreEqual(std::string("0x0000"), emulator.FormatAddress(0x00000000U)); - Assert::AreEqual(std::string("0x00ff"), emulator.FormatAddress(0x000000FFU)); - Assert::AreEqual(std::string("0x0100"), emulator.FormatAddress(0x00000100U)); - Assert::AreEqual(std::string("0xffff"), emulator.FormatAddress(0x0000FFFFU)); - Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); - Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); - Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); - Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); - - emulator.AddMemoryBlock(1, 0x80, nullptr, nullptr); // total size = 0x100 - Assert::AreEqual(std::string("0x0000"), emulator.FormatAddress(0x00000000U)); - Assert::AreEqual(std::string("0x00ff"), emulator.FormatAddress(0x000000FFU)); - Assert::AreEqual(std::string("0x0100"), emulator.FormatAddress(0x00000100U)); - Assert::AreEqual(std::string("0xffff"), emulator.FormatAddress(0x0000FFFFU)); - Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); - Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); - Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); - Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); - - emulator.AddMemoryBlock(2, 0xFF00, nullptr, nullptr); // total size = 0x10000 - Assert::AreEqual(std::string("0x0000"), emulator.FormatAddress(0x00000000U)); - Assert::AreEqual(std::string("0x00ff"), emulator.FormatAddress(0x000000FFU)); - Assert::AreEqual(std::string("0x0100"), emulator.FormatAddress(0x00000100U)); - Assert::AreEqual(std::string("0xffff"), emulator.FormatAddress(0x0000FFFFU)); - Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); - Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); - Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); - Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); - - emulator.AddMemoryBlock(3, 1, nullptr, nullptr); // total size = 0x10001 - Assert::AreEqual(std::string("0x000000"), emulator.FormatAddress(0x00000000U)); - Assert::AreEqual(std::string("0x0000ff"), emulator.FormatAddress(0x000000FFU)); - Assert::AreEqual(std::string("0x000100"), emulator.FormatAddress(0x00000100U)); - Assert::AreEqual(std::string("0x00ffff"), emulator.FormatAddress(0x0000FFFFU)); - Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); - Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); - Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); - Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); - - emulator.AddMemoryBlock(4, 0xFEFFFF, nullptr, nullptr); // total size = 0x1000000 - Assert::AreEqual(std::string("0x000000"), emulator.FormatAddress(0x00000000U)); - Assert::AreEqual(std::string("0x0000ff"), emulator.FormatAddress(0x000000FFU)); - Assert::AreEqual(std::string("0x000100"), emulator.FormatAddress(0x00000100U)); - Assert::AreEqual(std::string("0x00ffff"), emulator.FormatAddress(0x0000FFFFU)); - Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); - Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); - Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); - Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); - - emulator.AddMemoryBlock(5, 1, nullptr, nullptr); // total size = 0x1000001 - Assert::AreEqual(std::string("0x00000000"), emulator.FormatAddress(0x00000000U)); - Assert::AreEqual(std::string("0x000000ff"), emulator.FormatAddress(0x000000FFU)); - Assert::AreEqual(std::string("0x00000100"), emulator.FormatAddress(0x00000100U)); - Assert::AreEqual(std::string("0x0000ffff"), emulator.FormatAddress(0x0000FFFFU)); - Assert::AreEqual(std::string("0x00010000"), emulator.FormatAddress(0x00010000U)); - Assert::AreEqual(std::string("0x00ffffff"), emulator.FormatAddress(0x00FFFFFFU)); - Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); - Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); - } - - TEST_METHOD(TestCaptureMemory) - { - EmulatorContextHarness emulator; - - InitializeMemory(); - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - - std::vector vBlocks; - emulator.CaptureMemory(vBlocks, 0, 30, 0); - Assert::AreEqual({ 2 }, vBlocks.size()); - - Assert::AreEqual(20U, vBlocks.at(0).GetBytesSize()); - const auto* pBytes = vBlocks.at(0).GetBytes(); - for (size_t i = 0; i < 20; i++) - Assert::AreEqual(memory.at(i), pBytes[i]); - - Assert::AreEqual(10U, vBlocks.at(1).GetBytesSize()); - pBytes = vBlocks.at(1).GetBytes(); - for (size_t i = 0; i < 10; i++) - Assert::AreEqual(memory.at(i + 20), pBytes[i]); - } - - TEST_METHOD(TestCaptureMemoryOffset) - { - EmulatorContextHarness emulator; - - InitializeMemory(); - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - - std::vector vBlocks; - emulator.CaptureMemory(vBlocks, 8, 20, 0); - Assert::AreEqual({ 2 }, vBlocks.size()); - - Assert::AreEqual(12U, vBlocks.at(0).GetBytesSize()); - const auto* pBytes = vBlocks.at(0).GetBytes(); - for (size_t i = 0; i < 12; i++) - Assert::AreEqual(memory.at(i + 8), pBytes[i]); - - Assert::AreEqual(8U, vBlocks.at(1).GetBytesSize()); - pBytes = vBlocks.at(1).GetBytes(); - for (size_t i = 0; i < 8; i++) - Assert::AreEqual(memory.at(i + 20), pBytes[i]); - } - - TEST_METHOD(TestCaptureMemorySecondBlockOnly) - { - EmulatorContextHarness emulator; - - InitializeMemory(); - emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); - - std::vector vBlocks; - emulator.CaptureMemory(vBlocks, 20, 10, 0); - Assert::AreEqual({ 1 }, vBlocks.size()); - - Assert::AreEqual(10U, vBlocks.at(0).GetBytesSize()); - const auto* pBytes = vBlocks.at(0).GetBytes(); - for (size_t i = 0; i < 10; i++) - Assert::AreEqual(memory.at(i + 20), pBytes[i]); - } - - TEST_METHOD(TestCaptureMemoryGap) - { - EmulatorContextHarness emulator; - - InitializeMemory(); - emulator.AddMemoryBlock(0, 10, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, nullptr, nullptr); - emulator.AddMemoryBlock(2, 10, &ReadMemory2, &WriteMemory2); - - std::vector vBlocks; - emulator.CaptureMemory(vBlocks, 0, 30, 0); - Assert::AreEqual({ 2 }, vBlocks.size()); - - Assert::AreEqual(10U, vBlocks.at(0).GetBytesSize()); - const auto* pBytes = vBlocks.at(0).GetBytes(); - for (size_t i = 0; i < 10; i++) - Assert::AreEqual(memory.at(i), pBytes[i]); - - Assert::AreEqual(10U, vBlocks.at(1).GetBytesSize()); - pBytes = vBlocks.at(1).GetBytes(); - for (size_t i = 0; i < 10; i++) - Assert::AreEqual(memory.at(i + 20), pBytes[i]); - } - - TEST_METHOD(TestCaptureMemoryGapBoundary) - { - EmulatorContextHarness emulator; - - InitializeMemory(); - emulator.AddMemoryBlock(0, 10, &ReadMemory0, &WriteMemory0); - emulator.AddMemoryBlock(1, 10, nullptr, nullptr); - emulator.AddMemoryBlock(2, 10, &ReadMemory2, &WriteMemory2); - - std::vector vBlocks; - emulator.CaptureMemory(vBlocks, 20, 10, 0); - Assert::AreEqual({ 1 }, vBlocks.size()); - - Assert::AreEqual(10U, vBlocks.at(0).GetBytesSize()); - const auto* pBytes = vBlocks.at(0).GetBytes(); - for (size_t i = 0; i < 10; i++) - Assert::AreEqual(memory.at(i + 20), pBytes[i]); - } }; -std::array EmulatorContext_Tests::memory; - } // namespace tests } // namespace context } // namespace data diff --git a/tests/data/context/GameContext_Tests.cpp b/tests/data/context/GameContext_Tests.cpp index eac3bc8c0..ff81be5ad 100644 --- a/tests/data/context/GameContext_Tests.cpp +++ b/tests/data/context/GameContext_Tests.cpp @@ -16,12 +16,13 @@ #include "tests\ui\UIAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" #include "tests\mocks\MockAudioSystem.hh" #include "tests\mocks\MockEmulatorContext.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockFrameEventQueue.hh" @@ -63,6 +64,7 @@ TEST_CLASS(GameContext_Tests) } ra::api::mocks::MockServer mockServer; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; ra::services::mocks::MockClock mockClock; ra::services::mocks::MockConfiguration mockConfiguration; diff --git a/tests/data/context/SessionTracker_Tests.cpp b/tests/data/context/SessionTracker_Tests.cpp index 385e0e32d..038eac55a 100644 --- a/tests/data/context/SessionTracker_Tests.cpp +++ b/tests/data/context/SessionTracker_Tests.cpp @@ -6,9 +6,9 @@ #include "tests\data\DataAsserts.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockLocalStorage.hh" diff --git a/tests/data/models/AchievementModel_Tests.cpp b/tests/data/models/AchievementModel_Tests.cpp index 091f2a3f8..3e3259791 100644 --- a/tests/data/models/AchievementModel_Tests.cpp +++ b/tests/data/models/AchievementModel_Tests.cpp @@ -9,8 +9,8 @@ #include "tests\data\DataAsserts.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\mocks\MockAchievementRuntime.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockGameContext.hh" using namespace Microsoft::VisualStudio::CppUnitTestFramework; diff --git a/tests/data/models/CodeNoteModel_Tests.cpp b/tests/data/models/CodeNoteModel_Tests.cpp index 6e84c2a17..e7b6b9b50 100644 --- a/tests/data/models/CodeNoteModel_Tests.cpp +++ b/tests/data/models/CodeNoteModel_Tests.cpp @@ -8,10 +8,10 @@ #include "tests\data\DataAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockDesktop.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockServer.hh" #include "tests\mocks\MockUserContext.hh" @@ -29,7 +29,7 @@ TEST_CLASS(CodeNoteModel_Tests) { public: ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; }; void TestCodeNoteSize(const std::wstring& sNote, unsigned int nExpectedBytes, Memory::Size nExpectedSize) @@ -644,14 +644,14 @@ TEST_CLASS(CodeNoteModel_Tests) memory.at(0x07) = 0x80; memory.at(0x14) = 0x20; // pointer@0x14 = 0x80000020 memory.at(0x17) = 0x80; - note.mockEmulatorContext.MockMemory(memory); + note.mockEmulatorMemoryContext.MockMemory(memory); const std::wstring sNote = L"[32-bit pointer] root\r\n" L"+0x80000004 = [32-bit pointer] nested\r\n" L"++0x80000006 = data (8-bit)"; note.SetAddress(0x04); note.SetNote(sNote); - note.UpdateRawPointerValue(0x04, note.mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x04, note.mockEmulatorMemoryContext, nullptr); Assert::AreEqual(Memory::Size::ThirtyTwoBit, note.GetMemSize()); @@ -674,14 +674,14 @@ TEST_CLASS(CodeNoteModel_Tests) memory.at(0x07) = 0x80; memory.at(0x08) = 0x20; // pointer@0x08 = 0x80000020 memory.at(0x0B) = 0x80; - note.mockEmulatorContext.MockMemory(memory); + note.mockEmulatorMemoryContext.MockMemory(memory); const std::wstring sNote = L"[32-bit pointer] root\r\n" L"+0xFFFFFFF8 = [32-bit pointer] nested\r\n" L"++0x80000006 = data (8-bit)"; note.SetAddress(0x04); note.SetNote(sNote); - note.UpdateRawPointerValue(0x04, note.mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x04, note.mockEmulatorMemoryContext, nullptr); Assert::AreEqual(Memory::Size::ThirtyTwoBit, note.GetMemSize()); @@ -710,13 +710,13 @@ TEST_CLASS(CodeNoteModel_Tests) note.SetNote(sNote); std::array memory{}; - note.mockEmulatorContext.MockMemory(memory); + note.mockEmulatorMemoryContext.MockMemory(memory); memory.at(4) = 8; // pointer = 8 memory.at(8) = 20; // obj1 pointer = 20 memory.at(12) = 28; // obj2 pointer = 28 - note.UpdateRawPointerValue(4U, note.mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(4U, note.mockEmulatorMemoryContext, nullptr); Assert::AreEqual(8U, note.GetPointerAddress()); const auto* pObj1Note = note.GetPointerNoteAtOffset(0); diff --git a/tests/data/models/CodeNotesModel_Tests.cpp b/tests/data/models/CodeNotesModel_Tests.cpp index ca444c3e2..1738ea71b 100644 --- a/tests/data/models/CodeNotesModel_Tests.cpp +++ b/tests/data/models/CodeNotesModel_Tests.cpp @@ -8,10 +8,10 @@ #include "tests\data\DataAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockDesktop.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockServer.hh" #include "tests\mocks\MockUserContext.hh" @@ -30,7 +30,7 @@ TEST_CLASS(CodeNotesModel_Tests) public: ra::api::mocks::MockServer mockServer; ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::data::context::mocks::MockUserContext mockUserContext; ra::services::mocks::MockThreadPool mockThreadPool; ra::ui::mocks::MockDesktop mockDesktop; @@ -425,7 +425,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"+04 - Bomb Timer"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 0x04; notes.DoFrame(); @@ -446,7 +446,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"---FRAGGER_HEAD = Fragger Helmet"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 0x04; notes.DoFrame(); @@ -467,7 +467,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"+0x8033 = [16-bit] Total race time"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 0x04; notes.DoFrame(); @@ -491,7 +491,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"+0x1B5CE = Lap"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 0x04; notes.DoFrame(); @@ -516,7 +516,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"+22 = Skill Points (8-bit)"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 0x04; notes.DoFrame(); @@ -541,7 +541,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"-- +2 | Flag"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 0x10; memory.at(0x10+4) = 0x20; memory.at(0x10+8) = 0x28; @@ -566,7 +566,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"+5E = Left Leg Health {16-bit}"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 4; notes.DoFrame(); @@ -588,7 +588,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"+0x1B5CE = Lap"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 4; notes.DoFrame(); @@ -612,7 +612,7 @@ TEST_CLASS(CodeNotesModel_Tests) L"+10 = Very Large (8 bytes)"; notes.AddCodeNote(12, "Author", sNote); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(12) = 0x10; notes.DoFrame(); @@ -645,7 +645,7 @@ TEST_CLASS(CodeNotesModel_Tests) CodeNotesModelHarness notes; notes.mockConsoleContext.AddMemoryRegion(0, 31, ra::data::MemoryRegion::Type::SystemRAM, 0x80); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(4) = 0x88; // start with initial value for pointer (real address = 0x88, RA address = 0x08) const std::wstring sPointerNote = @@ -698,7 +698,7 @@ TEST_CLASS(CodeNotesModel_Tests) memory.at(4) = 8; // pointer = 8 memory.at(8) = 20; // obj1 pointer = 20 memory.at(12) = 28; // obj2 pointer = 28 - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); notes.DoFrame(); @@ -816,7 +816,7 @@ TEST_CLASS(CodeNotesModel_Tests) { CodeNotesModelHarness notes; std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(120) = 0x02; // start with initial value for pointer const std::wstring sPointerNote = @@ -876,7 +876,7 @@ TEST_CLASS(CodeNotesModel_Tests) CodeNotesModelHarness notes; notes.mockConsoleContext.AddMemoryRegion(0, 31, ra::data::MemoryRegion::Type::SystemRAM, 0x80); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(4) = 0x88; // start with initial value for pointer (real address = 0x88, RA address = 0x08) const std::wstring sPointerNote = @@ -945,7 +945,7 @@ TEST_CLASS(CodeNotesModel_Tests) std::array memory{}; for (uint8_t i = 0; i < memory.size(); i++) memory.at(i) = i; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(0) = 16; // start with initial value for pointer const std::wstring sNote = @@ -1018,7 +1018,7 @@ TEST_CLASS(CodeNotesModel_Tests) std::array memory{}; for (uint8_t i = 4; i < memory.size(); i++) memory.at(i) = i; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(0) = 0x90; // start with initial value for pointer (real address = 0x90, RA address = 0x10) const std::wstring sNote = @@ -1066,7 +1066,7 @@ TEST_CLASS(CodeNotesModel_Tests) std::array memory{}; for (uint8_t i = 4; i < memory.size(); i++) memory.at(i) = i; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(3) = 0x90; // start with initial value for pointer (real address = 0x90, RA address = 0x10) const std::wstring sNote = @@ -1114,7 +1114,7 @@ TEST_CLASS(CodeNotesModel_Tests) std::array memory{}; for (uint8_t i = 4; i < memory.size(); i++) memory.at(i) = i; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(0) = 0x90; // start with initial value for pointer (real address = 0x90, RA address = 0x10) const std::wstring sNote = @@ -1161,7 +1161,7 @@ TEST_CLASS(CodeNotesModel_Tests) std::array memory{}; for (uint8_t i = 0; i < memory.size(); i++) memory.at(i) = i; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(0) = 16; // start with initial value for pointer const std::wstring sNote = @@ -1189,7 +1189,7 @@ TEST_CLASS(CodeNotesModel_Tests) CodeNotesModelHarness notes; notes.mockConsoleContext.AddMemoryRegion(0, 31, ra::data::MemoryRegion::Type::SystemRAM, 0x80); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(4) = 0x88; // start with initial value for pointer (real address = 0x88, RA address = 0x08) const std::wstring sPointerNote = @@ -1223,7 +1223,7 @@ TEST_CLASS(CodeNotesModel_Tests) std::array memory{}; for (uint8_t i = 0; i < memory.size(); i++) memory.at(i) = i; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(0) = 16; // start with initial value for pointer const std::wstring sNote = @@ -1255,7 +1255,7 @@ TEST_CLASS(CodeNotesModel_Tests) CodeNotesModelHarness notes; notes.mockConsoleContext.AddMemoryRegion(0, 31, ra::data::MemoryRegion::Type::SystemRAM, 0x80); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(4) = 0x90; // start with initial value for pointer (real address = 0x90, RA address = 0x10) const std::wstring sNote = @@ -1441,7 +1441,7 @@ TEST_CLASS(CodeNotesModel_Tests) CodeNotesModelHarness notes; notes.mockConsoleContext.AddMemoryRegion(0, 31, ra::data::MemoryRegion::Type::SystemRAM, 0x80); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(4) = 0x88; // start with initial value for pointer (real address = 0x88, RA address = 0x08) const std::wstring sPointerNote = @@ -1504,7 +1504,7 @@ TEST_CLASS(CodeNotesModel_Tests) CodeNotesModelHarness notes; notes.mockConsoleContext.AddMemoryRegion(0, 31, ra::data::MemoryRegion::Type::SystemRAM, 0x80); std::array memory{}; - notes.mockEmulatorContext.MockMemory(memory); + notes.mockEmulatorMemoryContext.MockMemory(memory); memory.at(4) = 0x88; // start with initial value for pointer (real address = 0x88, RA address = 0x08) const std::wstring sPointerNote = diff --git a/tests/data/models/MemoryRegionsModel_Tests.cpp b/tests/data/models/MemoryRegionsModel_Tests.cpp index cc3495d79..531103e81 100644 --- a/tests/data/models/MemoryRegionsModel_Tests.cpp +++ b/tests/data/models/MemoryRegionsModel_Tests.cpp @@ -7,7 +7,7 @@ #include "tests\RA_UnitTestHelpers.h" #include "tests\data\DataAsserts.hh" -#include "tests\mocks\MockEmulatorContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -112,8 +112,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeEmpty) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsTrue(MemoryRegionsModel::ParseFilterRange(L"", nStartAddress, nEndAddress)); @@ -123,8 +123,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeHexPrefix) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsTrue(MemoryRegionsModel::ParseFilterRange(L"0xbeef-0xfeed", nStartAddress, nEndAddress)); @@ -134,8 +134,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeDollarPrefix) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsTrue(MemoryRegionsModel::ParseFilterRange(L"$beef-$feed", nStartAddress, nEndAddress)); @@ -145,8 +145,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeNoPrefix) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsTrue(MemoryRegionsModel::ParseFilterRange(L"1234-face", nStartAddress, nEndAddress)); @@ -156,8 +156,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeWhitespace) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsTrue(MemoryRegionsModel::ParseFilterRange(L"0xbeef - 0xfeed", nStartAddress, nEndAddress)); @@ -167,8 +167,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeNoHyphen) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsTrue(MemoryRegionsModel::ParseFilterRange(L"8765", nStartAddress, nEndAddress)); @@ -178,8 +178,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeNoStart) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsFalse(MemoryRegionsModel::ParseFilterRange(L"-8765", nStartAddress, nEndAddress)); @@ -189,8 +189,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeNoEnd) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsFalse(MemoryRegionsModel::ParseFilterRange(L"8765-", nStartAddress, nEndAddress)); @@ -200,8 +200,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeNotHex) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsFalse(MemoryRegionsModel::ParseFilterRange(L"banana", nStartAddress, nEndAddress)); @@ -211,8 +211,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeEndOutOfRange) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsTrue(MemoryRegionsModel::ParseFilterRange(L"0xF000-0x10000", nStartAddress, nEndAddress)); @@ -222,8 +222,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeStartOutOfRange) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsFalse(MemoryRegionsModel::ParseFilterRange(L"0x10000-0x1FFFF", nStartAddress, nEndAddress)); @@ -233,8 +233,8 @@ TEST_CLASS(MemoryRegionsModel_Tests) TEST_METHOD(TestParseFilterRangeStartAfterEnd) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); ra::data::ByteAddress nStartAddress, nEndAddress; Assert::IsTrue(MemoryRegionsModel::ParseFilterRange(L"0x9876-0x1234", nStartAddress, nEndAddress)); diff --git a/tests/data/models/TriggerValidation_Tests.cpp b/tests/data/models/TriggerValidation_Tests.cpp index 2eee3657c..9555ad8cd 100644 --- a/tests/data/models/TriggerValidation_Tests.cpp +++ b/tests/data/models/TriggerValidation_Tests.cpp @@ -3,8 +3,8 @@ #include "data\models\TriggerValidation.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\mocks\MockGameContext.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockUserContext.hh" using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -156,10 +156,10 @@ TEST_CLASS(TriggerValidation_Tests) // instead, max valid address is determined by how much memory the emulator/core exposes ra::context::mocks::MockConsoleContext mockConsoleContext(Arcade, L"Arcade"); Assert::AreEqual(0U, mockConsoleContext.MaxAddress()); - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; unsigned char pMemory[256]; - mockEmulatorContext.MockMemory(pMemory, sizeof(pMemory)); - Assert::AreEqual({ 256U }, mockEmulatorContext.TotalMemorySize()); + mockEmulatorMemoryContext.MockMemory(pMemory, sizeof(pMemory)); + Assert::AreEqual({ 256U }, mockEmulatorMemoryContext.TotalMemorySize()); AssertValidation("0xH12>0xH34", L""); AssertValidation("0xH123>0xH34", L"Condition 1: Address 0123 out of range (max 00FF)"); diff --git a/tests/devkit/RADevKit.Tests.vcxproj.vcxproj b/tests/devkit/RADevKit.Tests.vcxproj.vcxproj index 56b44fba7..3782a41d7 100644 --- a/tests/devkit/RADevKit.Tests.vcxproj.vcxproj +++ b/tests/devkit/RADevKit.Tests.vcxproj.vcxproj @@ -61,14 +61,18 @@ - + + + + + diff --git a/tests/devkit/RADevKit.Tests.vcxproj.vcxproj.filters b/tests/devkit/RADevKit.Tests.vcxproj.vcxproj.filters index 309e96a6a..e93a4dca8 100644 --- a/tests/devkit/RADevKit.Tests.vcxproj.vcxproj.filters +++ b/tests/devkit/RADevKit.Tests.vcxproj.vcxproj.filters @@ -31,7 +31,13 @@ context\impl - + + context\impl + + + context\mocks + + context\impl @@ -95,5 +101,11 @@ context\mocks + + services\mocks + + + context\mocks + \ No newline at end of file diff --git a/tests/data/context/ConsoleContext_Tests.cpp b/tests/devkit/context/impl/ConsoleContext_Tests.cpp similarity index 100% rename from tests/data/context/ConsoleContext_Tests.cpp rename to tests/devkit/context/impl/ConsoleContext_Tests.cpp diff --git a/tests/devkit/context/impl/EmulatorMemoryContext_Tests.cpp b/tests/devkit/context/impl/EmulatorMemoryContext_Tests.cpp new file mode 100644 index 000000000..e4a5346d6 --- /dev/null +++ b/tests/devkit/context/impl/EmulatorMemoryContext_Tests.cpp @@ -0,0 +1,771 @@ +#include "context/impl/EmulatorMemoryContext.hh" + +#include "tests/devkit/services/mocks/MockClock.hh" +#include "tests/devkit/services/mocks/MockDebuggerDetector.hh" + +#include "testutil\CppUnitTest.hh" + +namespace ra { +namespace context { +namespace impl { +namespace tests { + +TEST_CLASS(EmulatorMemoryContext_Tests) +{ +private: + class EmulatorMemoryContextHarness : public EmulatorMemoryContext + { + public: + ra::services::mocks::MockClock mockClock; + ra::services::mocks::MockDebuggerDetector mockDebuggerDetector; + + GSL_SUPPRESS_F6 EmulatorMemoryContextHarness() noexcept + : m_Override(this) + { + } + + private: + ra::services::ServiceLocator::ServiceOverride m_Override; + }; + + class EmulatorMemoryContextNotifyHarness : public EmulatorMemoryContext::NotifyTarget + { + public: + void OnByteWritten(ra::data::ByteAddress nAddress, uint8_t nValue) noexcept override + { + nLastByteWrittenAddress = nAddress; + nLastByteWritten = nValue; + } + + ra::data::ByteAddress nLastByteWrittenAddress = 0xFFFFFFFFU; + uint8_t nLastByteWritten = 0xFF; + }; + + static std::array memory; + + static uint8_t ReadMemory0(uint32_t nAddress) noexcept { return memory.at(nAddress); } + static uint8_t ReadMemory1(uint32_t nAddress) noexcept { return memory.at(gsl::narrow_cast(nAddress) + 10); } + static uint8_t ReadMemory2(uint32_t nAddress) noexcept { return memory.at(gsl::narrow_cast(nAddress) + 20); } + static uint8_t ReadMemory3(uint32_t nAddress) noexcept { return memory.at(gsl::narrow_cast(nAddress) + 30); } + + static uint32_t ReadMemoryBlock0(uint32_t nAddress, uint8_t* pBuffer, uint32_t nBytes) noexcept + { + memcpy(pBuffer, &memory.at(nAddress), nBytes); + return nBytes; + } + + static uint32_t ReadMemoryBlock1(uint32_t nAddress, uint8_t* pBuffer, uint32_t nBytes) noexcept + { + memcpy(pBuffer, &memory.at(gsl::narrow_cast(nAddress)) + 10, nBytes); + return nBytes; + } + + static void WriteMemory0(uint32_t nAddress, uint8_t nValue) noexcept { memory.at(nAddress) = nValue; } + static void WriteMemory1(uint32_t nAddress, uint8_t nValue) noexcept { memory.at(gsl::narrow_cast(nAddress) + 10) = nValue; } + static void WriteMemory2(uint32_t nAddress, uint8_t nValue) noexcept { memory.at(gsl::narrow_cast(nAddress) + 20) = nValue; } + static void WriteMemory3(uint32_t nAddress, uint8_t nValue) noexcept { memory.at(gsl::narrow_cast(nAddress) + 30) = nValue; } + + static void InitializeMemory() + { + for (size_t i = 0; i < memory.size(); ++i) + memory.at(i) = gsl::narrow_cast(i); + } + +public: + TEST_METHOD(TestIsValidAddress) + { + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); + + Assert::IsTrue(emulator.IsValidAddress(12U)); + Assert::IsTrue(emulator.IsValidAddress(25U)); + Assert::IsTrue(emulator.IsValidAddress(29U)); + Assert::IsFalse(emulator.IsValidAddress(30U)); + } + + TEST_METHOD(TestReadMemoryByte) + { + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); + + Assert::AreEqual(12, static_cast(emulator.ReadMemoryByte(12U))); + Assert::AreEqual(25, static_cast(emulator.ReadMemoryByte(25U))); + Assert::AreEqual(4, static_cast(emulator.ReadMemoryByte(4U))); + Assert::AreEqual(29, static_cast(emulator.ReadMemoryByte(29U))); + Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(30U))); + } + + TEST_METHOD(TestAddMemoryBlocksOutOfOrder) + { + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); + + Assert::AreEqual(12, static_cast(emulator.ReadMemoryByte(12U))); + Assert::AreEqual(25, static_cast(emulator.ReadMemoryByte(25U))); + Assert::AreEqual(4, static_cast(emulator.ReadMemoryByte(4U))); + Assert::AreEqual(29, static_cast(emulator.ReadMemoryByte(29U))); + Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(30U))); + } + + TEST_METHOD(TestAddMemoryBlockDoesNotOverwrite) + { + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + emulator.AddMemoryBlock(0, 20, &ReadMemory3, &WriteMemory3); + Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); + + Assert::AreEqual(12, static_cast(emulator.ReadMemoryByte(12U))); + Assert::AreEqual(25, static_cast(emulator.ReadMemoryByte(25U))); + Assert::AreEqual(4, static_cast(emulator.ReadMemoryByte(4U))); + Assert::AreEqual(29, static_cast(emulator.ReadMemoryByte(29U))); + Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(30U))); + } + + TEST_METHOD(TestClearMemoryBlocks) + { + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + emulator.ClearMemoryBlocks(); + emulator.AddMemoryBlock(0, 20, &ReadMemory3, &WriteMemory3); + Assert::AreEqual({ 20U }, emulator.TotalMemorySize()); + + Assert::AreEqual(32, static_cast(emulator.ReadMemoryByte(2U))); + Assert::AreEqual(41, static_cast(emulator.ReadMemoryByte(11U))); + Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(55U))); + } + + TEST_METHOD(TestInvalidMemoryBlock) + { + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, nullptr, nullptr); + emulator.AddMemoryBlock(2, 10, &ReadMemory3, &WriteMemory3); + Assert::AreEqual({ 40U }, emulator.TotalMemorySize()); + + Assert::IsTrue(emulator.IsValidAddress(12U)); + Assert::IsTrue(emulator.IsValidAddress(19U)); + Assert::IsFalse(emulator.IsValidAddress(20U)); + Assert::IsFalse(emulator.IsValidAddress(29U)); + Assert::IsTrue(emulator.IsValidAddress(30U)); + Assert::IsTrue(emulator.IsValidAddress(39U)); + Assert::IsFalse(emulator.IsValidAddress(40U)); + + Assert::AreEqual(12, static_cast(emulator.ReadMemoryByte(12U))); + Assert::AreEqual(19, static_cast(emulator.ReadMemoryByte(19U))); + Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(20U))); + Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(29U))); + Assert::AreEqual(30, static_cast(emulator.ReadMemoryByte(30U))); + Assert::AreEqual(39, static_cast(emulator.ReadMemoryByte(39U))); + Assert::AreEqual(0, static_cast(emulator.ReadMemoryByte(40U))); + } + + TEST_METHOD(TestReadMemory) + { + memory.at(4) = 0xA8; + memory.at(5) = 0x00; + memory.at(6) = 0x37; + memory.at(7) = 0x2E; + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + + // ReadMemory calls ReadMemoryByte for small sizes + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit0))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit1))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit2))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit3))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit4))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit5))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit6))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit7))); + Assert::AreEqual(3, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::BitCount))); + Assert::AreEqual(8, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::NibbleLower))); + Assert::AreEqual(10, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::NibbleUpper))); + Assert::AreEqual(0xA8, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::EightBit))); + Assert::AreEqual(0xA8, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::SixteenBit))); + Assert::AreEqual(0x2E37, static_cast(emulator.ReadMemory(6U, ra::data::Memory::Size::SixteenBit))); + Assert::AreEqual(0x2E3700, static_cast(emulator.ReadMemory(5U, ra::data::Memory::Size::TwentyFourBit))); + Assert::AreEqual(0x2E3700A8, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::ThirtyTwoBit))); + Assert::AreEqual(0x372E, static_cast(emulator.ReadMemory(6U, ra::data::Memory::Size::SixteenBitBigEndian))); + Assert::AreEqual(0x00372E, static_cast(emulator.ReadMemory(5U, ra::data::Memory::Size::TwentyFourBitBigEndian))); + Assert::AreEqual(0xA800372EU, emulator.ReadMemory(4U, ra::data::Memory::Size::ThirtyTwoBitBigEndian)); + + memory.at(4) ^= 0xFF; // toggle all bits and verify again + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit0))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit1))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit2))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit3))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit4))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit5))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit6))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit7))); + Assert::AreEqual(5, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::BitCount))); + Assert::AreEqual(7, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::NibbleLower))); + Assert::AreEqual(5, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::NibbleUpper))); + Assert::AreEqual(0x57, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::EightBit))); + } + + TEST_METHOD(TestReadMemoryBlock) + { + for (size_t i = 0; i < memory.size(); i++) + memory.at(i) = gsl::narrow_cast(i); + + memory.at(4) = 0xA8; + memory.at(5) = 0x00; + memory.at(6) = 0x37; + memory.at(7) = 0x2E; + + memory.at(14) = 0x57; + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory1, &WriteMemory0); // purposefully use ReadMemory1 to detect using byte reader for non-byte reads + emulator.AddMemoryBlockReader(0, &ReadMemoryBlock0); + + // ReadMemory calls ReadMemoryByte for small sizes - should call ReadMemory1 ($4 => $14) + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit0))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit1))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit2))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit3))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit4))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit5))); + Assert::AreEqual(1, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit6))); + Assert::AreEqual(0, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::Bit7))); + Assert::AreEqual(5, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::BitCount))); + Assert::AreEqual(7, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::NibbleLower))); + Assert::AreEqual(5, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::NibbleUpper))); + Assert::AreEqual(0x57, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::EightBit))); + + // sizes larger than 8 bits should use the block reader ($4 => $4) + Assert::AreEqual(0xA8, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::SixteenBit))); + Assert::AreEqual(0x2E37, static_cast(emulator.ReadMemory(6U, ra::data::Memory::Size::SixteenBit))); + Assert::AreEqual(0x2E3700, static_cast(emulator.ReadMemory(5U, ra::data::Memory::Size::TwentyFourBit))); + Assert::AreEqual(0x2E3700A8, static_cast(emulator.ReadMemory(4U, ra::data::Memory::Size::ThirtyTwoBit))); + Assert::AreEqual(0x372E, static_cast(emulator.ReadMemory(6U, ra::data::Memory::Size::SixteenBitBigEndian))); + Assert::AreEqual(0x00372E, static_cast(emulator.ReadMemory(5U, ra::data::Memory::Size::TwentyFourBitBigEndian))); + Assert::AreEqual(0xA800372EU, emulator.ReadMemory(4U, ra::data::Memory::Size::ThirtyTwoBitBigEndian)); + + // test the block reader directly + uint8_t buffer[16]; + emulator.ReadMemory(0U, buffer, sizeof(buffer)); + for (size_t i = 0; i < sizeof(buffer); i++) + Assert::AreEqual(gsl::at(buffer, i), memory.at(i)); + + emulator.ReadMemory(4U, buffer, 1); + Assert::AreEqual(gsl::at(buffer, 0), memory.at(4)); + Assert::AreEqual(gsl::at(buffer, 1), memory.at(1)); + } + + TEST_METHOD(TestReadMemoryBuffer) + { + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); + + uint8_t buffer[32]; + + // simple read within a block + emulator.ReadMemory(6U, buffer, 12); + Assert::IsTrue(memcmp(buffer, &memory.at(6), 11) == 0); + + // read across block + emulator.ReadMemory(19U, buffer, 4); + Assert::IsTrue(memcmp(buffer, &memory.at(19), 4) == 0); + + // read end of block + emulator.ReadMemory(13U, buffer, 7); + Assert::IsTrue(memcmp(buffer, &memory.at(13), 7) == 0); + + // read start of block + emulator.ReadMemory(20U, buffer, 5); + Assert::IsTrue(memcmp(buffer, &memory.at(20), 5) == 0); + + // read passed end of total memory + emulator.ReadMemory(28U, buffer, 4); + Assert::AreEqual(28, static_cast(buffer[0])); + Assert::AreEqual(29, static_cast(buffer[1])); + Assert::AreEqual(0, static_cast(buffer[2])); + Assert::AreEqual(0, static_cast(buffer[3])); + + // read outside memory + buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xFF; + emulator.ReadMemory(37U, buffer, 4); + Assert::AreEqual(0, static_cast(buffer[0])); + Assert::AreEqual(0, static_cast(buffer[1])); + Assert::AreEqual(0, static_cast(buffer[2])); + Assert::AreEqual(0, static_cast(buffer[3])); + } + + TEST_METHOD(TestReadMemoryBufferInvalidMemoryBlock) + { + constexpr uint8_t zero = 0; + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, nullptr, nullptr); + emulator.AddMemoryBlock(2, 10, &ReadMemory3, &WriteMemory3); + Assert::AreEqual({ 40U }, emulator.TotalMemorySize()); + + uint8_t buffer[32]; + + // simple read within valid block + emulator.ReadMemory(6U, buffer, 12); + Assert::IsTrue(memcmp(buffer, &memory.at(6), 11) == 0); + + // simple read within invalid block + emulator.ReadMemory(22U, buffer, 4); + Assert::AreEqual(zero, buffer[0]); + Assert::AreEqual(zero, buffer[1]); + Assert::AreEqual(zero, buffer[2]); + Assert::AreEqual(zero, buffer[3]); + + // read across block (valid -> invalid) + emulator.ReadMemory(16U, buffer, 8); + Assert::AreEqual(memory.at(16), buffer[0]); + Assert::AreEqual(memory.at(17), buffer[1]); + Assert::AreEqual(memory.at(18), buffer[2]); + Assert::AreEqual(memory.at(19), buffer[3]); + Assert::AreEqual(zero, buffer[4]); + Assert::AreEqual(zero, buffer[5]); + Assert::AreEqual(zero, buffer[6]); + Assert::AreEqual(zero, buffer[7]); + + // read across block (invalid -> valid) + emulator.ReadMemory(26U, buffer, 8); + Assert::AreEqual(zero, buffer[0]); + Assert::AreEqual(zero, buffer[1]); + Assert::AreEqual(zero, buffer[2]); + Assert::AreEqual(zero, buffer[3]); + Assert::AreEqual(memory.at(30), buffer[4]); + Assert::AreEqual(memory.at(31), buffer[5]); + Assert::AreEqual(memory.at(32), buffer[6]); + Assert::AreEqual(memory.at(33), buffer[7]); + } + + TEST_METHOD(TestWriteMemoryByte) + { + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); + + // attempt to write all 64 bytes + for (ra::data::ByteAddress i = 0; i < memory.size(); ++i) + emulator.WriteMemoryByte(i, gsl::narrow_cast(i + 4)); + + // only the 30 mapped bytes should be updated + for (uint8_t i = 0; i < emulator.TotalMemorySize(); ++i) + Assert::AreEqual(static_cast(i + 4), memory.at(i)); + + // the others should have their original values + for (uint8_t i = gsl::narrow_cast(emulator.TotalMemorySize()); i < memory.size(); ++i) + Assert::AreEqual(i, memory.at(i)); + } + + TEST_METHOD(TestWriteMemoryByteEvents) + { + InitializeMemory(); + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + Assert::AreEqual({ 30U }, emulator.TotalMemorySize()); + + EmulatorMemoryContextNotifyHarness notify; + emulator.AddNotifyTarget(notify); + + // write to first block + uint8_t nByte = 0xCE; + emulator.WriteMemoryByte(6U, nByte); + Assert::AreEqual(6U, notify.nLastByteWrittenAddress); + Assert::AreEqual(nByte, notify.nLastByteWritten); + + // write to second block + nByte = 0xEE; + emulator.WriteMemoryByte(26U, nByte); + Assert::AreEqual(26U, notify.nLastByteWrittenAddress); + Assert::AreEqual(nByte, notify.nLastByteWritten); + + // write to invalid address + emulator.WriteMemoryByte(36U, nByte + 3); + Assert::AreEqual(26U, notify.nLastByteWrittenAddress); + Assert::AreEqual(nByte, notify.nLastByteWritten); + + // write partial value + nByte = 0xC4; + emulator.WriteMemory(6U, ra::data::Memory::Size::NibbleLower, 0x04); + Assert::AreEqual(6U, notify.nLastByteWrittenAddress); + Assert::AreEqual(nByte, notify.nLastByteWritten); + } + + TEST_METHOD(TestWriteMemory) + { + memory.at(4) = 0xA8; + memory.at(5) = 0x60; + memory.at(6) = 0x37; + memory.at(7) = 0x2E; + memory.at(8) = 0x04; + + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + + emulator.WriteMemory(4U, ra::data::Memory::Size::EightBit, 0xFC); + Assert::AreEqual((uint8_t)0xFC, memory.at(4)); + Assert::AreEqual((uint8_t)0x60, memory.at(5)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::EightBit, 0x12345678); + Assert::AreEqual((uint8_t)0x78, memory.at(4)); + Assert::AreEqual((uint8_t)0x60, memory.at(5)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::SixteenBit, 0xABCD); + Assert::AreEqual((uint8_t)0xCD, memory.at(4)); + Assert::AreEqual((uint8_t)0xAB, memory.at(5)); + Assert::AreEqual((uint8_t)0x37, memory.at(6)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::SixteenBit, 0x12345678); + Assert::AreEqual((uint8_t)0x78, memory.at(4)); + Assert::AreEqual((uint8_t)0x56, memory.at(5)); + Assert::AreEqual((uint8_t)0x37, memory.at(6)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::TwentyFourBit, 0x12345678); + Assert::AreEqual((uint8_t)0x78, memory.at(4)); + Assert::AreEqual((uint8_t)0x56, memory.at(5)); + Assert::AreEqual((uint8_t)0x34, memory.at(6)); + Assert::AreEqual((uint8_t)0x2E, memory.at(7)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::ThirtyTwoBit, 0x76543210); + Assert::AreEqual((uint8_t)0x10, memory.at(4)); + Assert::AreEqual((uint8_t)0x32, memory.at(5)); + Assert::AreEqual((uint8_t)0x54, memory.at(6)); + Assert::AreEqual((uint8_t)0x76, memory.at(7)); + Assert::AreEqual((uint8_t)0x04, memory.at(8)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::SixteenBitBigEndian, 0x12345678); + Assert::AreEqual((uint8_t)0x56, memory.at(4)); + Assert::AreEqual((uint8_t)0x78, memory.at(5)); + Assert::AreEqual((uint8_t)0x54, memory.at(6)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::TwentyFourBitBigEndian, 0x12345678); + Assert::AreEqual((uint8_t)0x34, memory.at(4)); + Assert::AreEqual((uint8_t)0x56, memory.at(5)); + Assert::AreEqual((uint8_t)0x78, memory.at(6)); + Assert::AreEqual((uint8_t)0x76, memory.at(7)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::ThirtyTwoBitBigEndian, 0x76543210); + Assert::AreEqual((uint8_t)0x76, memory.at(4)); + Assert::AreEqual((uint8_t)0x54, memory.at(5)); + Assert::AreEqual((uint8_t)0x32, memory.at(6)); + Assert::AreEqual((uint8_t)0x10, memory.at(7)); + Assert::AreEqual((uint8_t)0x04, memory.at(8)); + + memory.at(4) = 0xFF; + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit0, 0x00); + Assert::AreEqual((uint8_t)0xFE, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit0, 0x01); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit1, 0x00); + Assert::AreEqual((uint8_t)0xFD, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit1, 0x01); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit2, 0x00); + Assert::AreEqual((uint8_t)0xFB, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit2, 0x01); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit3, 0x00); + Assert::AreEqual((uint8_t)0xF7, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit3, 0x01); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit4, 0x00); + Assert::AreEqual((uint8_t)0xEF, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit4, 0x01); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit5, 0x00); + Assert::AreEqual((uint8_t)0xDF, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit5, 0x01); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit6, 0x00); + Assert::AreEqual((uint8_t)0xBF, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit6, 0x01); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit7, 0x00); + Assert::AreEqual((uint8_t)0x7F, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::Bit7, 0x01); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::NibbleLower, 0x00); + Assert::AreEqual((uint8_t)0xF0, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::NibbleLower, 0x0F); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::NibbleUpper, 0x00); + Assert::AreEqual((uint8_t)0x0F, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::NibbleUpper, 0x0F); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + + emulator.WriteMemory(4U, ra::data::Memory::Size::BitCount, 0x00); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + emulator.WriteMemory(4U, ra::data::Memory::Size::BitCount, 0x02); + Assert::AreEqual((uint8_t)0xFF, memory.at(4)); + } + + TEST_METHOD(TestIsMemoryInsecureCached) + { + EmulatorMemoryContextHarness emulator; + Assert::IsFalse(emulator.IsMemoryInsecure()); + + emulator.mockDebuggerDetector.SetDebuggerPresent(true); + Assert::IsFalse(emulator.IsMemoryInsecure()); + + emulator.mockClock.AdvanceTime(std::chrono::seconds(5)); + Assert::IsFalse(emulator.IsMemoryInsecure()); + + emulator.mockClock.AdvanceTime(std::chrono::seconds(6)); + Assert::IsTrue(emulator.IsMemoryInsecure()); + } + + TEST_METHOD(TestIsMemoryInsecureRememberedUntilReset) + { + EmulatorMemoryContextHarness emulator; + emulator.mockDebuggerDetector.SetDebuggerPresent(true); + Assert::IsTrue(emulator.IsMemoryInsecure()); + + emulator.mockDebuggerDetector.SetDebuggerPresent(false); + Assert::IsTrue(emulator.IsMemoryInsecure()); + + emulator.mockClock.AdvanceTime(std::chrono::seconds(100)); + Assert::IsTrue(emulator.IsMemoryInsecure()); + + emulator.ResetMemoryModified(); + Assert::IsFalse(emulator.IsMemoryInsecure()); + } + + TEST_METHOD(TestIsMemoryInsecureRecheckedWhenReset) + { + EmulatorMemoryContextHarness emulator; + emulator.mockDebuggerDetector.SetDebuggerPresent(true); + Assert::IsTrue(emulator.IsMemoryInsecure()); + + emulator.mockClock.AdvanceTime(std::chrono::seconds(100)); + Assert::IsTrue(emulator.IsMemoryInsecure()); + + emulator.ResetMemoryModified(); + Assert::IsTrue(emulator.IsMemoryInsecure()); + } + + TEST_METHOD(TestFormatAddress) + { + EmulatorMemoryContextHarness emulator; + emulator.AddMemoryBlock(0, 0x80, nullptr, nullptr); + + Assert::AreEqual(std::string("0x0000"), emulator.FormatAddress(0x00000000U)); + Assert::AreEqual(std::string("0x00ff"), emulator.FormatAddress(0x000000FFU)); + Assert::AreEqual(std::string("0x0100"), emulator.FormatAddress(0x00000100U)); + Assert::AreEqual(std::string("0xffff"), emulator.FormatAddress(0x0000FFFFU)); + Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); + Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); + Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); + Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); + + emulator.AddMemoryBlock(1, 0x80, nullptr, nullptr); // total size = 0x100 + Assert::AreEqual(std::string("0x0000"), emulator.FormatAddress(0x00000000U)); + Assert::AreEqual(std::string("0x00ff"), emulator.FormatAddress(0x000000FFU)); + Assert::AreEqual(std::string("0x0100"), emulator.FormatAddress(0x00000100U)); + Assert::AreEqual(std::string("0xffff"), emulator.FormatAddress(0x0000FFFFU)); + Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); + Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); + Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); + Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); + + emulator.AddMemoryBlock(2, 0xFF00, nullptr, nullptr); // total size = 0x10000 + Assert::AreEqual(std::string("0x0000"), emulator.FormatAddress(0x00000000U)); + Assert::AreEqual(std::string("0x00ff"), emulator.FormatAddress(0x000000FFU)); + Assert::AreEqual(std::string("0x0100"), emulator.FormatAddress(0x00000100U)); + Assert::AreEqual(std::string("0xffff"), emulator.FormatAddress(0x0000FFFFU)); + Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); + Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); + Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); + Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); + + emulator.AddMemoryBlock(3, 1, nullptr, nullptr); // total size = 0x10001 + Assert::AreEqual(std::string("0x000000"), emulator.FormatAddress(0x00000000U)); + Assert::AreEqual(std::string("0x0000ff"), emulator.FormatAddress(0x000000FFU)); + Assert::AreEqual(std::string("0x000100"), emulator.FormatAddress(0x00000100U)); + Assert::AreEqual(std::string("0x00ffff"), emulator.FormatAddress(0x0000FFFFU)); + Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); + Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); + Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); + Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); + + emulator.AddMemoryBlock(4, 0xFEFFFF, nullptr, nullptr); // total size = 0x1000000 + Assert::AreEqual(std::string("0x000000"), emulator.FormatAddress(0x00000000U)); + Assert::AreEqual(std::string("0x0000ff"), emulator.FormatAddress(0x000000FFU)); + Assert::AreEqual(std::string("0x000100"), emulator.FormatAddress(0x00000100U)); + Assert::AreEqual(std::string("0x00ffff"), emulator.FormatAddress(0x0000FFFFU)); + Assert::AreEqual(std::string("0x010000"), emulator.FormatAddress(0x00010000U)); + Assert::AreEqual(std::string("0xffffff"), emulator.FormatAddress(0x00FFFFFFU)); + Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); + Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); + + emulator.AddMemoryBlock(5, 1, nullptr, nullptr); // total size = 0x1000001 + Assert::AreEqual(std::string("0x00000000"), emulator.FormatAddress(0x00000000U)); + Assert::AreEqual(std::string("0x000000ff"), emulator.FormatAddress(0x000000FFU)); + Assert::AreEqual(std::string("0x00000100"), emulator.FormatAddress(0x00000100U)); + Assert::AreEqual(std::string("0x0000ffff"), emulator.FormatAddress(0x0000FFFFU)); + Assert::AreEqual(std::string("0x00010000"), emulator.FormatAddress(0x00010000U)); + Assert::AreEqual(std::string("0x00ffffff"), emulator.FormatAddress(0x00FFFFFFU)); + Assert::AreEqual(std::string("0x01000000"), emulator.FormatAddress(0x01000000U)); + Assert::AreEqual(std::string("0xffffffff"), emulator.FormatAddress(0xFFFFFFFFU)); + } + + TEST_METHOD(TestCaptureMemory) + { + EmulatorMemoryContextHarness emulator; + + InitializeMemory(); + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + + std::vector vBlocks; + emulator.CaptureMemory(vBlocks, 0, 30, 0); + Assert::AreEqual({ 2 }, vBlocks.size()); + + Assert::AreEqual(20U, vBlocks.at(0).GetBytesSize()); + const auto* pBytes = vBlocks.at(0).GetBytes(); + Expects(pBytes != nullptr); + for (size_t i = 0; i < 20; i++) + Assert::AreEqual(memory.at(i), pBytes[i]); + + Assert::AreEqual(10U, vBlocks.at(1).GetBytesSize()); + pBytes = vBlocks.at(1).GetBytes(); + Expects(pBytes != nullptr); + for (size_t i = 0; i < 10; i++) + Assert::AreEqual(memory.at(i + 20), pBytes[i]); + } + + TEST_METHOD(TestCaptureMemoryOffset) + { + EmulatorMemoryContextHarness emulator; + + InitializeMemory(); + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + + std::vector vBlocks; + emulator.CaptureMemory(vBlocks, 8, 20, 0); + Assert::AreEqual({ 2 }, vBlocks.size()); + + Assert::AreEqual(12U, vBlocks.at(0).GetBytesSize()); + const auto* pBytes = vBlocks.at(0).GetBytes(); + Expects(pBytes != nullptr); + for (size_t i = 0; i < 12; i++) + Assert::AreEqual(memory.at(i + 8), pBytes[i]); + + Assert::AreEqual(8U, vBlocks.at(1).GetBytesSize()); + pBytes = vBlocks.at(1).GetBytes(); + Expects(pBytes != nullptr); + for (size_t i = 0; i < 8; i++) + Assert::AreEqual(memory.at(i + 20), pBytes[i]); + } + + TEST_METHOD(TestCaptureMemorySecondBlockOnly) + { + EmulatorMemoryContextHarness emulator; + + InitializeMemory(); + emulator.AddMemoryBlock(0, 20, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, &ReadMemory2, &WriteMemory2); + + std::vector vBlocks; + emulator.CaptureMemory(vBlocks, 20, 10, 0); + Assert::AreEqual({ 1 }, vBlocks.size()); + + Assert::AreEqual(10U, vBlocks.at(0).GetBytesSize()); + const auto* pBytes = vBlocks.at(0).GetBytes(); + Expects(pBytes != nullptr); + for (size_t i = 0; i < 10; i++) + Assert::AreEqual(memory.at(i + 20), pBytes[i]); + } + + TEST_METHOD(TestCaptureMemoryGap) + { + EmulatorMemoryContextHarness emulator; + + InitializeMemory(); + emulator.AddMemoryBlock(0, 10, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, nullptr, nullptr); + emulator.AddMemoryBlock(2, 10, &ReadMemory2, &WriteMemory2); + + std::vector vBlocks; + emulator.CaptureMemory(vBlocks, 0, 30, 0); + Assert::AreEqual({ 2 }, vBlocks.size()); + + Assert::AreEqual(10U, vBlocks.at(0).GetBytesSize()); + const auto* pBytes = vBlocks.at(0).GetBytes(); + Expects(pBytes != nullptr); + for (size_t i = 0; i < 10; i++) + Assert::AreEqual(memory.at(i), pBytes[i]); + + Assert::AreEqual(10U, vBlocks.at(1).GetBytesSize()); + pBytes = vBlocks.at(1).GetBytes(); + Expects(pBytes != nullptr); + for (size_t i = 0; i < 10; i++) + Assert::AreEqual(memory.at(i + 20), pBytes[i]); + } + + TEST_METHOD(TestCaptureMemoryGapBoundary) + { + EmulatorMemoryContextHarness emulator; + + InitializeMemory(); + emulator.AddMemoryBlock(0, 10, &ReadMemory0, &WriteMemory0); + emulator.AddMemoryBlock(1, 10, nullptr, nullptr); + emulator.AddMemoryBlock(2, 10, &ReadMemory2, &WriteMemory2); + + std::vector vBlocks; + emulator.CaptureMemory(vBlocks, 20, 10, 0); + Assert::AreEqual({ 1 }, vBlocks.size()); + + Assert::AreEqual(10U, vBlocks.at(0).GetBytesSize()); + const auto* pBytes = vBlocks.at(0).GetBytes(); + Expects(pBytes != nullptr); + for (size_t i = 0; i < 10; i++) + Assert::AreEqual(memory.at(i + 20), pBytes[i]); + } +}; + +std::array EmulatorMemoryContext_Tests::memory; + +} // namespace tests +} // namespace impl +} // namespace context +} // namespace ra diff --git a/tests/devkit/context/mocks/MockEmulatorMemoryContext.cpp b/tests/devkit/context/mocks/MockEmulatorMemoryContext.cpp new file mode 100644 index 000000000..28d5c5331 --- /dev/null +++ b/tests/devkit/context/mocks/MockEmulatorMemoryContext.cpp @@ -0,0 +1,94 @@ +#include "MockEmulatorMemoryContext.hh" + +#include "context/IRcClient.hh" + +#include + +namespace ra { +namespace context { +namespace mocks { + +void MockEmulatorMemoryContext::MockMemory(uint8_t pMemory[], size_t nBytes) +{ + m_pMemory = pMemory; + m_mMemoryValues.clear(); + + ClearMemoryBlocks(); + AddMemoryBlock(0, nBytes, ReadMemoryHelper, WriteMemoryHelper); + + if (ra::services::ServiceLocator::Exists()) + { + auto* pClient = ra::services::ServiceLocator::Get().GetClient(); + auto* pGame = pClient->game; + if (pGame && pGame->max_valid_address == 0U) + pGame->max_valid_address = gsl::narrow_cast(nBytes); + } +} + +void MockEmulatorMemoryContext::MockTotalMemorySizeChanged(size_t nNewSize) +{ + m_nTotalMemorySize = nNewSize; + + if (m_vNotifyTargets.LockIfNotEmpty()) + { + for (auto& target : m_vNotifyTargets.Targets()) + target.OnTotalMemorySizeChanged(); + + m_vNotifyTargets.Unlock(); + } +} + +uint8_t MockEmulatorMemoryContext::ReadMemoryHelper(uint32_t nAddress) +{ + const auto* mockEmulator = + dynamic_cast(&ra::services::ServiceLocator::Get()); + + if (!mockEmulator) + return 0; + + if (!mockEmulator->m_mMemoryValues.empty()) + { + auto iter = mockEmulator->m_mMemoryValues.lower_bound(nAddress); + if (iter != mockEmulator->m_mMemoryValues.end() && nAddress == iter->first) + return iter->second & 0xFF; + + if (iter != mockEmulator->m_mMemoryValues.begin()) + { + --iter; + if (nAddress - iter->first < 4) + { + uint32_t nValue = iter->second; + while (nAddress > iter->first) + { + nValue >>= 8; + nAddress--; + } + + return nValue & 0xFF; + } + } + + return 0; + } + + if (nAddress >= mockEmulator->m_nTotalMemorySize) + return 0; + + return mockEmulator->m_pMemory[nAddress]; +} + +void MockEmulatorMemoryContext::WriteMemoryHelper(uint32_t nAddress, uint8_t nValue) +{ + const auto* mockEmulator = + dynamic_cast(&ra::services::ServiceLocator::GetMutable()); + + if (!mockEmulator) + return; + + if (nAddress < mockEmulator->m_nTotalMemorySize) + mockEmulator->m_pMemory[nAddress] = nValue; +} + +} // namespace mocks +} // namespace context +} // namespace ra diff --git a/tests/devkit/context/mocks/MockEmulatorMemoryContext.hh b/tests/devkit/context/mocks/MockEmulatorMemoryContext.hh new file mode 100644 index 000000000..026f6ebf6 --- /dev/null +++ b/tests/devkit/context/mocks/MockEmulatorMemoryContext.hh @@ -0,0 +1,75 @@ +#ifndef RA_CONTEXT_MOCK_EMULATORMEMORYCONTEXT_HH +#define RA_CONTEXT_MOCK_EMULATORMEMORYCONTEXT_HH +#pragma once + +#include "context/impl/EmulatorMemoryContext.hh" + +#include "services/ServiceLocator.hh" + +#pragma warning(push) +#pragma warning(disable: 26440) +#include +#pragma warning(pop) + +#include + +namespace ra { +namespace context { +namespace mocks { + +class MockEmulatorMemoryContext : public impl::EmulatorMemoryContext +{ +public: + MockEmulatorMemoryContext() noexcept + : m_Override(this) + { + } + + template + void MockMemory(std::array& arr) + { + MockMemory(arr.data(), N); + } + + void MockMemory(uint8_t pMemory[], size_t nBytes); + + /// + /// Mocks a specific memory address without having to allocate the entire memory space + /// + void MockMemoryValue(uint32_t nAddress, uint32_t nValue) + { + m_mMemoryValues[nAddress] = nValue; + + if (gsl::narrow_cast(nAddress) + 4 > m_nTotalMemorySize) + { + const size_t nNewMemorySize = gsl::narrow_cast(nAddress) + 4; + ClearMemoryBlocks(); + AddMemoryBlock(0, nNewMemorySize, ReadMemoryHelper, WriteMemoryHelper); + } + } + + void MockMemoryModified(bool bModified) noexcept + { + m_bMemoryModified = bModified; + } + + void MockTotalMemorySizeChanged(size_t nNewSize); + + void MockMemoryInsecure(bool bValue) noexcept { m_bMemoryInsecure = bValue; } + bool IsMemoryInsecure() const noexcept override { return m_bMemoryInsecure; } + +private: + static uint8_t ReadMemoryHelper(uint32_t nAddress); + static void WriteMemoryHelper(uint32_t nAddress, uint8_t nValue); + + ra::services::ServiceLocator::ServiceOverride m_Override; + uint8_t* m_pMemory = nullptr; + + std::map m_mMemoryValues; +}; + +} // namespace mocks +} // namespace context +} // namespace ra + +#endif // !RA_CONTEXT_MOCK_EMULATORMEMORYCONTEXT_HH diff --git a/tests/mocks/MockClock.hh b/tests/devkit/services/mocks/MockClock.hh similarity index 100% rename from tests/mocks/MockClock.hh rename to tests/devkit/services/mocks/MockClock.hh diff --git a/tests/devkit/services/mocks/MockDebuggerDetector.hh b/tests/devkit/services/mocks/MockDebuggerDetector.hh new file mode 100644 index 000000000..8d4ec16e4 --- /dev/null +++ b/tests/devkit/services/mocks/MockDebuggerDetector.hh @@ -0,0 +1,33 @@ +#ifndef RA_SERVICES_MOCK_DEBUGGER_DETECTOR_HH +#define RA_SERVICES_MOCK_DEBUGGER_DETECTOR_HH +#pragma once + +#include "services/IDebuggerDetector.hh" +#include "services/ServiceLocator.hh" + +namespace ra { +namespace services { +namespace mocks { + +class MockDebuggerDetector : public IDebuggerDetector +{ +public: + explicit MockDebuggerDetector() noexcept + : m_Override(this) + { + } + + bool IsDebuggerPresent() const noexcept override { return m_bDebuggerPresent; } + void SetDebuggerPresent(bool bValue) noexcept { m_bDebuggerPresent = bValue; } + +private: + ra::services::ServiceLocator::ServiceOverride m_Override; + + bool m_bDebuggerPresent = false; +}; + +} // namespace mocks +} // namespace services +} // namespace ra + +#endif // !RA_SERVICES_MOCK_DEBUGGER_DETECTOR_HH diff --git a/tests/mocks/MockAchievementRuntime.cpp b/tests/mocks/MockAchievementRuntime.cpp index 8c22d22df..b08a91880 100644 --- a/tests/mocks/MockAchievementRuntime.cpp +++ b/tests/mocks/MockAchievementRuntime.cpp @@ -315,17 +315,6 @@ namespace data { namespace context { namespace mocks { -void MockEmulatorContext::SetRuntimeMemorySize(size_t nBytes) -{ - if (ra::services::ServiceLocator::Exists()) - { - auto* pClient = ra::services::ServiceLocator::Get().GetClient(); - auto* pGame = pClient->game; - if (pGame && pGame->max_valid_address == 0U) - pGame->max_valid_address = gsl::narrow_cast(nBytes); - } -} - void MockGameContext::InitializeFromAchievementRuntime() { auto* pMockRuntime = dynamic_cast( diff --git a/tests/mocks/MockEmulatorContext.hh b/tests/mocks/MockEmulatorContext.hh index 3198d45d7..6676fa078 100644 --- a/tests/mocks/MockEmulatorContext.hh +++ b/tests/mocks/MockEmulatorContext.hh @@ -81,113 +81,13 @@ public: return true; } - void MockMemory(gsl::span pMemory) - { - m_pMemory = pMemory; - m_mMemoryValues.clear(); - - ClearMemoryBlocks(); - AddMemoryBlock(0, m_pMemory.size_bytes(), ReadMemoryHelper, WriteMemoryHelper); - - SetRuntimeMemorySize(m_pMemory.size_bytes()); - } - - void MockMemory(unsigned char pMemory[], size_t nBytes) - { - m_pMemory = gsl::make_span(pMemory, nBytes); - m_mMemoryValues.clear(); - - ClearMemoryBlocks(); - AddMemoryBlock(0, nBytes, ReadMemoryHelper, WriteMemoryHelper); - - SetRuntimeMemorySize(nBytes); - } - - void MockMemoryValue(uint32_t nAddress, uint32_t nValue) - { - m_mMemoryValues[nAddress] = nValue; - - if (gsl::narrow_cast(nAddress) + 4 > m_nTotalMemorySize) - { - const size_t nNewMemorySize = gsl::narrow_cast(nAddress) + 4; - ClearMemoryBlocks(); - AddMemoryBlock(0, nNewMemorySize, ReadMemoryHelper, WriteMemoryHelper); - } - } - - void MockMemoryModified(bool bModified) noexcept - { - m_bMemoryModified = bModified; - } - - void MockTotalMemorySizeChanged(size_t nNewSize) - { - m_nTotalMemorySize = nNewSize; - OnTotalMemorySizeChanged(); - } - - void MockMemoryInsecure(bool bValue) noexcept { m_bMemoryInsecure = bValue; } - bool IsMemoryInsecure() const noexcept override { return m_bMemoryInsecure; } - private: - static uint8_t ReadMemoryHelper(uint32_t nAddress) - { - const auto* mockEmulator = - dynamic_cast(&ra::services::ServiceLocator::Get()); - - if (!mockEmulator) - return 0; - - if (!mockEmulator->m_mMemoryValues.empty()) - { - auto iter = mockEmulator->m_mMemoryValues.lower_bound(nAddress); - if (iter != mockEmulator->m_mMemoryValues.end() && nAddress == iter->first) - return iter->second & 0xFF; - - if (iter != mockEmulator->m_mMemoryValues.begin()) - { - --iter; - if (nAddress - iter->first < 4) - { - uint32_t nValue = iter->second; - while (nAddress > iter->first) - { - nValue >>= 8; - nAddress--; - } - - return nValue & 0xFF; - } - } - - return 0; - } - - return mockEmulator->m_pMemory.at(nAddress); - } - - static void WriteMemoryHelper(uint32_t nAddress, uint8_t nValue) - { - auto* mockEmulator = - dynamic_cast(&ra::services::ServiceLocator::GetMutable()); - - if (!mockEmulator) - return; - - mockEmulator->m_pMemory.at(nAddress) = nValue; - } - - static void SetRuntimeMemorySize(size_t nBytes); - bool m_bInvalid = false; std::string m_sWarnDisableHardcoreActivity; ra::ui::DialogResult m_nWarnDisableHardcoreResult = ra::ui::DialogResult::No; ra::services::ServiceLocator::ServiceOverride m_Override; - gsl::span m_pMemory; - - std::map m_mMemoryValues; }; } // namespace mocks diff --git a/tests/mocks/MockGameContext.hh b/tests/mocks/MockGameContext.hh index 9c0539618..068000ce8 100644 --- a/tests/mocks/MockGameContext.hh +++ b/tests/mocks/MockGameContext.hh @@ -103,8 +103,8 @@ public: auto* pNote = const_cast(pCodeNotes->FindCodeNoteModel(nAddress, false)); if (pNote && pNote->IsPointer()) { - const auto& pEmulatorContext = ra::services::ServiceLocator::Get(); - pNote->UpdateRawPointerValue(nAddress, pEmulatorContext, nullptr); + const auto& pMemoryContext = ra::services::ServiceLocator::Get(); + pNote->UpdateRawPointerValue(nAddress, pMemoryContext, nullptr); } } diff --git a/tests/services/AchievementLogicSerializer_Tests.cpp b/tests/services/AchievementLogicSerializer_Tests.cpp index d9b2cb3a0..f34e85f34 100644 --- a/tests/services/AchievementLogicSerializer_Tests.cpp +++ b/tests/services/AchievementLogicSerializer_Tests.cpp @@ -6,7 +6,7 @@ #include "tests\data\DataAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" -#include "tests\mocks\MockEmulatorContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -20,7 +20,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) TEST_METHOD(TestBuildMemRefChain) { ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::data::models::CodeNoteModel note; const std::wstring sNote = @@ -35,7 +35,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) L"+0x448 | [32-bit BE] Not-nested number"; note.SetNote(sNote); note.SetAddress(0x1234); - note.UpdateRawPointerValue(0x1234, mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x1234, mockEmulatorMemoryContext, nullptr); const auto* note2 = note.GetPointerNoteAtOffset(0x438); Assert::IsNotNull(note2); @@ -49,7 +49,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) TEST_METHOD(TestBuildMemRefChain24Bit) { ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; mockConsoleContext.SetId(ConsoleID::PlayStation); // 24-bit read ra::data::models::CodeNoteModel note; @@ -59,7 +59,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) L"++0x24C | [16-bit] State"; note.SetNote(sNote); note.SetAddress(0x1234); - note.UpdateRawPointerValue(0x1234, mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x1234, mockEmulatorMemoryContext, nullptr); const auto* note2 = note.GetPointerNoteAtOffset(0x428); Assert::IsNotNull(note2); @@ -73,7 +73,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) TEST_METHOD(TestBuildMemRefChain25Bit) { ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; mockConsoleContext.SetId(ConsoleID::PSP); // 25-bit read ra::data::models::CodeNoteModel note; @@ -83,7 +83,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) L"++0x24C | [16-bit] State"; note.SetNote(sNote); note.SetAddress(0x1234); - note.UpdateRawPointerValue(0x1234, mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x1234, mockEmulatorMemoryContext, nullptr); const auto* note2 = note.GetPointerNoteAtOffset(0x428); Assert::IsNotNull(note2); @@ -97,7 +97,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) TEST_METHOD(TestBuildMemRefChain25BitBE) { ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; mockConsoleContext.SetId(ConsoleID::GameCube); // 25-bit BE read ra::data::models::CodeNoteModel note; @@ -107,7 +107,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) L"++0x24C | [16-bit BE] State"; note.SetNote(sNote); note.SetAddress(0x1234); - note.UpdateRawPointerValue(0x1234, mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x1234, mockEmulatorMemoryContext, nullptr); const auto* note2 = note.GetPointerNoteAtOffset(0x428); Assert::IsNotNull(note2); @@ -121,7 +121,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) TEST_METHOD(TestBuildMemRefChain25BitOverflowOffset) { ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; mockConsoleContext.SetId(ConsoleID::GameCube); // 25-bit BE read ra::data::models::CodeNoteModel note; @@ -131,7 +131,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) L"++0x8000024C | [16-bit BE] State"; note.SetNote(sNote); note.SetAddress(0x1234); - note.UpdateRawPointerValue(0x1234, mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x1234, mockEmulatorMemoryContext, nullptr); const auto* note2 = note.GetPointerNoteAtOffset(0x80000428); Assert::IsNotNull(note2); @@ -145,7 +145,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) TEST_METHOD(TestBuildMemRefChainGBA) { ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; mockConsoleContext.SetId(ConsoleID::GBA); // 24-bit read with explicit offset in note ra::data::models::CodeNoteModel note; @@ -155,7 +155,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) L"++0x824C | [16-bit] State"; note.SetNote(sNote); note.SetAddress(0x1234); - note.UpdateRawPointerValue(0x1234, mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x1234, mockEmulatorMemoryContext, nullptr); const auto* note2 = note.GetPointerNoteAtOffset(0x8428); Assert::IsNotNull(note2); @@ -169,7 +169,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) TEST_METHOD(TestBuildMemRefChainNegativeOffset) { ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; mockConsoleContext.SetId(ConsoleID::GameCube); // 29-bit BE read ra::data::models::CodeNoteModel note; @@ -179,7 +179,7 @@ TEST_CLASS(AchievementLogicSerializer_Tests) L"++0x824C | [16-bit] State"; note.SetNote(sNote); note.SetAddress(0x1234); - note.UpdateRawPointerValue(0x1234, mockEmulatorContext, nullptr); + note.UpdateRawPointerValue(0x1234, mockEmulatorMemoryContext, nullptr); const auto* note2 = note.GetPointerNoteAtOffset(0xFFFFFFF8); Assert::IsNotNull(note2); diff --git a/tests/services/AchievementRuntimeExports_Tests.cpp b/tests/services/AchievementRuntimeExports_Tests.cpp index e1c05f1b6..a3f0d502a 100644 --- a/tests/services/AchievementRuntimeExports_Tests.cpp +++ b/tests/services/AchievementRuntimeExports_Tests.cpp @@ -5,6 +5,7 @@ #include "tests\RA_UnitTestHelpers.h" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" @@ -62,6 +63,7 @@ class AchievementRuntimeExportsHarness : public AchievementRuntime AchievementRuntimeExportsHarness(AchievementRuntimeExportsHarness&&) noexcept = delete; AchievementRuntimeExportsHarness& operator=(AchievementRuntimeExportsHarness&&) noexcept = delete; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; ra::data::context::mocks::MockUserContext mockUserContext; @@ -476,17 +478,17 @@ TEST_CLASS(AchievementRuntimeExports_Tests) runtime.InitializeMemoryFunctions(); Assert::AreEqual({0}, runtime.GetMemoryByte(1)); - Assert::AreEqual({0}, runtime.mockEmulatorContext.ReadMemoryByte(1)); + Assert::AreEqual({0}, runtime.mockEmulatorMemoryContext.ReadMemoryByte(1)); - runtime.mockEmulatorContext.WriteMemoryByte(1, 3); + runtime.mockEmulatorMemoryContext.WriteMemoryByte(1, 3); Assert::AreEqual({3}, runtime.GetMemoryByte(1)); - Assert::AreEqual({3}, runtime.mockEmulatorContext.ReadMemoryByte(1)); + Assert::AreEqual({3}, runtime.mockEmulatorMemoryContext.ReadMemoryByte(1)); - runtime.mockEmulatorContext.WriteMemoryByte(2, 7); + runtime.mockEmulatorMemoryContext.WriteMemoryByte(2, 7); Assert::AreEqual({7}, runtime.GetMemoryByte(2)); - Assert::AreEqual({7}, runtime.mockEmulatorContext.ReadMemoryByte(2)); - Assert::AreEqual({0x0703}, runtime.mockEmulatorContext.ReadMemory(1, ra::data::Memory::Size::SixteenBit)); + Assert::AreEqual({7}, runtime.mockEmulatorMemoryContext.ReadMemoryByte(2)); + Assert::AreEqual({0x0703}, runtime.mockEmulatorMemoryContext.ReadMemory(1, ra::data::Memory::Size::SixteenBit)); } TEST_METHOD(TestPauseEvent) diff --git a/tests/services/AchievementRuntime_Tests.cpp b/tests/services/AchievementRuntime_Tests.cpp index ca9958f15..b6957452b 100644 --- a/tests/services/AchievementRuntime_Tests.cpp +++ b/tests/services/AchievementRuntime_Tests.cpp @@ -3,12 +3,13 @@ #include "tests\RA_UnitTestHelpers.h" #include "tests\data\DataAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\devkit\services\mocks\MockHttpRequester.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAudioSystem.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockEmulatorContext.hh" @@ -58,6 +59,7 @@ class AchievementRuntimeHarness : public AchievementRuntime rc_client_set_userdata(GetClient(), this); } + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; ra::data::context::mocks::MockGameContext mockGameContext; @@ -688,7 +690,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{ 0x00 }; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); runtime.MockAchievement(6U, "0xH0000=1"); // expect no events for untriggered achievement @@ -712,7 +714,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{ 0x00 }; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); runtime.MockAchievement(6U, "0xH0000=1"); runtime.SetPaused(true); @@ -761,7 +763,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pAchievement = runtime.MockAchievement(6U, "0xH0000=1"); // expect no events for untriggered achievement @@ -811,7 +813,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); runtime.MockAchievement(4U, "M:0xH0002=100"); // value did not change, expect no event from initialization @@ -848,7 +850,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{ 0x00 }; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* sTrigger = "0xH0000=1"; // achievement not active, should not raise events @@ -1112,7 +1114,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pLeaderboard = runtime.MockLeaderboard(6U, "STA:0xH00=1::CAN:0xH00=2::SUB:0xH00=3::VAL:0xH02"); // expect no events for inactive leaderboard @@ -1199,7 +1201,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); Assert::IsFalse(runtime.HasRichPresence()); const char* pRichPresence = "Format:Num\nFormatType:Value\n\nDisplay:\n@Num(0xH01) @Num(d0xH01)\n"; @@ -1237,7 +1239,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); Assert::IsFalse(runtime.HasRichPresence()); runtime.ActivateRichPresence("Display:\nHello, World\n"); @@ -1258,7 +1260,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); const char* pRichPresence = "Format:Num\nFormatType:Value\n\nDisplay:\n@Num(0H01) @Num(d0xH01)\n"; runtime.ActivateRichPresence(pRichPresence); @@ -1272,7 +1274,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pAchievement = runtime.MockAchievement(6U, "0xH0000=1"); auto* vmAchievement = runtime.WrapAchievement(pAchievement); @@ -1315,7 +1317,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pAchievement = runtime.MockAchievement(4U, "1=1.3._R:0xH0000=1"); auto* vmAchievement = runtime.WrapAchievement(pAchievement); @@ -1361,7 +1363,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{ 0x00, 0x00 }; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pLeaderboard = runtime.MockLeaderboard(6U, "STA:0xH0000=0_0xH0000=9_R:0xH0001=1::SUB:0xH0000=1::CAN:0xH0000=2::VAL:0xH0000"); auto* vmLeaderboard = runtime.WrapLeaderboard(pLeaderboard); @@ -1407,7 +1409,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x00}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pLeaderboard = runtime.MockLeaderboard(6U, "STA:0xH0000=1::SUB:0xH0000=0_0xH0000=9_R:0xH0001=1::CAN:0xH0000=2::VAL:0xH0000"); auto* vmLeaderboard = runtime.WrapLeaderboard(pLeaderboard); @@ -1453,7 +1455,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x00}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pLeaderboard = runtime.MockLeaderboard(6U, "STA:0xH0000=1::SUB:0xH0000=2::CAN:0xH0000=0_0xH0000=9_R:0xH0001=1::VAL:0xH0000"); auto* vmLeaderboard = runtime.WrapLeaderboard(pLeaderboard); @@ -1499,7 +1501,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x00, 0x00}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pLeaderboard = runtime.MockLeaderboard(6U, "STA:0xH0000=0::SUB:0xH0000=2::CAN:0xH0000=3::VAL:R:0xH0001=1_M:0xH0002=0"); auto* vmLeaderboard = runtime.WrapLeaderboard(pLeaderboard); @@ -1549,7 +1551,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x00}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pLeaderboard = runtime.MockLeaderboard(6U, "STA:0xH0000=1::SUB:0xH0000=2::CAN:0xH0000=3::VAL:0xH0001"); auto* vmLeaderboard = runtime.WrapLeaderboard(pLeaderboard); @@ -1591,7 +1593,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x00}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pLeaderboard = runtime.MockLeaderboard(6U, "STA:0xH0000=1::SUB:0xH0000=2::CAN:0xH0000=3::VAL:0xH0001"); auto* vmLeaderboard = runtime.WrapLeaderboard(pLeaderboard); @@ -1638,7 +1640,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x00}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pLeaderboard = runtime.MockLeaderboard(6U, "STA:0xH0000=1::SUB:0xH0000=2::CAN:0xH0000=3::VAL:0xH0001"); auto* vmLeaderboard = runtime.WrapLeaderboard(pLeaderboard); @@ -1684,7 +1686,7 @@ TEST_CLASS(AchievementRuntime_Tests) std::array memory{0x00, 0x00}; AchievementRuntimeHarness runtime; - runtime.mockEmulatorContext.MockMemory(memory); + runtime.mockEmulatorMemoryContext.MockMemory(memory); auto* pAch6 = runtime.MockAchievement(6U, "0xH0004=1"); runtime.SyncToRuntime(); auto* vmAch6 = runtime.WrapAchievement(pAch6); @@ -2011,7 +2013,7 @@ TEST_CLASS(AchievementRuntime_Tests) auto* vmAch6 = runtime.WrapAchievement(pAch6); runtime.mockGameContext.SetRichPresenceDisplayString(L"Titles"); runtime.mockGameContext.Assets().FindRichPresence()->Activate(); - runtime.mockEmulatorContext.SetMemoryModified(); + runtime.mockEmulatorMemoryContext.SetMemoryModified(); runtime.mockConfiguration.SetPopupLocation(ra::ui::viewmodels::Popup::AchievementTriggered, ra::ui::viewmodels::PopupLocation::BottomLeft); @@ -2046,7 +2048,7 @@ TEST_CLASS(AchievementRuntime_Tests) runtime.GetClient()->state.hardcore = 1; runtime.mockGameContext.SetRichPresenceDisplayString(L"Titles"); runtime.mockGameContext.Assets().FindRichPresence()->Activate(); - runtime.mockEmulatorContext.MockMemoryInsecure(true); + runtime.mockEmulatorMemoryContext.MockMemoryInsecure(true); runtime.mockConfiguration.SetPopupLocation(ra::ui::viewmodels::Popup::AchievementTriggered, ra::ui::viewmodels::PopupLocation::BottomLeft); @@ -2083,7 +2085,7 @@ TEST_CLASS(AchievementRuntime_Tests) runtime.GetClient()->state.hardcore = 0; runtime.mockGameContext.SetRichPresenceDisplayString(L"Titles"); runtime.mockGameContext.Assets().FindRichPresence()->Activate(); - runtime.mockEmulatorContext.MockMemoryInsecure(true); + runtime.mockEmulatorMemoryContext.MockMemoryInsecure(true); runtime.mockConfiguration.SetPopupLocation(ra::ui::viewmodels::Popup::AchievementTriggered, ra::ui::viewmodels::PopupLocation::BottomLeft); @@ -2837,7 +2839,7 @@ TEST_CLASS(AchievementRuntime_Tests) auto* pLbd4 = runtime.MockLeaderboard(4U, "STA:0xH0000=1::CAN:0xH0000=1::SUB:0xH0000=2::VAL:0xH0001"); pLbd4->public_.tracker_value = "1:23.45"; runtime.WrapLeaderboard(pLbd4); - runtime.mockEmulatorContext.MockMemoryModified(true); + runtime.mockEmulatorMemoryContext.MockMemoryModified(true); runtime.mockConfiguration.SetFeatureEnabled(ra::services::Feature::Leaderboards, true); runtime.mockConfiguration.SetPopupLocation(ra::ui::viewmodels::Popup::LeaderboardScoreboard, ra::ui::viewmodels::PopupLocation::BottomRight); @@ -2898,7 +2900,7 @@ TEST_CLASS(AchievementRuntime_Tests) auto* pLbd4 = runtime.MockLeaderboard(4U, "STA:0xH0000=1::CAN:0xH0000=1::SUB:0xH0000=2::VAL:0xH0001"); pLbd4->public_.tracker_value = "1:23.45"; runtime.WrapLeaderboard(pLbd4); - runtime.mockEmulatorContext.MockMemoryInsecure(true); + runtime.mockEmulatorMemoryContext.MockMemoryInsecure(true); runtime.mockConfiguration.SetFeatureEnabled(ra::services::Feature::Leaderboards, true); runtime.mockConfiguration.SetPopupLocation(ra::ui::viewmodels::Popup::LeaderboardScoreboard, ra::ui::viewmodels::PopupLocation::BottomRight); diff --git a/tests/services/FileLocalStorage_Tests.cpp b/tests/services/FileLocalStorage_Tests.cpp index cf7f47ae2..cf394e1f3 100644 --- a/tests/services/FileLocalStorage_Tests.cpp +++ b/tests/services/FileLocalStorage_Tests.cpp @@ -1,7 +1,7 @@ #include "services\impl\FileLocalStorage.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" -#include "tests\mocks\MockClock.hh" #include "tests\RA_UnitTestHelpers.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; diff --git a/tests/services/FileLogger_Tests.cpp b/tests/services/FileLogger_Tests.cpp index 94df55b0a..1243bbf4e 100644 --- a/tests/services/FileLogger_Tests.cpp +++ b/tests/services/FileLogger_Tests.cpp @@ -1,7 +1,7 @@ #include "services\impl\FileLogger.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" -#include "tests\mocks\MockClock.hh" #include "tests\RA_UnitTestHelpers.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; diff --git a/tests/services/GameIdentifier_Tests.cpp b/tests/services/GameIdentifier_Tests.cpp index 1df0526a3..4d9b460b1 100644 --- a/tests/services/GameIdentifier_Tests.cpp +++ b/tests/services/GameIdentifier_Tests.cpp @@ -6,11 +6,12 @@ #include "tests\ui\UIAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" #include "tests\mocks\MockAudioSystem.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockEmulatorContext.hh" @@ -74,8 +75,9 @@ class GameIdentifierHarness : public GameIdentifier } ra::api::mocks::MockServer mockServer; - ra::context::mocks::MockRcClient mockRcClient; ra::context::mocks::MockConsoleContext mockConsoleContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + ra::context::mocks::MockRcClient mockRcClient; ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockSessionTracker mockSessionTracker; diff --git a/tests/services/SearchResults_Tests.cpp b/tests/services/SearchResults_Tests.cpp index 1b37dcb0d..18619ad27 100644 --- a/tests/services/SearchResults_Tests.cpp +++ b/tests/services/SearchResults_Tests.cpp @@ -1,7 +1,7 @@ #include "services\SearchResults.h" #include "tests\RA_UnitTestHelpers.h" -#include "tests\mocks\MockEmulatorContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -28,8 +28,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryEightBit) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -62,8 +62,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemorySixteenBit) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 3U, ra::services::SearchType::SixteenBit); @@ -90,8 +90,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryThirtyTwoBit) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 4U, ra::services::SearchType::ThirtyTwoBit); @@ -112,8 +112,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemorySixteenBitAligned) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, 4U, ra::services::SearchType::SixteenBitAligned); @@ -141,8 +141,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryThirtyTwoBitAligned) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD, 0x44, 0x20 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, 8U, ra::services::SearchType::ThirtyTwoBitAligned); @@ -173,8 +173,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemorySixteenBitBigEndian) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 3U, ra::services::SearchType::SixteenBitBigEndian); @@ -201,8 +201,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryThirtyTwoBitBigEndian) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 4U, ra::services::SearchType::ThirtyTwoBitBigEndian); @@ -223,8 +223,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemorySixteenBitBigEndianAligned) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, 4U, ra::services::SearchType::SixteenBitBigEndianAligned); @@ -252,8 +252,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryThirtyTwoBitBigEndianAligned) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD, 0x44, 0x20 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, 8U, ra::services::SearchType::ThirtyTwoBitBigEndianAligned); @@ -284,8 +284,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryNibble) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 3U, ra::services::SearchType::FourBit); @@ -334,8 +334,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemorySixteenBitBounded) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 8U, ra::services::SearchType::SixteenBit); @@ -368,8 +368,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitEqualsConstant) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -395,8 +395,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitEqualsInvalidConstant) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -414,8 +414,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitEqualsConstantGap) { std::array memory{ 0x00, 0x12, 0x00, 0x00, 0x56, 0x00 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 6U, ra::services::SearchType::EightBit); @@ -458,8 +458,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitNotEqualsConstant) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -490,8 +490,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitNotEqualsConstantGap) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -522,8 +522,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitGreaterThanConstant) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -549,8 +549,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitGreaterThanOrEqualConstant) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -581,8 +581,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitLessThanConstant) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -608,8 +608,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitLessThanOrEqualConstant) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -640,8 +640,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitEqualsConstantModified) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -670,8 +670,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitEqualsPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 5U, ra::services::SearchType::EightBit); @@ -727,8 +727,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitNotEqualsPrevious) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -766,10 +766,10 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitNotEqualsPreviousLargeData) { std::array memory{}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; for (unsigned int i = 0; i < memory.size(); ++i) GSL_SUPPRESS_BOUNDS4 memory[i] = (i % 256); - mockEmulatorContext.MockMemory(memory); + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 1024U, ra::services::SearchType::EightBit); @@ -821,8 +821,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitEqualsPreviousPlusTwo) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -855,8 +855,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitEqualsPreviousMinusTwo) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -889,8 +889,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsEightBitGreaterThanPreviousPlusTwo) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -918,8 +918,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsSixteenBitNotEqualPrevious) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 4U, ra::services::SearchType::SixteenBit); @@ -950,8 +950,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsThirtyTwoBitNotEqualPrevious) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 5U, ra::services::SearchType::ThirtyTwoBit); @@ -975,8 +975,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsSixteenBitAlignedNotEqualPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 4U, ra::services::SearchType::SixteenBitAligned); @@ -1019,8 +1019,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsThirtyTwoBitAlignedNotEqualPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD, 0x44, 0x20 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 8U, ra::services::SearchType::ThirtyTwoBitAligned); @@ -1066,8 +1066,8 @@ TEST_CLASS(SearchResults_Tests) auto memory = std::move(std::make_unique(BIG_BLOCK_SIZE)); for (unsigned int i = 0; i < BIG_BLOCK_SIZE; ++i) GSL_SUPPRESS_BOUNDS4 memory[i] = (i % 256); - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory.get(), BIG_BLOCK_SIZE); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory.get(), BIG_BLOCK_SIZE); SearchResults results; results.Initialize(0U, BIG_BLOCK_SIZE, ra::services::SearchType::ThirtyTwoBitAligned); @@ -1113,8 +1113,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsThirtyTwoBitAlignedOffset) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD, 0x44, 0x20, 0x11, 0x22, 0x33, 0x44 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(4U, 12U, ra::services::SearchType::ThirtyTwoBitAligned); @@ -1147,8 +1147,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsSixteenBitBigEndianNotEqualPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 4U, ra::services::SearchType::SixteenBitBigEndian); @@ -1179,8 +1179,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsThirtyTwoBitBigEndianNotEqualPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 5U, ra::services::SearchType::ThirtyTwoBitBigEndian); @@ -1204,8 +1204,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsThirtyTwoBitBigEndianLessThanPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 5U, ra::services::SearchType::ThirtyTwoBitBigEndian); @@ -1229,8 +1229,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsSixteenBitBigEndianAlignedNotEqualPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 4U, ra::services::SearchType::SixteenBitBigEndianAligned); @@ -1273,8 +1273,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsThirtyTwoBitBigEndianAlignedNotEqualPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0xCD, 0x44, 0x20 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 8U, ra::services::SearchType::ThirtyTwoBitBigEndianAligned); @@ -1317,8 +1317,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsFourBitNotEqualsPrevious) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::FourBit); @@ -1356,8 +1356,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsFourBitEqualsSameByte) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 3U, ra::services::SearchType::FourBit); @@ -1394,8 +1394,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsWithAddressLimits) { std::array memory{0x00, 0x12, 0x04, 0x16, 0x08}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 5U, ra::services::SearchType::EightBit); @@ -1433,8 +1433,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestExcludeAddressEightBit) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -1475,8 +1475,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestExcludeAddressFourBit) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::FourBit); @@ -1532,8 +1532,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestExcludeAddressSixteenBitAligned) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56, 0x88 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 5U, ra::services::SearchType::SixteenBitAligned); @@ -1576,8 +1576,8 @@ TEST_CLASS(SearchResults_Tests) auto memory = std::make_unique(BIG_BLOCK_SIZE); for (unsigned int i = 0; i < BIG_BLOCK_SIZE; ++i) GSL_SUPPRESS_BOUNDS4 memory[i] = (i % 256); - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory.get(), BIG_BLOCK_SIZE); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory.get(), BIG_BLOCK_SIZE); SearchResults results; results.Initialize(0U, BIG_BLOCK_SIZE, ra::services::SearchType::EightBit); @@ -1613,8 +1613,8 @@ TEST_CLASS(SearchResults_Tests) auto memory = std::make_unique(BIG_BLOCK_SIZE); for (unsigned int i = 0; i < BIG_BLOCK_SIZE; ++i) GSL_SUPPRESS_BOUNDS4 memory[i] = (i % 256); - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory.get(), BIG_BLOCK_SIZE); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory.get(), BIG_BLOCK_SIZE); SearchResults results; results.Initialize(0U, BIG_BLOCK_SIZE, ra::services::SearchType::SixteenBit); @@ -1648,8 +1648,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemorySixteenBitZeroBytes) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, 0U, ra::services::SearchType::SixteenBit); @@ -1664,8 +1664,8 @@ TEST_CLASS(SearchResults_Tests) 'l', 'l', 's', ' ', 'b', 'y', ' ', 't', 'h', 'e', ' ', 's', 'e', 'a', 's', 'h', 'o', 'r', 'e', '.' }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::AsciiText); @@ -1694,8 +1694,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryFloat) { std::array memory{ 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x46, 0x41 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Float); @@ -1726,8 +1726,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryFloatAligned) { std::array memory{ 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x46, 0x41 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::FloatAligned); @@ -1758,8 +1758,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryFloatBE) { std::array memory{ 0xC0, 0x00, 0x00, 0x00, 0x41, 0x46, 0x00, 0x00 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::FloatBigEndian); @@ -1790,8 +1790,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryFloatBEAligned) { std::array memory{ 0xC0, 0x00, 0x00, 0x00, 0x41, 0x46, 0x00, 0x00 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::FloatBigEndianAligned); @@ -1823,8 +1823,8 @@ TEST_CLASS(SearchResults_Tests) { std::array memory{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, // -2.0 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x28, 0x40}; // 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Double32); @@ -1858,8 +1858,8 @@ TEST_CLASS(SearchResults_Tests) { std::array memory{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, // -2.0 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x28, 0x40}; // 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Double32Aligned); @@ -1893,8 +1893,8 @@ TEST_CLASS(SearchResults_Tests) { std::array memory{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // -2.0 0x40, 0x28, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00}; // 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Double32BigEndian); @@ -1928,8 +1928,8 @@ TEST_CLASS(SearchResults_Tests) { std::array memory{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // -2.0 0x40, 0x28, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00}; // 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Double32BigEndianAligned); @@ -1962,8 +1962,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryMBF32) { std::array memory{ 0x87, 0x46, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00 }; // 99.0, -0.5 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::MBF32); @@ -1994,8 +1994,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryMBF32LE) { std::array memory{ 0x00, 0x00, 0x46, 0x87, 0x00, 0x00, 0x80, 0x80 }; // 99.0, -0.5 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::MBF32LE); @@ -2030,8 +2030,8 @@ TEST_CLASS(SearchResults_Tests) 'l', 'l', 's', ' ', 'b', 'y', ' ', 't', 'h', 'e', ' ', 's', 'e', 'a', 's', 'h', 'o', 'r', 'e', '.' }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, memory.size(), ra::services::SearchType::AsciiText); @@ -2078,8 +2078,8 @@ TEST_CLASS(SearchResults_Tests) 'l', 'l', 's', ' ', 'b', 'y', ' ', 't', 'h', 'e', ' ', 's', 'e', 'a', 's', 'h', 'o', 'r', 'e', '.' }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, memory.size(), ra::services::SearchType::AsciiText); @@ -2102,8 +2102,8 @@ TEST_CLASS(SearchResults_Tests) 'l', 'l', 's', ' ', 'b', 'y', ' ', 't', 'h', 'e', ' ', 's', 'e', 'a', 's', 'h', 'o', 'r', 'e', '.' }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, memory.size(), ra::services::SearchType::AsciiText); @@ -2173,8 +2173,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsFloatEqualsConstant) { std::array memory{ 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x46, 0x41 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Float); @@ -2195,8 +2195,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsFloatGreaterThanLast) { std::array memory{ 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x46, 0x41 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Float); @@ -2220,8 +2220,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsFloatAlignedGreaterThanLast) { std::array memory{ 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x46, 0x41 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::FloatAligned); @@ -2245,8 +2245,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsFloatBEGreaterThanLast) { std::array memory{ 0xC0, 0x00, 0x00, 0x00, 0x41, 0x46, 0x00, 0x00 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::FloatBigEndian); @@ -2271,8 +2271,8 @@ TEST_CLASS(SearchResults_Tests) { std::array memory{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, // -2.0 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x28, 0x40}; // 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Double32Aligned); @@ -2297,8 +2297,8 @@ TEST_CLASS(SearchResults_Tests) { std::array memory{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // -2.0 0x40, 0x28, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00}; // 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::Double32BigEndianAligned); @@ -2322,8 +2322,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsMBF32EqualsConstant) { std::array memory{ 0x87, 0x46, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00 }; // 99.0, -0.5 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::MBF32); @@ -2344,8 +2344,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsMBF32GreaterThanLast) { std::array memory{ 0x87, 0x46, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00 }; // 99.0, -0.5 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::MBF32); @@ -2368,8 +2368,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsMBF32LEEqualsConstant) { std::array memory{ 0x00, 0x00, 0x46, 0x87, 0x00, 0x00, 0x80, 0x80 }; // 99.0, -0.5 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::MBF32LE); @@ -2390,8 +2390,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsMBF32LEGreaterThanLast) { std::array memory{ 0x00, 0x00, 0x46, 0x87, 0x00, 0x00, 0x80, 0x80 }; // 99.0, -0.5 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(0U, memory.size(), ra::services::SearchType::MBF32LE); @@ -2414,8 +2414,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestCopyConstructor) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -2456,8 +2456,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestGetFormattedValueEightBit) { std::array memory{ 0x00, 0x02, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -2472,8 +2472,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestGetFormattedValueSixteenBit) { std::array memory{ 0x00, 0x02, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::SixteenBit); @@ -2488,8 +2488,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestGetFormattedValueFourBit) { std::array memory{ 0x00, 0x02, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(1U, 3U, ra::services::SearchType::FourBit); @@ -2510,8 +2510,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestGetFormattedValueFloat) { std::array memory{ 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x46, 0x41 }; // -2.0, 12.375 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 8U, ra::services::SearchType::Float); @@ -2526,8 +2526,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestGetFormattedValueMBF32) { std::array memory{ 0x87, 0x46, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00 }; // 99.0, -0.5 - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 8U, ra::services::SearchType::MBF32); @@ -2542,8 +2542,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestMatchesFilterEightBitGreaterThanLast) { std::array memory{ 6, 12, 18, 24, 30 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1, results2; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -2571,8 +2571,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestMatchesFilterEightBitGreaterThanLastPlus) { std::array memory{ 6, 12, 18, 24, 30 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1, results2; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -2600,8 +2600,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestMatchesFilterEightBitGreaterThanLastMinus) { std::array memory{ 6, 12, 18, 24, 30 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1, results2; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -2629,8 +2629,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestMatchesFilterEightBitGreaterThanConstant) { std::array memory{ 6, 12, 18, 24, 30 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1, results2; results1.Initialize(1U, 3U, ra::services::SearchType::EightBit); @@ -2649,8 +2649,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryAsciiEmpty) { - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - Assert::AreEqual({0U}, mockEmulatorContext.TotalMemorySize()); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + Assert::AreEqual({0U}, mockMemoryContext.TotalMemorySize()); SearchResults results; results.Initialize(0U, 16, ra::services::SearchType::AsciiText); @@ -2663,8 +2663,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromMemoryBitCount) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results; results.Initialize(1U, 3U, ra::services::SearchType::BitCount); @@ -2697,8 +2697,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsBitCountEqualsPrevious) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 5U, ra::services::SearchType::BitCount); @@ -2743,8 +2743,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromResultsBitCountEqualsPreviousPlusOne) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 5U, ra::services::SearchType::BitCount); @@ -2773,8 +2773,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestGetFormattedValueBitCount) { std::array memory{ 0x00, 0x12, 0x34, 0xAB, 0x56 }; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); SearchResults results1; results1.Initialize(0U, 8U, ra::services::SearchType::BitCount); @@ -2791,15 +2791,15 @@ TEST_CLASS(SearchResults_Tests) std::wstring sFormattedValue; SearchResult pResult; results1.GetMatchingAddress(3, pResult); - Assert::IsTrue(results1.UpdateValue(pResult, &sFormattedValue, mockEmulatorContext)); + Assert::IsTrue(results1.UpdateValue(pResult, &sFormattedValue, mockMemoryContext)); Assert::AreEqual(std::wstring(L"5 (00111011)"), sFormattedValue); } TEST_METHOD(TestInitializeFromListEightBit) { std::array memory{0x00, 0x12, 0x34, 0xAB, 0x56}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); std::vector vResults; vResults.push_back({2, 0x07, ra::data::Memory::Size::Unknown}); @@ -2831,8 +2831,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromListThirtyTwoBit) { std::array memory{}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); std::vector vResults; vResults.push_back({2, 0x12345678, ra::data::Memory::Size::Unknown}); @@ -2870,8 +2870,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromListThirtyTwoBitAligned) { std::array memory{}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); std::vector vResults; vResults.push_back({2, 0x12345678, ra::data::Memory::Size::Unknown}); // not aligned - should be ignored @@ -2904,8 +2904,8 @@ TEST_CLASS(SearchResults_Tests) TEST_METHOD(TestInitializeFromListThirtyTwoBitBigEndian) { std::array memory{}; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; - mockEmulatorContext.MockMemory(memory); + ra::context::mocks::MockEmulatorMemoryContext mockMemoryContext; + mockMemoryContext.MockMemory(memory); std::vector vResults; vResults.push_back({2, 0x12345678, ra::data::Memory::Size::Unknown}); diff --git a/tests/ui/viewmodels/AssetEditorViewModel_Tests.cpp b/tests/ui/viewmodels/AssetEditorViewModel_Tests.cpp index e3ad578a7..4c5e98cc4 100644 --- a/tests/ui/viewmodels/AssetEditorViewModel_Tests.cpp +++ b/tests/ui/viewmodels/AssetEditorViewModel_Tests.cpp @@ -11,12 +11,13 @@ #include "tests\data\DataAsserts.hh" #include "tests\ui\viewmodels\TriggerConditionAsserts.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockAchievementRuntime.hh" #include "tests\mocks\MockClipboard.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockEmulatorContext.hh" @@ -65,6 +66,7 @@ TEST_CLASS(AssetEditorViewModel_Tests) AssetEditorViewModelHarness(AssetEditorViewModelHarness&&) noexcept = delete; AssetEditorViewModelHarness& operator=(AssetEditorViewModelHarness&&) noexcept = delete; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; ra::services::mocks::MockAchievementRuntime mockRuntime; ra::services::mocks::MockClock mockClock; diff --git a/tests/ui/viewmodels/AssetListViewModel_Tests.cpp b/tests/ui/viewmodels/AssetListViewModel_Tests.cpp index eff493259..ecb0da28e 100644 --- a/tests/ui/viewmodels/AssetListViewModel_Tests.cpp +++ b/tests/ui/viewmodels/AssetListViewModel_Tests.cpp @@ -14,11 +14,12 @@ #include "tests\data\DataAsserts.hh" #include "tests\ui\UIAsserts.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockEmulatorContext.hh" @@ -160,6 +161,7 @@ TEST_CLASS(AssetListViewModel_Tests) class AssetListViewModelHarness : public AssetListViewModel { public: + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::context::mocks::MockRcClient mockRcClient; ra::services::mocks::MockAchievementRuntime mockRuntime; ra::services::mocks::MockClock mockClock; @@ -5489,17 +5491,17 @@ TEST_CLASS(AssetListViewModel_Tests) AssetListViewModelHarness vmAssetList; Assert::IsTrue(vmAssetList.IsProcessingActive()); Assert::IsFalse(vmAssetList.mockRuntime.IsPaused()); - Assert::IsFalse(vmAssetList.mockEmulatorContext.WasMemoryModified()); + Assert::IsFalse(vmAssetList.mockEmulatorMemoryContext.WasMemoryModified()); vmAssetList.SetProcessingActive(false); Assert::IsFalse(vmAssetList.IsProcessingActive()); Assert::IsTrue(vmAssetList.mockRuntime.IsPaused()); - Assert::IsTrue(vmAssetList.mockEmulatorContext.WasMemoryModified()); + Assert::IsTrue(vmAssetList.mockEmulatorMemoryContext.WasMemoryModified()); vmAssetList.SetProcessingActive(true); Assert::IsTrue(vmAssetList.IsProcessingActive()); Assert::IsFalse(vmAssetList.mockRuntime.IsPaused()); - Assert::IsTrue(vmAssetList.mockEmulatorContext.WasMemoryModified()); + Assert::IsTrue(vmAssetList.mockEmulatorMemoryContext.WasMemoryModified()); } TEST_METHOD(TestOpenEditorNonHardcore) diff --git a/tests/ui/viewmodels/CodeNotesViewModel_Tests.cpp b/tests/ui/viewmodels/CodeNotesViewModel_Tests.cpp index a17602a77..b9fab6060 100644 --- a/tests/ui/viewmodels/CodeNotesViewModel_Tests.cpp +++ b/tests/ui/viewmodels/CodeNotesViewModel_Tests.cpp @@ -7,11 +7,11 @@ #include "tests\ui\UIAsserts.hh" #include "tests\RA_UnitTestHelpers.h" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockLocalStorage.hh" #include "tests\mocks\MockServer.hh" @@ -33,7 +33,7 @@ TEST_CLASS(CodeNotesViewModel_Tests) public: ra::api::mocks::MockServer mockServer; ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; ra::services::mocks::MockConfiguration mockConfiguration; @@ -75,7 +75,7 @@ TEST_CLASS(CodeNotesViewModel_Tests) std::array memory = {}; for (uint8_t i = 0; i < memory.size(); ++i) memory.at(i) = i; - mockEmulatorContext.MockMemory(memory); + mockEmulatorMemoryContext.MockMemory(memory); } void PreparePublish() diff --git a/tests/ui/viewmodels/IntegrationMenuViewModel_Tests.cpp b/tests/ui/viewmodels/IntegrationMenuViewModel_Tests.cpp index 2dec8b356..40c9be02d 100644 --- a/tests/ui/viewmodels/IntegrationMenuViewModel_Tests.cpp +++ b/tests/ui/viewmodels/IntegrationMenuViewModel_Tests.cpp @@ -18,6 +18,7 @@ #include "tests\data\DataAsserts.hh" #include "tests\ui\UIAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" @@ -45,8 +46,9 @@ TEST_CLASS(IntegrationMenuViewModel_Tests) { public: ra::api::mocks::MockServer mockServer; - ra::context::mocks::MockRcClient mockRcClient; ra::context::mocks::MockConsoleContext mockConsoleContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; + ra::context::mocks::MockRcClient mockRcClient; ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; diff --git a/tests/ui/viewmodels/MemoryBookmarksViewModel_Tests.cpp b/tests/ui/viewmodels/MemoryBookmarksViewModel_Tests.cpp index bb64af75d..95ef719e2 100644 --- a/tests/ui/viewmodels/MemoryBookmarksViewModel_Tests.cpp +++ b/tests/ui/viewmodels/MemoryBookmarksViewModel_Tests.cpp @@ -7,13 +7,13 @@ #include "tests\ui\UIAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockAchievementRuntime.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockFrameEventQueue.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockLocalStorage.hh" @@ -60,8 +60,8 @@ TEST_CLASS(MemoryBookmarksViewModel_Tests) class MemoryBookmarksViewModelHarness : public MemoryBookmarksViewModel { public: + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorContext; ra::context::mocks::MockRcClient mockRcClient; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; ra::context::mocks::MockConsoleContext mockConsoleContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; diff --git a/tests/ui/viewmodels/MemoryInspectorViewModel_Tests.cpp b/tests/ui/viewmodels/MemoryInspectorViewModel_Tests.cpp index a8e2e5e52..49bf13036 100644 --- a/tests/ui/viewmodels/MemoryInspectorViewModel_Tests.cpp +++ b/tests/ui/viewmodels/MemoryInspectorViewModel_Tests.cpp @@ -9,13 +9,13 @@ #include "tests\RA_UnitTestHelpers.h" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockAchievementRuntime.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockLocalStorage.hh" #include "tests\mocks\MockUserContext.hh" @@ -38,7 +38,7 @@ TEST_CLASS(MemoryInspectorViewModel_Tests) ra::api::mocks::MockServer mockServer; ra::context::mocks::MockRcClient mockRcClient; ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; ra::services::mocks::MockConfiguration mockConfiguration; diff --git a/tests/ui/viewmodels/MemoryRegionsViewModel_Tests.cpp b/tests/ui/viewmodels/MemoryRegionsViewModel_Tests.cpp index 8212947d9..6b7d3719b 100644 --- a/tests/ui/viewmodels/MemoryRegionsViewModel_Tests.cpp +++ b/tests/ui/viewmodels/MemoryRegionsViewModel_Tests.cpp @@ -4,6 +4,7 @@ #include "ui\viewmodels\MemoryRegionsViewModel.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\ui\UIAsserts.hh" #include "tests\RA_UnitTestHelpers.h" #include "tests\mocks\MockConfiguration.hh" @@ -27,6 +28,7 @@ TEST_CLASS(MemoryRegionsViewModel_Tests) { public: ra::context::mocks::MockConsoleContext mockConsoleContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::services::mocks::MockConfiguration mockConfiguration; diff --git a/tests/ui/viewmodels/MemorySearchViewModel_Tests.cpp b/tests/ui/viewmodels/MemorySearchViewModel_Tests.cpp index 726351e31..ea3a826d2 100644 --- a/tests/ui/viewmodels/MemorySearchViewModel_Tests.cpp +++ b/tests/ui/viewmodels/MemorySearchViewModel_Tests.cpp @@ -7,12 +7,12 @@ #include "tests\ui\UIAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockUserContext.hh" #include "tests\mocks\MockWindowManager.hh" @@ -90,7 +90,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) } ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; ra::services::mocks::MockClock mockClock; @@ -106,7 +106,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) for (size_t i = 0; i < memory.size(); ++i) memory.at(i) = gsl::narrow_cast(i); - mockEmulatorContext.MockMemory(memory); + mockEmulatorMemoryContext.MockMemory(memory); } void InitializeAsciiMemory() @@ -119,7 +119,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) for (size_t i = 0; i < memory.size(); ++i) memory.at(i) = text.at(i); - mockEmulatorContext.MockMemory(memory); + mockEmulatorMemoryContext.MockMemory(memory); } bool CanBeginNewSearch() const { return GetValue(CanBeginNewSearchProperty); } @@ -1393,7 +1393,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) // only system range defined MemorySearchViewModelHarness search; search.mockConsoleContext.AddMemoryRegion(0U, 0xFFFFU, ra::data::MemoryRegion::Type::SystemRAM, L"System RAM"); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); Assert::AreEqual({ 2U }, search.PredefinedFilterRanges().Count()); Assert::AreEqual(0, search.PredefinedFilterRanges().GetItemAt(0)->GetId()); @@ -1408,7 +1408,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) MemorySearchViewModelHarness search; search.mockConsoleContext.AddMemoryRegion(0U, 0xBFFFU, ra::data::MemoryRegion::Type::SystemRAM, L"System RAM"); search.mockConsoleContext.AddMemoryRegion(0xE000U, 0xEFFFU, ra::data::MemoryRegion::Type::SaveRAM, L"Cartridge RAM"); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); Assert::AreEqual({ 4U }, search.PredefinedFilterRanges().Count()); Assert::AreEqual(0, search.PredefinedFilterRanges().GetItemAt(0)->GetId()); @@ -1429,7 +1429,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) search.mockConsoleContext.AddMemoryRegion(0x8000U, 0xBFFFU, ra::data::MemoryRegion::Type::SystemRAM, L"System RAM"); search.mockConsoleContext.AddMemoryRegion(0xE000U, 0xEFFFU, ra::data::MemoryRegion::Type::SaveRAM, L"Cartridge RAM"); search.mockConsoleContext.AddMemoryRegion(0xF000U, 0xFFFFU, ra::data::MemoryRegion::Type::SaveRAM, L"Cartridge RAM"); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); Assert::AreEqual({ 4U }, search.PredefinedFilterRanges().Count()); Assert::AreEqual(0, search.PredefinedFilterRanges().GetItemAt(0)->GetId()); @@ -1450,7 +1450,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) search.mockConsoleContext.AddMemoryRegion(0x8000U, 0xBFFFU, ra::data::MemoryRegion::Type::SystemRAM, L"System RAM 2"); search.mockConsoleContext.AddMemoryRegion(0xE000U, 0xEFFFU, ra::data::MemoryRegion::Type::SaveRAM, L"Cartridge RAM 1"); search.mockConsoleContext.AddMemoryRegion(0xF000U, 0xFFFFU, ra::data::MemoryRegion::Type::SaveRAM, L"Cartridge RAM 2"); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); Assert::AreEqual({ 8U }, search.PredefinedFilterRanges().Count()); Assert::AreEqual(0, search.PredefinedFilterRanges().GetItemAt(0)->GetId()); @@ -1491,7 +1491,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) search.mockConsoleContext.AddMemoryRegion(0xFF00U, 0xFF7FU, ra::data::MemoryRegion::Type::HardwareController, L"Hardware I/O"); search.mockConsoleContext.AddMemoryRegion(0xFF80U, 0xFFFEU, ra::data::MemoryRegion::Type::SystemRAM, L"Quick RAM"); search.mockConsoleContext.AddMemoryRegion(0xFFFFU, 0xFFFFU, ra::data::MemoryRegion::Type::HardwareController, L"Interrupt Enable"); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); Assert::AreEqual({ 6U }, search.PredefinedFilterRanges().Count()); Assert::AreEqual(0, search.PredefinedFilterRanges().GetItemAt(0)->GetId()); @@ -1513,7 +1513,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) MemorySearchViewModelHarness search; search.mockConsoleContext.AddMemoryRegion(0U, 0x7FFFU, ra::data::MemoryRegion::Type::SystemRAM); search.mockConsoleContext.AddMemoryRegion(0xC000U, 0xCFFFU, ra::data::MemoryRegion::Type::SaveRAM); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); search.SetFilterRange(L"0x0000-0x1FFF"); search.SetPredefinedFilterRange(0); @@ -1525,7 +1525,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) MemorySearchViewModelHarness search; search.mockConsoleContext.AddMemoryRegion(0U, 0x7FFFU, ra::data::MemoryRegion::Type::SystemRAM); search.mockConsoleContext.AddMemoryRegion(0xC000U, 0xCFFFU, ra::data::MemoryRegion::Type::SaveRAM); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); search.SetFilterRange(L"0x0000-0x1FFF"); search.SetPredefinedFilterRange(1); @@ -1537,7 +1537,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) MemorySearchViewModelHarness search; search.mockConsoleContext.AddMemoryRegion(0U, 0x7FFFU, ra::data::MemoryRegion::Type::SystemRAM); search.mockConsoleContext.AddMemoryRegion(0xC000U, 0xCFFFU, ra::data::MemoryRegion::Type::SaveRAM); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); search.SetFilterRange(L"0x0000-0x1FFF"); search.SetPredefinedFilterRange(2); @@ -1549,7 +1549,7 @@ TEST_CLASS(MemorySearchViewModel_Tests) MemorySearchViewModelHarness search; search.mockConsoleContext.AddMemoryRegion(0U, 0x7FFFU, ra::data::MemoryRegion::Type::SystemRAM); search.mockConsoleContext.AddMemoryRegion(0xC000U, 0xCFFFU, ra::data::MemoryRegion::Type::SaveRAM); - search.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000U); + search.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000U); search.SetFilterRange(L"0x0000-0x1FFF"); search.SetPredefinedFilterRange(0); diff --git a/tests/ui/viewmodels/MemoryViewerViewModel_Tests.cpp b/tests/ui/viewmodels/MemoryViewerViewModel_Tests.cpp index 65bc8d297..b3f769816 100644 --- a/tests/ui/viewmodels/MemoryViewerViewModel_Tests.cpp +++ b/tests/ui/viewmodels/MemoryViewerViewModel_Tests.cpp @@ -6,6 +6,7 @@ #include "tests\RA_UnitTestHelpers.h" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockGameContext.hh" @@ -34,7 +35,7 @@ TEST_CLASS(MemoryViewerViewModel_Tests) { public: ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::ui::viewmodels::mocks::MockWindowManager mockWindowManager; diff --git a/tests/ui/viewmodels/MemoryWatchListViewModel_Tests.cpp b/tests/ui/viewmodels/MemoryWatchListViewModel_Tests.cpp index b1ae67cfb..1bd7ac4f6 100644 --- a/tests/ui/viewmodels/MemoryWatchListViewModel_Tests.cpp +++ b/tests/ui/viewmodels/MemoryWatchListViewModel_Tests.cpp @@ -6,13 +6,13 @@ #include "tests\ui\UIAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockAchievementRuntime.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockFrameEventQueue.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockLocalStorage.hh" @@ -32,8 +32,8 @@ TEST_CLASS(MemoryWatchListViewModel_Tests) class MemoryWatchListViewModelHarness : public MemoryWatchListViewModel { public: + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorContext; ra::context::mocks::MockRcClient mockRcClient; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; ra::context::mocks::MockConsoleContext mockConsoleContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; diff --git a/tests/ui/viewmodels/OverlayAchievementsPageViewModel_Tests.cpp b/tests/ui/viewmodels/OverlayAchievementsPageViewModel_Tests.cpp index d59799290..71a0ab31e 100644 --- a/tests/ui/viewmodels/OverlayAchievementsPageViewModel_Tests.cpp +++ b/tests/ui/viewmodels/OverlayAchievementsPageViewModel_Tests.cpp @@ -3,9 +3,9 @@ #include "ui\viewmodels\OverlayAchievementsPageViewModel.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockImageRepository.hh" #include "tests\mocks\MockOverlayManager.hh" diff --git a/tests/ui/viewmodels/OverlayFriendsPageViewModel_Tests.cpp b/tests/ui/viewmodels/OverlayFriendsPageViewModel_Tests.cpp index c2e3b4219..ff18494e5 100644 --- a/tests/ui/viewmodels/OverlayFriendsPageViewModel_Tests.cpp +++ b/tests/ui/viewmodels/OverlayFriendsPageViewModel_Tests.cpp @@ -2,8 +2,8 @@ #include "ui\viewmodels\OverlayFriendsPageViewModel.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockImageRepository.hh" #include "tests\mocks\MockOverlayManager.hh" #include "tests\mocks\MockServer.hh" diff --git a/tests/ui/viewmodels/OverlayManager_Tests.cpp b/tests/ui/viewmodels/OverlayManager_Tests.cpp index 943d53661..06c65e656 100644 --- a/tests/ui/viewmodels/OverlayManager_Tests.cpp +++ b/tests/ui/viewmodels/OverlayManager_Tests.cpp @@ -5,9 +5,9 @@ #include "ui\OverlayTheme.hh" #include "tests\devkit\context\mocks\MockRcClient.hh" +#include "tests\devkit\services\mocks\MockClock.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\mocks\MockAchievementRuntime.hh" -#include "tests\mocks\MockClock.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockEmulatorContext.hh" diff --git a/tests/ui/viewmodels/PointerFinderViewModel_Tests.cpp b/tests/ui/viewmodels/PointerFinderViewModel_Tests.cpp index 18801dbb6..261e8b3a1 100644 --- a/tests/ui/viewmodels/PointerFinderViewModel_Tests.cpp +++ b/tests/ui/viewmodels/PointerFinderViewModel_Tests.cpp @@ -7,9 +7,9 @@ #include "tests\RA_UnitTestHelpers.h" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\services\mocks\MockFileSystem.hh" #include "tests\mocks\MockConfiguration.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockWindowManager.hh" @@ -27,7 +27,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) class PointerFinderViewModelHarness : public PointerFinderViewModel { public: - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::services::mocks::MockConfiguration mockConfiguration; ra::services::mocks::MockFileSystem mockFileSystem; @@ -102,7 +102,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) PointerFinderViewModelHarness vmPointerFinder; vmPointerFinder.mockGameContext.SetGameId(1U); std::array pMemory{}; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); bool bDialogSeen = false; vmPointerFinder.mockDesktop.ExpectWindow([&bDialogSeen](MessageBoxViewModel& vmMessageBox) { @@ -155,7 +155,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) { PointerFinderViewModelHarness vmPointerFinder; vmPointerFinder.mockGameContext.SetGameId(1U); - vmPointerFinder.mockEmulatorContext.MockTotalMemorySizeChanged(0x10000); + vmPointerFinder.mockEmulatorMemoryContext.MockTotalMemorySizeChanged(0x10000); for (auto& pState : vmPointerFinder.States()) { @@ -215,7 +215,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) PointerFinderViewModelHarness vmPointerFinder; vmPointerFinder.mockGameContext.SetGameId(1U); std::array pMemory{}; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); bool bDialogSeen = false; vmPointerFinder.mockDesktop.ExpectWindow([&bDialogSeen](MessageBoxViewModel& vmMessageBox) { @@ -240,7 +240,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) PointerFinderViewModelHarness vmPointerFinder; vmPointerFinder.mockGameContext.SetGameId(1U); std::array pMemory{}; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); bool bDialogSeen = false; vmPointerFinder.mockDesktop.ExpectWindow([&bDialogSeen](MessageBoxViewModel& vmMessageBox) { @@ -272,7 +272,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) pMemory.at(0x08) = 0x1c; pMemory.at(0x1c) = 0x55; pMemory.at(0x1d) = 0x46; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x1c"); vmPointerFinder.States().at(0).ToggleCapture(); @@ -301,7 +301,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) pMemory.at(0x08) = 0x1c; pMemory.at(0x1c) = 0x55; pMemory.at(0x1d) = 0x46; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x20"); vmPointerFinder.States().at(0).ToggleCapture(); @@ -330,7 +330,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) pMemory.at(0x08) = 0x1c; pMemory.at(0x1c) = 0x55; pMemory.at(0x1d) = 0x46; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x18"); vmPointerFinder.States().at(0).ToggleCapture(); @@ -361,7 +361,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) pMemory.at(0x1d) = 0x46; pMemory.at(0x70) = 0x1c; pMemory.at(0x9c) = 0x20; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x20"); vmPointerFinder.States().at(0).ToggleCapture(); @@ -395,7 +395,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) pMemory.at(0x70) = 0x1c; pMemory.at(0x9c) = 0x20; pMemory.at(0xa4) = 0x20; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x20"); vmPointerFinder.States().at(0).ToggleCapture(); @@ -432,7 +432,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) std::array pMemory{}; pMemory.at(0x08) = 0x1c; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x18"); vmPointerFinder.States().at(0).ToggleCapture(); @@ -468,7 +468,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) pMemory.at(0x08) = 0x1c; pMemory.at(0x70) = 0x1c; pMemory.at(0x9c) = 0x20; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x20"); vmPointerFinder.States().at(0).ToggleCapture(); @@ -509,7 +509,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) pMemory.at(0x08) = 0x1c; pMemory.at(0x70) = 0x1c; pMemory.at(0x9c) = 0x20; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x20"); vmPointerFinder.States().at(0).ToggleCapture(); @@ -562,7 +562,7 @@ TEST_CLASS(PointerFinderViewModel_Tests) pMemory.at(0x08) = 0x1c; pMemory.at(0x70) = 0x1c; pMemory.at(0x9c) = 0x20; - vmPointerFinder.mockEmulatorContext.MockMemory(pMemory); + vmPointerFinder.mockEmulatorMemoryContext.MockMemory(pMemory); vmPointerFinder.States().at(0).SetAddress(L"0x20"); vmPointerFinder.States().at(0).ToggleCapture(); diff --git a/tests/ui/viewmodels/PointerInspectorViewModel_Tests.cpp b/tests/ui/viewmodels/PointerInspectorViewModel_Tests.cpp index 561fc3378..d9002b8d0 100644 --- a/tests/ui/viewmodels/PointerInspectorViewModel_Tests.cpp +++ b/tests/ui/viewmodels/PointerInspectorViewModel_Tests.cpp @@ -9,12 +9,12 @@ #include "tests\RA_UnitTestHelpers.h" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\services\mocks\MockThreadPool.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockClipboard.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockLocalStorage.hh" #include "tests\mocks\MockUserContext.hh" @@ -35,9 +35,9 @@ TEST_CLASS(PointerInspectorViewModel_Tests) { public: ra::context::mocks::MockConsoleContext mockConsoleContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; ra::services::mocks::MockClipboard mockClipboard; ra::services::mocks::MockLocalStorage mockLocalStorage; diff --git a/tests/ui/viewmodels/TriggerConditionViewModel_Tests.cpp b/tests/ui/viewmodels/TriggerConditionViewModel_Tests.cpp index 458823778..cdc5807a5 100644 --- a/tests/ui/viewmodels/TriggerConditionViewModel_Tests.cpp +++ b/tests/ui/viewmodels/TriggerConditionViewModel_Tests.cpp @@ -8,9 +8,9 @@ #include "tests\RA_UnitTestHelpers.h" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\devkit\testutil\MemoryAsserts.hh" #include "tests\mocks\MockConfiguration.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockGameContext.hh" #include "tests\mocks\MockUserContext.hh" #include "tests\ui\viewmodels\TriggerConditionAsserts.hh" @@ -760,14 +760,14 @@ TEST_CLASS(TriggerConditionViewModel_Tests) class IndirectAddressTriggerViewModelHarness : public TriggerViewModel { public: - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; ra::services::mocks::MockConfiguration mockConfiguration; void Parse(const std::string& sInput) { - mockEmulatorContext.MockMemory(m_pMemory); + mockEmulatorMemoryContext.MockMemory(m_pMemory); ra::data::models::CapturedTriggerHits pCapturedHits; InitializeFrom(sInput, pCapturedHits); @@ -1475,9 +1475,9 @@ TEST_CLASS(TriggerConditionViewModel_Tests) // ... ... // Parse registers the default memory. Replace it with specific values - vmTrigger.mockEmulatorContext.MockMemoryValue(0x001234, 0xa05bb680); - vmTrigger.mockEmulatorContext.MockMemoryValue(0x002222, 0x00c0d6ac); - vmTrigger.mockEmulatorContext.MockMemoryValue(0xb65ba8, 0xc02e3980); + vmTrigger.mockEmulatorMemoryContext.MockMemoryValue(0x001234, 0xa05bb680); + vmTrigger.mockEmulatorMemoryContext.MockMemoryValue(0x002222, 0x00c0d6ac); + vmTrigger.mockEmulatorMemoryContext.MockMemoryValue(0xb65ba8, 0xc02e3980); auto* pTrigger = vmTrigger.GetTriggerFromString(); auto* pMemrefs = rc_trigger_get_memrefs(pTrigger); diff --git a/tests/ui/viewmodels/TriggerViewModel_Tests.cpp b/tests/ui/viewmodels/TriggerViewModel_Tests.cpp index bd9934a04..04da9d768 100644 --- a/tests/ui/viewmodels/TriggerViewModel_Tests.cpp +++ b/tests/ui/viewmodels/TriggerViewModel_Tests.cpp @@ -4,11 +4,11 @@ #include "tests\ui\UIAsserts.hh" #include "tests\devkit\context\mocks\MockConsoleContext.hh" +#include "tests\devkit\context\mocks\MockEmulatorMemoryContext.hh" #include "tests\mocks\MockClipboard.hh" #include "tests\mocks\MockConfiguration.hh" #include "tests\mocks\MockDesktop.hh" #include "tests\mocks\MockGameContext.hh" -#include "tests\mocks\MockEmulatorContext.hh" #include "tests\mocks\MockImageRepository.hh" #include "tests\mocks\MockUserContext.hh" #include "tests\mocks\MockWindowManager.hh" @@ -27,7 +27,7 @@ TEST_CLASS(TriggerViewModel_Tests) { public: ra::context::mocks::MockConsoleContext mockConsoleContext; - ra::data::context::mocks::MockEmulatorContext mockEmulatorContext; + ra::context::mocks::MockEmulatorMemoryContext mockEmulatorMemoryContext; ra::data::context::mocks::MockGameContext mockGameContext; ra::data::context::mocks::MockUserContext mockUserContext; ra::services::mocks::MockClipboard mockClipboard; @@ -40,7 +40,7 @@ TEST_CLASS(TriggerViewModel_Tests) { // make sure to hook up the memory inspector first or we won't be able to set an address mockWindowManager.MemoryInspector.Viewer().InitializeNotifyTargets(); - mockEmulatorContext.MockMemory(pMemory, nMemorySize); + mockEmulatorMemoryContext.MockMemory(pMemory, nMemorySize); } const std::set& GetSelectedItems() const noexcept