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