mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-02-22 14:12:35 +01:00
byuu says: Changelog: - higan now uses Natural<Size>/Integer<Size> for its internal types - Super Famicom emulation now uses uint24 instead of uint for bus addresses (it's a 24-bit bus) - cleaned up gb/apu MMIO writes - cleaned up sfc/coprocessor/msu1 MMIO writes - ~3% speed penalty I've wanted to do that 24-bit bus thing for so long, but have always been afraid of the speed impact. It's probably going to hurt balanced/performance once they compile again, but it wasn't significant enough to harm the accuracy core's frame rate, thankfully. Only lost one frame per second. The GBA core handlers are clearly going to take a lot more work. The bit-ranges will make it substantially easier to handle, though. Lots of 32-bit registers where certain values span multiple bytes, but we have to be able to read/write at byte-granularity.
93 lines
2.5 KiB
C++
93 lines
2.5 KiB
C++
//Memory
|
|
|
|
auto Memory::size() const -> uint { return 0; }
|
|
|
|
//StaticRAM
|
|
|
|
StaticRAM::StaticRAM(uint n) : size_(n) { data_ = new uint8[size_]; }
|
|
StaticRAM::~StaticRAM() { delete[] data_; }
|
|
|
|
auto StaticRAM::data() -> uint8* { return data_; }
|
|
auto StaticRAM::size() const -> uint { return size_; }
|
|
|
|
auto StaticRAM::read(uint24 addr, uint8) -> uint8 { return data_[addr]; }
|
|
auto StaticRAM::write(uint24 addr, uint8 data) -> void { data_[addr] = data; }
|
|
auto StaticRAM::operator[](uint24 addr) -> uint8& { return data_[addr]; }
|
|
auto StaticRAM::operator[](uint24 addr) const -> const uint8& { return data_[addr]; }
|
|
|
|
//MappedRAM
|
|
|
|
auto MappedRAM::reset() -> void {
|
|
if(data_) {
|
|
delete[] data_;
|
|
data_ = nullptr;
|
|
}
|
|
size_ = 0;
|
|
write_protect_ = false;
|
|
}
|
|
|
|
auto MappedRAM::map(uint8* source, uint length) -> void {
|
|
reset();
|
|
data_ = source;
|
|
size_ = data_ ? length : 0;
|
|
}
|
|
|
|
auto MappedRAM::copy(const stream& memory) -> void {
|
|
if(data_) delete[] data_;
|
|
//round size up to multiple of 256-bytes
|
|
size_ = (memory.size() & ~255) + ((bool)(memory.size() & 255) << 8);
|
|
data_ = new uint8[size_]();
|
|
memory.read((uint8_t*)data_, memory.size());
|
|
}
|
|
|
|
auto MappedRAM::read(const stream& memory) -> void {
|
|
memory.read((uint8_t*)data_, min(memory.size(), size_));
|
|
}
|
|
|
|
auto MappedRAM::write_protect(bool status) -> void { write_protect_ = status; }
|
|
auto MappedRAM::data() -> uint8* { return data_; }
|
|
auto MappedRAM::size() const -> uint { return size_; }
|
|
|
|
auto MappedRAM::read(uint24 addr, uint8) -> uint8 { return data_[addr]; }
|
|
auto MappedRAM::write(uint24 addr, uint8 data) -> void { if(!write_protect_) data_[addr] = data; }
|
|
auto MappedRAM::operator[](uint24 addr) const -> const uint8& { return data_[addr]; }
|
|
|
|
//Bus
|
|
|
|
auto Bus::mirror(uint addr, uint size) -> uint {
|
|
if(size == 0) return 0;
|
|
uint base = 0;
|
|
uint mask = 1 << 23;
|
|
while(addr >= size) {
|
|
while(!(addr & mask)) mask >>= 1;
|
|
addr -= mask;
|
|
if(size > mask) {
|
|
size -= mask;
|
|
base += mask;
|
|
}
|
|
mask >>= 1;
|
|
}
|
|
return base + addr;
|
|
}
|
|
|
|
auto Bus::reduce(uint addr, uint mask) -> uint {
|
|
while(mask) {
|
|
uint bits = (mask & -mask) - 1;
|
|
addr = ((addr >> 1) & ~bits) | (addr & bits);
|
|
mask = (mask & (mask - 1)) >> 1;
|
|
}
|
|
return addr;
|
|
}
|
|
|
|
auto Bus::read(uint24 addr, uint8 data) -> uint8 {
|
|
data = reader[lookup[addr]](target[addr], data);
|
|
if(cheat.enable()) {
|
|
if(auto result = cheat.find(addr, data)) return result();
|
|
}
|
|
return data;
|
|
}
|
|
|
|
auto Bus::write(uint24 addr, uint8 data) -> void {
|
|
return writer[lookup[addr]](target[addr], data);
|
|
}
|