bsnes: DMA tracing
[lsnes.git] / bsnes-patches / v085 / 0012-Support-unlimited-number-of-breakpoints.patch
blobf4b27023008d9f843e7fa862fa5a3e3c9097dfdf
1 From a5b380757b086e3a00b47fe14e2a63c74683e8da Mon Sep 17 00:00:00 2001
2 From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
3 Date: Thu, 28 Nov 2013 22:36:29 +0200
4 Subject: [PATCH 12/22] Support unlimited number of breakpoints
6 ---
7 snes/alt/cpu/cpu.cpp | 22 +++++++-------
8 snes/alt/ppu-compatibility/ppu.cpp | 4 +--
9 snes/alt/ppu-parallel/ppu.cpp | 4 +--
10 snes/alt/ppu-performance/ppu.cpp | 4 +--
11 snes/cartridge/cartridge.hpp | 17 +++++++++++
12 snes/cartridge/markup.cpp | 11 +++++++
13 snes/cheat/cheat.cpp | 11 ++++---
14 snes/cheat/cheat.hpp | 1 +
15 snes/chip/bsx/satellaview/satellaview.cpp | 4 +--
16 snes/chip/hitachidsp/hitachidsp.cpp | 2 +-
17 snes/chip/hitachidsp/memory.cpp | 2 +-
18 snes/chip/nss/nss.cpp | 4 +--
19 snes/chip/sa1/memory/memory.cpp | 2 +-
20 snes/chip/sa1/memory/memory.hpp | 2 +-
21 snes/chip/sa1/sa1.cpp | 2 +-
22 snes/chip/sdd1/sdd1.cpp | 4 +--
23 snes/cpu/core/core.hpp | 2 +-
24 snes/cpu/core/disassembler/disassembler.cpp | 2 +-
25 snes/cpu/core/memory.hpp | 2 +-
26 snes/cpu/cpu.cpp | 26 ++++++++--------
27 snes/cpu/debugger/debugger.cpp | 4 +--
28 snes/cpu/debugger/debugger.hpp | 2 +-
29 snes/cpu/dma/dma.cpp | 4 +--
30 snes/cpu/memory/memory.cpp | 4 +--
31 snes/cpu/memory/memory.hpp | 2 +-
32 snes/cpu/mmio/mmio.cpp | 2 +-
33 snes/debugger/debugger.cpp | 2 +-
34 snes/memory/memory-inline.hpp | 21 +++++++++++--
35 snes/memory/memory.cpp | 47 ++++++++++++++++++++++++++---
36 snes/memory/memory.hpp | 13 +++++++-
37 snes/ppu/ppu.cpp | 4 +--
38 snes/smp/core/core.hpp | 2 +-
39 snes/snes.hpp | 1 +
40 33 files changed, 166 insertions(+), 70 deletions(-)
42 diff --git a/snes/alt/cpu/cpu.cpp b/snes/alt/cpu/cpu.cpp
43 index 814908d..dcbb92d 100755
44 --- a/snes/alt/cpu/cpu.cpp
45 +++ b/snes/alt/cpu/cpu.cpp
46 @@ -89,24 +89,24 @@ void CPU::enable() {
47 function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
48 function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
50 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
51 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
52 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, 0, read, write);
53 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, 0, read, write);
55 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
56 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
57 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, 0, read, write);
58 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, 0, read, write);
60 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
61 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
62 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, 0, read, write);
63 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, 0, read, write);
65 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
66 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
67 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, 0, read, write);
68 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, 0, read, write);
70 read = [](unsigned addr) { return cpu.wram[addr]; };
71 write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
73 - bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
74 - bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
75 - bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
76 + bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, 3, read, write, 0x000000, 0x002000);
77 + bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, 3, read, write, 0x000000, 0x002000);
78 + bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, 3, read, write);
81 void CPU::power() {
82 diff --git a/snes/alt/ppu-compatibility/ppu.cpp b/snes/alt/ppu-compatibility/ppu.cpp
83 index a21e5e3..122b143 100755
84 --- a/snes/alt/ppu-compatibility/ppu.cpp
85 +++ b/snes/alt/ppu-compatibility/ppu.cpp
86 @@ -126,8 +126,8 @@ void PPU::enable() {
87 function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
88 function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
90 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
91 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
92 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, 0, read, write);
93 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, 0, read, write);
96 void PPU::power() {
97 diff --git a/snes/alt/ppu-parallel/ppu.cpp b/snes/alt/ppu-parallel/ppu.cpp
98 index 1c3dcb7..8dd118b 100755
99 --- a/snes/alt/ppu-parallel/ppu.cpp
100 +++ b/snes/alt/ppu-parallel/ppu.cpp
101 @@ -36,8 +36,8 @@ void PPU::frame() {
104 void PPU::enable() {
105 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, { &PPU::mmio_read, this }, { &PPU::mmio_write, this });
106 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, { &PPU::mmio_read, this }, { &PPU::mmio_write, this });
107 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, 0, { &PPU::mmio_read, this }, { &PPU::mmio_write, this });
108 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, 0, { &PPU::mmio_read, this }, { &PPU::mmio_write, this });
111 void PPU::power() {
112 diff --git a/snes/alt/ppu-performance/ppu.cpp b/snes/alt/ppu-performance/ppu.cpp
113 index 7c231bc..4b2b294 100755
114 --- a/snes/alt/ppu-performance/ppu.cpp
115 +++ b/snes/alt/ppu-performance/ppu.cpp
116 @@ -90,8 +90,8 @@ void PPU::enable() {
117 function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
118 function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
120 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
121 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
122 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, 0, read, write);
123 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, 0, read, write);
126 void PPU::power() {
127 diff --git a/snes/cartridge/cartridge.hpp b/snes/cartridge/cartridge.hpp
128 index 37555bc..82e73c4 100755
129 --- a/snes/cartridge/cartridge.hpp
130 +++ b/snes/cartridge/cartridge.hpp
131 @@ -12,6 +12,22 @@ struct Cartridge : property<Cartridge> {
132 PAL,
135 + enum class MemoryClass : unsigned {
136 + MISC = 0,
137 + ROM = 1,
138 + SRAM = 2,
139 + WRAM = 3,
140 + SUPERFXROM = 4,
141 + SUPERFXRAM = 5,
142 + SA1IRAM = 6,
143 + SA1BWRAM = 7,
144 + SUFAMITURBO_ROMA = 8,
145 + SUFAMITURBO_ROMB = 9,
146 + SUFAMITURBO_RAMA = 10,
147 + SUFAMITURBO_RAMB = 11,
148 + BSXFLASH = 12,
149 + };
151 enum class Slot : unsigned {
152 Base,
153 Bsx,
154 @@ -68,6 +84,7 @@ struct Cartridge : property<Cartridge> {
155 unsigned addrhi;
156 unsigned offset;
157 unsigned size;
158 + MemoryClass clazz;
160 Mapping();
161 Mapping(const function<uint8 (unsigned)>&, const function<void (unsigned, uint8)>&);
162 diff --git a/snes/cartridge/markup.cpp b/snes/cartridge/markup.cpp
163 index e639fe5..2dd0d64 100755
164 --- a/snes/cartridge/markup.cpp
165 +++ b/snes/cartridge/markup.cpp
166 @@ -74,6 +74,7 @@ void Cartridge::parse_markup_rom(XML::Node &root) {
167 for(auto &node : root) {
168 if(node.name != "map") continue;
169 Mapping m(rom);
170 + m.clazz = MemoryClass::ROM;
171 parse_markup_map(m, node);
172 if(m.size == 0) m.size = rom.size();
173 mapping.append(m);
174 @@ -85,6 +86,7 @@ void Cartridge::parse_markup_ram(XML::Node &root) {
175 ram_size = parse_markup_integer(root["size"].data);
176 for(auto &node : root) {
177 Mapping m(ram);
178 + m.clazz = MemoryClass::SRAM;
179 parse_markup_map(m, node);
180 if(m.size == 0) m.size = ram_size;
181 mapping.append(m);
182 @@ -133,6 +135,7 @@ void Cartridge::parse_markup_superfx(XML::Node &root) {
183 for(auto &leaf : node) {
184 if(leaf.name != "map") continue;
185 Mapping m(superfx.rom);
186 + //m.clazz = MemoryClass::SUPERFXROM; -- Aliases ROM.
187 parse_markup_map(m, leaf);
188 mapping.append(m);
190 @@ -145,6 +148,7 @@ void Cartridge::parse_markup_superfx(XML::Node &root) {
192 if(leaf.name != "map") continue;
193 Mapping m(superfx.ram);
194 + //m.clazz = MemoryClass::SUPERFXRAM; -- Aliases SRAM.
195 parse_markup_map(m, leaf);
196 if(m.size == 0) m.size = ram_size;
197 mapping.append(m);
198 @@ -188,6 +192,7 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
199 for(auto &node : iram) {
200 if(node.name != "map") continue;
201 Mapping m(sa1.cpuiram);
202 + m.clazz = MemoryClass::SA1IRAM;
203 parse_markup_map(m, node);
204 if(m.size == 0) m.size = 2048;
205 mapping.append(m);
206 @@ -197,6 +202,7 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
207 for(auto &node : bwram) {
208 if(node.name != "map") continue;
209 Mapping m(sa1.cpubwram);
210 + //m.clazz = MemoryClass::SA1BWRAM; -- Aliases SRAM
211 parse_markup_map(m, node);
212 if(m.size == 0) m.size = ram_size;
213 mapping.append(m);
214 @@ -341,6 +347,7 @@ void Cartridge::parse_markup_bsx(XML::Node &root) {
215 for(auto &node : root["slot"]) {
216 if(node.name != "map") continue;
217 Mapping m(bsxflash.memory);
218 + m.clazz = MemoryClass::BSXFLASH;
219 parse_markup_map(m, node);
220 mapping.append(m);
222 @@ -373,6 +380,7 @@ void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
223 if(leaf.name != "map") continue;
224 Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom;
225 Mapping m(memory);
226 + m.clazz = slotid ? MemoryClass::SUFAMITURBO_ROMB : MemoryClass::SUFAMITURBO_ROMA;
227 parse_markup_map(m, leaf);
228 if(m.size == 0) m.size = memory.size();
229 if(m.size) mapping.append(m);
230 @@ -384,6 +392,7 @@ void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
231 if(leaf.name != "map") continue;
232 Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram;
233 Mapping m(memory);
234 + m.clazz = slotid ? MemoryClass::SUFAMITURBO_RAMB : MemoryClass::SUFAMITURBO_RAMA;
235 parse_markup_map(m, leaf);
236 if(m.size == 0) m.size = ram_size;
237 if(m.size) mapping.append(m);
238 @@ -536,11 +545,13 @@ void Cartridge::parse_markup_link(XML::Node &root) {
241 Cartridge::Mapping::Mapping() {
242 + clazz = MemoryClass::MISC;
243 mode = Bus::MapMode::Direct;
244 banklo = bankhi = addrlo = addrhi = offset = size = 0;
247 Cartridge::Mapping::Mapping(Memory &memory) {
248 + clazz = MemoryClass::MISC;
249 read = { &Memory::read, &memory };
250 write = { &Memory::write, &memory };
251 mode = Bus::MapMode::Direct;
252 diff --git a/snes/cheat/cheat.cpp b/snes/cheat/cheat.cpp
253 index 46c42d1..3a269cc 100755
254 --- a/snes/cheat/cheat.cpp
255 +++ b/snes/cheat/cheat.cpp
256 @@ -21,9 +21,9 @@ void Cheat::synchronize() {
257 for(unsigned i = 0; i < size(); i++) {
258 const CheatCode &code = operator[](i);
260 - unsigned addr = mirror(code.addr);
261 + unsigned addr = code.nomirror ? code.addr : mirror(code.addr);
262 override[addr] = true;
263 - if((addr & 0xffe000) == 0x7e0000) {
264 + if(!code.nomirror && (addr & 0xffe000) == 0x7e0000) {
265 //mirror $7e:0000-1fff to $00-3f|80-bf:0000-1fff
266 unsigned mirroraddr;
267 for(unsigned x = 0; x <= 0x3f; x++) {
268 @@ -40,11 +40,14 @@ void Cheat::synchronize() {
271 uint8 Cheat::read(unsigned addr) const {
272 - addr = mirror(addr);
273 + unsigned raddr = mirror(addr);
275 for(unsigned i = 0; i < size(); i++) {
276 const CheatCode &code = operator[](i);
277 - if(addr == mirror(code.addr)) {
278 + if(!code.nomirror && addr == mirror(code.addr)) {
279 + return code.data;
281 + if(code.nomirror && raddr == code.addr) {
282 return code.data;
285 diff --git a/snes/cheat/cheat.hpp b/snes/cheat/cheat.hpp
286 index 306b99b..b4d2a42 100755
287 --- a/snes/cheat/cheat.hpp
288 +++ b/snes/cheat/cheat.hpp
289 @@ -1,6 +1,7 @@
290 struct CheatCode {
291 unsigned addr;
292 unsigned data;
293 + bool nomirror;
296 struct Cheat : public linear_vector<CheatCode> {
297 diff --git a/snes/chip/bsx/satellaview/satellaview.cpp b/snes/chip/bsx/satellaview/satellaview.cpp
298 index 3c98019..25af8e5 100755
299 --- a/snes/chip/bsx/satellaview/satellaview.cpp
300 +++ b/snes/chip/bsx/satellaview/satellaview.cpp
301 @@ -6,8 +6,8 @@ void BSXSatellaview::init() {
304 void BSXSatellaview::load() {
305 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2188, 0x219f, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
306 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2188, 0x219f, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
307 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2188, 0x219f, 0, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
308 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2188, 0x219f, 0, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
311 void BSXSatellaview::unload() {
312 diff --git a/snes/chip/hitachidsp/hitachidsp.cpp b/snes/chip/hitachidsp/hitachidsp.cpp
313 index 1042267..3e5c5bd 100755
314 --- a/snes/chip/hitachidsp/hitachidsp.cpp
315 +++ b/snes/chip/hitachidsp/hitachidsp.cpp
316 @@ -23,7 +23,7 @@ void HitachiDSP::enter() {
317 break;
318 case State::DMA:
319 for(unsigned n = 0; n < regs.dma_length; n++) {
320 - bus.write(regs.dma_target + n, bus.read(regs.dma_source + n));
321 + bus.write(regs.dma_target + n, bus.read(regs.dma_source + n, false));
322 step(2);
324 state = State::Idle;
325 diff --git a/snes/chip/hitachidsp/memory.cpp b/snes/chip/hitachidsp/memory.cpp
326 index 3c9c3af..36868e8 100755
327 --- a/snes/chip/hitachidsp/memory.cpp
328 +++ b/snes/chip/hitachidsp/memory.cpp
329 @@ -1,7 +1,7 @@
330 #ifdef HITACHIDSP_CPP
332 uint8 HitachiDSP::bus_read(unsigned addr) {
333 - if((addr & 0x408000) == 0x008000) return bus.read(addr);
334 + if((addr & 0x408000) == 0x008000) return bus.read(addr, false);
335 return 0x00;
338 diff --git a/snes/chip/nss/nss.cpp b/snes/chip/nss/nss.cpp
339 index 964973d..5946af3 100755
340 --- a/snes/chip/nss/nss.cpp
341 +++ b/snes/chip/nss/nss.cpp
342 @@ -10,8 +10,8 @@ void NSS::init() {
344 void NSS::load() {
345 dip = 0x0000;
346 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this });
347 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this });
348 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4100, 0x4101, 0, { &NSS::read, this }, { &NSS::write, this });
349 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4100, 0x4101, 0, { &NSS::read, this }, { &NSS::write, this });
352 void NSS::unload() {
353 diff --git a/snes/chip/sa1/memory/memory.cpp b/snes/chip/sa1/memory/memory.cpp
354 index d13ac92..9bb4ff2 100755
355 --- a/snes/chip/sa1/memory/memory.cpp
356 +++ b/snes/chip/sa1/memory/memory.cpp
357 @@ -107,7 +107,7 @@ void SA1::op_io() {
358 tick();
361 -uint8 SA1::op_read(unsigned addr) {
362 +uint8 SA1::op_read(unsigned addr, bool exec) {
363 tick();
364 if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
365 return bus_read(addr);
366 diff --git a/snes/chip/sa1/memory/memory.hpp b/snes/chip/sa1/memory/memory.hpp
367 index ffb9e9f..ab8e1ed 100755
368 --- a/snes/chip/sa1/memory/memory.hpp
369 +++ b/snes/chip/sa1/memory/memory.hpp
370 @@ -3,7 +3,7 @@ void bus_write(unsigned addr, uint8 data);
371 uint8 vbr_read(unsigned addr);
373 alwaysinline void op_io();
374 -alwaysinline uint8 op_read(unsigned addr);
375 +alwaysinline uint8 op_read(unsigned addr, bool exec);
376 alwaysinline void op_write(unsigned addr, uint8 data);
378 uint8 mmc_read(unsigned addr);
379 diff --git a/snes/chip/sa1/sa1.cpp b/snes/chip/sa1/sa1.cpp
380 index 71c6310..30e0080 100755
381 --- a/snes/chip/sa1/sa1.cpp
382 +++ b/snes/chip/sa1/sa1.cpp
383 @@ -37,7 +37,7 @@ void SA1::enter() {
386 void SA1::op_irq() {
387 - op_read(regs.pc.d);
388 + op_read(regs.pc.d, false);
389 op_io();
390 if(!regs.e) op_writestack(regs.pc.b);
391 op_writestack(regs.pc.h);
392 diff --git a/snes/chip/sdd1/sdd1.cpp b/snes/chip/sdd1/sdd1.cpp
393 index c9b8b1c..5d6cc55 100755
394 --- a/snes/chip/sdd1/sdd1.cpp
395 +++ b/snes/chip/sdd1/sdd1.cpp
396 @@ -14,8 +14,8 @@ void SDD1::init() {
397 void SDD1::load() {
398 //hook S-CPU DMA MMIO registers to gather information for struct dma[];
399 //buffer address and transfer size information for use in SDD1::mcu_read()
400 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
401 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
402 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, 0, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
403 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, 0, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
406 void SDD1::unload() {
407 diff --git a/snes/cpu/core/core.hpp b/snes/cpu/core/core.hpp
408 index 7a685a8..9d77f3c 100755
409 --- a/snes/cpu/core/core.hpp
410 +++ b/snes/cpu/core/core.hpp
411 @@ -10,7 +10,7 @@ struct CPUcore {
412 void powercycle();
414 virtual void op_io() = 0;
415 - virtual uint8_t op_read(uint32_t addr) = 0;
416 + virtual uint8_t op_read(uint32_t addr, bool exec = false) = 0;
417 virtual void op_write(uint32_t addr, uint8_t data) = 0;
418 virtual void last_cycle() = 0;
419 virtual bool interrupt_pending() = 0;
420 diff --git a/snes/cpu/core/disassembler/disassembler.cpp b/snes/cpu/core/disassembler/disassembler.cpp
421 index 030b3ab..ab8dde2 100755
422 --- a/snes/cpu/core/disassembler/disassembler.cpp
423 +++ b/snes/cpu/core/disassembler/disassembler.cpp
424 @@ -6,7 +6,7 @@ uint8 CPUcore::dreadb(uint32 addr) {
425 //do not read MMIO registers within debugger
426 return 0x00;
428 - return bus.read(addr);
429 + return bus.read(addr, false);
432 uint16 CPUcore::dreadw(uint32 addr) {
433 diff --git a/snes/cpu/core/memory.hpp b/snes/cpu/core/memory.hpp
434 index 4992657..132501c 100755
435 --- a/snes/cpu/core/memory.hpp
436 +++ b/snes/cpu/core/memory.hpp
437 @@ -1,5 +1,5 @@
438 alwaysinline uint8_t op_readpc() {
439 - return op_read((regs.pc.b << 16) + regs.pc.w++);
440 + return op_read((regs.pc.b << 16) + regs.pc.w++, true);
443 alwaysinline uint8_t op_readstack() {
444 diff --git a/snes/cpu/cpu.cpp b/snes/cpu/cpu.cpp
445 index 2d7d343..39da6b1 100755
446 --- a/snes/cpu/cpu.cpp
447 +++ b/snes/cpu/cpu.cpp
448 @@ -78,8 +78,8 @@ void CPU::enter() {
449 } else if(status.reset_pending) {
450 status.reset_pending = false;
451 add_clocks(186);
452 - regs.pc.l = bus.read(0xfffc);
453 - regs.pc.h = bus.read(0xfffd);
454 + regs.pc.l = bus.read(0xfffc, false);
455 + regs.pc.h = bus.read(0xfffd, false);
459 @@ -95,24 +95,24 @@ void CPU::enable() {
460 function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
461 function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
463 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
464 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
465 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, 0, read, write);
466 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, 0, read, write);
468 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
469 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
470 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, 0, read, write);
471 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, 0, read, write);
473 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
474 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
475 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, 0, read, write);
476 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, 0, read, write);
478 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
479 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
480 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, 0, read, write);
481 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, 0, read, write);
483 read = [](unsigned addr) { return cpu.wram[addr]; };
484 write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
486 - bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
487 - bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
488 - bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
489 + bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, 3, read, write, 0x000000, 0x002000);
490 + bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, 3, read, write, 0x000000, 0x002000);
491 + bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, 3, read, write);
494 void CPU::power() {
495 diff --git a/snes/cpu/debugger/debugger.cpp b/snes/cpu/debugger/debugger.cpp
496 index a33518e..8301bdb 100755
497 --- a/snes/cpu/debugger/debugger.cpp
498 +++ b/snes/cpu/debugger/debugger.cpp
499 @@ -19,8 +19,8 @@ void CPUDebugger::op_step() {
500 synchronize_smp();
503 -uint8 CPUDebugger::op_read(uint32 addr) {
504 - uint8 data = CPU::op_read(addr);
505 +uint8 CPUDebugger::op_read(uint32 addr, bool exec) {
506 + uint8 data = CPU::op_read(addr, exec);
507 usage[addr] |= UsageRead;
508 debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Read, addr, data);
509 return data;
510 diff --git a/snes/cpu/debugger/debugger.hpp b/snes/cpu/debugger/debugger.hpp
511 index 579f6f0..c3d66db 100755
512 --- a/snes/cpu/debugger/debugger.hpp
513 +++ b/snes/cpu/debugger/debugger.hpp
514 @@ -16,7 +16,7 @@ public:
515 bool opcode_edge; //true right before an opcode execues, used to skip over opcodes
517 void op_step();
518 - uint8 op_read(uint32 addr);
519 + uint8 op_read(uint32 addr, bool exec = false);
520 void op_write(uint32 addr, uint8 data);
522 CPUDebugger();
523 diff --git a/snes/cpu/dma/dma.cpp b/snes/cpu/dma/dma.cpp
524 index e8cdb3e..0a00bfe 100755
525 --- a/snes/cpu/dma/dma.cpp
526 +++ b/snes/cpu/dma/dma.cpp
527 @@ -26,7 +26,7 @@ bool CPU::dma_addr_valid(uint32 abus) {
529 uint8 CPU::dma_read(uint32 abus) {
530 if(dma_addr_valid(abus) == false) return 0x00;
531 - return bus.read(abus);
532 + return bus.read(abus, false);
535 //simulate two-stage pipeline for DMA transfers; example:
536 @@ -49,7 +49,7 @@ void CPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
537 dma_write(dma_transfer_valid(bbus, abus), 0x2100 | bbus, regs.mdr);
538 } else {
539 dma_add_clocks(4);
540 - regs.mdr = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus) : 0x00;
541 + regs.mdr = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus, false) : 0x00;
542 dma_add_clocks(4);
543 dma_write(dma_addr_valid(abus), abus, regs.mdr);
545 diff --git a/snes/cpu/memory/memory.cpp b/snes/cpu/memory/memory.cpp
546 index c2c8f1f..31f82c3 100755
547 --- a/snes/cpu/memory/memory.cpp
548 +++ b/snes/cpu/memory/memory.cpp
549 @@ -10,11 +10,11 @@ void CPU::op_io() {
550 alu_edge();
553 -uint8 CPU::op_read(uint32 addr) {
554 +uint8 CPU::op_read(uint32 addr, bool exec) {
555 status.clock_count = speed(addr);
556 dma_edge();
557 add_clocks(status.clock_count - 4);
558 - regs.mdr = bus.read(addr);
559 + regs.mdr = bus.read(addr, exec);
560 add_clocks(4);
561 alu_edge();
562 return regs.mdr;
563 diff --git a/snes/cpu/memory/memory.hpp b/snes/cpu/memory/memory.hpp
564 index d33861d..fd64ba8 100755
565 --- a/snes/cpu/memory/memory.hpp
566 +++ b/snes/cpu/memory/memory.hpp
567 @@ -1,4 +1,4 @@
568 void op_io();
569 -debugvirtual uint8 op_read(uint32 addr);
570 +debugvirtual uint8 op_read(uint32 addr, bool exec);
571 debugvirtual void op_write(uint32 addr, uint8 data);
572 alwaysinline unsigned speed(unsigned addr) const;
573 diff --git a/snes/cpu/mmio/mmio.cpp b/snes/cpu/mmio/mmio.cpp
574 index b7afff0..30048c1 100755
575 --- a/snes/cpu/mmio/mmio.cpp
576 +++ b/snes/cpu/mmio/mmio.cpp
577 @@ -5,7 +5,7 @@ bool CPU::joylatch() { return status.joypad_strobe_latch; }
579 //WMDATA
580 uint8 CPU::mmio_r2180() {
581 - return bus.read(0x7e0000 | status.wram_addr++);
582 + return bus.read(0x7e0000 | status.wram_addr++, false);
585 //WMDATA
586 diff --git a/snes/debugger/debugger.cpp b/snes/debugger/debugger.cpp
587 index b131233..e8d0f5a 100755
588 --- a/snes/debugger/debugger.cpp
589 +++ b/snes/debugger/debugger.cpp
590 @@ -33,7 +33,7 @@ uint8 Debugger::read(Debugger::MemorySource source, unsigned addr) {
591 case MemorySource::CPUBus: {
592 //do not read from memory-mapped registers that could affect program behavior
593 if(((addr - 0x2000) & 0x40c000) == 0x000000) break; //$00-3f:2000-5fff MMIO
594 - return bus.read(addr & 0xffffff);
595 + return bus.read(addr & 0xffffff, false);
596 } break;
598 case MemorySource::APUBus: {
599 diff --git a/snes/memory/memory-inline.hpp b/snes/memory/memory-inline.hpp
600 index 70503be..45f150c 100755
601 --- a/snes/memory/memory-inline.hpp
602 +++ b/snes/memory/memory-inline.hpp
603 @@ -51,11 +51,26 @@ MappedRAM::MappedRAM() : data_(0), size_(0), write_protect_(false) {}
605 //Bus
607 -uint8 Bus::read(unsigned addr) {
608 - if(cheat.override[addr]) return cheat.read(addr);
609 - return reader[lookup[addr]](target[addr]);
610 +uint8 Bus::read(unsigned addr, bool exec) {
611 + uint8 emask = exec ? 0x24 : 0x09;
612 + uint8 val;
613 + if(__builtin_expect(cheat.override[addr], 0))
614 + val = cheat.read(addr);
615 + else
616 + val = reader[lookup[addr]](target[addr]);
617 + if(__builtin_expect((u_debugflags | debugflags[addr]) & emask, 0)) {
618 + unsigned daddr = target[addr];
619 + uint8 mclass = classmap[addr];
620 + debug_read(mclass, daddr, addr, val, exec);
622 + return val;
625 void Bus::write(unsigned addr, uint8 data) {
626 + if(__builtin_expect((u_debugflags | debugflags[addr]) & 0x12, 0)) {
627 + unsigned daddr = target[addr];
628 + uint8 mclass = classmap[addr];
629 + debug_write(mclass, daddr, addr, data);
631 return writer[lookup[addr]](target[addr], data);
633 diff --git a/snes/memory/memory.cpp b/snes/memory/memory.cpp
634 index ede9cbd..a9a484a 100755
635 --- a/snes/memory/memory.cpp
636 +++ b/snes/memory/memory.cpp
637 @@ -27,6 +27,7 @@ void Bus::map(
638 MapMode mode,
639 unsigned bank_lo, unsigned bank_hi,
640 unsigned addr_lo, unsigned addr_hi,
641 + unsigned mclass,
642 const function<uint8 (unsigned)> &rd,
643 const function<void (unsigned, uint8)> &wr,
644 unsigned base, unsigned length
645 @@ -48,6 +49,7 @@ void Bus::map(
646 if(mode == MapMode::Shadow) destaddr = mirror(base + destaddr, length);
647 lookup[(bank << 16) | addr] = id;
648 target[(bank << 16) | addr] = destaddr;
649 + if(mclass) classmap[(bank << 16) | addr] = mclass;
653 @@ -57,23 +59,58 @@ void Bus::map_reset() {
654 function<void (unsigned, uint8)> writer = [](unsigned, uint8) {};
656 idcount = 0;
657 - map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, reader, writer);
658 + map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, 0xFF, reader, writer);
661 void Bus::map_xml() {
662 for(auto &m : cartridge.mapping) {
663 - map(m.mode, m.banklo, m.bankhi, m.addrlo, m.addrhi, m.read, m.write, m.offset, m.size);
664 + map(m.mode, m.banklo, m.bankhi, m.addrlo, m.addrhi, (unsigned)m.clazz, m.read, m.write, m.offset, m.size);
668 +unsigned Bus::enumerateMirrors(uint8 clazz, uint32 offset, unsigned start)
670 + unsigned i;
671 + for(i = start; i < 0x1000000; i++)
672 + if((classmap[i] == clazz && target[i] == offset) || (i == offset && clazz == 255))
673 + return i;
674 + return i;
677 +void Bus::clearDebugFlags()
679 + u_debugflags = 0;
680 + memset(debugflags, 0, 0x1000000);
683 +void Bus::debugFlags(uint8 setf, uint8 clrf)
685 + u_debugflags = (u_debugflags | setf) & ~clrf;
688 +void Bus::debugFlags(uint8 setf, uint8 clrf, uint8 clazz, uint32 offset)
690 + if(clazz == 255) {
691 + setf <<= 3;
692 + clrf <<= 3;
693 + debugflags[offset] = (debugflags[offset] | setf) & ~clrf;
694 + } else
695 + for(unsigned i = 0; i < 0x1000000; i++)
696 + if(classmap[i] == clazz && target[i] == offset)
697 + debugflags[i] = (debugflags[i] | setf) & ~clrf;
700 Bus::Bus() {
701 - lookup = new uint8 [16 * 1024 * 1024];
702 - target = new uint32[16 * 1024 * 1024];
703 + u_debugflags = 0;
704 + lookup = new uint8 [112 * 1024 * 1024];
705 + target = (uint32*)(lookup + 0x3000000);
706 + classmap = lookup + 0x1000000;
707 + debugflags = lookup + 0x2000000;
708 + memset(debugflags, 0, 0x1000000);
711 Bus::~Bus() {
712 delete[] lookup;
713 - delete[] target;
717 diff --git a/snes/memory/memory.hpp b/snes/memory/memory.hpp
718 index 634e071..c20e14d 100755
719 --- a/snes/memory/memory.hpp
720 +++ b/snes/memory/memory.hpp
721 @@ -44,10 +44,13 @@ private:
722 struct Bus {
723 unsigned mirror(unsigned addr, unsigned size);
725 - alwaysinline uint8 read(unsigned addr);
726 + alwaysinline uint8 read(unsigned addr, bool exec);
727 alwaysinline void write(unsigned addr, uint8 data);
729 uint8 *lookup;
730 + uint8 *classmap;
731 + uint8 *debugflags;
732 + uint8 u_debugflags;
733 uint32 *target;
735 unsigned idcount;
736 @@ -59,6 +62,7 @@ struct Bus {
737 MapMode mode,
738 unsigned bank_lo, unsigned bank_hi,
739 unsigned addr_lo, unsigned addr_hi,
740 + unsigned mclass,
741 const function<uint8 (unsigned)> &read,
742 const function<void (unsigned, uint8)> &write,
743 unsigned base = 0, unsigned length = 0
744 @@ -67,6 +71,13 @@ struct Bus {
745 void map_reset();
746 void map_xml();
748 + void clearDebugFlags();
749 + void debugFlags(uint8 setf, uint8 clrf);
750 + void debugFlags(uint8 setf, uint8 clrf, uint8 clazz, uint32 offset);
751 + unsigned enumerateMirrors(uint8 clazz, uint32 offset, unsigned start);
752 + function<void (uint8, unsigned, unsigned, uint8, bool)> debug_read;
753 + function<void (uint8, unsigned, unsigned, uint8)> debug_write;
755 Bus();
756 ~Bus();
758 diff --git a/snes/ppu/ppu.cpp b/snes/ppu/ppu.cpp
759 index 8545175..13e231c 100755
760 --- a/snes/ppu/ppu.cpp
761 +++ b/snes/ppu/ppu.cpp
762 @@ -87,8 +87,8 @@ void PPU::enable() {
763 function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
764 function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
766 - bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
767 - bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
768 + bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, 0, read, write);
769 + bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, 0, read, write);
772 void PPU::power() {
773 diff --git a/snes/smp/core/core.hpp b/snes/smp/core/core.hpp
774 index 1489fce..13d6936 100755
775 --- a/snes/smp/core/core.hpp
776 +++ b/snes/smp/core/core.hpp
777 @@ -2,7 +2,7 @@ struct SMPcore {
778 virtual void op_io() = 0;
779 virtual uint8 op_read(uint16 addr) = 0;
780 virtual void op_write(uint16 addr, uint8 data) = 0;
781 - void op_step();
782 + virtual void op_step();
784 #include "registers.hpp"
785 #include "memory.hpp"
786 diff --git a/snes/snes.hpp b/snes/snes.hpp
787 index dffeeee..37ed1fe 100755
788 --- a/snes/snes.hpp
789 +++ b/snes/snes.hpp
790 @@ -1,5 +1,6 @@
791 #ifndef SNES_HPP
792 #define SNES_HPP
793 +#define BSNES_SUPPORTS_ADV_BREAKPOINTS
795 namespace SNES {
796 namespace Info {
798 2.1.4