Skip to content

Commit

Permalink
Adding "msan"-like feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasnoble committed Feb 15, 2025
1 parent fe5a246 commit 1359143
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/core/debug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ uint32_t PCSX::Debug::normalizeAddress(uint32_t address) {

bool PCSX::Debug::isInKernel(uint32_t address, bool biosIsKernel) {
PSXAddress addr(address);
if (addr.type == PSXAddress::Type::MSAN) return false;
const bool ramExpansion = PCSX::g_emulator->settings.get<PCSX::Emulator::Setting8MB>();
if (addr.type == PSXAddress::Type::ROM) return biosIsKernel;
if (addr.type != PSXAddress::Type::RAM) return false;
Expand Down
20 changes: 18 additions & 2 deletions src/core/psxhw.cc
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,17 @@ uint32_t PCSX::HW::read32(uint32_t add) {
case 0x1f802080:
hard = 0x58534350;
break;

case 0x1f80208c: {
uint32_t size = g_emulator->m_cpu->m_regs.GPR.n.a0;
hard = g_emulator->m_mem->msanAlloc(size);
break;
}
case 0x1f802090: {
uint32_t ptr = g_emulator->m_cpu->m_regs.GPR.n.a0;
uint32_t size = g_emulator->m_cpu->m_regs.GPR.n.a1;
hard = g_emulator->m_mem->msanRealloc(ptr, size);
break;
}

Check warning on line 373 in src/core/psxhw.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::HW::read32 increases in cyclomatic complexity from 24 to 26, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
default: {
uint32_t *ptr = (uint32_t *)&g_emulator->m_mem->m_hard[hwadd & 0xffff];
hard = SWAP_LEu32(*ptr);
Expand Down Expand Up @@ -445,7 +455,9 @@ void PCSX::HW::write8(uint32_t add, uint32_t rawvalue) {
case 0x1f802088:
g_emulator->m_debug->m_checkKernel = value;
break;

case 0x1f802089:
g_emulator->m_mem->initMsan(value);
break;

Check warning on line 460 in src/core/psxhw.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::HW::write8 increases in cyclomatic complexity from 23 to 24, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
default:
if (addressInRegisterSpace(hwadd)) {
uint32_t *ptr = (uint32_t *)&g_emulator->m_mem->m_hard[hwadd & 0xffff];
Expand Down Expand Up @@ -789,6 +801,10 @@ void PCSX::HW::write32(uint32_t add, uint32_t value) {
g_system->message("%s", memFile->gets<false>());
break;
}
case 0x1f80208c: {
g_emulator->m_mem->msanFree(value);
break;
}

Check warning on line 807 in src/core/psxhw.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::HW::write32 increases in cyclomatic complexity from 48 to 49, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
default: {
if ((hwadd >= 0x1f801c00) && (hwadd < 0x1f801e00)) {
write16(add, value & 0xffff);
Expand Down
223 changes: 221 additions & 2 deletions src/core/psxmem.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ static const std::map<uint32_t, std::string_view> s_knownBioses = {
#endif
};

PCSX::Memory::Memory() : m_listener(g_system->m_eventBus) {
m_listener.listen<Events::ExecutionFlow::Reset>([this](auto &) {
free(m_msanRAM);
free(m_msanBitmap);
free(m_msanWrittenBitmap);
m_msanRAM = nullptr;
m_msanBitmap = nullptr;
m_msanWrittenBitmap = nullptr;
m_msanAllocs.clear();
});
}

int PCSX::Memory::init() {
m_readLUT = (uint8_t **)calloc(0x10000, sizeof(void *));
m_writeLUT = (uint8_t **)calloc(0x10000, sizeof(void *));
Expand Down Expand Up @@ -140,7 +152,7 @@ bool PCSX::Memory::loadEXP1FromFile(std::filesystem::path rom_path) {
memset(m_exp1, 0xff, exp1_size);
f->read(m_exp1, rom_size);
f->close();
PCSX::g_system->printf(_("Loaded %i bytes to EXP1 from file: %s\n"), rom_size, exp1Path.string());
g_system->printf(_("Loaded %i bytes to EXP1 from file: %s\n"), rom_size, exp1Path.string());
result = true;
}
} else {
Expand Down Expand Up @@ -222,7 +234,7 @@ The distributed OpenBIOS.bin file can be an appropriate BIOS replacement.
f->read(m_bios, bios_size);
}
f->close();
PCSX::g_system->printf(_("Loaded BIOS: %s\n"), biosPath.string());
g_system->printf(_("Loaded BIOS: %s\n"), biosPath.string());
}
}

Expand Down Expand Up @@ -250,6 +262,14 @@ void PCSX::Memory::shutdown() {

free(m_readLUT);
free(m_writeLUT);

free(m_msanRAM);
free(m_msanBitmap);
free(m_msanWrittenBitmap);
m_msanRAM = nullptr;
m_msanBitmap = nullptr;
m_msanWrittenBitmap = nullptr;
m_msanAllocs.clear();
}

uint8_t PCSX::Memory::read8(uint32_t address) {
Expand All @@ -261,6 +281,20 @@ uint8_t PCSX::Memory::read8(uint32_t address) {
if (pointer != nullptr) {
const uint32_t offset = address & 0xffff;
return *(pointer + offset);
} else if (msanInitialized() && (address >= 0x20000000) && (address < (0x20000000 + c_msanSize))) {
uint32_t msanAddress = address - 0x20000000;
if ((m_msanWrittenBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) == 0) {
g_system->log(LogClass::CPU, _("8-bit read from usable but uninitialized msan memory: %8.8lx\n"), address);
g_system->pause();
return 0;
}
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
return m_msanRAM[msanAddress];
} else {
g_system->log(LogClass::CPU, _("8-bit read from unsable msan memory: %8.8lx\n"), address);
g_system->pause();
return 0;
}

Check warning on line 297 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::Memory::read8 increases in cyclomatic complexity from 14 to 19, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 297 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Conditional

PCSX::Memory::read8 increases from 2 complex conditionals with 4 branches to 3 complex conditionals with 6 branches, threshold = 2. A complex conditional is an expression inside a branch (e.g. if, for, while) which consists of multiple, logical operators such as AND/OR. The more logical operators in an expression, the more severe the code smell.
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
if ((address & 0xffff) < 0x400) {
return m_hard[address & 0x3ff];
Expand Down Expand Up @@ -296,6 +330,23 @@ uint16_t PCSX::Memory::read16(uint32_t address) {
if (pointer != nullptr) {
const uint32_t offset = address & 0xffff;
return SWAP_LEu16(*(uint16_t *)(pointer + offset));
} else if (msanInitialized() && (address >= 0x20000000) && (address < (0x20000000 + c_msanSize))) {
uint32_t msanAddress = address - 0x20000000;
for (unsigned offset = 0; offset < 2; offset++) {
if ((m_msanWrittenBitmap[(msanAddress + offset) / 8] & (1 << ((msanAddress + offset) % 8))) == 0) {
g_system->log(LogClass::CPU, _("16-bit read from usable but uninitialized msan memory: %8.8lx\n"),
address);
g_system->pause();
return 0;
}
}
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
return *(uint16_t *)&m_msanRAM[msanAddress];
} else {
g_system->log(LogClass::CPU, _("16-bit read from unsable msan memory: %8.8lx\n"), address);
g_system->pause();
return 0;
}

Check warning on line 349 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::Memory::read16 increases in cyclomatic complexity from 12 to 18, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 349 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Conditional

PCSX::Memory::read16 increases from 2 complex conditionals with 4 branches to 3 complex conditionals with 6 branches, threshold = 2. A complex conditional is an expression inside a branch (e.g. if, for, while) which consists of multiple, logical operators such as AND/OR. The more logical operators in an expression, the more severe the code smell.
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
if ((address & 0xffff) < 0x400) {
uint16_t *ptr = (uint16_t *)&m_hard[address & 0x3ff];
Expand Down Expand Up @@ -328,6 +379,23 @@ uint32_t PCSX::Memory::read32(uint32_t address, ReadType readType) {
if (pointer != nullptr) {
const uint32_t offset = address & 0xffff;
return SWAP_LEu32(*(uint32_t *)(pointer + offset));
} else if (msanInitialized() && (address >= 0x20000000) && (address < (0x20000000 + c_msanSize))) {
uint32_t msanAddress = address - 0x20000000;
for (unsigned offset = 0; offset < 4; offset++) {
if ((m_msanWrittenBitmap[(msanAddress + offset) / 8] & (1 << ((msanAddress + offset) % 8))) == 0) {
g_system->log(LogClass::CPU, _("32-bit read from usable but uninitialized msan memory: %8.8lx\n"),
address);
g_system->pause();
return 0;
}
}
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
return *(uint32_t *)&m_msanRAM[msanAddress];
} else {
g_system->log(LogClass::CPU, _("32-bit read from unsable msan memory: %8.8lx\n"), address);
g_system->pause();
return 0;
}

Check warning on line 398 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::Memory::read32 increases in cyclomatic complexity from 14 to 20, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 398 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Conditional

PCSX::Memory::read32 increases from 2 complex conditionals with 4 branches to 3 complex conditionals with 6 branches, threshold = 2. A complex conditional is an expression inside a branch (e.g. if, for, while) which consists of multiple, logical operators such as AND/OR. The more logical operators in an expression, the more severe the code smell.
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
if ((address & 0xffff) < 0x400) {
uint32_t *ptr = (uint32_t *)&m_hard[address & 0x3ff];
Expand Down Expand Up @@ -437,6 +505,15 @@ void PCSX::Memory::write8(uint32_t address, uint32_t value) {
const uint32_t offset = address & 0xffff;
*(pointer + offset) = static_cast<uint8_t>(value);
g_emulator->m_cpu->Clear((address & (~3)), 1);
} else if (msanInitialized() && (address >= 0x20000000) && (address < (0x20000000 + c_msanSize))) {
uint32_t msanAddress = address - 0x20000000;
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
m_msanWrittenBitmap[msanAddress / 8] |= (1 << (msanAddress % 8));
m_msanRAM[msanAddress] = value;
} else {
g_system->log(LogClass::CPU, _("8-bit write to unsable msan memory: %8.8lx\n"), address);
g_system->pause();
}

Check warning on line 516 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::Memory::write8 increases in cyclomatic complexity from 12 to 16, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 516 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Conditional

PCSX::Memory::write8 increases from 2 complex conditionals with 4 branches to 3 complex conditionals with 6 branches, threshold = 2. A complex conditional is an expression inside a branch (e.g. if, for, while) which consists of multiple, logical operators such as AND/OR. The more logical operators in an expression, the more severe the code smell.
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
if ((address & 0xffff) < 0x400) {
m_hard[address & 0x3ff] = value;
Expand Down Expand Up @@ -465,6 +542,17 @@ void PCSX::Memory::write16(uint32_t address, uint32_t value) {
const uint32_t offset = address & 0xffff;
*(uint16_t *)(pointer + offset) = SWAP_LEu16(static_cast<uint16_t>(value));
g_emulator->m_cpu->Clear((address & (~3)), 1);
} else if (msanInitialized() && (address >= 0x20000000) && (address < (0x20000000 + c_msanSize))) {
uint32_t msanAddress = address - 0x20000000;
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
for (unsigned offset = 0; offset < 2; offset++) {
m_msanWrittenBitmap[(msanAddress + offset) / 8] |= (1 << ((msanAddress + offset) % 8));
}
*(uint16_t *)&m_msanRAM[msanAddress] = value;
} else {
g_system->log(LogClass::CPU, _("16-bit write to unsable msan memory: %8.8lx\n"), address);
g_system->pause();
}

Check warning on line 555 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::Memory::write16 increases in cyclomatic complexity from 12 to 17, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 555 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Conditional

PCSX::Memory::write16 increases from 2 complex conditionals with 4 branches to 3 complex conditionals with 6 branches, threshold = 2. A complex conditional is an expression inside a branch (e.g. if, for, while) which consists of multiple, logical operators such as AND/OR. The more logical operators in an expression, the more severe the code smell.
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
if ((address & 0xffff) < 0x400) {
uint16_t *ptr = (uint16_t *)&m_hard[address & 0x3ff];
Expand Down Expand Up @@ -494,6 +582,17 @@ void PCSX::Memory::write32(uint32_t address, uint32_t value) {
const uint32_t offset = address & 0xffff;
*(uint32_t *)(pointer + offset) = SWAP_LEu32(value);
g_emulator->m_cpu->Clear((address & (~3)), 1);
} else if (msanInitialized() && (address >= 0x20000000) && (address < (0x20000000 + c_msanSize))) {
uint32_t msanAddress = address - 0x20000000;
if (m_msanBitmap[msanAddress / 8] & (1 << (msanAddress % 8))) {
for (unsigned offset = 0; offset < 4; offset++) {
m_msanWrittenBitmap[(msanAddress + offset) / 8] |= (1 << ((msanAddress + offset) % 8));
}
*(uint32_t *)&m_msanRAM[msanAddress] = value;
} else {
g_system->log(LogClass::CPU, _("32-bit write to unsable msan memory: %8.8lx\n"), address);
g_system->pause();
}

Check warning on line 595 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

PCSX::Memory::write32 increases in cyclomatic complexity from 19 to 24, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 595 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Conditional

PCSX::Memory::write32 increases from 2 complex conditionals with 4 branches to 3 complex conditionals with 6 branches, threshold = 2. A complex conditional is an expression inside a branch (e.g. if, for, while) which consists of multiple, logical operators such as AND/OR. The more logical operators in an expression, the more severe the code smell.
} else if (page == 0x1f80 || page == 0x9f80 || page == 0xbf80) {
if ((address & 0xffff) < 0x400) {
uint32_t *ptr = (uint32_t *)&m_hard[address & 0x3ff];
Expand Down Expand Up @@ -717,3 +816,123 @@ void PCSX::Memory::MemoryAsFile::writeBlock(const void *src, size_t size, size_t
auto toCopy = std::min(size, c_blockSize - offset);
memcpy(block + offset, src, toCopy);
}

void PCSX::Memory::initMsan(bool reset) {
if (reset) {
free(m_msanRAM);
free(m_msanBitmap);
free(m_msanWrittenBitmap);
m_msanRAM = nullptr;
m_msanBitmap = nullptr;
m_msanWrittenBitmap = nullptr;
m_msanAllocs.clear();
}
if (msanInitialized()) {
g_system->printf(_("MSAN system was already initialized.\n"));
g_system->pause();
return;
}

// 1.5GB of RAM, with 384MB worth of bitmap, between 0x20000000 and 0x80000000
m_msanRAM = (uint8_t *)calloc(c_msanSize, 1);
m_msanBitmap = (uint8_t *)calloc(c_msanSize / 8, 1);
m_msanWrittenBitmap = (uint8_t *)calloc(c_msanSize / 8, 1);
m_msanPtr = 1024;
}

uint32_t PCSX::Memory::msanAlloc(uint32_t size) {
// Allocate 1kB more than requested, to redzone the allocation.
// This is to detect out-of-bounds accesses.
uint32_t actualSize = size + 1 * 1024;
// Then round up to the next 16-byte boundary.
actualSize = actualSize + 15 & ~15;

// Check if we still have enough memory.
if (m_msanPtr + actualSize > c_msanSize) {
g_system->printf(_("Out of memory in MsanAlloc\n"));
g_system->pause();
return 0;
}

// Allocate the memory.
uint32_t ptr = m_msanPtr;
m_msanPtr += actualSize;
// Mark the allocation as usable.
for (uint32_t i = 0; i < size; i++) {
m_msanBitmap[(ptr + i) / 8] |= 1 << ((ptr + i) % 8);
}

// Insert the allocation into the list of allocations.
m_msanAllocs.insert({ptr, size});
return ptr + 0x20000000;
}

void PCSX::Memory::msanFree(uint32_t ptr) {
if (ptr == 0) {
return;
}
// Check if the pointer is valid.
if (ptr < 0x20000000 || ptr >= 0x20000000 + c_msanSize) {
g_system->printf(_("Invalid pointer passed to MsanFree: %08x\n"), ptr);
g_system->pause();
return;
}
ptr -= 0x20000000;
auto it = m_msanAllocs.find(ptr);
if (it == m_msanAllocs.end()) {
g_system->printf(_("Invalid pointer passed to MsanFree: %08x\n"), ptr);
g_system->pause();
return;
}
// Mark the allocation as unusable.
for (uint32_t i = 0; i < m_msanAllocs[ptr]; i++) {
m_msanBitmap[(ptr + i) / 8] &= ~(1 << ((ptr + i) % 8));
}
// Remove the allocation from the list of allocations.
m_msanAllocs.erase(ptr);
}

uint32_t PCSX::Memory::msanRealloc(uint32_t ptr, uint32_t size) {
if (ptr == 0) {
return msanAlloc(size);
}
if (size == 0) {
msanFree(ptr);
return 0;
}
// Check if the pointer is valid.
if (ptr < 0x20000000 || ptr >= 0x20000000 + c_msanSize) {
g_system->printf(_("Invalid pointer passed to MsanRealloc: %08x\n"), ptr);
g_system->pause();
return 0;
}
ptr -= 0x20000000;
auto it = m_msanAllocs.find(ptr);
if (it == m_msanAllocs.end()) {
g_system->printf(_("Invalid pointer passed to MsanRealloc: %08x\n"), ptr);
g_system->pause();
return 0;
}
auto oldSize = it->second;

// Allocate new memory.
uint32_t newPtr = msanAlloc(size);
if (!newPtr) return 0;
newPtr -= 0x20000000;

// Copy the old memory to the new memory.
memcpy(m_msanRAM + newPtr, m_msanRAM + ptr, std::min(size, oldSize));

// Mark the old allocation as unusable
for (uint32_t i = 0; i < oldSize; i++) {
m_msanBitmap[(ptr + i) / 8] &= ~(1 << ((ptr + i) % 8));
}
// Mark the new allocation as written to
auto toCopy = std::min(size, oldSize);
for (uint32_t i = 0; i < toCopy; i++) {
m_msanWrittenBitmap[(newPtr + i) / 8] |= 1 << ((newPtr + i) % 8);
}
// Remove the allocation from the list of allocations.
m_msanAllocs.erase(ptr);
return newPtr + 0x20000000;
}

Check warning on line 938 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Complex Method

PCSX::Memory::msanRealloc has a cyclomatic complexity of 9, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
18 changes: 18 additions & 0 deletions src/core/psxmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
#pragma once

#include <string_view>
#include <unordered_map>
#include <vector>

#include "core/psxemulator.h"
#include "support/eventbus.h"
#include "support/polyfills.h"
#include "support/sharedmem.h"

Expand All @@ -47,6 +49,7 @@ namespace PCSX {

class Memory {
public:
Memory();
int init();
void reset();
void shutdown();
Expand Down Expand Up @@ -74,6 +77,12 @@ class Memory {
static constexpr uint16_t DMA_PCR = 0x10f0;
static constexpr uint16_t DMA_ICR = 0x10f4;

void initMsan(bool reset);
bool msanInitialized() { return m_msanRAM != nullptr; }
uint32_t msanAlloc(uint32_t size);
void msanFree(uint32_t ptr);
uint32_t msanRealloc(uint32_t ptr, uint32_t size);

template <unsigned n>
void dmaInterrupt() {
uint32_t icr = readHardwareRegister<DMA_ICR>();
Expand Down Expand Up @@ -249,6 +258,15 @@ class Memory {
uint8_t **m_writeLUT = nullptr;
uint8_t **m_readLUT = nullptr;

static constexpr uint32_t c_msanSize = 1'610'612'736;
uint8_t *m_msanRAM = nullptr;
uint8_t *m_msanBitmap = nullptr;
uint8_t *m_msanWrittenBitmap = nullptr;
uint32_t m_msanPtr = 1024;
EventBus::Listener m_listener;

std::unordered_map<uint32_t, uint32_t> m_msanAllocs;

template <typename T = void>
T *getPointer(uint32_t address) {
auto lut = m_readLUT[address >> 16];
Expand Down
Loading

0 comments on commit 1359143

Please sign in to comment.