1 #include <../base.hpp>
2
3 #define MEMORY_CPP
4 namespace bSNES_v059 {
5
6 namespace memory {
7 MMIOAccess mmio;
8 StaticRAM wram(128 * 1024);
9 StaticRAM apuram(64 * 1024);
10 StaticRAM vram(64 * 1024);
11 StaticRAM oam(544);
12 StaticRAM cgram(512);
13
14 UnmappedMemory memory_unmapped;
15 UnmappedMMIO mmio_unmapped;
16 };
17
size() const18 unsigned UnmappedMemory::size() const { return 16 * 1024 * 1024; }
read(unsigned)19 uint8 UnmappedMemory::read(unsigned) { return cpu.regs.mdr; }
write(unsigned,uint8)20 void UnmappedMemory::write(unsigned, uint8) {}
21
mmio_read(unsigned)22 uint8 UnmappedMMIO::mmio_read(unsigned) { return cpu.regs.mdr; }
mmio_write(unsigned,uint8)23 void UnmappedMMIO::mmio_write(unsigned, uint8) {}
24
map(unsigned addr,MMIO & access)25 void MMIOAccess::map(unsigned addr, MMIO &access) {
26 //MMIO: $[00-3f]:[2000-5fff]
27 mmio[(addr - 0x2000) & 0x3fff] = &access;
28 }
29
read(unsigned addr)30 uint8 MMIOAccess::read(unsigned addr) {
31 return mmio[(addr - 0x2000) & 0x3fff]->mmio_read(addr);
32 }
33
write(unsigned addr,uint8 data)34 void MMIOAccess::write(unsigned addr, uint8 data) {
35 mmio[(addr - 0x2000) & 0x3fff]->mmio_write(addr, data);
36 }
37
mirror(unsigned addr,unsigned size)38 unsigned Bus::mirror(unsigned addr, unsigned size) {
39 unsigned base = 0;
40 if(size) {
41 unsigned mask = 1 << 23;
42 while(addr >= size) {
43 while(!(addr & mask)) mask >>= 1;
44 addr -= mask;
45 if(size > mask) {
46 size -= mask;
47 base += mask;
48 }
49 mask >>= 1;
50 }
51 base += addr;
52 }
53 return base;
54 }
55
map(unsigned addr,Memory & access,unsigned offset)56 void Bus::map(unsigned addr, Memory &access, unsigned offset) {
57 page[addr >> 8].access = &access;
58 page[addr >> 8].offset = offset - addr;
59 }
60
map(MapMode mode,uint8 bank_lo,uint8 bank_hi,uint16 addr_lo,uint16 addr_hi,Memory & access,unsigned offset,unsigned size)61 void Bus::map(
62 MapMode mode,
63 uint8 bank_lo, uint8 bank_hi,
64 uint16 addr_lo, uint16 addr_hi,
65 Memory &access, unsigned offset, unsigned size
66 ) {
67 assert(bank_lo <= bank_hi);
68 assert(addr_lo <= addr_hi);
69 if(access.size() == -1U) return;
70
71 uint8 page_lo = addr_lo >> 8;
72 uint8 page_hi = addr_hi >> 8;
73 unsigned index = 0;
74
75 switch(mode) {
76 case MapDirect: {
77 for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
78 for(unsigned page = page_lo; page <= page_hi; page++) {
79 map((bank << 16) + (page << 8), access, (bank << 16) + (page << 8));
80 }
81 }
82 } break;
83
84 case MapLinear: {
85 for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
86 for(unsigned page = page_lo; page <= page_hi; page++) {
87 map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
88 index += 256;
89 if(size) index %= size;
90 }
91 }
92 } break;
93
94 case MapShadow: {
95 for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
96 index += page_lo * 256;
97 if(size) index %= size;
98
99 for(unsigned page = page_lo; page <= page_hi; page++) {
100 map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
101 index += 256;
102 if(size) index %= size;
103 }
104
105 index += (255 - page_hi) * 256;
106 if(size) index %= size;
107 }
108 } break;
109 }
110 }
111
112 };
113