bsnes/higan/sfc/chip/sa1/memory/memory.cpp

279 lines
8.0 KiB
C++
Raw Normal View History

#ifdef SA1_CPP
uint8 SA1::bus_read(unsigned addr) {
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
return mmio_read(addr);
}
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return mmcrom_read(addr);
}
if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff
return mmcrom_read(addr);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return mmc_sa1_read(addr);
}
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
synchronize_cpu();
return iram.read(addr & 2047);
}
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
synchronize_cpu();
return iram.read(addr & 2047);
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
synchronize_cpu();
return bwram.read(addr & (bwram.size() - 1));
}
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
synchronize_cpu();
return bitmap_read(addr & 0x0fffff);
}
}
void SA1::bus_write(unsigned addr, uint8 data) {
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
return mmio_write(addr, data);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return mmc_sa1_write(addr, data);
}
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
synchronize_cpu();
return iram.write(addr & 2047, data);
}
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
synchronize_cpu();
return iram.write(addr & 2047, data);
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
synchronize_cpu();
return bwram.write(addr & (bwram.size() - 1), data);
}
if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff
synchronize_cpu();
return bitmap_write(addr & 0x0fffff, data);
}
}
//$230c (VDPL), $230d (VDPH) use this bus to read variable-length data.
//this is used both to keep VBR-reads from accessing MMIO registers, and
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
//these ports.
uint8 SA1::vbr_read(unsigned addr) {
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
return mmcrom_read(addr);
}
if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff
return mmcrom_read(addr);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
return bwram.read(addr & (bwram.size() - 1));
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
return bwram.read(addr & (bwram.size() - 1));
}
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
return iram.read(addr & 2047);
}
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
return iram.read(addr & 0x2047);
}
}
//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)
//BW-RAM is accessed at ~5.37MHz (4 clock ticks)
//tick() == 2 clock ticks
//note: bus conflict delays are not emulated at this time
void SA1::op_io() {
tick();
}
uint8 SA1::op_read(unsigned addr) {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
return bus_read(addr);
}
void SA1::op_write(unsigned addr, uint8 data) {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
bus_write(addr, data);
}
uint8 SA1::mmcrom_read(unsigned addr) {
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
if((addr & 0xffffe0) == 0x00ffe0) {
if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
if(addr == 0xffee && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 0;
if(addr == 0xffef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;
}
static auto read = [](unsigned addr) {
return sa1.rom.read(bus.mirror(addr, sa1.rom.size()));
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
};
if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
if(mmio.cbmode == 0) return read(0x000000 | addr);
return read((mmio.cb << 20) | addr);
}
if((addr & 0xe08000) == 0x208000) { //$20-3f:8000-ffff
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
if(mmio.dbmode == 0) return read(0x100000 | addr);
return read((mmio.db << 20) | addr);
}
if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
if(mmio.ebmode == 0) return read(0x200000 | addr);
return read((mmio.eb << 20) | addr);
}
if((addr & 0xe08000) == 0xa08000) { //$a0-bf:8000-ffff
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);
if(mmio.fbmode == 0) return read(0x300000 | addr);
return read((mmio.fb << 20) | addr);
}
if((addr & 0xf00000) == 0xc00000) { //$c0-cf:0000-ffff
return read((mmio.cb << 20) | (addr & 0x0fffff));
}
if((addr & 0xf00000) == 0xd00000) { //$d0-df:0000-ffff
return read((mmio.db << 20) | (addr & 0x0fffff));
}
if((addr & 0xf00000) == 0xe00000) { //$e0-ef:0000-ffff
return read((mmio.eb << 20) | (addr & 0x0fffff));
}
if((addr & 0xf00000) == 0xf00000) { //$f0-ff:0000-ffff
return read((mmio.fb << 20) | (addr & 0x0fffff));
}
return 0x00;
}
void SA1::mmcrom_write(unsigned addr, uint8 data) {
}
uint8 SA1::mmcbwram_read(unsigned addr) {
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
cpu.synchronize_coprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
return cpubwram.read(addr);
}
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
return cpubwram.read(addr & 0x0fffff);
}
return cpu.regs.mdr;
}
void SA1::mmcbwram_write(unsigned addr, uint8 data) {
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
cpu.synchronize_coprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
return cpubwram.write(addr, data);
}
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
return cpubwram.write(addr & 0x0fffff, data);
}
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
}
uint8 SA1::mmc_sa1_read(unsigned addr) {
synchronize_cpu();
if(mmio.sw46 == 0) {
//$40-43:0000-ffff x 32 projection
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), bwram.size());
return bwram.read(addr);
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
} else {
//$60-6f:0000-ffff x 128 projection
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000);
return bitmap_read(addr);
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
}
}
void SA1::mmc_sa1_write(unsigned addr, uint8 data) {
synchronize_cpu();
if(mmio.sw46 == 0) {
//$40-43:0000-ffff x 32 projection
addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), bwram.size());
bwram.write(addr, data);
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
} else {
//$60-6f:0000-ffff x 128 projection
addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000);
bitmap_write(addr, data);
}
}
uint8 SA1::bitmap_read(unsigned addr) {
if(mmio.bbf == 0) {
//4bpp
unsigned shift = addr & 1;
addr = (addr >> 1) & (bwram.size() - 1);
switch(shift) { default:
case 0: return (bwram.read(addr) >> 0) & 15;
case 1: return (bwram.read(addr) >> 4) & 15;
}
} else {
//2bpp
unsigned shift = addr & 3;
addr = (addr >> 2) & (bwram.size() - 1);
switch(shift) { default:
case 0: return (bwram.read(addr) >> 0) & 3;
case 1: return (bwram.read(addr) >> 2) & 3;
case 2: return (bwram.read(addr) >> 4) & 3;
case 3: return (bwram.read(addr) >> 6) & 3;
}
Update to v074r03 release. byuu says: You guys are going to hate the hell out of this one. It's twenty hours of non-stop work, no exaggeration at all. Started at 4AM, just wrapped up now at 8PM. I rewrote the entire memory subsystem. Old system: 65536 pages that map 256 bytes each Mapping a new page overwrites old page Granularity capped at 256 bytes minimum, requiring ST-001x to map 60:0000-00ff instead of 60:0000,0001 Classes inherit from MMIO and Memory, forcing only one mappable function per class, and fixed names MMIO sub-mapper inside memory: 00-3f:2000-5fff for one-byte granularity Can dynamically change the map at run-time, MMC register settings perform dynamic remapping New system: XML mapping is still based around banklo-bankhi:addrlo-addrhi, as that shapes almost everything on the SNES very well Internally, 2048 pages that map 8192 bytes each Pages are vectors, scans O(n) from last to first (O(log n) would not help, n is never > 3) Can multi-cast writes, but not reads [for the obvious reason of: which read do you return?] Can map reads and writes separately Granularity of one for entire 24-bit address range, no need for MMIO - whatever is in XML is exactly what you get Read/Write tables bind function callbacks, so I can have any number of functions with any names from any classes with no inheritance (no more uPD7725DR, uPD7725SR helpers, etc) Less memory usage overall due to less tables [ I tried 16 million tables and it used 2GB of RAM >_o ] Cannot dynamically change the map at run-time, MMC read/write functions perform address translation [worse average case speed, better worst case speed] Now the hate me part, functors can't beat virtual functions for speed. There are speed penalties involved: -4.5% on average games -11% on SuperFX games (SFX has its own bus) -15% on SA-1 games (SA-1 has two buses) Of course the two that need the speed the most get the biggest hits. I'm afraid there's really not a lot of wiggle room to boost speed back up. I suppose one bright spot is that we can much more easily try out entirely new mapping systems now, since the dynamic portions have been eliminated.
2011-01-15 04:30:29 +00:00
}
}
void SA1::bitmap_write(unsigned addr, uint8 data) {
if(mmio.bbf == 0) {
//4bpp
unsigned shift = addr & 1;
addr = (addr >> 1) & (bwram.size() - 1);
switch(shift) { default:
case 0: data = (bwram.read(addr) & 0xf0) | ((data & 15) << 0); break;
case 1: data = (bwram.read(addr) & 0x0f) | ((data & 15) << 4); break;
}
} else {
//2bpp
unsigned shift = addr & 3;
addr = (addr >> 2) & (bwram.size() - 1);
switch(shift) { default:
case 0: data = (bwram.read(addr) & 0xfc) | ((data & 3) << 0); break;
case 1: data = (bwram.read(addr) & 0xf3) | ((data & 3) << 2); break;
case 2: data = (bwram.read(addr) & 0xcf) | ((data & 3) << 4); break;
case 3: data = (bwram.read(addr) & 0x3f) | ((data & 3) << 6); break;
}
}
bwram.write(addr, data);
}
#endif