Path: blob/master/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp
2 views
#ifdef SA1_CPP12uint8 SA1::bus_read(unsigned addr) {3if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff4return mmio_read(addr);5}67if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff8return mmc_read(addr);9}1011if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff12return mmc_read(addr);13}1415if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff16return mmc_sa1_read(addr);17}1819if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff20synchronize_cpu();21return iram.read(addr & 2047);22}2324if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff25synchronize_cpu();26return iram.read(addr & 2047);27}2829if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff30synchronize_cpu();31return cartridge.ram.read(addr & (cartridge.ram.size() - 1));32}3334if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff35synchronize_cpu();36return bitmap_read(addr & 0x0fffff);37}38}3940void SA1::bus_write(unsigned addr, uint8 data) {41if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff42return mmio_write(addr, data);43}4445if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff46return mmc_sa1_write(addr, data);47}4849if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff50synchronize_cpu();51return iram.write(addr & 2047, data);52}5354if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff55synchronize_cpu();56return iram.write(addr & 2047, data);57}5859if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff60synchronize_cpu();61return cartridge.ram.write(addr & (cartridge.ram.size() - 1), data);62}6364if((addr & 0xf00000) == 0x600000) { //$60-6f:0000-ffff65synchronize_cpu();66return bitmap_write(addr & 0x0fffff, data);67}68}6970//$230c (VDPL), $230d (VDPH) use this bus to read variable-length data.71//this is used both to keep VBR-reads from accessing MMIO registers, and72//to avoid syncing the S-CPU and SA-1*; as both chips are able to access73//these ports.74uint8 SA1::vbr_read(unsigned addr) {75if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff76return mmc_read(addr);77}7879if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff80return mmc_read(addr);81}8283if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff84return cartridge.ram.read(addr & (cartridge.ram.size() - 1));85}8687if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff88return cartridge.ram.read(addr & (cartridge.ram.size() - 1));89}9091if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff92return iram.read(addr & 2047);93}9495if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff96return iram.read(addr & 0x2047);97}98}99100//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)101//BW-RAM is accessed at ~5.37MHz (4 clock ticks)102//tick() == 2 clock ticks103//note: bus conflict delays are not emulated at this time104105void SA1::op_io() {106tick();107}108109uint8 SA1::op_read(unsigned addr, eCDLog_Flags flags) {110(void)flags; //this was needed for inheritance purposes, as SA-1 is derived from the main CPU class111tick();112if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();113return bus_read(addr);114}115116void SA1::op_write(unsigned addr, uint8 data) {117tick();118if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();119bus_write(addr, data);120}121122uint8 SA1::mmc_read(unsigned addr) {123if((addr & 0xffffe0) == 0x00ffe0) {124if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;125if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;126if(addr == 0xffee && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 0;127if(addr == 0xffef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;128}129130static auto read = [](unsigned addr) {131return cartridge.rom.read(bus.mirror(addr, cartridge.rom.size()));132};133134if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff135addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);136if(mmio.cbmode == 0) return read(0x000000 | addr);137return read((mmio.cb << 20) | addr);138}139140if((addr & 0xe08000) == 0x208000) { //$20-3f:8000-ffff141addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);142if(mmio.dbmode == 0) return read(0x100000 | addr);143return read((mmio.db << 20) | addr);144}145146if((addr & 0xe08000) == 0x808000) { //$80-9f:8000-ffff147addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);148if(mmio.ebmode == 0) return read(0x200000 | addr);149return read((mmio.eb << 20) | addr);150}151152if((addr & 0xe08000) == 0xa08000) { //$a0-bf:8000-ffff153addr = ((addr & 0x1f0000) >> 1) | (addr & 0x007fff);154if(mmio.fbmode == 0) return read(0x300000 | addr);155return read((mmio.fb << 20) | addr);156}157158if((addr & 0xf00000) == 0xc00000) { //$c0-cf:0000-ffff159return read((mmio.cb << 20) | (addr & 0x0fffff));160}161162if((addr & 0xf00000) == 0xd00000) { //$d0-df:0000-ffff163return read((mmio.db << 20) | (addr & 0x0fffff));164}165166if((addr & 0xf00000) == 0xe00000) { //$e0-ef:0000-ffff167return read((mmio.eb << 20) | (addr & 0x0fffff));168}169170if((addr & 0xf00000) == 0xf00000) { //$f0-ff:0000-ffff171return read((mmio.fb << 20) | (addr & 0x0fffff));172}173174return 0x00;175}176177void SA1::mmc_write(unsigned addr, uint8 data) {178}179180uint8 SA1::mmc_cpu_read(unsigned addr) {181cpu.synchronize_coprocessors();182addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());183return cpubwram.read(addr);184}185186void SA1::mmc_cpu_write(unsigned addr, uint8 data) {187cpu.synchronize_coprocessors();188addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());189cpubwram.write(addr, data);190}191192uint8 SA1::mmc_sa1_read(unsigned addr) {193synchronize_cpu();194if(mmio.sw46 == 0) {195//$40-43:0000-ffff x 32 projection196addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), cartridge.ram.size());197return cartridge.ram.read(addr);198} else {199//$60-6f:0000-ffff x 128 projection200addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000);201return bitmap_read(addr);202}203}204205void SA1::mmc_sa1_write(unsigned addr, uint8 data) {206synchronize_cpu();207if(mmio.sw46 == 0) {208//$40-43:0000-ffff x 32 projection209addr = bus.mirror((mmio.cbm & 0x1f) * 0x2000 + (addr & 0x1fff), cartridge.ram.size());210cartridge.ram.write(addr, data);211} else {212//$60-6f:0000-ffff x 128 projection213addr = bus.mirror(mmio.cbm * 0x2000 + (addr & 0x1fff), 0x100000);214bitmap_write(addr, data);215}216}217218uint8 SA1::bitmap_read(unsigned addr) {219if(mmio.bbf == 0) {220//4bpp221unsigned shift = addr & 1;222addr = (addr >> 1) & (cartridge.ram.size() - 1);223switch(shift) { default:224case 0: return (cartridge.ram.read(addr) >> 0) & 15;225case 1: return (cartridge.ram.read(addr) >> 4) & 15;226}227} else {228//2bpp229unsigned shift = addr & 3;230addr = (addr >> 2) & (cartridge.ram.size() - 1);231switch(shift) { default:232case 0: return (cartridge.ram.read(addr) >> 0) & 3;233case 1: return (cartridge.ram.read(addr) >> 2) & 3;234case 2: return (cartridge.ram.read(addr) >> 4) & 3;235case 3: return (cartridge.ram.read(addr) >> 6) & 3;236}237}238}239240void SA1::bitmap_write(unsigned addr, uint8 data) {241if(mmio.bbf == 0) {242//4bpp243unsigned shift = addr & 1;244addr = (addr >> 1) & (cartridge.ram.size() - 1);245switch(shift) { default:246case 0: data = (cartridge.ram.read(addr) & 0xf0) | ((data & 15) << 0); break;247case 1: data = (cartridge.ram.read(addr) & 0x0f) | ((data & 15) << 4); break;248}249} else {250//2bpp251unsigned shift = addr & 3;252addr = (addr >> 2) & (cartridge.ram.size() - 1);253switch(shift) { default:254case 0: data = (cartridge.ram.read(addr) & 0xfc) | ((data & 3) << 0); break;255case 1: data = (cartridge.ram.read(addr) & 0xf3) | ((data & 3) << 2); break;256case 2: data = (cartridge.ram.read(addr) & 0xcf) | ((data & 3) << 4); break;257case 3: data = (cartridge.ram.read(addr) & 0x3f) | ((data & 3) << 6); break;258}259}260261cartridge.ram.write(addr, data);262}263264#endif265266267