#include 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& read, const function& 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; } } } } } }