bsnes/higan/sfc/memory/memory.cpp

104 lines
2.7 KiB
C++

#include <sfc/sfc.hpp>
namespace SuperFamicom {
Bus bus;
Bus::~Bus() {
if(lookup) delete[] lookup;
if(target) delete[] target;
}
auto Bus::reset() -> void {
for(auto id : range(256)) {
reader[id].reset();
writer[id].reset();
counter[id] = 0;
}
if(lookup) delete[] lookup;
if(target) delete[] target;
lookup = new uint8 [16 * 1024 * 1024]();
target = new uint32[16 * 1024 * 1024]();
reader[0] = [](uint24, uint8 data) -> uint8 { return data; };
writer[0] = [](uint24, uint8) -> void {};
}
auto Bus::map(
const function<uint8 (uint24, uint8)>& read,
const function<void (uint24, uint8)>& write,
const string& addr, uint size, uint base, uint mask
) -> void {
uint id = 1;
while(counter[id]) {
if(++id >= 256) return print("SFC error: bus map exhausted\n");
}
//print("map[", hex(id, 2), "] => ", addr, "\n");
reader[id] = read;
writer[id] = write;
auto p = addr.split(":", 1L);
auto banks = p(0).split(",");
auto addrs = p(1).split(",");
for(auto& bank : banks) {
for(auto& addr : addrs) {
auto bankRange = bank.split("-", 1L);
auto addrRange = addr.split("-", 1L);
uint bankLo = hex(bankRange(0));
uint bankHi = hex(bankRange(1, bankRange(0)));
uint addrLo = hex(addrRange(0));
uint addrHi = hex(addrRange(1, addrRange(0)));
for(uint bank = bankLo; bank <= bankHi; bank++) {
for(uint addr = addrLo; addr <= addrHi; addr++) {
uint pid = lookup[bank << 16 | addr];
if(pid && --counter[pid] == 0) {
reader[pid].reset();
writer[pid].reset();
}
uint offset = reduce(bank << 16 | addr, mask);
if(size) offset = base + mirror(offset, size - base);
lookup[bank << 16 | addr] = id;
target[bank << 16 | addr] = offset;
counter[id]++;
}
}
}
}
}
auto Bus::unmap(const string& addr) -> void {
auto p = addr.split(":", 1L);
auto banks = p(0).split(",");
auto addrs = p(1).split(",");
for(auto& bank : banks) {
for(auto& addr : addrs) {
auto bankRange = bank.split("-", 1L);
auto addrRange = addr.split("-", 1L);
uint bankLo = hex(bankRange(0));
uint bankHi = hex(bankRange(1, bankRange(0)));
uint addrLo = hex(addrRange(0));
uint addrHi = hex(addrRange(1, addrRange(1)));
for(uint bank = bankLo; bank <= bankHi; bank++) {
for(uint addr = addrLo; addr <= addrHi; addr++) {
uint pid = lookup[bank << 16 | addr];
if(pid && --counter[pid] == 0) {
reader[pid].reset();
writer[pid].reset();
}
lookup[bank << 16 | addr] = 0;
target[bank << 16 | addr] = 0;
}
}
}
}
}
}