Browse Source

WIP: Memory remapping support.

* Block insertion not yet implemented.
    * Block unassignment partially implemented. Currently only entire blocks
      can be removed.
    * Test code included.
master
Ian Burgmyer 4 years ago
parent
commit
969df74d33
  1. 69
      libplip/PlipMemoryMap.cpp
  2. 12
      libplip/PlipMemoryMap.h
  3. 27
      plip-sdl/main.cpp

69
libplip/PlipMemoryMap.cpp

@ -28,8 +28,16 @@ namespace Plip {
});
}
void PlipMemoryMap::AssignBlock(PlipMemory *memory, uint32_t address, uint32_t offset, uint32_t length) {
UnassignBlock(address, length);
AssignBlockDirect(memory, address, offset, length);
}
void PlipMemoryMap::AssignBlockDirect(PlipMemory *memory, uint32_t address, uint32_t offset, uint32_t length) {
// TODO: Search for the appropriate spot and insert an entry.
}
std::tuple<PlipMemory*, uint32_t> PlipMemoryMap::FindAddress(uint32_t address) {
printf("Finding memory address: 0x%.8X\n", address);
for(auto const &memory : m_range) {
if(address < memory.startAddress || address > memory.startAddress + memory.length - 1)
continue;
@ -54,10 +62,69 @@ namespace Plip {
return last.startAddress + last.length;
}
PlipMemoryMap::BlockRangeResult PlipMemoryMap::IsBlockInRange(
const PlipMemoryMapRange &block, uint32_t startAddress, uint32_t endAddress) {
auto blockEnd = block.startAddress + block.length - 1;
if(block.startAddress >= startAddress && blockEnd <= endAddress)
return CompletelyInRange;
else if(block.startAddress > endAddress || blockEnd < startAddress)
return NotInRange;
return PartiallyInRange;
}
void PlipMemoryMap::SetByte(uint32_t address, uint8_t value) {
auto [ memory, offset ] = FindAddress(address);
if(memory == nullptr) return;
memory->SetByte(offset, value);
}
void PlipMemoryMap::UnassignBlock(uint32_t address, uint32_t length) {
/* This function must handle the following cases:
*
* 1. Handle empty, unmapped areas of memory.
* 2. Remove blocks entirely if necessary.
* 3. Adjust offsets/lengths for clipped blocks.
* 4. Potentially handle multiple blocks at once.
* 5. Split blocks in half if necessary.
*/
auto endAddress = address + length - 1; // end address
auto it = m_range.begin();
auto end = m_range.end();
auto foundBlock = false;
while(it != end) {
switch(IsBlockInRange(*it, address, endAddress)) {
case NotInRange:
if(foundBlock) {
// We're now out of range. It's safe to abort.
it = end;
continue;
}
// Block is not in range. Ignore.
it++;
continue;
case CompletelyInRange:
// This block can be removed.
foundBlock = true;
it = m_range.erase(it);
continue;
case PartiallyInRange:
// Remove the portion of the block that overlaps.
foundBlock = true;
// TODO: Implement me.
it++;
continue;
}
}
}
}

12
libplip/PlipMemoryMap.h

@ -20,14 +20,24 @@ namespace Plip {
class PlipMemoryMap {
public:
void AddBlock(PlipMemory *memory, uint32_t offset);
void AddBlock(PlipMemory *memory, uint32_t offset = 0);
void AddBlock(PlipMemory *memory, uint32_t offset, uint32_t length);
void AssignBlock(PlipMemory *memory, uint32_t address, uint32_t offset, uint32_t length);
uint8_t GetByte(uint32_t address);
uint32_t GetLength();
void SetByte(uint32_t address, uint8_t value);
void UnassignBlock(uint32_t address, uint32_t length);
private:
enum BlockRangeResult {
NotInRange,
PartiallyInRange,
CompletelyInRange
};
void AssignBlockDirect(PlipMemory *memory, uint32_t address, uint32_t offset, uint32_t length);
std::tuple<PlipMemory*, uint32_t> FindAddress(uint32_t address);
static inline BlockRangeResult IsBlockInRange(const PlipMemoryMapRange &block, uint32_t startAddress, uint32_t endAddress);
std::list<PlipMemoryMapRange> m_range;
};

27
plip-sdl/main.cpp

@ -63,6 +63,8 @@ cxxopts::ParseResult parseCmdLine(int argc, char **argv) {
}
}
#include "PlipMemoryMap.h"
#include "PlipMemoryRam.h"
int main(int argc, char **argv) {
auto opts = parseCmdLine(argc, argv);
auto version = Plip::Plip::GetVersion();
@ -78,6 +80,7 @@ int main(int argc, char **argv) {
return 1;
}
/*
auto wnd = new PlipSdl::SdlWindow(opts["scale"].as<int>(), version);
auto event = new PlipSdl::SdlEvent();
auto plip = new Plip::Plip(event, wnd);
@ -89,6 +92,30 @@ int main(int argc, char **argv) {
#endif
gameLoop(plip, timer);
*/
auto memMap = new Plip::PlipMemoryMap();
auto ram1 = new Plip::PlipMemoryRam(0x2000);
auto ram2 = new Plip::PlipMemoryRam(0x2000);
auto ram3 = new Plip::PlipMemoryRam(0x1000);
auto ram4 = new Plip::PlipMemoryRam(0x1000);
auto ram5 = new Plip::PlipMemoryRam(0x2000);
auto ram6 = new Plip::PlipMemoryRam(0x2000);
auto ram7 = new Plip::PlipMemoryRam(0x2000);
auto ram8 = new Plip::PlipMemoryRam(0x4000);
memMap->AddBlock(ram1); // 0x0000 - 0x1FFF
memMap->AddBlock(ram2); // 0x2000 - 0x3FFF
memMap->AddBlock(ram3); // 0x4000 - 0x4FFF
memMap->AddBlock(ram4); // 0x5000 - 0x5FFF
memMap->AddBlock(ram5); // 0x6000 - 0x7FFF
memMap->AddBlock(ram6); // 0x8000 - 0x9FFF
memMap->AddBlock(ram7); // 0xA000 - 0xBFFF
memMap->AddBlock(ram8); // 0xC000 - 0xFFFF
memMap->AssignBlock(ram4, 0x1000, 0x0000, 0x1000);
memMap->UnassignBlock(0x4000, 0x800);
std::cout << "Map length: " << memMap->GetLength() << std::endl;
return 0;
}

Loading…
Cancel
Save