Update to v098r16 release.

byuu says:

Changelog:
- GNUmakefile: reverted $(call unique,) to $(strip)
- processor/r6502: removed templates; reduces object size from 146.5kb
  to 107.6kb
- processor/lr35902: removed templates; reduces object size from 386.2kb
  to 197.4kb
- processor/spc700: merged op macros for switch table declarations
- sfc/coprocessor/sa1: partial cleanups; flattened directory structure
- sfc/coprocessor/superfx: partial cleanups; flattened directory structure
- sfc/coprocessor/icd2: flattened directory structure
- gb/ppu: changed behavior of STAT IRQs

Major caveat! The GB/GBC STAT IRQ changes has a major bug in it somewhere
that's seriously breaking most games. I'm pushing the WIP anyway, because
I believe the changes to be mostly correct. I'd like to get more people
looking at these changes, and also try more heavy-handed hacking and
diff comparison logging between the previous WIP and this one.
This commit is contained in:
Tim Allen 2016-06-05 15:03:21 +10:00
parent 20ac95ee49
commit 3681961ca5
47 changed files with 1432 additions and 1433 deletions

View File

@ -9,7 +9,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "098.15";
static const string Version = "098.16";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -44,32 +44,38 @@ auto CPU::interrupt_raise(CPU::Interrupt id) -> void {
}
}
auto CPU::interrupt_lower(CPU::Interrupt id) -> void {
if(id == Interrupt::Stat) {
status.interrupt_request_stat = 0;
}
}
auto CPU::interrupt_test() -> void {
if(r.ime) {
if(status.interrupt_request_vblank && status.interrupt_enable_vblank) {
status.interrupt_request_vblank = 0;
return interrupt_exec(0x0040);
}
if(!r.ime) return;
if(status.interrupt_request_stat && status.interrupt_enable_stat) {
status.interrupt_request_stat = 0;
return interrupt_exec(0x0048);
}
if(status.interrupt_request_vblank && status.interrupt_enable_vblank) {
status.interrupt_request_vblank = 0;
return interrupt_exec(0x0040);
}
if(status.interrupt_request_timer && status.interrupt_enable_timer) {
status.interrupt_request_timer = 0;
return interrupt_exec(0x0050);
}
if(status.interrupt_request_stat && status.interrupt_enable_stat) {
status.interrupt_request_stat = 0;
return interrupt_exec(0x0048);
}
if(status.interrupt_request_serial && status.interrupt_enable_serial) {
status.interrupt_request_serial = 0;
return interrupt_exec(0x0058);
}
if(status.interrupt_request_timer && status.interrupt_enable_timer) {
status.interrupt_request_timer = 0;
return interrupt_exec(0x0050);
}
if(status.interrupt_request_joypad && status.interrupt_enable_joypad) {
status.interrupt_request_joypad = 0;
return interrupt_exec(0x0060);
}
if(status.interrupt_request_serial && status.interrupt_enable_serial) {
status.interrupt_request_serial = 0;
return interrupt_exec(0x0058);
}
if(status.interrupt_request_joypad && status.interrupt_enable_joypad) {
status.interrupt_request_joypad = 0;
return interrupt_exec(0x0060);
}
}

View File

@ -4,6 +4,7 @@ struct CPU : Processor::LR35902, Thread, MMIO {
static auto Enter() -> void;
auto main() -> void;
auto interrupt_raise(Interrupt id) -> void;
auto interrupt_lower(Interrupt id) -> void;
auto interrupt_test() -> void;
auto interrupt_exec(uint16 pc) -> void;
auto stop() -> bool;

View File

@ -24,18 +24,12 @@ auto PPU::mmio_read(uint16 addr) -> uint8 {
}
if(addr == 0xff41) { //STAT
uint mode;
if(status.ly >= 144) mode = 1; //Vblank
else if(status.lx < 80) mode = 2; //OAM
else if(status.lx < 252) mode = 3; //LCD
else mode = 0; //Hblank
return (status.interrupt_lyc << 6)
| (status.interrupt_oam << 5)
| (status.interrupt_vblank << 4)
| (status.interrupt_hblank << 3)
| ((status.ly == status.lyc) << 2)
| (mode << 0);
| (status.mode << 0);
}
if(addr == 0xff42) { //SCY

View File

@ -1,11 +1,5 @@
#include <gb/gb.hpp>
//LY = 0-153
//Raster = 0-143
//Vblank = 144-153
//LX = 0-455
namespace GameBoy {
PPU ppu;
@ -22,53 +16,74 @@ auto PPU::main() -> void {
status.lx = 0;
interface->lcdScanline(); //Super Game Boy notification
if(status.display_enable) {
//LYC of zero triggers on LY==153
if((status.lyc && status.ly == status.lyc) || (!status.lyc && status.ly == 153)) {
if(status.interrupt_lyc) cpu.interrupt_raise(CPU::Interrupt::Stat);
}
if(status.display_enable && status.ly <= 143) {
mode(2);
scanline();
wait(92);
if(status.ly <= 143) {
scanline();
if(status.interrupt_oam) cpu.interrupt_raise(CPU::Interrupt::Stat);
}
if(status.ly == 144) {
if(status.interrupt_vblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
else if(status.interrupt_oam) cpu.interrupt_raise(CPU::Interrupt::Stat); //hardware quirk
cpu.interrupt_raise(CPU::Interrupt::Vblank);
}
}
add_clocks(92);
if(status.ly <= 143) {
mode(3);
for(auto n : range(160)) {
if(status.display_enable) run();
add_clocks(1);
run();
wait(1);
}
if(status.display_enable) {
if(status.interrupt_hblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
cpu.hblank();
}
mode(0);
cpu.hblank();
wait(204);
} else {
add_clocks(160);
mode(1);
wait(456);
}
add_clocks(204);
status.ly++;
if(++status.ly == 154) {
status.ly = 0;
if(status.ly == 144) {
cpu.interrupt_raise(CPU::Interrupt::Vblank);
scheduler.exit(Scheduler::Event::Frame);
}
if(status.ly == 154) {
status.ly = 0;
}
}
auto PPU::mode(uint mode) -> void {
status.mode = mode;
bool irq = status.irq;
if(status.mode == 0) { //hblank
status.irq = status.interrupt_hblank;
}
if(status.mode == 1) { //vblank
status.irq = status.interrupt_vblank || (status.interrupt_lyc && coincidence());
}
if(status.mode == 2) { //oam
status.irq = status.interrupt_oam || (status.interrupt_lyc && coincidence());
}
if(status.mode == 3) { //render
status.irq = false;
}
if(!irq && status.irq) {
cpu.interrupt_raise(CPU::Interrupt::Stat);
} else if(!status.irq) {
cpu.interrupt_lower(CPU::Interrupt::Stat);
}
}
auto PPU::coincidence() -> bool {
//LYC of zero triggers on LYC=153
return (status.lyc && status.ly == status.lyc) || (!status.lyc && status.ly == 153);
}
auto PPU::refresh() -> void {
if(!system.sgb()) Emulator::video.refresh(screen, 160 * sizeof(uint32), 160, 144);
}
auto PPU::add_clocks(uint clocks) -> void {
auto PPU::wait(uint clocks) -> void {
while(clocks--) {
if(status.dma_active) {
uint hi = status.dma_clock++;
@ -93,10 +108,10 @@ auto PPU::add_clocks(uint clocks) -> void {
}
auto PPU::hflip(uint data) const -> uint {
return ((data & 0x8080) >> 7) | ((data & 0x4040) >> 5)
| ((data & 0x2020) >> 3) | ((data & 0x1010) >> 1)
| ((data & 0x0808) << 1) | ((data & 0x0404) << 3)
| ((data & 0x0202) << 5) | ((data & 0x0101) << 7);
return (data & 0x8080) >> 7 | (data & 0x4040) >> 5
| (data & 0x2020) >> 3 | (data & 0x1010) >> 1
| (data & 0x0808) << 1 | (data & 0x0404) << 3
| (data & 0x0202) << 5 | (data & 0x0101) << 7;
}
auto PPU::power() -> void {
@ -142,6 +157,7 @@ auto PPU::power() -> void {
for(auto& n : bgpd) n = 0x0000;
for(auto& n : obpd) n = 0x0000;
status.irq = false;
status.lx = 0;
status.display_enable = 0;
@ -157,6 +173,7 @@ auto PPU::power() -> void {
status.interrupt_oam = 0;
status.interrupt_vblank = 0;
status.interrupt_hblank = 0;
status.mode = 0;
status.scy = 0;
status.scx = 0;

View File

@ -1,8 +1,10 @@
struct PPU : Thread, MMIO {
static auto Enter() -> void;
auto main() -> void;
auto mode(uint) -> void;
auto coincidence() -> bool;
auto refresh() -> void;
auto add_clocks(uint clocks) -> void;
auto wait(uint clocks) -> void;
auto hflip(uint data) const -> uint;
@ -42,6 +44,7 @@ struct PPU : Thread, MMIO {
function<auto () -> void> run;
struct Status {
bool irq; //STAT IRQ line
uint lx;
//$ff40 LCDC
@ -59,6 +62,7 @@ struct PPU : Thread, MMIO {
bool interrupt_oam;
bool interrupt_vblank;
bool interrupt_hblank;
uint2 mode;
//$ff42 SCY
uint8 scy;

View File

@ -9,6 +9,7 @@ auto PPU::serialize(serializer& s) -> void {
s.array(bgpd);
s.array(obpd);
s.integer(status.irq);
s.integer(status.lx);
s.integer(status.display_enable);
@ -24,6 +25,7 @@ auto PPU::serialize(serializer& s) -> void {
s.integer(status.interrupt_oam);
s.integer(status.interrupt_vblank);
s.integer(status.interrupt_hblank);
s.integer(status.mode);
s.integer(status.scy);
s.integer(status.scx);

View File

@ -7,19 +7,19 @@ auto LR35902::op_cb() {
//8-bit load commands
template<uint x, uint y> auto LR35902::op_ld_r_r() {
auto LR35902::op_ld_r_r(uint x, uint y) {
r[x] = r[y];
}
template<uint x> auto LR35902::op_ld_r_n() {
auto LR35902::op_ld_r_n(uint x) {
r[x] = op_read(r[PC]++);
}
template<uint x> auto LR35902::op_ld_r_hl() {
auto LR35902::op_ld_r_hl(uint x) {
r[x] = op_read(r[HL]);
}
template<uint x> auto LR35902::op_ld_hl_r() {
auto LR35902::op_ld_hl_r(uint x) {
op_write(r[HL], r[x]);
}
@ -27,7 +27,7 @@ auto LR35902::op_ld_hl_n() {
op_write(r[HL], op_read(r[PC]++));
}
template<uint x> auto LR35902::op_ld_a_rr() {
auto LR35902::op_ld_a_rr(uint x) {
r[A] = op_read(r[x]);
}
@ -37,7 +37,7 @@ auto LR35902::op_ld_a_nn() {
r[A] = op_read((hi << 8) | (lo << 0));
}
template<uint x> auto LR35902::op_ld_rr_a() {
auto LR35902::op_ld_rr_a(uint x) {
op_write(r[x], r[A]);
}
@ -85,7 +85,7 @@ auto LR35902::op_ldd_a_hl() {
//16-bit load commands
template<uint x> auto LR35902::op_ld_rr_nn() {
auto LR35902::op_ld_rr_nn(uint x) {
r[x] = op_read(r[PC]++) << 0;
r[x] |= op_read(r[PC]++) << 8;
}
@ -102,13 +102,13 @@ auto LR35902::op_ld_sp_hl() {
op_io();
}
template<uint x> auto LR35902::op_push_rr() {
auto LR35902::op_push_rr(uint x) {
op_io();
op_write(--r[SP], r[x] >> 8);
op_write(--r[SP], r[x] >> 0);
}
template<uint x> auto LR35902::op_pop_rr() {
auto LR35902::op_pop_rr(uint x) {
r[x] = op_read(r[SP]++) << 0;
r[x] |= op_read(r[SP]++) << 8;
}
@ -125,7 +125,7 @@ auto LR35902::opi_add_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<uint x> auto LR35902::op_add_a_r() { opi_add_a(r[x]); }
auto LR35902::op_add_a_r(uint x) { opi_add_a(r[x]); }
auto LR35902::op_add_a_n() { opi_add_a(op_read(r[PC]++)); }
auto LR35902::op_add_a_hl() { opi_add_a(op_read(r[HL])); }
@ -139,7 +139,7 @@ auto LR35902::opi_adc_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<uint x> auto LR35902::op_adc_a_r() { opi_adc_a(r[x]); }
auto LR35902::op_adc_a_r(uint x) { opi_adc_a(r[x]); }
auto LR35902::op_adc_a_n() { opi_adc_a(op_read(r[PC]++)); }
auto LR35902::op_adc_a_hl() { opi_adc_a(op_read(r[HL])); }
@ -153,7 +153,7 @@ auto LR35902::opi_sub_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<uint x> auto LR35902::op_sub_a_r() { opi_sub_a(r[x]); }
auto LR35902::op_sub_a_r(uint x) { opi_sub_a(r[x]); }
auto LR35902::op_sub_a_n() { opi_sub_a(op_read(r[PC]++)); }
auto LR35902::op_sub_a_hl() { opi_sub_a(op_read(r[HL])); }
@ -167,7 +167,7 @@ auto LR35902::opi_sbc_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<uint x> auto LR35902::op_sbc_a_r() { opi_sbc_a(r[x]); }
auto LR35902::op_sbc_a_r(uint x) { opi_sbc_a(r[x]); }
auto LR35902::op_sbc_a_n() { opi_sbc_a(op_read(r[PC]++)); }
auto LR35902::op_sbc_a_hl() { opi_sbc_a(op_read(r[HL])); }
@ -179,7 +179,7 @@ auto LR35902::opi_and_a(uint8 x) {
r.f.c = 0;
}
template<uint x> auto LR35902::op_and_a_r() { opi_and_a(r[x]); }
auto LR35902::op_and_a_r(uint x) { opi_and_a(r[x]); }
auto LR35902::op_and_a_n() { opi_and_a(op_read(r[PC]++)); }
auto LR35902::op_and_a_hl() { opi_and_a(op_read(r[HL])); }
@ -191,7 +191,7 @@ auto LR35902::opi_xor_a(uint8 x) {
r.f.c = 0;
}
template<uint x> auto LR35902::op_xor_a_r() { opi_xor_a(r[x]); }
auto LR35902::op_xor_a_r(uint x) { opi_xor_a(r[x]); }
auto LR35902::op_xor_a_n() { opi_xor_a(op_read(r[PC]++)); }
auto LR35902::op_xor_a_hl() { opi_xor_a(op_read(r[HL])); }
@ -203,7 +203,7 @@ auto LR35902::opi_or_a(uint8 x) {
r.f.c = 0;
}
template<uint x> auto LR35902::op_or_a_r() { opi_or_a(r[x]); }
auto LR35902::op_or_a_r(uint x) { opi_or_a(r[x]); }
auto LR35902::op_or_a_n() { opi_or_a(op_read(r[PC]++)); }
auto LR35902::op_or_a_hl() { opi_or_a(op_read(r[HL])); }
@ -216,11 +216,11 @@ auto LR35902::opi_cp_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<uint x> auto LR35902::op_cp_a_r() { opi_cp_a(r[x]); }
auto LR35902::op_cp_a_r(uint x) { opi_cp_a(r[x]); }
auto LR35902::op_cp_a_n() { opi_cp_a(op_read(r[PC]++)); }
auto LR35902::op_cp_a_hl() { opi_cp_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_inc_r() {
auto LR35902::op_inc_r(uint x) {
r[x]++;
r.f.z = r[x] == 0;
r.f.n = 0;
@ -235,7 +235,7 @@ auto LR35902::op_inc_hl() {
r.f.h = (n & 0x0f) == 0x00;
}
template<uint x> auto LR35902::op_dec_r() {
auto LR35902::op_dec_r(uint x) {
r[x]--;
r.f.z = r[x] == 0;
r.f.n = 1;
@ -276,7 +276,7 @@ auto LR35902::op_cpl() {
//16-bit arithmetic commands
template<uint x> auto LR35902::op_add_hl_rr() {
auto LR35902::op_add_hl_rr(uint x) {
op_io();
uint32 rb = (r[HL] + r[x]);
uint32 rn = (r[HL] & 0xfff) + (r[x] & 0xfff);
@ -286,12 +286,12 @@ template<uint x> auto LR35902::op_add_hl_rr() {
r.f.c = rb > 0xffff;
}
template<uint x> auto LR35902::op_inc_rr() {
auto LR35902::op_inc_rr(uint x) {
op_io();
r[x]++;
}
template<uint x> auto LR35902::op_dec_rr() {
auto LR35902::op_dec_rr(uint x) {
op_io();
r[x]--;
}
@ -353,7 +353,7 @@ auto LR35902::op_rra() {
r.f.c = c;
}
template<uint x> auto LR35902::op_rlc_r() {
auto LR35902::op_rlc_r(uint x) {
r[x] = (r[x] << 1) | (r[x] >> 7);
r.f.z = r[x] == 0;
r.f.n = 0;
@ -371,7 +371,7 @@ auto LR35902::op_rlc_hl() {
r.f.c = n & 0x01;
}
template<uint x> auto LR35902::op_rl_r() {
auto LR35902::op_rl_r(uint x) {
bool c = r[x] & 0x80;
r[x] = (r[x] << 1) | (r.f.c << 0);
r.f.z = r[x] == 0;
@ -391,7 +391,7 @@ auto LR35902::op_rl_hl() {
r.f.c = c;
}
template<uint x> auto LR35902::op_rrc_r() {
auto LR35902::op_rrc_r(uint x) {
r[x] = (r[x] >> 1) | (r[x] << 7);
r.f.z = r[x] == 0;
r.f.n = 0;
@ -409,7 +409,7 @@ auto LR35902::op_rrc_hl() {
r.f.c = n & 0x80;
}
template<uint x> auto LR35902::op_rr_r() {
auto LR35902::op_rr_r(uint x) {
bool c = r[x] & 0x01;
r[x] = (r[x] >> 1) | (r.f.c << 7);
r.f.z = r[x] == 0;
@ -429,7 +429,7 @@ auto LR35902::op_rr_hl() {
r.f.c = c;
}
template<uint x> auto LR35902::op_sla_r() {
auto LR35902::op_sla_r(uint x) {
bool c = r[x] & 0x80;
r[x] <<= 1;
r.f.z = r[x] == 0;
@ -449,7 +449,7 @@ auto LR35902::op_sla_hl() {
r.f.c = c;
}
template<uint x> auto LR35902::op_swap_r() {
auto LR35902::op_swap_r(uint x) {
r[x] = (r[x] << 4) | (r[x] >> 4);
r.f.z = r[x] == 0;
r.f.n = 0;
@ -467,7 +467,7 @@ auto LR35902::op_swap_hl() {
r.f.c = 0;
}
template<uint x> auto LR35902::op_sra_r() {
auto LR35902::op_sra_r(uint x) {
bool c = r[x] & 0x01;
r[x] = (int8)r[x] >> 1;
r.f.z = r[x] == 0;
@ -487,7 +487,7 @@ auto LR35902::op_sra_hl() {
r.f.c = c;
}
template<uint x> auto LR35902::op_srl_r() {
auto LR35902::op_srl_r(uint x) {
bool c = r[x] & 0x01;
r[x] >>= 1;
r.f.z = r[x] == 0;
@ -509,34 +509,34 @@ auto LR35902::op_srl_hl() {
//single-bit commands
template<uint b, uint x> auto LR35902::op_bit_n_r() {
auto LR35902::op_bit_n_r(uint b, uint x) {
r.f.z = (r[x] & (1 << b)) == 0;
r.f.n = 0;
r.f.h = 1;
}
template<uint b> auto LR35902::op_bit_n_hl() {
auto LR35902::op_bit_n_hl(uint b) {
uint8 n = op_read(r[HL]);
r.f.z = (n & (1 << b)) == 0;
r.f.n = 0;
r.f.h = 1;
}
template<uint b, uint x> auto LR35902::op_set_n_r() {
auto LR35902::op_set_n_r(uint b, uint x) {
r[x] |= 1 << b;
}
template<uint b> auto LR35902::op_set_n_hl() {
auto LR35902::op_set_n_hl(uint b) {
uint8 n = op_read(r[HL]);
n |= 1 << b;
op_write(r[HL], n);
}
template<uint b, uint x> auto LR35902::op_res_n_r() {
auto LR35902::op_res_n_r(uint b, uint x) {
r[x] &= ~(1 << b);
}
template<uint b> auto LR35902::op_res_n_hl() {
auto LR35902::op_res_n_hl(uint b) {
uint n = op_read(r[HL]);
n &= ~(1 << b);
op_write(r[HL], n);
@ -592,7 +592,7 @@ auto LR35902::op_jp_hl() {
r[PC] = r[HL];
}
template<uint x, bool y> auto LR35902::op_jp_f_nn() {
auto LR35902::op_jp_f_nn(uint x, bool y) {
uint8 lo = op_read(r[PC]++);
uint8 hi = op_read(r[PC]++);
if(r.f[x] == y) {
@ -607,7 +607,7 @@ auto LR35902::op_jr_n() {
op_io();
}
template<uint x, bool y> auto LR35902::op_jr_f_n() {
auto LR35902::op_jr_f_n(uint x, bool y) {
int8 n = op_read(r[PC]++);
if(r.f[x] == y) {
r[PC] += n;
@ -624,7 +624,7 @@ auto LR35902::op_call_nn() {
r[PC] = (hi << 8) | (lo << 0);
}
template<uint x, bool y> auto LR35902::op_call_f_nn() {
auto LR35902::op_call_f_nn(uint x, bool y) {
uint8 lo = op_read(r[PC]++);
uint8 hi = op_read(r[PC]++);
if(r.f[x] == y) {
@ -642,7 +642,7 @@ auto LR35902::op_ret() {
op_io();
}
template<uint x, bool y> auto LR35902::op_ret_f() {
auto LR35902::op_ret_f(uint x, bool y) {
op_io();
if(r.f[x] == y) {
uint8 lo = op_read(r[SP]++);
@ -660,7 +660,7 @@ auto LR35902::op_reti() {
r.ime = 1;
}
template<uint n> auto LR35902::op_rst_n() {
auto LR35902::op_rst_n(uint n) {
op_io();
op_write(--r[SP], r[PC] >> 8);
op_write(--r[SP], r[PC] >> 0);

View File

@ -18,237 +18,237 @@ auto LR35902::exec() -> void {
uint8 opcode = op_read(r[PC]++);
switch(opcode) {
case 0x00: return op_nop();
case 0x01: return op_ld_rr_nn<BC>();
case 0x02: return op_ld_rr_a<BC>();
case 0x03: return op_inc_rr<BC>();
case 0x04: return op_inc_r<B>();
case 0x05: return op_dec_r<B>();
case 0x06: return op_ld_r_n<B>();
case 0x01: return op_ld_rr_nn(BC);
case 0x02: return op_ld_rr_a(BC);
case 0x03: return op_inc_rr(BC);
case 0x04: return op_inc_r(B);
case 0x05: return op_dec_r(B);
case 0x06: return op_ld_r_n(B);
case 0x07: return op_rlca();
case 0x08: return op_ld_nn_sp();
case 0x09: return op_add_hl_rr<BC>();
case 0x0a: return op_ld_a_rr<BC>();
case 0x0b: return op_dec_rr<BC>();
case 0x0c: return op_inc_r<C>();
case 0x0d: return op_dec_r<C>();
case 0x0e: return op_ld_r_n<C>();
case 0x09: return op_add_hl_rr(BC);
case 0x0a: return op_ld_a_rr(BC);
case 0x0b: return op_dec_rr(BC);
case 0x0c: return op_inc_r(C);
case 0x0d: return op_dec_r(C);
case 0x0e: return op_ld_r_n(C);
case 0x0f: return op_rrca();
case 0x10: return op_stop();
case 0x11: return op_ld_rr_nn<DE>();
case 0x12: return op_ld_rr_a<DE>();
case 0x13: return op_inc_rr<DE>();
case 0x14: return op_inc_r<D>();
case 0x15: return op_dec_r<D>();
case 0x16: return op_ld_r_n<D>();
case 0x11: return op_ld_rr_nn(DE);
case 0x12: return op_ld_rr_a(DE);
case 0x13: return op_inc_rr(DE);
case 0x14: return op_inc_r(D);
case 0x15: return op_dec_r(D);
case 0x16: return op_ld_r_n(D);
case 0x17: return op_rla();
case 0x18: return op_jr_n();
case 0x19: return op_add_hl_rr<DE>();
case 0x1a: return op_ld_a_rr<DE>();
case 0x1b: return op_dec_rr<DE>();
case 0x1c: return op_inc_r<E>();
case 0x1d: return op_dec_r<E>();
case 0x1e: return op_ld_r_n<E>();
case 0x19: return op_add_hl_rr(DE);
case 0x1a: return op_ld_a_rr(DE);
case 0x1b: return op_dec_rr(DE);
case 0x1c: return op_inc_r(E);
case 0x1d: return op_dec_r(E);
case 0x1e: return op_ld_r_n(E);
case 0x1f: return op_rra();
case 0x20: return op_jr_f_n<ZF, 0>();
case 0x21: return op_ld_rr_nn<HL>();
case 0x20: return op_jr_f_n(ZF, 0);
case 0x21: return op_ld_rr_nn(HL);
case 0x22: return op_ldi_hl_a();
case 0x23: return op_inc_rr<HL>();
case 0x24: return op_inc_r<H>();
case 0x25: return op_dec_r<H>();
case 0x26: return op_ld_r_n<H>();
case 0x23: return op_inc_rr(HL);
case 0x24: return op_inc_r(H);
case 0x25: return op_dec_r(H);
case 0x26: return op_ld_r_n(H);
case 0x27: return op_daa();
case 0x28: return op_jr_f_n<ZF, 1>();
case 0x29: return op_add_hl_rr<HL>();
case 0x28: return op_jr_f_n(ZF, 1);
case 0x29: return op_add_hl_rr(HL);
case 0x2a: return op_ldi_a_hl();
case 0x2b: return op_dec_rr<HL>();
case 0x2c: return op_inc_r<L>();
case 0x2d: return op_dec_r<L>();
case 0x2e: return op_ld_r_n<L>();
case 0x2b: return op_dec_rr(HL);
case 0x2c: return op_inc_r(L);
case 0x2d: return op_dec_r(L);
case 0x2e: return op_ld_r_n(L);
case 0x2f: return op_cpl();
case 0x30: return op_jr_f_n<CF, 0>();
case 0x31: return op_ld_rr_nn<SP>();
case 0x30: return op_jr_f_n(CF, 0);
case 0x31: return op_ld_rr_nn(SP);
case 0x32: return op_ldd_hl_a();
case 0x33: return op_inc_rr<SP>();
case 0x33: return op_inc_rr(SP);
case 0x34: return op_inc_hl();
case 0x35: return op_dec_hl();
case 0x36: return op_ld_hl_n();
case 0x37: return op_scf();
case 0x38: return op_jr_f_n<CF, 1>();
case 0x39: return op_add_hl_rr<SP>();
case 0x38: return op_jr_f_n(CF, 1);
case 0x39: return op_add_hl_rr(SP);
case 0x3a: return op_ldd_a_hl();
case 0x3b: return op_dec_rr<SP>();
case 0x3c: return op_inc_r<A>();
case 0x3d: return op_dec_r<A>();
case 0x3e: return op_ld_r_n<A>();
case 0x3b: return op_dec_rr(SP);
case 0x3c: return op_inc_r(A);
case 0x3d: return op_dec_r(A);
case 0x3e: return op_ld_r_n(A);
case 0x3f: return op_ccf();
case 0x40: return op_ld_r_r<B, B>();
case 0x41: return op_ld_r_r<B, C>();
case 0x42: return op_ld_r_r<B, D>();
case 0x43: return op_ld_r_r<B, E>();
case 0x44: return op_ld_r_r<B, H>();
case 0x45: return op_ld_r_r<B, L>();
case 0x46: return op_ld_r_hl<B>();
case 0x47: return op_ld_r_r<B, A>();
case 0x48: return op_ld_r_r<C, B>();
case 0x49: return op_ld_r_r<C, C>();
case 0x4a: return op_ld_r_r<C, D>();
case 0x4b: return op_ld_r_r<C, E>();
case 0x4c: return op_ld_r_r<C, H>();
case 0x4d: return op_ld_r_r<C, L>();
case 0x4e: return op_ld_r_hl<C>();
case 0x4f: return op_ld_r_r<C, A>();
case 0x50: return op_ld_r_r<D, B>();
case 0x51: return op_ld_r_r<D, C>();
case 0x52: return op_ld_r_r<D, D>();
case 0x53: return op_ld_r_r<D, E>();
case 0x54: return op_ld_r_r<D, H>();
case 0x55: return op_ld_r_r<D, L>();
case 0x56: return op_ld_r_hl<D>();
case 0x57: return op_ld_r_r<D, A>();
case 0x58: return op_ld_r_r<E, B>();
case 0x59: return op_ld_r_r<E, C>();
case 0x5a: return op_ld_r_r<E, D>();
case 0x5b: return op_ld_r_r<E, E>();
case 0x5c: return op_ld_r_r<E, H>();
case 0x5d: return op_ld_r_r<E, L>();
case 0x5e: return op_ld_r_hl<E>();
case 0x5f: return op_ld_r_r<E, A>();
case 0x60: return op_ld_r_r<H, B>();
case 0x61: return op_ld_r_r<H, C>();
case 0x62: return op_ld_r_r<H, D>();
case 0x63: return op_ld_r_r<H, E>();
case 0x64: return op_ld_r_r<H, H>();
case 0x65: return op_ld_r_r<H, L>();
case 0x66: return op_ld_r_hl<H>();
case 0x67: return op_ld_r_r<H, A>();
case 0x68: return op_ld_r_r<L, B>();
case 0x69: return op_ld_r_r<L, C>();
case 0x6a: return op_ld_r_r<L, D>();
case 0x6b: return op_ld_r_r<L, E>();
case 0x6c: return op_ld_r_r<L, H>();
case 0x6d: return op_ld_r_r<L, L>();
case 0x6e: return op_ld_r_hl<L>();
case 0x6f: return op_ld_r_r<L, A>();
case 0x70: return op_ld_hl_r<B>();
case 0x71: return op_ld_hl_r<C>();
case 0x72: return op_ld_hl_r<D>();
case 0x73: return op_ld_hl_r<E>();
case 0x74: return op_ld_hl_r<H>();
case 0x75: return op_ld_hl_r<L>();
case 0x40: return op_ld_r_r(B, B);
case 0x41: return op_ld_r_r(B, C);
case 0x42: return op_ld_r_r(B, D);
case 0x43: return op_ld_r_r(B, E);
case 0x44: return op_ld_r_r(B, H);
case 0x45: return op_ld_r_r(B, L);
case 0x46: return op_ld_r_hl(B);
case 0x47: return op_ld_r_r(B, A);
case 0x48: return op_ld_r_r(C, B);
case 0x49: return op_ld_r_r(C, C);
case 0x4a: return op_ld_r_r(C, D);
case 0x4b: return op_ld_r_r(C, E);
case 0x4c: return op_ld_r_r(C, H);
case 0x4d: return op_ld_r_r(C, L);
case 0x4e: return op_ld_r_hl(C);
case 0x4f: return op_ld_r_r(C, A);
case 0x50: return op_ld_r_r(D, B);
case 0x51: return op_ld_r_r(D, C);
case 0x52: return op_ld_r_r(D, D);
case 0x53: return op_ld_r_r(D, E);
case 0x54: return op_ld_r_r(D, H);
case 0x55: return op_ld_r_r(D, L);
case 0x56: return op_ld_r_hl(D);
case 0x57: return op_ld_r_r(D, A);
case 0x58: return op_ld_r_r(E, B);
case 0x59: return op_ld_r_r(E, C);
case 0x5a: return op_ld_r_r(E, D);
case 0x5b: return op_ld_r_r(E, E);
case 0x5c: return op_ld_r_r(E, H);
case 0x5d: return op_ld_r_r(E, L);
case 0x5e: return op_ld_r_hl(E);
case 0x5f: return op_ld_r_r(E, A);
case 0x60: return op_ld_r_r(H, B);
case 0x61: return op_ld_r_r(H, C);
case 0x62: return op_ld_r_r(H, D);
case 0x63: return op_ld_r_r(H, E);
case 0x64: return op_ld_r_r(H, H);
case 0x65: return op_ld_r_r(H, L);
case 0x66: return op_ld_r_hl(H);
case 0x67: return op_ld_r_r(H, A);
case 0x68: return op_ld_r_r(L, B);
case 0x69: return op_ld_r_r(L, C);
case 0x6a: return op_ld_r_r(L, D);
case 0x6b: return op_ld_r_r(L, E);
case 0x6c: return op_ld_r_r(L, H);
case 0x6d: return op_ld_r_r(L, L);
case 0x6e: return op_ld_r_hl(L);
case 0x6f: return op_ld_r_r(L, A);
case 0x70: return op_ld_hl_r(B);
case 0x71: return op_ld_hl_r(C);
case 0x72: return op_ld_hl_r(D);
case 0x73: return op_ld_hl_r(E);
case 0x74: return op_ld_hl_r(H);
case 0x75: return op_ld_hl_r(L);
case 0x76: return op_halt();
case 0x77: return op_ld_hl_r<A>();
case 0x78: return op_ld_r_r<A, B>();
case 0x79: return op_ld_r_r<A, C>();
case 0x7a: return op_ld_r_r<A, D>();
case 0x7b: return op_ld_r_r<A, E>();
case 0x7c: return op_ld_r_r<A, H>();
case 0x7d: return op_ld_r_r<A, L>();
case 0x7e: return op_ld_r_hl<A>();
case 0x7f: return op_ld_r_r<A, A>();
case 0x80: return op_add_a_r<B>();
case 0x81: return op_add_a_r<C>();
case 0x82: return op_add_a_r<D>();
case 0x83: return op_add_a_r<E>();
case 0x84: return op_add_a_r<H>();
case 0x85: return op_add_a_r<L>();
case 0x77: return op_ld_hl_r(A);
case 0x78: return op_ld_r_r(A, B);
case 0x79: return op_ld_r_r(A, C);
case 0x7a: return op_ld_r_r(A, D);
case 0x7b: return op_ld_r_r(A, E);
case 0x7c: return op_ld_r_r(A, H);
case 0x7d: return op_ld_r_r(A, L);
case 0x7e: return op_ld_r_hl(A);
case 0x7f: return op_ld_r_r(A, A);
case 0x80: return op_add_a_r(B);
case 0x81: return op_add_a_r(C);
case 0x82: return op_add_a_r(D);
case 0x83: return op_add_a_r(E);
case 0x84: return op_add_a_r(H);
case 0x85: return op_add_a_r(L);
case 0x86: return op_add_a_hl();
case 0x87: return op_add_a_r<A>();
case 0x88: return op_adc_a_r<B>();
case 0x89: return op_adc_a_r<C>();
case 0x8a: return op_adc_a_r<D>();
case 0x8b: return op_adc_a_r<E>();
case 0x8c: return op_adc_a_r<H>();
case 0x8d: return op_adc_a_r<L>();
case 0x87: return op_add_a_r(A);
case 0x88: return op_adc_a_r(B);
case 0x89: return op_adc_a_r(C);
case 0x8a: return op_adc_a_r(D);
case 0x8b: return op_adc_a_r(E);
case 0x8c: return op_adc_a_r(H);
case 0x8d: return op_adc_a_r(L);
case 0x8e: return op_adc_a_hl();
case 0x8f: return op_adc_a_r<A>();
case 0x90: return op_sub_a_r<B>();
case 0x91: return op_sub_a_r<C>();
case 0x92: return op_sub_a_r<D>();
case 0x93: return op_sub_a_r<E>();
case 0x94: return op_sub_a_r<H>();
case 0x95: return op_sub_a_r<L>();
case 0x8f: return op_adc_a_r(A);
case 0x90: return op_sub_a_r(B);
case 0x91: return op_sub_a_r(C);
case 0x92: return op_sub_a_r(D);
case 0x93: return op_sub_a_r(E);
case 0x94: return op_sub_a_r(H);
case 0x95: return op_sub_a_r(L);
case 0x96: return op_sub_a_hl();
case 0x97: return op_sub_a_r<A>();
case 0x98: return op_sbc_a_r<B>();
case 0x99: return op_sbc_a_r<C>();
case 0x9a: return op_sbc_a_r<D>();
case 0x9b: return op_sbc_a_r<E>();
case 0x9c: return op_sbc_a_r<H>();
case 0x9d: return op_sbc_a_r<L>();
case 0x97: return op_sub_a_r(A);
case 0x98: return op_sbc_a_r(B);
case 0x99: return op_sbc_a_r(C);
case 0x9a: return op_sbc_a_r(D);
case 0x9b: return op_sbc_a_r(E);
case 0x9c: return op_sbc_a_r(H);
case 0x9d: return op_sbc_a_r(L);
case 0x9e: return op_sbc_a_hl();
case 0x9f: return op_sbc_a_r<A>();
case 0xa0: return op_and_a_r<B>();
case 0xa1: return op_and_a_r<C>();
case 0xa2: return op_and_a_r<D>();
case 0xa3: return op_and_a_r<E>();
case 0xa4: return op_and_a_r<H>();
case 0xa5: return op_and_a_r<L>();
case 0x9f: return op_sbc_a_r(A);
case 0xa0: return op_and_a_r(B);
case 0xa1: return op_and_a_r(C);
case 0xa2: return op_and_a_r(D);
case 0xa3: return op_and_a_r(E);
case 0xa4: return op_and_a_r(H);
case 0xa5: return op_and_a_r(L);
case 0xa6: return op_and_a_hl();
case 0xa7: return op_and_a_r<A>();
case 0xa8: return op_xor_a_r<B>();
case 0xa9: return op_xor_a_r<C>();
case 0xaa: return op_xor_a_r<D>();
case 0xab: return op_xor_a_r<E>();
case 0xac: return op_xor_a_r<H>();
case 0xad: return op_xor_a_r<L>();
case 0xa7: return op_and_a_r(A);
case 0xa8: return op_xor_a_r(B);
case 0xa9: return op_xor_a_r(C);
case 0xaa: return op_xor_a_r(D);
case 0xab: return op_xor_a_r(E);
case 0xac: return op_xor_a_r(H);
case 0xad: return op_xor_a_r(L);
case 0xae: return op_xor_a_hl();
case 0xaf: return op_xor_a_r<A>();
case 0xb0: return op_or_a_r<B>();
case 0xb1: return op_or_a_r<C>();
case 0xb2: return op_or_a_r<D>();
case 0xb3: return op_or_a_r<E>();
case 0xb4: return op_or_a_r<H>();
case 0xb5: return op_or_a_r<L>();
case 0xaf: return op_xor_a_r(A);
case 0xb0: return op_or_a_r(B);
case 0xb1: return op_or_a_r(C);
case 0xb2: return op_or_a_r(D);
case 0xb3: return op_or_a_r(E);
case 0xb4: return op_or_a_r(H);
case 0xb5: return op_or_a_r(L);
case 0xb6: return op_or_a_hl();
case 0xb7: return op_or_a_r<A>();
case 0xb8: return op_cp_a_r<B>();
case 0xb9: return op_cp_a_r<C>();
case 0xba: return op_cp_a_r<D>();
case 0xbb: return op_cp_a_r<E>();
case 0xbc: return op_cp_a_r<H>();
case 0xbd: return op_cp_a_r<L>();
case 0xb7: return op_or_a_r(A);
case 0xb8: return op_cp_a_r(B);
case 0xb9: return op_cp_a_r(C);
case 0xba: return op_cp_a_r(D);
case 0xbb: return op_cp_a_r(E);
case 0xbc: return op_cp_a_r(H);
case 0xbd: return op_cp_a_r(L);
case 0xbe: return op_cp_a_hl();
case 0xbf: return op_cp_a_r<A>();
case 0xc0: return op_ret_f<ZF, 0>();
case 0xc1: return op_pop_rr<BC>();
case 0xc2: return op_jp_f_nn<ZF, 0>();
case 0xbf: return op_cp_a_r(A);
case 0xc0: return op_ret_f(ZF, 0);
case 0xc1: return op_pop_rr(BC);
case 0xc2: return op_jp_f_nn(ZF, 0);
case 0xc3: return op_jp_nn();
case 0xc4: return op_call_f_nn<ZF, 0>();
case 0xc5: return op_push_rr<BC>();
case 0xc4: return op_call_f_nn(ZF, 0);
case 0xc5: return op_push_rr(BC);
case 0xc6: return op_add_a_n();
case 0xc7: return op_rst_n<0x00>();
case 0xc8: return op_ret_f<ZF, 1>();
case 0xc7: return op_rst_n(0x00);
case 0xc8: return op_ret_f(ZF, 1);
case 0xc9: return op_ret();
case 0xca: return op_jp_f_nn<ZF, 1>();
case 0xca: return op_jp_f_nn(ZF, 1);
case 0xcb: return op_cb();
case 0xcc: return op_call_f_nn<ZF, 1>();
case 0xcc: return op_call_f_nn(ZF, 1);
case 0xcd: return op_call_nn();
case 0xce: return op_adc_a_n();
case 0xcf: return op_rst_n<0x08>();
case 0xd0: return op_ret_f<CF, 0>();
case 0xd1: return op_pop_rr<DE>();
case 0xd2: return op_jp_f_nn<CF, 0>();
case 0xcf: return op_rst_n(0x08);
case 0xd0: return op_ret_f(CF, 0);
case 0xd1: return op_pop_rr(DE);
case 0xd2: return op_jp_f_nn(CF, 0);
case 0xd3: return op_xx();
case 0xd4: return op_call_f_nn<CF, 0>();
case 0xd5: return op_push_rr<DE>();
case 0xd4: return op_call_f_nn(CF, 0);
case 0xd5: return op_push_rr(DE);
case 0xd6: return op_sub_a_n();
case 0xd7: return op_rst_n<0x10>();
case 0xd8: return op_ret_f<CF, 1>();
case 0xd7: return op_rst_n(0x10);
case 0xd8: return op_ret_f(CF, 1);
case 0xd9: return op_reti();
case 0xda: return op_jp_f_nn<CF, 1>();
case 0xda: return op_jp_f_nn(CF, 1);
case 0xdb: return op_xx();
case 0xdc: return op_call_f_nn<CF, 1>();
case 0xdc: return op_call_f_nn(CF, 1);
case 0xdd: return op_xx();
case 0xde: return op_sbc_a_n();
case 0xdf: return op_rst_n<0x18>();
case 0xdf: return op_rst_n(0x18);
case 0xe0: return op_ld_ffn_a();
case 0xe1: return op_pop_rr<HL>();
case 0xe1: return op_pop_rr(HL);
case 0xe2: return op_ld_ffc_a();
case 0xe3: return op_xx();
case 0xe4: return op_xx();
case 0xe5: return op_push_rr<HL>();
case 0xe5: return op_push_rr(HL);
case 0xe6: return op_and_a_n();
case 0xe7: return op_rst_n<0x20>();
case 0xe7: return op_rst_n(0x20);
case 0xe8: return op_add_sp_n();
case 0xe9: return op_jp_hl();
case 0xea: return op_ld_nn_a();
@ -256,15 +256,15 @@ auto LR35902::exec() -> void {
case 0xec: return op_xx();
case 0xed: return op_xx();
case 0xee: return op_xor_a_n();
case 0xef: return op_rst_n<0x28>();
case 0xef: return op_rst_n(0x28);
case 0xf0: return op_ld_a_ffn();
case 0xf1: return op_pop_rr<AF>();
case 0xf1: return op_pop_rr(AF);
case 0xf2: return op_ld_a_ffc();
case 0xf3: return op_di();
case 0xf4: return op_xx();
case 0xf5: return op_push_rr<AF>();
case 0xf5: return op_push_rr(AF);
case 0xf6: return op_or_a_n();
case 0xf7: return op_rst_n<0x30>();
case 0xf7: return op_rst_n(0x30);
case 0xf8: return op_ld_hl_sp_n();
case 0xf9: return op_ld_sp_hl();
case 0xfa: return op_ld_a_nn();
@ -272,269 +272,269 @@ auto LR35902::exec() -> void {
case 0xfc: return op_xx();
case 0xfd: return op_xx();
case 0xfe: return op_cp_a_n();
case 0xff: return op_rst_n<0x38>();
case 0xff: return op_rst_n(0x38);
}
}
auto LR35902::execCB() -> void {
uint8 opcode = op_read(r[PC]++);
switch(opcode) {
case 0x00: return op_rlc_r<B>();
case 0x01: return op_rlc_r<C>();
case 0x02: return op_rlc_r<D>();
case 0x03: return op_rlc_r<E>();
case 0x04: return op_rlc_r<H>();
case 0x05: return op_rlc_r<L>();
case 0x00: return op_rlc_r(B);
case 0x01: return op_rlc_r(C);
case 0x02: return op_rlc_r(D);
case 0x03: return op_rlc_r(E);
case 0x04: return op_rlc_r(H);
case 0x05: return op_rlc_r(L);
case 0x06: return op_rlc_hl();
case 0x07: return op_rlc_r<A>();
case 0x08: return op_rrc_r<B>();
case 0x09: return op_rrc_r<C>();
case 0x0a: return op_rrc_r<D>();
case 0x0b: return op_rrc_r<E>();
case 0x0c: return op_rrc_r<H>();
case 0x0d: return op_rrc_r<L>();
case 0x07: return op_rlc_r(A);
case 0x08: return op_rrc_r(B);
case 0x09: return op_rrc_r(C);
case 0x0a: return op_rrc_r(D);
case 0x0b: return op_rrc_r(E);
case 0x0c: return op_rrc_r(H);
case 0x0d: return op_rrc_r(L);
case 0x0e: return op_rrc_hl();
case 0x0f: return op_rrc_r<A>();
case 0x10: return op_rl_r<B>();
case 0x11: return op_rl_r<C>();
case 0x12: return op_rl_r<D>();
case 0x13: return op_rl_r<E>();
case 0x14: return op_rl_r<H>();
case 0x15: return op_rl_r<L>();
case 0x0f: return op_rrc_r(A);
case 0x10: return op_rl_r(B);
case 0x11: return op_rl_r(C);
case 0x12: return op_rl_r(D);
case 0x13: return op_rl_r(E);
case 0x14: return op_rl_r(H);
case 0x15: return op_rl_r(L);
case 0x16: return op_rl_hl();
case 0x17: return op_rl_r<A>();
case 0x18: return op_rr_r<B>();
case 0x19: return op_rr_r<C>();
case 0x1a: return op_rr_r<D>();
case 0x1b: return op_rr_r<E>();
case 0x1c: return op_rr_r<H>();
case 0x1d: return op_rr_r<L>();
case 0x17: return op_rl_r(A);
case 0x18: return op_rr_r(B);
case 0x19: return op_rr_r(C);
case 0x1a: return op_rr_r(D);
case 0x1b: return op_rr_r(E);
case 0x1c: return op_rr_r(H);
case 0x1d: return op_rr_r(L);
case 0x1e: return op_rr_hl();
case 0x1f: return op_rr_r<A>();
case 0x20: return op_sla_r<B>();
case 0x21: return op_sla_r<C>();
case 0x22: return op_sla_r<D>();
case 0x23: return op_sla_r<E>();
case 0x24: return op_sla_r<H>();
case 0x25: return op_sla_r<L>();
case 0x1f: return op_rr_r(A);
case 0x20: return op_sla_r(B);
case 0x21: return op_sla_r(C);
case 0x22: return op_sla_r(D);
case 0x23: return op_sla_r(E);
case 0x24: return op_sla_r(H);
case 0x25: return op_sla_r(L);
case 0x26: return op_sla_hl();
case 0x27: return op_sla_r<A>();
case 0x28: return op_sra_r<B>();
case 0x29: return op_sra_r<C>();
case 0x2a: return op_sra_r<D>();
case 0x2b: return op_sra_r<E>();
case 0x2c: return op_sra_r<H>();
case 0x2d: return op_sra_r<L>();
case 0x27: return op_sla_r(A);
case 0x28: return op_sra_r(B);
case 0x29: return op_sra_r(C);
case 0x2a: return op_sra_r(D);
case 0x2b: return op_sra_r(E);
case 0x2c: return op_sra_r(H);
case 0x2d: return op_sra_r(L);
case 0x2e: return op_sra_hl();
case 0x2f: return op_sra_r<A>();
case 0x30: return op_swap_r<B>();
case 0x31: return op_swap_r<C>();
case 0x32: return op_swap_r<D>();
case 0x33: return op_swap_r<E>();
case 0x34: return op_swap_r<H>();
case 0x35: return op_swap_r<L>();
case 0x2f: return op_sra_r(A);
case 0x30: return op_swap_r(B);
case 0x31: return op_swap_r(C);
case 0x32: return op_swap_r(D);
case 0x33: return op_swap_r(E);
case 0x34: return op_swap_r(H);
case 0x35: return op_swap_r(L);
case 0x36: return op_swap_hl();
case 0x37: return op_swap_r<A>();
case 0x38: return op_srl_r<B>();
case 0x39: return op_srl_r<C>();
case 0x3a: return op_srl_r<D>();
case 0x3b: return op_srl_r<E>();
case 0x3c: return op_srl_r<H>();
case 0x3d: return op_srl_r<L>();
case 0x37: return op_swap_r(A);
case 0x38: return op_srl_r(B);
case 0x39: return op_srl_r(C);
case 0x3a: return op_srl_r(D);
case 0x3b: return op_srl_r(E);
case 0x3c: return op_srl_r(H);
case 0x3d: return op_srl_r(L);
case 0x3e: return op_srl_hl();
case 0x3f: return op_srl_r<A>();
case 0x40: return op_bit_n_r<0, B>();
case 0x41: return op_bit_n_r<0, C>();
case 0x42: return op_bit_n_r<0, D>();
case 0x43: return op_bit_n_r<0, E>();
case 0x44: return op_bit_n_r<0, H>();
case 0x45: return op_bit_n_r<0, L>();
case 0x46: return op_bit_n_hl<0>();
case 0x47: return op_bit_n_r<0, A>();
case 0x48: return op_bit_n_r<1, B>();
case 0x49: return op_bit_n_r<1, C>();
case 0x4a: return op_bit_n_r<1, D>();
case 0x4b: return op_bit_n_r<1, E>();
case 0x4c: return op_bit_n_r<1, H>();
case 0x4d: return op_bit_n_r<1, L>();
case 0x4e: return op_bit_n_hl<1>();
case 0x4f: return op_bit_n_r<1, A>();
case 0x50: return op_bit_n_r<2, B>();
case 0x51: return op_bit_n_r<2, C>();
case 0x52: return op_bit_n_r<2, D>();
case 0x53: return op_bit_n_r<2, E>();
case 0x54: return op_bit_n_r<2, H>();
case 0x55: return op_bit_n_r<2, L>();
case 0x56: return op_bit_n_hl<2>();
case 0x57: return op_bit_n_r<2, A>();
case 0x58: return op_bit_n_r<3, B>();
case 0x59: return op_bit_n_r<3, C>();
case 0x5a: return op_bit_n_r<3, D>();
case 0x5b: return op_bit_n_r<3, E>();
case 0x5c: return op_bit_n_r<3, H>();
case 0x5d: return op_bit_n_r<3, L>();
case 0x5e: return op_bit_n_hl<3>();
case 0x5f: return op_bit_n_r<3, A>();
case 0x60: return op_bit_n_r<4, B>();
case 0x61: return op_bit_n_r<4, C>();
case 0x62: return op_bit_n_r<4, D>();
case 0x63: return op_bit_n_r<4, E>();
case 0x64: return op_bit_n_r<4, H>();
case 0x65: return op_bit_n_r<4, L>();
case 0x66: return op_bit_n_hl<4>();
case 0x67: return op_bit_n_r<4, A>();
case 0x68: return op_bit_n_r<5, B>();
case 0x69: return op_bit_n_r<5, C>();
case 0x6a: return op_bit_n_r<5, D>();
case 0x6b: return op_bit_n_r<5, E>();
case 0x6c: return op_bit_n_r<5, H>();
case 0x6d: return op_bit_n_r<5, L>();
case 0x6e: return op_bit_n_hl<5>();
case 0x6f: return op_bit_n_r<5, A>();
case 0x70: return op_bit_n_r<6, B>();
case 0x71: return op_bit_n_r<6, C>();
case 0x72: return op_bit_n_r<6, D>();
case 0x73: return op_bit_n_r<6, E>();
case 0x74: return op_bit_n_r<6, H>();
case 0x75: return op_bit_n_r<6, L>();
case 0x76: return op_bit_n_hl<6>();
case 0x77: return op_bit_n_r<6, A>();
case 0x78: return op_bit_n_r<7, B>();
case 0x79: return op_bit_n_r<7, C>();
case 0x7a: return op_bit_n_r<7, D>();
case 0x7b: return op_bit_n_r<7, E>();
case 0x7c: return op_bit_n_r<7, H>();
case 0x7d: return op_bit_n_r<7, L>();
case 0x7e: return op_bit_n_hl<7>();
case 0x7f: return op_bit_n_r<7, A>();
case 0x80: return op_res_n_r<0, B>();
case 0x81: return op_res_n_r<0, C>();
case 0x82: return op_res_n_r<0, D>();
case 0x83: return op_res_n_r<0, E>();
case 0x84: return op_res_n_r<0, H>();
case 0x85: return op_res_n_r<0, L>();
case 0x86: return op_res_n_hl<0>();
case 0x87: return op_res_n_r<0, A>();
case 0x88: return op_res_n_r<1, B>();
case 0x89: return op_res_n_r<1, C>();
case 0x8a: return op_res_n_r<1, D>();
case 0x8b: return op_res_n_r<1, E>();
case 0x8c: return op_res_n_r<1, H>();
case 0x8d: return op_res_n_r<1, L>();
case 0x8e: return op_res_n_hl<1>();
case 0x8f: return op_res_n_r<1, A>();
case 0x90: return op_res_n_r<2, B>();
case 0x91: return op_res_n_r<2, C>();
case 0x92: return op_res_n_r<2, D>();
case 0x93: return op_res_n_r<2, E>();
case 0x94: return op_res_n_r<2, H>();
case 0x95: return op_res_n_r<2, L>();
case 0x96: return op_res_n_hl<2>();
case 0x97: return op_res_n_r<2, A>();
case 0x98: return op_res_n_r<3, B>();
case 0x99: return op_res_n_r<3, C>();
case 0x9a: return op_res_n_r<3, D>();
case 0x9b: return op_res_n_r<3, E>();
case 0x9c: return op_res_n_r<3, H>();
case 0x9d: return op_res_n_r<3, L>();
case 0x9e: return op_res_n_hl<3>();
case 0x9f: return op_res_n_r<3, A>();
case 0xa0: return op_res_n_r<4, B>();
case 0xa1: return op_res_n_r<4, C>();
case 0xa2: return op_res_n_r<4, D>();
case 0xa3: return op_res_n_r<4, E>();
case 0xa4: return op_res_n_r<4, H>();
case 0xa5: return op_res_n_r<4, L>();
case 0xa6: return op_res_n_hl<4>();
case 0xa7: return op_res_n_r<4, A>();
case 0xa8: return op_res_n_r<5, B>();
case 0xa9: return op_res_n_r<5, C>();
case 0xaa: return op_res_n_r<5, D>();
case 0xab: return op_res_n_r<5, E>();
case 0xac: return op_res_n_r<5, H>();
case 0xad: return op_res_n_r<5, L>();
case 0xae: return op_res_n_hl<5>();
case 0xaf: return op_res_n_r<5, A>();
case 0xb0: return op_res_n_r<6, B>();
case 0xb1: return op_res_n_r<6, C>();
case 0xb2: return op_res_n_r<6, D>();
case 0xb3: return op_res_n_r<6, E>();
case 0xb4: return op_res_n_r<6, H>();
case 0xb5: return op_res_n_r<6, L>();
case 0xb6: return op_res_n_hl<6>();
case 0xb7: return op_res_n_r<6, A>();
case 0xb8: return op_res_n_r<7, B>();
case 0xb9: return op_res_n_r<7, C>();
case 0xba: return op_res_n_r<7, D>();
case 0xbb: return op_res_n_r<7, E>();
case 0xbc: return op_res_n_r<7, H>();
case 0xbd: return op_res_n_r<7, L>();
case 0xbe: return op_res_n_hl<7>();
case 0xbf: return op_res_n_r<7, A>();
case 0xc0: return op_set_n_r<0, B>();
case 0xc1: return op_set_n_r<0, C>();
case 0xc2: return op_set_n_r<0, D>();
case 0xc3: return op_set_n_r<0, E>();
case 0xc4: return op_set_n_r<0, H>();
case 0xc5: return op_set_n_r<0, L>();
case 0xc6: return op_set_n_hl<0>();
case 0xc7: return op_set_n_r<0, A>();
case 0xc8: return op_set_n_r<1, B>();
case 0xc9: return op_set_n_r<1, C>();
case 0xca: return op_set_n_r<1, D>();
case 0xcb: return op_set_n_r<1, E>();
case 0xcc: return op_set_n_r<1, H>();
case 0xcd: return op_set_n_r<1, L>();
case 0xce: return op_set_n_hl<1>();
case 0xcf: return op_set_n_r<1, A>();
case 0xd0: return op_set_n_r<2, B>();
case 0xd1: return op_set_n_r<2, C>();
case 0xd2: return op_set_n_r<2, D>();
case 0xd3: return op_set_n_r<2, E>();
case 0xd4: return op_set_n_r<2, H>();
case 0xd5: return op_set_n_r<2, L>();
case 0xd6: return op_set_n_hl<2>();
case 0xd7: return op_set_n_r<2, A>();
case 0xd8: return op_set_n_r<3, B>();
case 0xd9: return op_set_n_r<3, C>();
case 0xda: return op_set_n_r<3, D>();
case 0xdb: return op_set_n_r<3, E>();
case 0xdc: return op_set_n_r<3, H>();
case 0xdd: return op_set_n_r<3, L>();
case 0xde: return op_set_n_hl<3>();
case 0xdf: return op_set_n_r<3, A>();
case 0xe0: return op_set_n_r<4, B>();
case 0xe1: return op_set_n_r<4, C>();
case 0xe2: return op_set_n_r<4, D>();
case 0xe3: return op_set_n_r<4, E>();
case 0xe4: return op_set_n_r<4, H>();
case 0xe5: return op_set_n_r<4, L>();
case 0xe6: return op_set_n_hl<4>();
case 0xe7: return op_set_n_r<4, A>();
case 0xe8: return op_set_n_r<5, B>();
case 0xe9: return op_set_n_r<5, C>();
case 0xea: return op_set_n_r<5, D>();
case 0xeb: return op_set_n_r<5, E>();
case 0xec: return op_set_n_r<5, H>();
case 0xed: return op_set_n_r<5, L>();
case 0xee: return op_set_n_hl<5>();
case 0xef: return op_set_n_r<5, A>();
case 0xf0: return op_set_n_r<6, B>();
case 0xf1: return op_set_n_r<6, C>();
case 0xf2: return op_set_n_r<6, D>();
case 0xf3: return op_set_n_r<6, E>();
case 0xf4: return op_set_n_r<6, H>();
case 0xf5: return op_set_n_r<6, L>();
case 0xf6: return op_set_n_hl<6>();
case 0xf7: return op_set_n_r<6, A>();
case 0xf8: return op_set_n_r<7, B>();
case 0xf9: return op_set_n_r<7, C>();
case 0xfa: return op_set_n_r<7, D>();
case 0xfb: return op_set_n_r<7, E>();
case 0xfc: return op_set_n_r<7, H>();
case 0xfd: return op_set_n_r<7, L>();
case 0xfe: return op_set_n_hl<7>();
case 0xff: return op_set_n_r<7, A>();
case 0x3f: return op_srl_r(A);
case 0x40: return op_bit_n_r(0, B);
case 0x41: return op_bit_n_r(0, C);
case 0x42: return op_bit_n_r(0, D);
case 0x43: return op_bit_n_r(0, E);
case 0x44: return op_bit_n_r(0, H);
case 0x45: return op_bit_n_r(0, L);
case 0x46: return op_bit_n_hl(0);
case 0x47: return op_bit_n_r(0, A);
case 0x48: return op_bit_n_r(1, B);
case 0x49: return op_bit_n_r(1, C);
case 0x4a: return op_bit_n_r(1, D);
case 0x4b: return op_bit_n_r(1, E);
case 0x4c: return op_bit_n_r(1, H);
case 0x4d: return op_bit_n_r(1, L);
case 0x4e: return op_bit_n_hl(1);
case 0x4f: return op_bit_n_r(1, A);
case 0x50: return op_bit_n_r(2, B);
case 0x51: return op_bit_n_r(2, C);
case 0x52: return op_bit_n_r(2, D);
case 0x53: return op_bit_n_r(2, E);
case 0x54: return op_bit_n_r(2, H);
case 0x55: return op_bit_n_r(2, L);
case 0x56: return op_bit_n_hl(2);
case 0x57: return op_bit_n_r(2, A);
case 0x58: return op_bit_n_r(3, B);
case 0x59: return op_bit_n_r(3, C);
case 0x5a: return op_bit_n_r(3, D);
case 0x5b: return op_bit_n_r(3, E);
case 0x5c: return op_bit_n_r(3, H);
case 0x5d: return op_bit_n_r(3, L);
case 0x5e: return op_bit_n_hl(3);
case 0x5f: return op_bit_n_r(3, A);
case 0x60: return op_bit_n_r(4, B);
case 0x61: return op_bit_n_r(4, C);
case 0x62: return op_bit_n_r(4, D);
case 0x63: return op_bit_n_r(4, E);
case 0x64: return op_bit_n_r(4, H);
case 0x65: return op_bit_n_r(4, L);
case 0x66: return op_bit_n_hl(4);
case 0x67: return op_bit_n_r(4, A);
case 0x68: return op_bit_n_r(5, B);
case 0x69: return op_bit_n_r(5, C);
case 0x6a: return op_bit_n_r(5, D);
case 0x6b: return op_bit_n_r(5, E);
case 0x6c: return op_bit_n_r(5, H);
case 0x6d: return op_bit_n_r(5, L);
case 0x6e: return op_bit_n_hl(5);
case 0x6f: return op_bit_n_r(5, A);
case 0x70: return op_bit_n_r(6, B);
case 0x71: return op_bit_n_r(6, C);
case 0x72: return op_bit_n_r(6, D);
case 0x73: return op_bit_n_r(6, E);
case 0x74: return op_bit_n_r(6, H);
case 0x75: return op_bit_n_r(6, L);
case 0x76: return op_bit_n_hl(6);
case 0x77: return op_bit_n_r(6, A);
case 0x78: return op_bit_n_r(7, B);
case 0x79: return op_bit_n_r(7, C);
case 0x7a: return op_bit_n_r(7, D);
case 0x7b: return op_bit_n_r(7, E);
case 0x7c: return op_bit_n_r(7, H);
case 0x7d: return op_bit_n_r(7, L);
case 0x7e: return op_bit_n_hl(7);
case 0x7f: return op_bit_n_r(7, A);
case 0x80: return op_res_n_r(0, B);
case 0x81: return op_res_n_r(0, C);
case 0x82: return op_res_n_r(0, D);
case 0x83: return op_res_n_r(0, E);
case 0x84: return op_res_n_r(0, H);
case 0x85: return op_res_n_r(0, L);
case 0x86: return op_res_n_hl(0);
case 0x87: return op_res_n_r(0, A);
case 0x88: return op_res_n_r(1, B);
case 0x89: return op_res_n_r(1, C);
case 0x8a: return op_res_n_r(1, D);
case 0x8b: return op_res_n_r(1, E);
case 0x8c: return op_res_n_r(1, H);
case 0x8d: return op_res_n_r(1, L);
case 0x8e: return op_res_n_hl(1);
case 0x8f: return op_res_n_r(1, A);
case 0x90: return op_res_n_r(2, B);
case 0x91: return op_res_n_r(2, C);
case 0x92: return op_res_n_r(2, D);
case 0x93: return op_res_n_r(2, E);
case 0x94: return op_res_n_r(2, H);
case 0x95: return op_res_n_r(2, L);
case 0x96: return op_res_n_hl(2);
case 0x97: return op_res_n_r(2, A);
case 0x98: return op_res_n_r(3, B);
case 0x99: return op_res_n_r(3, C);
case 0x9a: return op_res_n_r(3, D);
case 0x9b: return op_res_n_r(3, E);
case 0x9c: return op_res_n_r(3, H);
case 0x9d: return op_res_n_r(3, L);
case 0x9e: return op_res_n_hl(3);
case 0x9f: return op_res_n_r(3, A);
case 0xa0: return op_res_n_r(4, B);
case 0xa1: return op_res_n_r(4, C);
case 0xa2: return op_res_n_r(4, D);
case 0xa3: return op_res_n_r(4, E);
case 0xa4: return op_res_n_r(4, H);
case 0xa5: return op_res_n_r(4, L);
case 0xa6: return op_res_n_hl(4);
case 0xa7: return op_res_n_r(4, A);
case 0xa8: return op_res_n_r(5, B);
case 0xa9: return op_res_n_r(5, C);
case 0xaa: return op_res_n_r(5, D);
case 0xab: return op_res_n_r(5, E);
case 0xac: return op_res_n_r(5, H);
case 0xad: return op_res_n_r(5, L);
case 0xae: return op_res_n_hl(5);
case 0xaf: return op_res_n_r(5, A);
case 0xb0: return op_res_n_r(6, B);
case 0xb1: return op_res_n_r(6, C);
case 0xb2: return op_res_n_r(6, D);
case 0xb3: return op_res_n_r(6, E);
case 0xb4: return op_res_n_r(6, H);
case 0xb5: return op_res_n_r(6, L);
case 0xb6: return op_res_n_hl(6);
case 0xb7: return op_res_n_r(6, A);
case 0xb8: return op_res_n_r(7, B);
case 0xb9: return op_res_n_r(7, C);
case 0xba: return op_res_n_r(7, D);
case 0xbb: return op_res_n_r(7, E);
case 0xbc: return op_res_n_r(7, H);
case 0xbd: return op_res_n_r(7, L);
case 0xbe: return op_res_n_hl(7);
case 0xbf: return op_res_n_r(7, A);
case 0xc0: return op_set_n_r(0, B);
case 0xc1: return op_set_n_r(0, C);
case 0xc2: return op_set_n_r(0, D);
case 0xc3: return op_set_n_r(0, E);
case 0xc4: return op_set_n_r(0, H);
case 0xc5: return op_set_n_r(0, L);
case 0xc6: return op_set_n_hl(0);
case 0xc7: return op_set_n_r(0, A);
case 0xc8: return op_set_n_r(1, B);
case 0xc9: return op_set_n_r(1, C);
case 0xca: return op_set_n_r(1, D);
case 0xcb: return op_set_n_r(1, E);
case 0xcc: return op_set_n_r(1, H);
case 0xcd: return op_set_n_r(1, L);
case 0xce: return op_set_n_hl(1);
case 0xcf: return op_set_n_r(1, A);
case 0xd0: return op_set_n_r(2, B);
case 0xd1: return op_set_n_r(2, C);
case 0xd2: return op_set_n_r(2, D);
case 0xd3: return op_set_n_r(2, E);
case 0xd4: return op_set_n_r(2, H);
case 0xd5: return op_set_n_r(2, L);
case 0xd6: return op_set_n_hl(2);
case 0xd7: return op_set_n_r(2, A);
case 0xd8: return op_set_n_r(3, B);
case 0xd9: return op_set_n_r(3, C);
case 0xda: return op_set_n_r(3, D);
case 0xdb: return op_set_n_r(3, E);
case 0xdc: return op_set_n_r(3, H);
case 0xdd: return op_set_n_r(3, L);
case 0xde: return op_set_n_hl(3);
case 0xdf: return op_set_n_r(3, A);
case 0xe0: return op_set_n_r(4, B);
case 0xe1: return op_set_n_r(4, C);
case 0xe2: return op_set_n_r(4, D);
case 0xe3: return op_set_n_r(4, E);
case 0xe4: return op_set_n_r(4, H);
case 0xe5: return op_set_n_r(4, L);
case 0xe6: return op_set_n_hl(4);
case 0xe7: return op_set_n_r(4, A);
case 0xe8: return op_set_n_r(5, B);
case 0xe9: return op_set_n_r(5, C);
case 0xea: return op_set_n_r(5, D);
case 0xeb: return op_set_n_r(5, E);
case 0xec: return op_set_n_r(5, H);
case 0xed: return op_set_n_r(5, L);
case 0xee: return op_set_n_hl(5);
case 0xef: return op_set_n_r(5, A);
case 0xf0: return op_set_n_r(6, B);
case 0xf1: return op_set_n_r(6, C);
case 0xf2: return op_set_n_r(6, D);
case 0xf3: return op_set_n_r(6, E);
case 0xf4: return op_set_n_r(6, H);
case 0xf5: return op_set_n_r(6, L);
case 0xf6: return op_set_n_hl(6);
case 0xf7: return op_set_n_r(6, A);
case 0xf8: return op_set_n_r(7, B);
case 0xf9: return op_set_n_r(7, C);
case 0xfa: return op_set_n_r(7, D);
case 0xfb: return op_set_n_r(7, E);
case 0xfc: return op_set_n_r(7, H);
case 0xfd: return op_set_n_r(7, L);
case 0xfe: return op_set_n_hl(7);
case 0xff: return op_set_n_r(7, A);
}
}

View File

@ -9,7 +9,7 @@ struct LR35902 {
virtual auto op_read(uint16 addr) -> uint8 = 0;
virtual auto op_write(uint16 addr, uint8 data) -> void = 0;
virtual auto stop() -> bool = 0;
virtual auto debugger_read(uint16 addr) -> uint8 { return 0u; }
virtual auto debugger_read(uint16 addr) -> uint8 { return 0; }
auto power() -> void;
auto exec() -> void;
@ -24,14 +24,14 @@ privileged:
auto op_cb();
//8-bit load commands
template<uint x, uint y> auto op_ld_r_r();
template<uint x> auto op_ld_r_n();
template<uint x> auto op_ld_r_hl();
template<uint x> auto op_ld_hl_r();
auto op_ld_r_r(uint x, uint y);
auto op_ld_r_n(uint x);
auto op_ld_r_hl(uint x);
auto op_ld_hl_r(uint x);
auto op_ld_hl_n();
template<uint x> auto op_ld_a_rr();
auto op_ld_a_rr(uint x);
auto op_ld_a_nn();
template<uint x> auto op_ld_rr_a();
auto op_ld_rr_a(uint x);
auto op_ld_nn_a();
auto op_ld_a_ffn();
auto op_ld_ffn_a();
@ -43,64 +43,64 @@ privileged:
auto op_ldd_a_hl();
//16-bit load commands
template<uint x> auto op_ld_rr_nn();
auto op_ld_rr_nn(uint x);
auto op_ld_nn_sp();
auto op_ld_sp_hl();
template<uint x> auto op_push_rr();
template<uint x> auto op_pop_rr();
auto op_push_rr(uint x);
auto op_pop_rr(uint x);
//8-bit arithmetic commands
auto opi_add_a(uint8 x);
template<uint x> auto op_add_a_r();
auto op_add_a_r(uint x);
auto op_add_a_n();
auto op_add_a_hl();
auto opi_adc_a(uint8 x);
template<uint x> auto op_adc_a_r();
auto op_adc_a_r(uint x);
auto op_adc_a_n();
auto op_adc_a_hl();
auto opi_sub_a(uint8 x);
template<uint x> auto op_sub_a_r();
auto op_sub_a_r(uint x);
auto op_sub_a_n();
auto op_sub_a_hl();
auto opi_sbc_a(uint8 x);
template<uint x> auto op_sbc_a_r();
auto op_sbc_a_r(uint x);
auto op_sbc_a_n();
auto op_sbc_a_hl();
auto opi_and_a(uint8 x);
template<uint x> auto op_and_a_r();
auto op_and_a_r(uint x);
auto op_and_a_n();
auto op_and_a_hl();
auto opi_xor_a(uint8 x);
template<uint x> auto op_xor_a_r();
auto op_xor_a_r(uint x);
auto op_xor_a_n();
auto op_xor_a_hl();
auto opi_or_a(uint8 x);
template<uint x> auto op_or_a_r();
auto op_or_a_r(uint x);
auto op_or_a_n();
auto op_or_a_hl();
auto opi_cp_a(uint8 x);
template<uint x> auto op_cp_a_r();
auto op_cp_a_r(uint x);
auto op_cp_a_n();
auto op_cp_a_hl();
template<uint x> auto op_inc_r();
auto op_inc_r(uint x);
auto op_inc_hl();
template<uint x> auto op_dec_r();
auto op_dec_r(uint x);
auto op_dec_hl();
auto op_daa();
auto op_cpl();
//16-bit arithmetic commands
template<uint x> auto op_add_hl_rr();
template<uint x> auto op_inc_rr();
template<uint x> auto op_dec_rr();
auto op_add_hl_rr(uint x);
auto op_inc_rr(uint x);
auto op_dec_rr(uint x);
auto op_add_sp_n();
auto op_ld_hl_sp_n();
@ -109,30 +109,30 @@ privileged:
auto op_rla();
auto op_rrca();
auto op_rra();
template<uint x> auto op_rlc_r();
auto op_rlc_r(uint x);
auto op_rlc_hl();
template<uint x> auto op_rl_r();
auto op_rl_r(uint x);
auto op_rl_hl();
template<uint x> auto op_rrc_r();
auto op_rrc_r(uint x);
auto op_rrc_hl();
template<uint x> auto op_rr_r();
auto op_rr_r(uint x);
auto op_rr_hl();
template<uint x> auto op_sla_r();
auto op_sla_r(uint x);
auto op_sla_hl();
template<uint x> auto op_swap_r();
auto op_swap_r(uint x);
auto op_swap_hl();
template<uint x> auto op_sra_r();
auto op_sra_r(uint x);
auto op_sra_hl();
template<uint x> auto op_srl_r();
auto op_srl_r(uint x);
auto op_srl_hl();
//single-bit commands
template<uint b, uint x> auto op_bit_n_r();
template<uint b> auto op_bit_n_hl();
template<uint b, uint x> auto op_set_n_r();
template<uint b> auto op_set_n_hl();
template<uint b, uint x> auto op_res_n_r();
template<uint b> auto op_res_n_hl();
auto op_bit_n_r(uint b, uint x);
auto op_bit_n_hl(uint b);
auto op_set_n_r(uint b, uint x);
auto op_set_n_hl(uint b);
auto op_res_n_r(uint b, uint x);
auto op_res_n_hl(uint b);
//control commands
auto op_ccf();
@ -146,15 +146,15 @@ privileged:
//jump commands
auto op_jp_nn();
auto op_jp_hl();
template<uint x, bool y> auto op_jp_f_nn();
auto op_jp_f_nn(uint x, bool y);
auto op_jr_n();
template<uint x, bool y> auto op_jr_f_n();
auto op_jr_f_n(uint x, bool y);
auto op_call_nn();
template<uint x, bool y> auto op_call_f_nn();
auto op_call_f_nn(uint x, bool y);
auto op_ret();
template<uint x, bool y> auto op_ret_f();
auto op_ret_f(uint x, bool y);
auto op_reti();
template<uint n> auto op_rst_n();
auto op_rst_n(uint n);
//disassembler.cpp
auto disassemble(uint16 pc) -> string;

View File

@ -99,7 +99,7 @@ struct Registers {
bool ime;
Register& operator[](unsigned r) {
static Register* table[] = {&a, &f, &af, &b, &c, &bc, &d, &e, &de, &h, &l, &hl, &sp, &pc};
static Register* const table[] = {&a, &f, &af, &b, &c, &bc, &d, &e, &de, &h, &l, &hl, &sp, &pc};
return *table[r];
}

View File

@ -197,16 +197,14 @@ auto R6502::opi_push(uint8& r) {
L op_writesp(r);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_absolute() {
auto R6502::opi_read_absolute(fp op) {
abs.l = op_readpci();
abs.h = op_readpci();
L rd = op_read(abs.w);
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_absolute_x() {
auto R6502::opi_read_absolute_x(fp op) {
abs.l = op_readpci();
abs.h = op_readpci();
op_page(abs.w, abs.w + regs.x);
@ -214,8 +212,7 @@ L rd = op_read(abs.w + regs.x);
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_absolute_y() {
auto R6502::opi_read_absolute_y(fp op) {
abs.l = op_readpci();
abs.h = op_readpci();
op_page(abs.w, abs.w + regs.y);
@ -223,14 +220,12 @@ L rd = op_read(abs.w + regs.y);
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_immediate() {
auto R6502::opi_read_immediate(fp op) {
L rd = op_readpci();
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_indirect_zero_page_x() {
auto R6502::opi_read_indirect_zero_page_x(fp op) {
zp = op_readpci();
op_readzp(zp);
abs.l = op_readzp(zp++ + regs.x);
@ -239,8 +234,7 @@ L rd = op_read(abs.w);
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_indirect_zero_page_y() {
auto R6502::opi_read_indirect_zero_page_y(fp op) {
rd = op_readpci();
abs.l = op_readzp(rd++);
abs.h = op_readzp(rd++);
@ -249,31 +243,27 @@ L rd = op_read(abs.w + regs.y);
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_zero_page() {
auto R6502::opi_read_zero_page(fp op) {
zp = op_readpci();
L rd = op_readzp(zp);
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_zero_page_x() {
auto R6502::opi_read_zero_page_x(fp op) {
zp = op_readpci();
op_readzp(zp);
L rd = op_readzp(zp + regs.x);
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_zero_page_y() {
auto R6502::opi_read_zero_page_y(fp op) {
zp = op_readpci();
op_readzp(zp);
L rd = op_readzp(zp + regs.y);
call(op);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_rmw_absolute() {
auto R6502::opi_rmw_absolute(fp op) {
abs.l = op_readpci();
abs.h = op_readpci();
rd = op_read(abs.w);
@ -282,8 +272,7 @@ auto R6502::opi_rmw_absolute() {
L op_write(abs.w, rd);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_rmw_absolute_x() {
auto R6502::opi_rmw_absolute_x(fp op) {
abs.l = op_readpci();
abs.h = op_readpci();
op_page_always(abs.w, abs.w + regs.x);
@ -293,8 +282,7 @@ auto R6502::opi_rmw_absolute_x() {
L op_write(abs.w + regs.x, rd);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_rmw_zero_page() {
auto R6502::opi_rmw_zero_page(fp op) {
zp = op_readpci();
rd = op_readzp(zp);
op_writezp(zp, rd);
@ -302,8 +290,7 @@ auto R6502::opi_rmw_zero_page() {
L op_writezp(zp, rd);
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_rmw_zero_page_x() {
auto R6502::opi_rmw_zero_page_x(fp op) {
zp = op_readpci();
op_readzp(zp);
rd = op_readzp(zp + regs.x);
@ -317,8 +304,7 @@ L op_readpc();
flag = 1;
}
template<auto (R6502::*op)() -> void>
auto R6502::opi_shift() {
auto R6502::opi_shift(fp op) {
L op_readpc();
call(op);
}

View File

@ -49,94 +49,94 @@ auto R6502::exec() -> void {
uint8 opcode = op_readpci();
switch(opcode) {
case 0x00: return op_brk();
case 0x01: return opi_read_indirect_zero_page_x<&R6502::opf_ora>();
case 0x01: return opi_read_indirect_zero_page_x(&R6502::opf_ora);
I case 0x04: return opill_nop_zero_page();
case 0x05: return opi_read_zero_page<&R6502::opf_ora>();
case 0x06: return opi_rmw_zero_page<&R6502::opf_asl>();
case 0x05: return opi_read_zero_page(&R6502::opf_ora);
case 0x06: return opi_rmw_zero_page(&R6502::opf_asl);
case 0x08: return op_php();
case 0x09: return opi_read_immediate<&R6502::opf_ora>();
case 0x0a: return opi_shift<&R6502::opf_sla>();
case 0x09: return opi_read_immediate(&R6502::opf_ora);
case 0x0a: return opi_shift(&R6502::opf_sla);
I case 0x0c: return opill_nop_absolute();
case 0x0d: return opi_read_absolute<&R6502::opf_ora>();
case 0x0e: return opi_rmw_absolute<&R6502::opf_asl>();
case 0x0d: return opi_read_absolute(&R6502::opf_ora);
case 0x0e: return opi_rmw_absolute(&R6502::opf_asl);
case 0x10: return opi_branch(regs.p.n == 0);
case 0x11: return opi_read_indirect_zero_page_y<&R6502::opf_ora>();
case 0x11: return opi_read_indirect_zero_page_y(&R6502::opf_ora);
I case 0x14: return opill_nop_zero_page_x();
case 0x15: return opi_read_zero_page_x<&R6502::opf_ora>();
case 0x16: return opi_rmw_zero_page_x<&R6502::opf_asl>();
case 0x15: return opi_read_zero_page_x(&R6502::opf_ora);
case 0x16: return opi_rmw_zero_page_x(&R6502::opf_asl);
case 0x18: return opi_clear_flag(regs.p.c);
case 0x19: return opi_read_absolute_y<&R6502::opf_ora>();
case 0x19: return opi_read_absolute_y(&R6502::opf_ora);
I case 0x1a: return opill_nop_implied();
I case 0x1c: return opill_nop_absolute_x();
case 0x1d: return opi_read_absolute_x<&R6502::opf_ora>();
case 0x1e: return opi_rmw_absolute_x<&R6502::opf_asl>();
case 0x1d: return opi_read_absolute_x(&R6502::opf_ora);
case 0x1e: return opi_rmw_absolute_x(&R6502::opf_asl);
case 0x20: return op_jsr_absolute();
case 0x21: return opi_read_indirect_zero_page_x<&R6502::opf_and>();
case 0x24: return opi_read_zero_page<&R6502::opf_bit>();
case 0x25: return opi_read_zero_page<&R6502::opf_and>();
case 0x26: return opi_rmw_zero_page<&R6502::opf_rol>();
case 0x21: return opi_read_indirect_zero_page_x(&R6502::opf_and);
case 0x24: return opi_read_zero_page(&R6502::opf_bit);
case 0x25: return opi_read_zero_page(&R6502::opf_and);
case 0x26: return opi_rmw_zero_page(&R6502::opf_rol);
case 0x28: return op_plp();
case 0x29: return opi_read_immediate<&R6502::opf_and>();
case 0x2a: return opi_shift<&R6502::opf_rla>();
case 0x2c: return opi_read_absolute<&R6502::opf_bit>();
case 0x2d: return opi_read_absolute<&R6502::opf_and>();
case 0x2e: return opi_rmw_absolute<&R6502::opf_rol>();
case 0x29: return opi_read_immediate(&R6502::opf_and);
case 0x2a: return opi_shift(&R6502::opf_rla);
case 0x2c: return opi_read_absolute(&R6502::opf_bit);
case 0x2d: return opi_read_absolute(&R6502::opf_and);
case 0x2e: return opi_rmw_absolute(&R6502::opf_rol);
case 0x30: return opi_branch(regs.p.n == 1);
case 0x31: return opi_read_indirect_zero_page_y<&R6502::opf_and>();
case 0x31: return opi_read_indirect_zero_page_y(&R6502::opf_and);
I case 0x34: return opill_nop_zero_page_x();
case 0x35: return opi_read_zero_page_x<&R6502::opf_and>();
case 0x36: return opi_rmw_zero_page_x<&R6502::opf_rol>();
case 0x35: return opi_read_zero_page_x(&R6502::opf_and);
case 0x36: return opi_rmw_zero_page_x(&R6502::opf_rol);
case 0x38: return opi_set_flag(regs.p.c);
case 0x39: return opi_read_absolute_y<&R6502::opf_and>();
case 0x39: return opi_read_absolute_y(&R6502::opf_and);
I case 0x3a: return opill_nop_implied();
I case 0x3c: return opill_nop_absolute_x();
case 0x3d: return opi_read_absolute_x<&R6502::opf_and>();
case 0x3e: return opi_rmw_absolute_x<&R6502::opf_rol>();
case 0x3d: return opi_read_absolute_x(&R6502::opf_and);
case 0x3e: return opi_rmw_absolute_x(&R6502::opf_rol);
case 0x40: return op_rti();
case 0x41: return opi_read_indirect_zero_page_x<&R6502::opf_eor>();
case 0x41: return opi_read_indirect_zero_page_x(&R6502::opf_eor);
I case 0x44: return opill_nop_zero_page();
case 0x45: return opi_read_zero_page<&R6502::opf_eor>();
case 0x46: return opi_rmw_zero_page<&R6502::opf_lsr>();
case 0x45: return opi_read_zero_page(&R6502::opf_eor);
case 0x46: return opi_rmw_zero_page(&R6502::opf_lsr);
case 0x48: return opi_push(regs.a);
case 0x49: return opi_read_immediate<&R6502::opf_eor>();
case 0x4a: return opi_shift<&R6502::opf_sra>();
case 0x49: return opi_read_immediate(&R6502::opf_eor);
case 0x4a: return opi_shift(&R6502::opf_sra);
case 0x4c: return op_jmp_absolute();
case 0x4d: return opi_read_absolute<&R6502::opf_eor>();
case 0x4e: return opi_rmw_absolute<&R6502::opf_lsr>();
case 0x4d: return opi_read_absolute(&R6502::opf_eor);
case 0x4e: return opi_rmw_absolute(&R6502::opf_lsr);
case 0x50: return opi_branch(regs.p.v == 0);
case 0x51: return opi_read_indirect_zero_page_y<&R6502::opf_eor>();
case 0x51: return opi_read_indirect_zero_page_y(&R6502::opf_eor);
I case 0x54: return opill_nop_zero_page_x();
case 0x55: return opi_read_zero_page_x<&R6502::opf_eor>();
case 0x56: return opi_rmw_zero_page_x<&R6502::opf_lsr>();
case 0x55: return opi_read_zero_page_x(&R6502::opf_eor);
case 0x56: return opi_rmw_zero_page_x(&R6502::opf_lsr);
case 0x58: return opi_clear_flag(regs.p.i);
case 0x59: return opi_read_absolute_y<&R6502::opf_eor>();
case 0x59: return opi_read_absolute_y(&R6502::opf_eor);
I case 0x5a: return opill_nop_implied();
I case 0x5c: return opill_nop_absolute_x();
case 0x5d: return opi_read_absolute_x<&R6502::opf_eor>();
case 0x5e: return opi_rmw_absolute_x<&R6502::opf_lsr>();
case 0x5d: return opi_read_absolute_x(&R6502::opf_eor);
case 0x5e: return opi_rmw_absolute_x(&R6502::opf_lsr);
case 0x60: return op_rts();
case 0x61: return opi_read_indirect_zero_page_x<&R6502::opf_adc>();
case 0x61: return opi_read_indirect_zero_page_x(&R6502::opf_adc);
I case 0x64: return opill_nop_zero_page();
case 0x65: return opi_read_zero_page<&R6502::opf_adc>();
case 0x66: return opi_rmw_zero_page<&R6502::opf_ror>();
case 0x65: return opi_read_zero_page(&R6502::opf_adc);
case 0x66: return opi_rmw_zero_page(&R6502::opf_ror);
case 0x68: return opi_pull(regs.a);
case 0x69: return opi_read_immediate<&R6502::opf_adc>();
case 0x6a: return opi_shift<&R6502::opf_rra>();
case 0x69: return opi_read_immediate(&R6502::opf_adc);
case 0x6a: return opi_shift(&R6502::opf_rra);
I case 0x6b: return opill_arr_immediate();
case 0x6c: return op_jmp_indirect_absolute();
case 0x6d: return opi_read_absolute<&R6502::opf_adc>();
case 0x6e: return opi_rmw_absolute<&R6502::opf_ror>();
case 0x6d: return opi_read_absolute(&R6502::opf_adc);
case 0x6e: return opi_rmw_absolute(&R6502::opf_ror);
case 0x70: return opi_branch(regs.p.v == 1);
I case 0x74: return opill_nop_zero_page_x();
case 0x71: return opi_read_indirect_zero_page_y<&R6502::opf_adc>();
case 0x75: return opi_read_zero_page_x<&R6502::opf_adc>();
case 0x76: return opi_rmw_zero_page_x<&R6502::opf_ror>();
case 0x71: return opi_read_indirect_zero_page_y(&R6502::opf_adc);
case 0x75: return opi_read_zero_page_x(&R6502::opf_adc);
case 0x76: return opi_rmw_zero_page_x(&R6502::opf_ror);
case 0x78: return opi_set_flag(regs.p.i);
case 0x79: return opi_read_absolute_y<&R6502::opf_adc>();
case 0x79: return opi_read_absolute_y(&R6502::opf_adc);
I case 0x7a: return opill_nop_implied();
I case 0x7c: return opill_nop_absolute_x();
case 0x7d: return opi_read_absolute_x<&R6502::opf_adc>();
case 0x7e: return opi_rmw_absolute_x<&R6502::opf_ror>();
case 0x7d: return opi_read_absolute_x(&R6502::opf_adc);
case 0x7e: return opi_rmw_absolute_x(&R6502::opf_ror);
I case 0x80: return opill_nop_absolute();
case 0x81: return opi_store_indirect_zero_page_x(regs.a);
I case 0x82: return opill_nop_immediate();
@ -158,76 +158,76 @@ I case 0x89: return opill_nop_immediate();
case 0x99: return opi_store_absolute_y(regs.a);
case 0x9a: return opi_transfer(regs.x, regs.s, 0);
case 0x9d: return opi_store_absolute_x(regs.a);
case 0xa0: return opi_read_immediate<&R6502::opf_ldy>();
case 0xa1: return opi_read_indirect_zero_page_x<&R6502::opf_lda>();
case 0xa2: return opi_read_immediate<&R6502::opf_ldx>();
case 0xa4: return opi_read_zero_page<&R6502::opf_ldy>();
case 0xa5: return opi_read_zero_page<&R6502::opf_lda>();
case 0xa6: return opi_read_zero_page<&R6502::opf_ldx>();
case 0xa0: return opi_read_immediate(&R6502::opf_ldy);
case 0xa1: return opi_read_indirect_zero_page_x(&R6502::opf_lda);
case 0xa2: return opi_read_immediate(&R6502::opf_ldx);
case 0xa4: return opi_read_zero_page(&R6502::opf_ldy);
case 0xa5: return opi_read_zero_page(&R6502::opf_lda);
case 0xa6: return opi_read_zero_page(&R6502::opf_ldx);
case 0xa8: return opi_transfer(regs.a, regs.y, 1);
case 0xa9: return opi_read_immediate<&R6502::opf_lda>();
case 0xa9: return opi_read_immediate(&R6502::opf_lda);
case 0xaa: return opi_transfer(regs.a, regs.x, 1);
case 0xac: return opi_read_absolute<&R6502::opf_ldy>();
case 0xad: return opi_read_absolute<&R6502::opf_lda>();
case 0xae: return opi_read_absolute<&R6502::opf_ldx>();
case 0xac: return opi_read_absolute(&R6502::opf_ldy);
case 0xad: return opi_read_absolute(&R6502::opf_lda);
case 0xae: return opi_read_absolute(&R6502::opf_ldx);
case 0xb0: return opi_branch(regs.p.c == 1);
case 0xb1: return opi_read_indirect_zero_page_y<&R6502::opf_lda>();
case 0xb4: return opi_read_zero_page_x<&R6502::opf_ldy>();
case 0xb5: return opi_read_zero_page_x<&R6502::opf_lda>();
case 0xb6: return opi_read_zero_page_y<&R6502::opf_ldx>();
case 0xb1: return opi_read_indirect_zero_page_y(&R6502::opf_lda);
case 0xb4: return opi_read_zero_page_x(&R6502::opf_ldy);
case 0xb5: return opi_read_zero_page_x(&R6502::opf_lda);
case 0xb6: return opi_read_zero_page_y(&R6502::opf_ldx);
case 0xb8: return opi_clear_flag(regs.p.v);
case 0xb9: return opi_read_absolute_y<&R6502::opf_lda>();
case 0xb9: return opi_read_absolute_y(&R6502::opf_lda);
case 0xba: return opi_transfer(regs.s, regs.x, 1);
case 0xbc: return opi_read_absolute_x<&R6502::opf_ldy>();
case 0xbd: return opi_read_absolute_x<&R6502::opf_lda>();
case 0xbe: return opi_read_absolute_y<&R6502::opf_ldx>();
case 0xc0: return opi_read_immediate<&R6502::opf_cpy>();
case 0xc1: return opi_read_indirect_zero_page_x<&R6502::opf_cmp>();
case 0xbc: return opi_read_absolute_x(&R6502::opf_ldy);
case 0xbd: return opi_read_absolute_x(&R6502::opf_lda);
case 0xbe: return opi_read_absolute_y(&R6502::opf_ldx);
case 0xc0: return opi_read_immediate(&R6502::opf_cpy);
case 0xc1: return opi_read_indirect_zero_page_x(&R6502::opf_cmp);
I case 0xc2: return opill_nop_immediate();
case 0xc4: return opi_read_zero_page<&R6502::opf_cpy>();
case 0xc5: return opi_read_zero_page<&R6502::opf_cmp>();
case 0xc6: return opi_rmw_zero_page<&R6502::opf_dec>();
case 0xc4: return opi_read_zero_page(&R6502::opf_cpy);
case 0xc5: return opi_read_zero_page(&R6502::opf_cmp);
case 0xc6: return opi_rmw_zero_page(&R6502::opf_dec);
case 0xc8: return opi_increment(regs.y);
case 0xc9: return opi_read_immediate<&R6502::opf_cmp>();
case 0xc9: return opi_read_immediate(&R6502::opf_cmp);
case 0xca: return opi_decrement(regs.x);
case 0xcc: return opi_read_absolute<&R6502::opf_cpy>();
case 0xcd: return opi_read_absolute<&R6502::opf_cmp>();
case 0xce: return opi_rmw_absolute<&R6502::opf_dec>();
case 0xcc: return opi_read_absolute(&R6502::opf_cpy);
case 0xcd: return opi_read_absolute(&R6502::opf_cmp);
case 0xce: return opi_rmw_absolute(&R6502::opf_dec);
case 0xd0: return opi_branch(regs.p.z == 0);
case 0xd1: return opi_read_indirect_zero_page_y<&R6502::opf_cmp>();
case 0xd1: return opi_read_indirect_zero_page_y(&R6502::opf_cmp);
I case 0xd4: return opill_nop_zero_page_x();
case 0xd5: return opi_read_zero_page_x<&R6502::opf_cmp>();
case 0xd6: return opi_rmw_zero_page_x<&R6502::opf_dec>();
case 0xd5: return opi_read_zero_page_x(&R6502::opf_cmp);
case 0xd6: return opi_rmw_zero_page_x(&R6502::opf_dec);
case 0xd8: return opi_clear_flag(regs.p.d);
case 0xd9: return opi_read_absolute_y<&R6502::opf_cmp>();
case 0xd9: return opi_read_absolute_y(&R6502::opf_cmp);
I case 0xda: return opill_nop_implied();
I case 0xdc: return opill_nop_absolute_x();
case 0xdd: return opi_read_absolute_x<&R6502::opf_cmp>();
case 0xde: return opi_rmw_absolute_x<&R6502::opf_dec>();
case 0xe0: return opi_read_immediate<&R6502::opf_cpx>();
case 0xe1: return opi_read_indirect_zero_page_x<&R6502::opf_sbc>();
case 0xdd: return opi_read_absolute_x(&R6502::opf_cmp);
case 0xde: return opi_rmw_absolute_x(&R6502::opf_dec);
case 0xe0: return opi_read_immediate(&R6502::opf_cpx);
case 0xe1: return opi_read_indirect_zero_page_x(&R6502::opf_sbc);
I case 0xe2: return opill_nop_immediate();
case 0xe4: return opi_read_zero_page<&R6502::opf_cpx>();
case 0xe5: return opi_read_zero_page<&R6502::opf_sbc>();
case 0xe6: return opi_rmw_zero_page<&R6502::opf_inc>();
case 0xe4: return opi_read_zero_page(&R6502::opf_cpx);
case 0xe5: return opi_read_zero_page(&R6502::opf_sbc);
case 0xe6: return opi_rmw_zero_page(&R6502::opf_inc);
case 0xe8: return opi_increment(regs.x);
case 0xe9: return opi_read_immediate<&R6502::opf_sbc>();
case 0xe9: return opi_read_immediate(&R6502::opf_sbc);
case 0xea: return op_nop();
I case 0xeb: return opi_read_immediate<&R6502::opf_sbc>();
case 0xec: return opi_read_absolute<&R6502::opf_cpx>();
case 0xed: return opi_read_absolute<&R6502::opf_sbc>();
case 0xee: return opi_rmw_absolute<&R6502::opf_inc>();
I case 0xeb: return opi_read_immediate(&R6502::opf_sbc);
case 0xec: return opi_read_absolute(&R6502::opf_cpx);
case 0xed: return opi_read_absolute(&R6502::opf_sbc);
case 0xee: return opi_rmw_absolute(&R6502::opf_inc);
case 0xf0: return opi_branch(regs.p.z == 1);
case 0xf1: return opi_read_indirect_zero_page_y<&R6502::opf_sbc>();
case 0xf1: return opi_read_indirect_zero_page_y(&R6502::opf_sbc);
I case 0xf4: return opill_nop_zero_page_x();
case 0xf5: return opi_read_zero_page_x<&R6502::opf_sbc>();
case 0xf6: return opi_rmw_zero_page_x<&R6502::opf_inc>();
case 0xf5: return opi_read_zero_page_x(&R6502::opf_sbc);
case 0xf6: return opi_rmw_zero_page_x(&R6502::opf_inc);
case 0xf8: return opi_set_flag(regs.p.d);
case 0xf9: return opi_read_absolute_y<&R6502::opf_sbc>();
case 0xf9: return opi_read_absolute_y(&R6502::opf_sbc);
I case 0xfa: return opill_nop_implied();
I case 0xfc: return opill_nop_absolute_x();
case 0xfd: return opi_read_absolute_x<&R6502::opf_sbc>();
case 0xfe: return opi_rmw_absolute_x<&R6502::opf_inc>();
case 0xfd: return opi_read_absolute_x(&R6502::opf_sbc);
case 0xfe: return opi_rmw_absolute_x(&R6502::opf_inc);
}
//unimplemented opcode

View File

@ -57,27 +57,29 @@ struct R6502 {
auto opf_sla();
auto opf_sra();
using fp = auto (R6502::*)() -> void;
auto opi_branch(bool condition);
auto opi_clear_flag(bool& flag);
auto opi_decrement(uint8& r);
auto opi_increment(uint8& r);
auto opi_pull(uint8& r);
auto opi_push(uint8& r);
template<auto (R6502::*op)() -> void> auto opi_read_absolute();
template<auto (R6502::*op)() -> void> auto opi_read_absolute_x();
template<auto (R6502::*op)() -> void> auto opi_read_absolute_y();
template<auto (R6502::*op)() -> void> auto opi_read_immediate();
template<auto (R6502::*op)() -> void> auto opi_read_indirect_zero_page_x();
template<auto (R6502::*op)() -> void> auto opi_read_indirect_zero_page_y();
template<auto (R6502::*op)() -> void> auto opi_read_zero_page();
template<auto (R6502::*op)() -> void> auto opi_read_zero_page_x();
template<auto (R6502::*op)() -> void> auto opi_read_zero_page_y();
template<auto (R6502::*op)() -> void> auto opi_rmw_absolute();
template<auto (R6502::*op)() -> void> auto opi_rmw_absolute_x();
template<auto (R6502::*op)() -> void> auto opi_rmw_zero_page();
template<auto (R6502::*op)() -> void> auto opi_rmw_zero_page_x();
auto opi_read_absolute(fp);
auto opi_read_absolute_x(fp);
auto opi_read_absolute_y(fp);
auto opi_read_immediate(fp);
auto opi_read_indirect_zero_page_x(fp);
auto opi_read_indirect_zero_page_y(fp);
auto opi_read_zero_page(fp);
auto opi_read_zero_page_x(fp);
auto opi_read_zero_page_y(fp);
auto opi_rmw_absolute(fp);
auto opi_rmw_absolute_x(fp);
auto opi_rmw_zero_page(fp);
auto opi_rmw_zero_page_x(fp);
auto opi_set_flag(bool& flag);
template<auto (R6502::*op)() -> void> auto opi_shift();
auto opi_shift(fp);
auto opi_store_absolute(uint8& r);
auto opi_store_absolute_x(uint8& r);
auto opi_store_absolute_y(uint8& r);

View File

@ -4,15 +4,15 @@ struct Flag {
| (h << 3) | (i << 2) | (z << 1) | (c << 0);
}
inline auto operator=(uint8 data) -> uint {
inline auto operator=(uint data) -> uint {
n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10;
h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return data;
}
inline auto operator|=(uint8 data) -> uint { return operator=(operator uint() | data); }
inline auto operator^=(uint8 data) -> uint { return operator=(operator uint() ^ data); }
inline auto operator&=(uint8 data) -> uint { return operator=(operator uint() & data); }
inline auto operator|=(uint data) -> uint { return operator=(operator uint() | data); }
inline auto operator^=(uint data) -> uint { return operator=(operator uint() ^ data); }
inline auto operator&=(uint data) -> uint { return operator=(operator uint() & data); }
bool n, v, p, b, h, i, z, c;
};
@ -24,8 +24,8 @@ struct Word {
inline auto operator++() -> uint { return ++w; }
inline auto operator--() -> uint { return --w; }
inline auto operator++(int) -> uint { unsigned data = w++; return data; }
inline auto operator--(int) -> uint { unsigned data = w--; return data; }
inline auto operator++(int) -> uint { uint data = w++; return data; }
inline auto operator--(int) -> uint { uint data = w--; return data; }
inline auto operator+=(uint data) -> uint { return w += data;; }
inline auto operator-=(uint data) -> uint { return w -= data;; }

View File

@ -8,57 +8,56 @@ namespace Processor {
#include "disassembler.cpp"
#include "serialization.cpp"
#define op(id, name, ...) case id: return op_##name(__VA_ARGS__);
#define ol(id, name, fp) case id: return op_##name(&SPC700::op_##fp);
#define of(id, name, fp, ...) case id: return op_##name(&SPC700::op_##fp, __VA_ARGS__);
#define op(id, name, ...) case id: return op_##name(__VA_ARGS__);
#define fp(name) &SPC700::op_##name
auto SPC700::instruction() -> void {
switch(opcode = readPC()) {
op(0x00, nop)
op(0x01, jst)
op(0x02, set_bit);
op(0x03, branch_bit);
of(0x04, read_dp, or, regs.a)
of(0x05, read_addr, or, regs.a)
ol(0x06, read_ix, or);
ol(0x07, read_idpx, or)
of(0x08, read_const, or, regs.a)
ol(0x09, write_dp_dp, or)
op(0x02, set_bit)
op(0x03, branch_bit)
op(0x04, read_dp, fp(or), regs.a)
op(0x05, read_addr, fp(or), regs.a)
op(0x06, read_ix, fp(or))
op(0x07, read_idpx, fp(or))
op(0x08, read_const, fp(or), regs.a)
op(0x09, write_dp_dp, fp(or))
op(0x0a, set_addr_bit)
ol(0x0b, adjust_dp, asl)
ol(0x0c, adjust_addr, asl)
op(0x0b, adjust_dp, fp(asl))
op(0x0c, adjust_addr, fp(asl))
op(0x0d, push, regs.p)
op(0x0e, test_addr, 1)
op(0x0f, brk)
op(0x10, branch, regs.p.n == 0)
op(0x11, jst)
op(0x12, set_bit)
op(0x13, branch_bit);
of(0x14, read_dpi, or, regs.a, regs.x)
of(0x15, read_addri, or, regs.x)
of(0x16, read_addri, or, regs.y)
ol(0x17, read_idpy, or)
ol(0x18, write_dp_const, or)
ol(0x19, write_ix_iy, or)
op(0x13, branch_bit)
op(0x14, read_dpi, fp(or), regs.a, regs.x)
op(0x15, read_addri, fp(or), regs.x)
op(0x16, read_addri, fp(or), regs.y)
op(0x17, read_idpy, fp(or))
op(0x18, write_dp_const, fp(or))
op(0x19, write_ix_iy, fp(or))
op(0x1a, adjust_dpw, -1)
ol(0x1b, adjust_dpx, asl)
of(0x1c, adjust, asl, regs.a)
of(0x1d, adjust, dec, regs.x)
of(0x1e, read_addr, cmp, regs.x)
op(0x1b, adjust_dpx, fp(asl))
op(0x1c, adjust, fp(asl), regs.a)
op(0x1d, adjust, fp(dec), regs.x)
op(0x1e, read_addr, fp(cmp), regs.x)
op(0x1f, jmp_iaddrx)
op(0x20, set_flag, regs.p.p, 0)
op(0x21, jst)
op(0x22, set_bit)
op(0x23, branch_bit)
of(0x24, read_dp, and, regs.a)
of(0x25, read_addr, and, regs.a)
ol(0x26, read_ix, and)
ol(0x27, read_idpx, and)
of(0x28, read_const, and, regs.a)
ol(0x29, write_dp_dp, and)
op(0x24, read_dp, fp(and), regs.a)
op(0x25, read_addr, fp(and), regs.a)
op(0x26, read_ix, fp(and))
op(0x27, read_idpx, fp(and))
op(0x28, read_const, fp(and), regs.a)
op(0x29, write_dp_dp, fp(and))
op(0x2a, set_addr_bit)
ol(0x2b, adjust_dp, rol)
ol(0x2c, adjust_addr, rol)
op(0x2b, adjust_dp, fp(rol))
op(0x2c, adjust_addr, fp(rol))
op(0x2d, push, regs.a)
op(0x2e, bne_dp)
op(0x2f, branch, true)
@ -66,31 +65,31 @@ auto SPC700::instruction() -> void {
op(0x31, jst)
op(0x32, set_bit)
op(0x33, branch_bit)
of(0x34, read_dpi, and, regs.a, regs.x)
of(0x35, read_addri, and, regs.x)
of(0x36, read_addri, and, regs.y)
ol(0x37, read_idpy, and)
ol(0x38, write_dp_const, and)
ol(0x39, write_ix_iy, and)
op(0x34, read_dpi, fp(and), regs.a, regs.x)
op(0x35, read_addri, fp(and), regs.x)
op(0x36, read_addri, fp(and), regs.y)
op(0x37, read_idpy, fp(and))
op(0x38, write_dp_const, fp(and))
op(0x39, write_ix_iy, fp(and))
op(0x3a, adjust_dpw, +1)
ol(0x3b, adjust_dpx, rol)
of(0x3c, adjust, rol, regs.a)
of(0x3d, adjust, inc, regs.x)
of(0x3e, read_dp, cmp, regs.x)
op(0x3b, adjust_dpx, fp(rol))
op(0x3c, adjust, fp(rol), regs.a)
op(0x3d, adjust, fp(inc), regs.x)
op(0x3e, read_dp, fp(cmp), regs.x)
op(0x3f, jsr_addr)
op(0x40, set_flag, regs.p.p, 1)
op(0x41, jst)
op(0x42, set_bit)
op(0x43, branch_bit)
of(0x44, read_dp, eor, regs.a)
of(0x45, read_addr, eor, regs.a)
ol(0x46, read_ix, eor)
ol(0x47, read_idpx, eor)
of(0x48, read_const, eor, regs.a)
ol(0x49, write_dp_dp, eor)
op(0x44, read_dp, fp(eor), regs.a)
op(0x45, read_addr, fp(eor), regs.a)
op(0x46, read_ix, fp(eor))
op(0x47, read_idpx, fp(eor))
op(0x48, read_const, fp(eor), regs.a)
op(0x49, write_dp_dp, fp(eor))
op(0x4a, set_addr_bit)
ol(0x4b, adjust_dp, lsr)
ol(0x4c, adjust_addr, lsr)
op(0x4b, adjust_dp, fp(lsr))
op(0x4c, adjust_addr, fp(lsr))
op(0x4d, push, regs.x)
op(0x4e, test_addr, 0)
op(0x4f, jsp_dp)
@ -98,31 +97,31 @@ auto SPC700::instruction() -> void {
op(0x51, jst)
op(0x52, set_bit)
op(0x53, branch_bit)
of(0x54, read_dpi, eor, regs.a, regs.x)
of(0x55, read_addri, eor, regs.x)
of(0x56, read_addri, eor, regs.y)
ol(0x57, read_idpy, eor)
ol(0x58, write_dp_const, eor)
ol(0x59, write_ix_iy, eor)
ol(0x5a, read_dpw, cpw)
ol(0x5b, adjust_dpx, lsr)
of(0x5c, adjust, lsr, regs.a)
op(0x54, read_dpi, fp(eor), regs.a, regs.x)
op(0x55, read_addri, fp(eor), regs.x)
op(0x56, read_addri, fp(eor), regs.y)
op(0x57, read_idpy, fp(eor))
op(0x58, write_dp_const, fp(eor))
op(0x59, write_ix_iy, fp(eor))
op(0x5a, read_dpw, fp(cpw))
op(0x5b, adjust_dpx, fp(lsr))
op(0x5c, adjust, fp(lsr), regs.a)
op(0x5d, transfer, regs.a, regs.x)
of(0x5e, read_addr, cmp, regs.y)
op(0x5e, read_addr, fp(cmp), regs.y)
op(0x5f, jmp_addr)
op(0x60, set_flag, regs.p.c, 0)
op(0x61, jst)
op(0x62, set_bit)
op(0x63, branch_bit)
of(0x64, read_dp, cmp, regs.a)
of(0x65, read_addr, cmp, regs.a)
ol(0x66, read_ix, cmp)
ol(0x67, read_idpx, cmp)
of(0x68, read_const, cmp, regs.a)
ol(0x69, write_dp_dp, cmp)
op(0x64, read_dp, fp(cmp), regs.a)
op(0x65, read_addr, fp(cmp), regs.a)
op(0x66, read_ix, fp(cmp))
op(0x67, read_idpx, fp(cmp))
op(0x68, read_const, fp(cmp), regs.a)
op(0x69, write_dp_dp, fp(cmp))
op(0x6a, set_addr_bit)
ol(0x6b, adjust_dp, ror)
ol(0x6c, adjust_addr, ror)
op(0x6b, adjust_dp, fp(ror))
op(0x6c, adjust_addr, fp(ror))
op(0x6d, push, regs.y)
op(0x6e, bne_dpdec)
op(0x6f, rts)
@ -130,47 +129,47 @@ auto SPC700::instruction() -> void {
op(0x71, jst)
op(0x72, set_bit)
op(0x73, branch_bit)
of(0x74, read_dpi, cmp, regs.a, regs.x)
of(0x75, read_addri, cmp, regs.x)
of(0x76, read_addri, cmp, regs.y)
ol(0x77, read_idpy, cmp)
ol(0x78, write_dp_const, cmp)
ol(0x79, write_ix_iy, cmp)
ol(0x7a, read_dpw, adw)
ol(0x7b, adjust_dpx, ror)
of(0x7c, adjust, ror, regs.a)
op(0x74, read_dpi, fp(cmp), regs.a, regs.x)
op(0x75, read_addri, fp(cmp), regs.x)
op(0x76, read_addri, fp(cmp), regs.y)
op(0x77, read_idpy, fp(cmp))
op(0x78, write_dp_const, fp(cmp))
op(0x79, write_ix_iy, fp(cmp))
op(0x7a, read_dpw, fp(adw))
op(0x7b, adjust_dpx, fp(ror))
op(0x7c, adjust, fp(ror), regs.a)
op(0x7d, transfer, regs.x, regs.a)
of(0x7e, read_dp, cmp, regs.y)
op(0x7e, read_dp, fp(cmp), regs.y)
op(0x7f, rti)
op(0x80, set_flag, regs.p.c, 1)
op(0x81, jst)
op(0x82, set_bit)
op(0x83, branch_bit)
of(0x84, read_dp, adc, regs.a)
of(0x85, read_addr, adc, regs.a)
ol(0x86, read_ix, adc)
ol(0x87, read_idpx, adc)
of(0x88, read_const, adc, regs.a)
ol(0x89, write_dp_dp, adc)
op(0x84, read_dp, fp(adc), regs.a)
op(0x85, read_addr, fp(adc), regs.a)
op(0x86, read_ix, fp(adc))
op(0x87, read_idpx, fp(adc))
op(0x88, read_const, fp(adc), regs.a)
op(0x89, write_dp_dp, fp(adc))
op(0x8a, set_addr_bit)
ol(0x8b, adjust_dp, dec)
ol(0x8c, adjust_addr, dec)
of(0x8d, read_const, ld, regs.y)
op(0x8b, adjust_dp, fp(dec))
op(0x8c, adjust_addr, fp(dec))
op(0x8d, read_const, fp(ld), regs.y)
op(0x8e, plp)
ol(0x8f, write_dp_const, st)
op(0x8f, write_dp_const, fp(st))
op(0x90, branch, regs.p.c == 0)
op(0x91, jst)
op(0x92, set_bit)
op(0x93, branch_bit)
of(0x94, read_dpi, adc, regs.a, regs.x)
of(0x95, read_addri, adc, regs.x)
of(0x96, read_addri, adc, regs.y)
ol(0x97, read_idpy, adc)
ol(0x98, write_dp_const, adc)
ol(0x99, write_ix_iy, adc)
ol(0x9a, read_dpw, sbw)
ol(0x9b, adjust_dpx, dec)
of(0x9c, adjust, dec, regs.a)
op(0x94, read_dpi, fp(adc), regs.a, regs.x)
op(0x95, read_addri, fp(adc), regs.x)
op(0x96, read_addri, fp(adc), regs.y)
op(0x97, read_idpy, fp(adc))
op(0x98, write_dp_const, fp(adc))
op(0x99, write_ix_iy, fp(adc))
op(0x9a, read_dpw, fp(sbw))
op(0x9b, adjust_dpx, fp(dec))
op(0x9c, adjust, fp(dec), regs.a)
op(0x9d, transfer, regs.s, regs.x)
op(0x9e, div_ya_x)
op(0x9f, xcn)
@ -178,31 +177,31 @@ auto SPC700::instruction() -> void {
op(0xa1, jst)
op(0xa2, set_bit)
op(0xa3, branch_bit)
of(0xa4, read_dp, sbc, regs.a)
of(0xa5, read_addr, sbc, regs.a)
ol(0xa6, read_ix, sbc)
ol(0xa7, read_idpx, sbc)
of(0xa8, read_const, sbc, regs.a)
ol(0xa9, write_dp_dp, sbc)
op(0xa4, read_dp, fp(sbc), regs.a)
op(0xa5, read_addr, fp(sbc), regs.a)
op(0xa6, read_ix, fp(sbc))
op(0xa7, read_idpx, fp(sbc))
op(0xa8, read_const, fp(sbc), regs.a)
op(0xa9, write_dp_dp, fp(sbc))
op(0xaa, set_addr_bit)
ol(0xab, adjust_dp, inc)
ol(0xac, adjust_addr, inc)
of(0xad, read_const, cmp, regs.y)
op(0xab, adjust_dp, fp(inc))
op(0xac, adjust_addr, fp(inc))
op(0xad, read_const, fp(cmp), regs.y)
op(0xae, pull, regs.a)
op(0xaf, sta_ixinc)
op(0xb0, branch, regs.p.c == 1)
op(0xb1, jst)
op(0xb2, set_bit)
op(0xb3, branch_bit)
of(0xb4, read_dpi, sbc, regs.a, regs.x)
of(0xb5, read_addri, sbc, regs.x)
of(0xb6, read_addri, sbc, regs.y)
ol(0xb7, read_idpy, sbc)
ol(0xb8, write_dp_const, sbc)
ol(0xb9, write_ix_iy, sbc)
ol(0xba, read_dpw, ldw)
ol(0xbb, adjust_dpx, inc)
of(0xbc, adjust, inc, regs.a)
op(0xb4, read_dpi, fp(sbc), regs.a, regs.x)
op(0xb5, read_addri, fp(sbc), regs.x)
op(0xb6, read_addri, fp(sbc), regs.y)
op(0xb7, read_idpy, fp(sbc))
op(0xb8, write_dp_const, fp(sbc))
op(0xb9, write_ix_iy, fp(sbc))
op(0xba, read_dpw, fp(ldw))
op(0xbb, adjust_dpx, fp(inc))
op(0xbc, adjust, fp(inc), regs.a)
op(0xbd, transfer, regs.x, regs.s)
op(0xbe, das)
op(0xbf, lda_ixinc)
@ -214,12 +213,12 @@ auto SPC700::instruction() -> void {
op(0xc5, write_addr, regs.a)
op(0xc6, sta_ix)
op(0xc7, sta_idpx)
of(0xc8, read_const, cmp, regs.x)
op(0xc8, read_const, fp(cmp), regs.x)
op(0xc9, write_addr, regs.x)
op(0xca, set_addr_bit)
op(0xcb, write_dp, regs.y)
op(0xcc, write_addr, regs.y)
of(0xcd, read_const, ld, regs.x)
op(0xcd, read_const, fp(ld), regs.x)
op(0xce, pull, regs.x)
op(0xcf, mul_ya)
op(0xd0, branch, regs.p.z == 0)
@ -234,7 +233,7 @@ auto SPC700::instruction() -> void {
op(0xd9, write_dpi, regs.x, regs.y)
op(0xda, stw_dp)
op(0xdb, write_dpi, regs.y, regs.x)
of(0xdc, adjust, dec, regs.y)
op(0xdc, adjust, fp(dec), regs.y)
op(0xdd, transfer, regs.y, regs.a)
op(0xde, bne_dpx)
op(0xdf, daa)
@ -242,15 +241,15 @@ auto SPC700::instruction() -> void {
op(0xe1, jst)
op(0xe2, set_bit)
op(0xe3, branch_bit)
of(0xe4, read_dp, ld, regs.a)
of(0xe5, read_addr, ld, regs.a)
ol(0xe6, read_ix, ld)
ol(0xe7, read_idpx, ld)
of(0xe8, read_const, ld, regs.a)
of(0xe9, read_addr, ld, regs.x)
op(0xe4, read_dp, fp(ld), regs.a)
op(0xe5, read_addr, fp(ld), regs.a)
op(0xe6, read_ix, fp(ld))
op(0xe7, read_idpx, fp(ld))
op(0xe8, read_const, fp(ld), regs.a)
op(0xe9, read_addr, fp(ld), regs.x)
op(0xea, set_addr_bit)
of(0xeb, read_dp, ld, regs.y)
of(0xec, read_addr, ld, regs.y)
op(0xeb, read_dp, fp(ld), regs.y)
op(0xec, read_addr, fp(ld), regs.y)
op(0xed, cmc)
op(0xee, pull, regs.y)
op(0xef, wait)
@ -258,15 +257,15 @@ auto SPC700::instruction() -> void {
op(0xf1, jst)
op(0xf2, set_bit)
op(0xf3, branch_bit)
of(0xf4, read_dpi, ld, regs.a, regs.x)
of(0xf5, read_addri, ld, regs.x)
of(0xf6, read_addri, ld, regs.y)
ol(0xf7, read_idpy, ld)
of(0xf8, read_dp, ld, regs.x)
of(0xf9, read_dpi, ld, regs.x, regs.y)
ol(0xfa, write_dp_dp, st)
of(0xfb, read_dpi, ld, regs.y, regs.x)
of(0xfc, adjust, inc, regs.y)
op(0xf4, read_dpi, fp(ld), regs.a, regs.x)
op(0xf5, read_addri, fp(ld), regs.x)
op(0xf6, read_addri, fp(ld), regs.y)
op(0xf7, read_idpy, fp(ld))
op(0xf8, read_dp, fp(ld), regs.x)
op(0xf9, read_dpi, fp(ld), regs.x, regs.y)
op(0xfa, write_dp_dp, fp(st))
op(0xfb, read_dpi, fp(ld), regs.y, regs.x)
op(0xfc, adjust, fp(inc), regs.y)
op(0xfd, transfer, regs.a, regs.y)
op(0xfe, bne_ydec)
op(0xff, wait)
@ -274,7 +273,6 @@ auto SPC700::instruction() -> void {
}
#undef op
#undef ol
#undef of
#undef fp
}

View File

@ -187,7 +187,7 @@ auto Cartridge::parseMarkupSA1(Markup::Node root) -> void {
parseMarkupMemory(sa1.iram, root["iram"], ID::SA1IRAM, true);
for(auto node : root.find("map")) {
parseMarkupMap(node, {&SA1::mmio_read, &sa1}, {&SA1::mmio_write, &sa1});
parseMarkupMap(node, {&SA1::readIO, &sa1}, {&SA1::writeIO, &sa1});
}
for(auto node : root["rom"].find("map")) {
@ -210,7 +210,7 @@ auto Cartridge::parseMarkupSuperFX(Markup::Node root) -> void {
parseMarkupMemory(superfx.ram, root["ram"], ID::SuperFXRAM, true);
for(auto node : root.find("map")) {
parseMarkupMap(node, {&SuperFX::mmio_read, &superfx}, {&SuperFX::mmio_write, &superfx});
parseMarkupMap(node, {&SuperFX::readIO, &superfx}, {&SuperFX::writeIO, &superfx});
}
for(auto node : root["rom"].find("map")) {

View File

@ -6,8 +6,8 @@ ICD2 icd2;
#if defined(SFC_SUPERGAMEBOY)
#include "interface/interface.cpp"
#include "mmio/mmio.cpp"
#include "interface.cpp"
#include "mmio.cpp"
#include "serialization.cpp"
auto ICD2::Enter() -> void {

View File

@ -12,19 +12,62 @@ struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Cothread {
auto power() -> void;
auto reset(bool soft = false) -> void;
//interface.cpp
auto lcdScanline() -> void override;
auto lcdOutput(uint2 color) -> void override;
auto joypWrite(bool p15, bool p14) -> void override;
auto loadRequest(uint id, string name, string type, bool required) -> void override;
auto loadRequest(uint id, string name, bool required) -> void override;
auto saveRequest(uint id, string name) -> void override;
auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override;
auto audioSample(const double* samples, uint channels) -> void override;
auto inputPoll(uint port, uint device, uint id) -> int16 override;
//mmio.cpp
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
uint revision;
private:
#include "interface/interface.hpp"
#include "mmio/mmio.hpp"
Emulator::Interface::Bind* bind = nullptr;
GameBoy::Interface::Hook* hook = nullptr;
struct Packet {
auto operator[](uint addr) -> uint8& { return data[addr & 15]; }
uint8 data[16];
};
Packet packet[64];
uint packetsize;
uint joyp_id;
bool joyp15lock;
bool joyp14lock;
bool pulselock;
bool strobelock;
bool packetlock;
Packet joyp_packet;
uint8 packetoffset;
uint8 bitdata, bitoffset;
uint8 r6003; //control port
uint8 r6004; //joypad 1
uint8 r6005; //joypad 2
uint8 r6006; //joypad 3
uint8 r6007; //joypad 4
uint8 r7000[16]; //JOYP packet data
uint8 mlt_req; //number of active joypads
uint8 output[4 * 512];
uint read_bank;
uint read_addr;
uint write_bank;
uint write_addr;
};
#else

View File

@ -1,28 +0,0 @@
auto lcdScanline() -> void override;
auto lcdOutput(uint2 color) -> void override;
auto joypWrite(bool p15, bool p14) -> void override;
auto loadRequest(uint id, string name, string type, bool required) -> void override;
auto loadRequest(uint id, string name, bool required) -> void override;
auto saveRequest(uint id, string name) -> void override;
auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override;
auto audioSample(const double* samples, uint channels) -> void override;
auto inputPoll(uint port, uint device, uint id) -> int16 override;
struct Packet {
auto operator[](uint addr) -> uint8& { return data[addr & 15]; }
uint8 data[16];
};
Packet packet[64];
uint packetsize;
uint joyp_id;
bool joyp15lock;
bool joyp14lock;
bool pulselock;
bool strobelock;
bool packetlock;
Packet joyp_packet;
uint8 packetoffset;
uint8 bitdata, bitoffset;

View File

@ -1,13 +0,0 @@
uint8 r6003; //control port
uint8 r6004; //joypad 1
uint8 r6005; //joypad 2
uint8 r6006; //joypad 3
uint8 r6007; //joypad 4
uint8 r7000[16]; //JOYP packet data
uint8 mlt_req; //number of active joypads
uint8 output[4 * 512];
uint read_bank;
uint read_addr;
uint write_bank;
uint write_addr;

View File

@ -1,12 +0,0 @@
struct CPUIRAM : Memory {
auto size() const -> uint;
alwaysinline auto read(uint24, uint8 = 0) -> uint8;
alwaysinline auto write(uint24, uint8) -> void;
} cpuiram;
struct CPUBWRAM : Memory {
auto size() const -> uint;
alwaysinline auto read(uint24, uint8 = 0) -> uint8;
alwaysinline auto write(uint24, uint8) -> void;
bool dma;
} cpubwram;

View File

@ -1,11 +0,0 @@
struct DMA {
enum CDEN : uint { DmaNormal = 0, DmaCharConversion = 1 };
enum SD : uint { SourceROM = 0, SourceBWRAM = 1, SourceIRAM = 2 };
enum DD : uint { DestIRAM = 0, DestBWRAM = 1 };
uint line;
} dma;
auto dma_normal() -> void;
auto dma_cc1() -> void;
auto dma_cc1_read(uint addr) -> uint8;
auto dma_cc2() -> void;

View File

@ -1,6 +1,6 @@
auto SA1::bus_read(uint24 addr, uint8 data) -> uint8 {
if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff
return mmio_read(addr, data);
return readIO(addr, data);
}
if((addr & 0x408000) == 0x008000) { //$00-3f,80-bf:8000-ffff
@ -42,7 +42,7 @@ auto SA1::bus_read(uint24 addr, uint8 data) -> uint8 {
auto SA1::bus_write(uint24 addr, uint8 data) -> void {
if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff
return mmio_write(addr, data);
return writeIO(addr, data);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f,80-bf:6000-7fff

View File

@ -1,19 +0,0 @@
auto bus_read(uint24 addr, uint8 data) -> uint8;
auto bus_write(uint24 addr, uint8 data) -> void;
auto vbr_read(uint24 addr, uint8 data = 0) -> uint8;
alwaysinline auto io() -> void override;
alwaysinline auto read(uint24 addr) -> uint8 override;
alwaysinline auto write(uint24 addr, uint8 data) -> void override;
auto mmcrom_read(uint24 addr, uint8 data) -> uint8;
auto mmcrom_write(uint24 addr, uint8 data) -> void;
auto mmcbwram_read(uint24 addr, uint8 data) -> uint8;
auto mmcbwram_write(uint24 addr, uint8 data) -> void;
auto mmc_sa1_read(uint addr, uint8 data) -> uint8;
auto mmc_sa1_write(uint addr, uint8 data) -> void;
auto bitmap_read(uint addr, uint8 data) -> uint8;
auto bitmap_write(uint addr, uint8 data) -> void;

View File

@ -366,115 +366,102 @@ auto SA1::mmio_w2259(uint8 data) -> void { mmio.va = (mmio.va & 0xffff00) | (dat
auto SA1::mmio_w225a(uint8 data) -> void { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
auto SA1::mmio_w225b(uint8 data) -> void { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
//(SFR) S-CPU flag read
auto SA1::mmio_r2300() -> uint8 {
uint8 data;
data = mmio.cpu_irqfl << 7;
data |= mmio.cpu_ivsw << 6;
data |= mmio.chdma_irqfl << 5;
data |= mmio.cpu_nvsw << 4;
data |= mmio.cmeg;
return data;
}
auto SA1::readIO(uint24 addr, uint8) -> uint8 {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
//(CFR) SA-1 flag read
auto SA1::mmio_r2301() -> uint8 {
uint8 data;
data = mmio.sa1_irqfl << 7;
data |= mmio.timer_irqfl << 6;
data |= mmio.dma_irqfl << 5;
data |= mmio.sa1_nmifl << 4;
data |= mmio.smeg;
return data;
}
switch(0x2300 | addr.bits(0,7)) {
//(HCR) hcounter read
auto SA1::mmio_r2302() -> uint8 {
//latch counters
mmio.hcr = status.hcounter >> 2;
mmio.vcr = status.vcounter;
return mmio.hcr >> 0;
}
auto SA1::mmio_r2303() -> uint8 {
return mmio.hcr >> 8;
}
//(VCR) vcounter read
auto SA1::mmio_r2304() -> uint8 { return mmio.vcr >> 0; }
auto SA1::mmio_r2305() -> uint8 { return mmio.vcr >> 8; }
//(MR) arithmetic result
auto SA1::mmio_r2306() -> uint8 { return mmio.mr >> 0; }
auto SA1::mmio_r2307() -> uint8 { return mmio.mr >> 8; }
auto SA1::mmio_r2308() -> uint8 { return mmio.mr >> 16; }
auto SA1::mmio_r2309() -> uint8 { return mmio.mr >> 24; }
auto SA1::mmio_r230a() -> uint8 { return mmio.mr >> 32; }
//(OF) arithmetic overflow flag
auto SA1::mmio_r230b() -> uint8 { return mmio.overflow << 7; }
//(VDPL) variable-length data read port low
auto SA1::mmio_r230c() -> uint8 {
uint32 data = (vbr_read(mmio.va + 0) << 0)
| (vbr_read(mmio.va + 1) << 8)
| (vbr_read(mmio.va + 2) << 16);
data >>= mmio.vbit;
return data >> 0;
}
//(VDPH) variable-length data read port high
auto SA1::mmio_r230d() -> uint8 {
uint32 data = (vbr_read(mmio.va + 0) << 0)
| (vbr_read(mmio.va + 1) << 8)
| (vbr_read(mmio.va + 2) << 16);
data >>= mmio.vbit;
if(mmio.hl == 1) {
//auto-increment mode
mmio.vbit += mmio.vb;
mmio.va += (mmio.vbit >> 3);
mmio.vbit &= 7;
//(SFR) S-CPU flag read
case 0x2300: {
uint8 data;
data = mmio.cpu_irqfl << 7;
data |= mmio.cpu_ivsw << 6;
data |= mmio.chdma_irqfl << 5;
data |= mmio.cpu_nvsw << 4;
data |= mmio.cmeg;
return data;
}
return data >> 8;
}
//(CFR) SA-1 flag read
case 0x2301: {
uint8 data;
data = mmio.sa1_irqfl << 7;
data |= mmio.timer_irqfl << 6;
data |= mmio.dma_irqfl << 5;
data |= mmio.sa1_nmifl << 4;
data |= mmio.smeg;
return data;
}
//(VC) version code register
auto SA1::mmio_r230e() -> uint8 {
return 0x01; //true value unknown
}
//(HCR) hcounter read
case 0x2302: {
//latch counters
mmio.hcr = status.hcounter >> 2;
mmio.vcr = status.vcounter;
return mmio.hcr >> 0;
}
auto SA1::mmio_read(uint24 addr, uint8) -> uint8 {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
addr &= 0xffff;
case 0x2303: {
return mmio.hcr >> 8;
}
//(VCR) vcounter read
case 0x2304: return mmio.vcr >> 0;
case 0x2305: return mmio.vcr >> 8;
//(MR) arithmetic result
case 0x2306: return mmio.mr >> 0;
case 0x2307: return mmio.mr >> 8;
case 0x2308: return mmio.mr >> 16;
case 0x2309: return mmio.mr >> 24;
case 0x230a: return mmio.mr >> 32;
//(OF) arithmetic overflow flag
case 0x230b: return mmio.overflow << 7;
//(VDPL) variable-length data read port low
case 0x230c: {
uint24 data;
data.byte(0) = vbr_read(mmio.va + 0);
data.byte(1) = vbr_read(mmio.va + 1);
data.byte(2) = vbr_read(mmio.va + 2);
data >>= mmio.vbit;
return data >> 0;
}
//(VDPH) variable-length data read port high
case 0x230d: {
uint24 data;
data.byte(0) = vbr_read(mmio.va + 0);
data.byte(1) = vbr_read(mmio.va + 1);
data.byte(2) = vbr_read(mmio.va + 2);
data >>= mmio.vbit;
if(mmio.hl == 1) {
//auto-increment mode
mmio.vbit += mmio.vb;
mmio.va += (mmio.vbit >> 3);
mmio.vbit &= 7;
}
return data >> 8;
}
//(VC) version code register
case 0x230e: {
return 0x01; //true value unknown
}
switch(addr) {
case 0x2300: return mmio_r2300();
case 0x2301: return mmio_r2301();
case 0x2302: return mmio_r2302();
case 0x2303: return mmio_r2303();
case 0x2304: return mmio_r2304();
case 0x2305: return mmio_r2305();
case 0x2306: return mmio_r2306();
case 0x2307: return mmio_r2307();
case 0x2308: return mmio_r2308();
case 0x2309: return mmio_r2309();
case 0x230a: return mmio_r230a();
case 0x230b: return mmio_r230b();
case 0x230c: return mmio_r230c();
case 0x230d: return mmio_r230d();
case 0x230e: return mmio_r230e();
}
return 0x00;
}
auto SA1::mmio_write(uint24 addr, uint8 data) -> void {
auto SA1::writeIO(uint24 addr, uint8 data) -> void {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
addr &= 0xffff;
switch(addr) {
switch(0x2200 | addr.bits(0,7)) {
case 0x2200: return mmio_w2200(data);
case 0x2201: return mmio_w2201(data);
case 0x2202: return mmio_w2202(data);

View File

@ -1,255 +0,0 @@
auto mmio_read(uint24 addr, uint8 data) -> uint8;
auto mmio_write(uint24 addr, uint8 data) -> void;
struct MMIO {
//$2200 CCNT
bool sa1_irq;
bool sa1_rdyb;
bool sa1_resb;
bool sa1_nmi;
uint8 smeg;
//$2201 SIE
bool cpu_irqen;
bool chdma_irqen;
//$2202 SIC
bool cpu_irqcl;
bool chdma_irqcl;
//$2203,$2204 CRV
uint16 crv;
//$2205,$2206 CNV
uint16 cnv;
//$2207,$2208 CIV
uint16 civ;
//$2209 SCNT
bool cpu_irq;
bool cpu_ivsw;
bool cpu_nvsw;
uint8 cmeg;
//$220a CIE
bool sa1_irqen;
bool timer_irqen;
bool dma_irqen;
bool sa1_nmien;
//$220b CIC
bool sa1_irqcl;
bool timer_irqcl;
bool dma_irqcl;
bool sa1_nmicl;
//$220c,$220d SNV
uint16 snv;
//$220e,$220f SIV
uint16 siv;
//$2210 TMC
bool hvselb;
bool ven;
bool hen;
//$2212,$2213
uint16 hcnt;
//$2214,$2215
uint16 vcnt;
//$2220 CXB
bool cbmode;
uint cb;
//$2221 DXB
bool dbmode;
uint db;
//$2222 EXB
bool ebmode;
uint eb;
//$2223 FXB
bool fbmode;
uint fb;
//$2224 BMAPS
uint8 sbm;
//$2225 BMAP
bool sw46;
uint8 cbm;
//$2226 SBWE
bool swen;
//$2227 CBWE
bool cwen;
//$2228 BWPA
uint8 bwp;
//$2229 SIWP
uint8 siwp;
//$222a CIWP
uint8 ciwp;
//$2230 DCNT
bool dmaen;
bool dprio;
bool cden;
bool cdsel;
bool dd;
uint8 sd;
//$2231 CDMA
bool chdend;
uint8 dmasize;
uint8 dmacb;
//$2232-$2234 SDA
uint32 dsa;
//$2235-$2237 DDA
uint32 dda;
//$2238,$2239 DTC
uint16 dtc;
//$223f BBF
bool bbf;
//$2240-224f BRF
uint8 brf[16];
//$2250 MCNT
bool acm;
bool md;
//$2251,$2252 MA
uint16 ma;
//$2253,$2254 MB
uint16 mb;
//$2258 VBD
bool hl;
uint8 vb;
//$2259-$225b VDA
uint32 va;
uint8 vbit;
//$2300 SFR
bool cpu_irqfl;
bool chdma_irqfl;
//$2301 CFR
bool sa1_irqfl;
bool timer_irqfl;
bool dma_irqfl;
bool sa1_nmifl;
//$2302,$2303 HCR
uint16 hcr;
//$2304,$2305 VCR
uint16 vcr;
//$2306-230a MR
uint64 mr;
//$230b OF
bool overflow;
} mmio;
auto mmio_w2200(uint8) -> void; //CCNT
auto mmio_w2201(uint8) -> void; //SIE
auto mmio_w2202(uint8) -> void; //SIC
auto mmio_w2203(uint8) -> void; //CRVL
auto mmio_w2204(uint8) -> void; //CRVH
auto mmio_w2205(uint8) -> void; //CNVL
auto mmio_w2206(uint8) -> void; //CNVH
auto mmio_w2207(uint8) -> void; //CIVL
auto mmio_w2208(uint8) -> void; //CIVH
auto mmio_w2209(uint8) -> void; //SCNT
auto mmio_w220a(uint8) -> void; //CIE
auto mmio_w220b(uint8) -> void; //CIC
auto mmio_w220c(uint8) -> void; //SNVL
auto mmio_w220d(uint8) -> void; //SNVH
auto mmio_w220e(uint8) -> void; //SIVL
auto mmio_w220f(uint8) -> void; //SIVH
auto mmio_w2210(uint8) -> void; //TMC
auto mmio_w2211(uint8) -> void; //CTR
auto mmio_w2212(uint8) -> void; //HCNTL
auto mmio_w2213(uint8) -> void; //HCNTH
auto mmio_w2214(uint8) -> void; //VCNTL
auto mmio_w2215(uint8) -> void; //VCNTH
auto mmio_w2220(uint8) -> void; //CXB
auto mmio_w2221(uint8) -> void; //DXB
auto mmio_w2222(uint8) -> void; //EXB
auto mmio_w2223(uint8) -> void; //FXB
auto mmio_w2224(uint8) -> void; //BMAPS
auto mmio_w2225(uint8) -> void; //BMAP
auto mmio_w2226(uint8) -> void; //SBWE
auto mmio_w2227(uint8) -> void; //CBWE
auto mmio_w2228(uint8) -> void; //BWPA
auto mmio_w2229(uint8) -> void; //SIWP
auto mmio_w222a(uint8) -> void; //CIWP
auto mmio_w2230(uint8) -> void; //DCNT
auto mmio_w2231(uint8) -> void; //CDMA
auto mmio_w2232(uint8) -> void; //SDAL
auto mmio_w2233(uint8) -> void; //SDAH
auto mmio_w2234(uint8) -> void; //SDAB
auto mmio_w2235(uint8) -> void; //DDAL
auto mmio_w2236(uint8) -> void; //DDAH
auto mmio_w2237(uint8) -> void; //DDAB
auto mmio_w2238(uint8) -> void; //DTCL
auto mmio_w2239(uint8) -> void; //DTCH
auto mmio_w223f(uint8) -> void; //BBF
auto mmio_w2240(uint8) -> void; //BRF0
auto mmio_w2241(uint8) -> void; //BRF1
auto mmio_w2242(uint8) -> void; //BRF2
auto mmio_w2243(uint8) -> void; //BRF3
auto mmio_w2244(uint8) -> void; //BRF4
auto mmio_w2245(uint8) -> void; //BRF5
auto mmio_w2246(uint8) -> void; //BRF6
auto mmio_w2247(uint8) -> void; //BRF7
auto mmio_w2248(uint8) -> void; //BRF8
auto mmio_w2249(uint8) -> void; //BRF9
auto mmio_w224a(uint8) -> void; //BRFA
auto mmio_w224b(uint8) -> void; //BRFB
auto mmio_w224c(uint8) -> void; //BRFC
auto mmio_w224d(uint8) -> void; //BRFD
auto mmio_w224e(uint8) -> void; //BRFE
auto mmio_w224f(uint8) -> void; //BRFF
auto mmio_w2250(uint8) -> void; //MCNT
auto mmio_w2251(uint8) -> void; //MAL
auto mmio_w2252(uint8) -> void; //MAH
auto mmio_w2253(uint8) -> void; //MBL
auto mmio_w2254(uint8) -> void; //MBH
auto mmio_w2258(uint8) -> void; //VBD
auto mmio_w2259(uint8) -> void; //VDAL
auto mmio_w225a(uint8) -> void; //VDAH
auto mmio_w225b(uint8) -> void; //VDAB
auto mmio_r2300() -> uint8; //SFR
auto mmio_r2301() -> uint8; //CFR
auto mmio_r2302() -> uint8; //HCRL
auto mmio_r2303() -> uint8; //HCRH
auto mmio_r2304() -> uint8; //VCRL
auto mmio_r2305() -> uint8; //VCRH
auto mmio_r2306() -> uint8; //MR [00-07]
auto mmio_r2307() -> uint8; //MR [08-15]
auto mmio_r2308() -> uint8; //MR [16-23]
auto mmio_r2309() -> uint8; //MR [24-31]
auto mmio_r230a() -> uint8; //MR [32-40]
auto mmio_r230b() -> uint8; //OF
auto mmio_r230c() -> uint8; //VDPL
auto mmio_r230d() -> uint8; //VDPH
auto mmio_r230e() -> uint8; //VC

View File

@ -2,13 +2,12 @@
namespace SuperFamicom {
SA1 sa1;
#include "bus.cpp"
#include "dma.cpp"
#include "memory.cpp"
#include "mmio.cpp"
#include "serialization.cpp"
#include "bus/bus.cpp"
#include "dma/dma.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
SA1 sa1;
auto SA1::Enter() -> void {
while(true) scheduler.synchronize(), sa1.main();
@ -22,8 +21,8 @@ auto SA1::main() -> void {
return;
}
if(status.interrupt_pending) {
status.interrupt_pending = false;
if(status.interruptPending) {
status.interruptPending = false;
interrupt();
return;
}
@ -46,24 +45,24 @@ auto SA1::interrupt() -> void {
auto SA1::lastCycle() -> void {
if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
status.interrupt_pending = true;
status.interruptPending = true;
r.vector = mmio.cnv;
mmio.sa1_nmifl = true;
mmio.sa1_nmicl = 1;
r.wai = false;
} else if(!r.p.i) {
if(mmio.timer_irqen && !mmio.timer_irqcl) {
status.interrupt_pending = true;
status.interruptPending = true;
r.vector = mmio.civ;
mmio.timer_irqfl = true;
r.wai = false;
} else if(mmio.dma_irqen && !mmio.dma_irqcl) {
status.interrupt_pending = true;
status.interruptPending = true;
r.vector = mmio.civ;
mmio.dma_irqfl = true;
r.wai = false;
} else if(mmio.sa1_irq && !mmio.sa1_irqcl) {
status.interrupt_pending = true;
status.interruptPending = true;
r.vector = mmio.civ;
mmio.sa1_irqfl = true;
r.wai = false;
@ -72,12 +71,12 @@ auto SA1::lastCycle() -> void {
}
auto SA1::interruptPending() const -> bool {
return status.interrupt_pending;
return status.interruptPending;
}
auto SA1::tick() -> void {
step(2);
if(++status.tick_counter == 0) synchronizeCPU();
if(++status.counter == 0) synchronizeCPU();
//adjust counters:
//note that internally, status counters are in clocks;
@ -100,13 +99,13 @@ auto SA1::tick() -> void {
//test counters for timer IRQ
switch((mmio.ven << 1) + (mmio.hen << 0)) {
case 0: break;
case 1: if(status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
case 2: if(status.vcounter == mmio.vcnt && status.hcounter == 0) trigger_irq(); break;
case 3: if(status.vcounter == mmio.vcnt && status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
case 1: if(status.hcounter == (mmio.hcnt << 2)) triggerIRQ(); break;
case 2: if(status.vcounter == mmio.vcnt && status.hcounter == 0) triggerIRQ(); break;
case 3: if(status.vcounter == mmio.vcnt && status.hcounter == (mmio.hcnt << 2)) triggerIRQ(); break;
}
}
auto SA1::trigger_irq() -> void {
auto SA1::triggerIRQ() -> void {
mmio.timer_irqfl = true;
if(mmio.timer_irqen) mmio.timer_irqcl = 0;
}
@ -150,9 +149,9 @@ auto SA1::reset() -> void {
r.wai = false;
r.vector = 0x0000;
status.tick_counter = 0;
status.counter = 0;
status.interrupt_pending = false;
status.interruptPending = false;
status.scanlines = (system.region() == System::Region::NTSC ? 262 : 312);
status.vcounter = 0;
@ -278,9 +277,7 @@ auto SA1::reset() -> void {
mmio.bbf = 0;
//$2240-$224f BRF
for(unsigned i = 0; i < 16; i++) {
mmio.brf[i] = 0x00;
}
for(auto& n : mmio.brf) n = 0x00;
//$2250 MCNT
mmio.acm = 0;

View File

@ -1,25 +1,11 @@
struct SA1 : Processor::R65816, Cothread {
#include "bus/bus.hpp"
#include "dma/dma.hpp"
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
struct Status {
uint8 tick_counter;
bool interrupt_pending;
uint16 scanlines;
uint16 vcounter;
uint16 hcounter;
} status;
//sa1.cpp
static auto Enter() -> void;
auto main() -> void;
auto tick() -> void;
auto interrupt() -> void override;
alwaysinline auto trigger_irq() -> void;
alwaysinline auto triggerIRQ() -> void;
alwaysinline auto lastCycle() -> void override;
alwaysinline auto interruptPending() const -> bool override;
@ -29,11 +15,318 @@ struct SA1 : Processor::R65816, Cothread {
auto power() -> void;
auto reset() -> void;
//bus.cpp
struct CPUIRAM : Memory {
auto size() const -> uint;
alwaysinline auto read(uint24, uint8 = 0) -> uint8;
alwaysinline auto write(uint24, uint8) -> void;
};
struct CPUBWRAM : Memory {
auto size() const -> uint;
alwaysinline auto read(uint24, uint8 = 0) -> uint8;
alwaysinline auto write(uint24, uint8) -> void;
bool dma;
};
//dma.cpp
struct DMA {
enum CDEN : uint { DmaNormal = 0, DmaCharConversion = 1 };
enum SD : uint { SourceROM = 0, SourceBWRAM = 1, SourceIRAM = 2 };
enum DD : uint { DestIRAM = 0, DestBWRAM = 1 };
uint line;
};
auto dma_normal() -> void;
auto dma_cc1() -> void;
auto dma_cc1_read(uint addr) -> uint8;
auto dma_cc2() -> void;
//memory.cpp
auto bus_read(uint24 addr, uint8 data) -> uint8;
auto bus_write(uint24 addr, uint8 data) -> void;
auto vbr_read(uint24 addr, uint8 data = 0) -> uint8;
alwaysinline auto io() -> void override;
alwaysinline auto read(uint24 addr) -> uint8 override;
alwaysinline auto write(uint24 addr, uint8 data) -> void override;
auto mmcrom_read(uint24 addr, uint8 data) -> uint8;
auto mmcrom_write(uint24 addr, uint8 data) -> void;
auto mmcbwram_read(uint24 addr, uint8 data) -> uint8;
auto mmcbwram_write(uint24 addr, uint8 data) -> void;
auto mmc_sa1_read(uint addr, uint8 data) -> uint8;
auto mmc_sa1_write(uint addr, uint8 data) -> void;
auto bitmap_read(uint addr, uint8 data) -> uint8;
auto bitmap_write(uint addr, uint8 data) -> void;
//mmio.cpp
auto readIO(uint24 addr, uint8 data) -> uint8;
auto writeIO(uint24 addr, uint8 data) -> void;
//todo: merge these functions into writeIO()
auto mmio_w2200(uint8) -> void; //CCNT
auto mmio_w2201(uint8) -> void; //SIE
auto mmio_w2202(uint8) -> void; //SIC
auto mmio_w2203(uint8) -> void; //CRVL
auto mmio_w2204(uint8) -> void; //CRVH
auto mmio_w2205(uint8) -> void; //CNVL
auto mmio_w2206(uint8) -> void; //CNVH
auto mmio_w2207(uint8) -> void; //CIVL
auto mmio_w2208(uint8) -> void; //CIVH
auto mmio_w2209(uint8) -> void; //SCNT
auto mmio_w220a(uint8) -> void; //CIE
auto mmio_w220b(uint8) -> void; //CIC
auto mmio_w220c(uint8) -> void; //SNVL
auto mmio_w220d(uint8) -> void; //SNVH
auto mmio_w220e(uint8) -> void; //SIVL
auto mmio_w220f(uint8) -> void; //SIVH
auto mmio_w2210(uint8) -> void; //TMC
auto mmio_w2211(uint8) -> void; //CTR
auto mmio_w2212(uint8) -> void; //HCNTL
auto mmio_w2213(uint8) -> void; //HCNTH
auto mmio_w2214(uint8) -> void; //VCNTL
auto mmio_w2215(uint8) -> void; //VCNTH
auto mmio_w2220(uint8) -> void; //CXB
auto mmio_w2221(uint8) -> void; //DXB
auto mmio_w2222(uint8) -> void; //EXB
auto mmio_w2223(uint8) -> void; //FXB
auto mmio_w2224(uint8) -> void; //BMAPS
auto mmio_w2225(uint8) -> void; //BMAP
auto mmio_w2226(uint8) -> void; //SBWE
auto mmio_w2227(uint8) -> void; //CBWE
auto mmio_w2228(uint8) -> void; //BWPA
auto mmio_w2229(uint8) -> void; //SIWP
auto mmio_w222a(uint8) -> void; //CIWP
auto mmio_w2230(uint8) -> void; //DCNT
auto mmio_w2231(uint8) -> void; //CDMA
auto mmio_w2232(uint8) -> void; //SDAL
auto mmio_w2233(uint8) -> void; //SDAH
auto mmio_w2234(uint8) -> void; //SDAB
auto mmio_w2235(uint8) -> void; //DDAL
auto mmio_w2236(uint8) -> void; //DDAH
auto mmio_w2237(uint8) -> void; //DDAB
auto mmio_w2238(uint8) -> void; //DTCL
auto mmio_w2239(uint8) -> void; //DTCH
auto mmio_w223f(uint8) -> void; //BBF
auto mmio_w2240(uint8) -> void; //BRF0
auto mmio_w2241(uint8) -> void; //BRF1
auto mmio_w2242(uint8) -> void; //BRF2
auto mmio_w2243(uint8) -> void; //BRF3
auto mmio_w2244(uint8) -> void; //BRF4
auto mmio_w2245(uint8) -> void; //BRF5
auto mmio_w2246(uint8) -> void; //BRF6
auto mmio_w2247(uint8) -> void; //BRF7
auto mmio_w2248(uint8) -> void; //BRF8
auto mmio_w2249(uint8) -> void; //BRF9
auto mmio_w224a(uint8) -> void; //BRFA
auto mmio_w224b(uint8) -> void; //BRFB
auto mmio_w224c(uint8) -> void; //BRFC
auto mmio_w224d(uint8) -> void; //BRFD
auto mmio_w224e(uint8) -> void; //BRFE
auto mmio_w224f(uint8) -> void; //BRFF
auto mmio_w2250(uint8) -> void; //MCNT
auto mmio_w2251(uint8) -> void; //MAL
auto mmio_w2252(uint8) -> void; //MAH
auto mmio_w2253(uint8) -> void; //MBL
auto mmio_w2254(uint8) -> void; //MBH
auto mmio_w2258(uint8) -> void; //VBD
auto mmio_w2259(uint8) -> void; //VDAL
auto mmio_w225a(uint8) -> void; //VDAH
auto mmio_w225b(uint8) -> void; //VDAB
//serialization.cpp
auto serialize(serializer&) -> void;
MappedRAM rom;
MappedRAM iram;
MappedRAM bwram;
CPUIRAM cpuiram;
CPUBWRAM cpubwram;
private:
DMA dma;
struct Status {
uint8 counter;
bool interruptPending;
uint16 scanlines;
uint16 vcounter;
uint16 hcounter;
} status;
struct MMIO {
//$2200 CCNT
bool sa1_irq;
bool sa1_rdyb;
bool sa1_resb;
bool sa1_nmi;
uint8 smeg;
//$2201 SIE
bool cpu_irqen;
bool chdma_irqen;
//$2202 SIC
bool cpu_irqcl;
bool chdma_irqcl;
//$2203,$2204 CRV
uint16 crv;
//$2205,$2206 CNV
uint16 cnv;
//$2207,$2208 CIV
uint16 civ;
//$2209 SCNT
bool cpu_irq;
bool cpu_ivsw;
bool cpu_nvsw;
uint8 cmeg;
//$220a CIE
bool sa1_irqen;
bool timer_irqen;
bool dma_irqen;
bool sa1_nmien;
//$220b CIC
bool sa1_irqcl;
bool timer_irqcl;
bool dma_irqcl;
bool sa1_nmicl;
//$220c,$220d SNV
uint16 snv;
//$220e,$220f SIV
uint16 siv;
//$2210 TMC
bool hvselb;
bool ven;
bool hen;
//$2212,$2213
uint16 hcnt;
//$2214,$2215
uint16 vcnt;
//$2220 CXB
bool cbmode;
uint cb;
//$2221 DXB
bool dbmode;
uint db;
//$2222 EXB
bool ebmode;
uint eb;
//$2223 FXB
bool fbmode;
uint fb;
//$2224 BMAPS
uint8 sbm;
//$2225 BMAP
bool sw46;
uint8 cbm;
//$2226 SBWE
bool swen;
//$2227 CBWE
bool cwen;
//$2228 BWPA
uint8 bwp;
//$2229 SIWP
uint8 siwp;
//$222a CIWP
uint8 ciwp;
//$2230 DCNT
bool dmaen;
bool dprio;
bool cden;
bool cdsel;
bool dd;
uint8 sd;
//$2231 CDMA
bool chdend;
uint8 dmasize;
uint8 dmacb;
//$2232-$2234 SDA
uint32 dsa;
//$2235-$2237 DDA
uint32 dda;
//$2238,$2239 DTC
uint16 dtc;
//$223f BBF
bool bbf;
//$2240-224f BRF
uint8 brf[16];
//$2250 MCNT
bool acm;
bool md;
//$2251,$2252 MA
uint16 ma;
//$2253,$2254 MB
uint16 mb;
//$2258 VBD
bool hl;
uint8 vb;
//$2259-$225b VDA
uint32 va;
uint8 vbit;
//$2300 SFR
bool cpu_irqfl;
bool chdma_irqfl;
//$2301 CFR
bool sa1_irqfl;
bool timer_irqfl;
bool dma_irqfl;
bool sa1_nmifl;
//$2302,$2303 HCR
uint16 hcr;
//$2304,$2305 VCR
uint16 vcr;
//$2306-230a MR
uint64 mr;
//$230b OF
bool overflow;
} mmio;
};
extern SA1 sa1;

View File

@ -6,9 +6,9 @@ auto SA1::serialize(serializer& s) -> void {
s.array(bwram.data(), bwram.size());
//sa1.hpp
s.integer(status.tick_counter);
s.integer(status.counter);
s.integer(status.interrupt_pending);
s.integer(status.interruptPending);
s.integer(status.scanlines);
s.integer(status.vcounter);

View File

@ -1,11 +0,0 @@
struct CPUROM : Memory {
auto size() const -> uint;
auto read(uint24, uint8) -> uint8;
auto write(uint24, uint8) -> void;
} cpurom;
struct CPURAM : Memory {
auto size() const -> uint;
auto read(uint24, uint8) -> uint8;
auto write(uint24, uint8) -> void;
} cpuram;

View File

@ -1,5 +0,0 @@
auto stop() -> void;
auto color(uint8 source) -> uint8;
auto plot(uint8 x, uint8 y) -> void;
auto rpix(uint8 x, uint8 y) -> uint8;
auto pixelcache_flush(pixelcache_t& cache) -> void;

View File

@ -1,15 +0,0 @@
uint rom_mask; //rom_size - 1
uint ram_mask; //ram_size - 1
auto bus_read(uint24 addr, uint8 data = 0x00) -> uint8 override;
auto bus_write(uint24 addr, uint8 data) -> void override;
auto op_read(uint16 addr) -> uint8;
alwaysinline auto peekpipe() -> uint8;
alwaysinline auto pipe() -> uint8;
auto cache_flush() -> void;
auto cache_mmio_read(uint16 addr) -> uint8;
auto cache_mmio_write(uint16 addr, uint8 data) -> void;
auto memory_reset() -> void;

View File

@ -1,6 +1,6 @@
auto SuperFX::mmio_read(uint24 addr, uint8) -> uint8 {
auto SuperFX::readIO(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors();
addr &= 0xffff;
addr = 0x3000 | addr.bits(0,9);
if(addr >= 0x3100 && addr <= 0x32ff) {
return cache_mmio_read(addr - 0x3100);
@ -50,9 +50,9 @@ auto SuperFX::mmio_read(uint24 addr, uint8) -> uint8 {
return 0x00;
}
auto SuperFX::mmio_write(uint24 addr, uint8 data) -> void {
auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors();
addr &= 0xffff;
addr = 0x3000 | addr.bits(0,9);
if(addr >= 0x3100 && addr <= 0x32ff) {
return cache_mmio_write(addr - 0x3100, data);

View File

@ -1,2 +0,0 @@
auto mmio_read(uint24 addr, uint8 data) -> uint8;
auto mmio_write(uint24 addr, uint8 data) -> void;

View File

@ -2,13 +2,12 @@
namespace SuperFamicom {
#include "bus.cpp"
#include "core.cpp"
#include "memory.cpp"
#include "mmio.cpp"
#include "timing.cpp"
#include "serialization.cpp"
#include "bus/bus.cpp"
#include "core/core.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
#include "timing/timing.cpp"
SuperFX superfx;
auto SuperFX::Enter() -> void {

View File

@ -2,12 +2,6 @@ struct SuperFX : Processor::GSU, Cothread {
MappedRAM rom;
MappedRAM ram;
#include "bus/bus.hpp"
#include "core/core.hpp"
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
#include "timing/timing.hpp"
//superfx.cpp
static auto Enter() -> void;
auto main() -> void;
@ -17,8 +11,71 @@ struct SuperFX : Processor::GSU, Cothread {
auto power() -> void;
auto reset() -> void;
//bus.cpp
struct CPUROM : Memory {
auto size() const -> uint;
auto read(uint24, uint8) -> uint8;
auto write(uint24, uint8) -> void;
};
struct CPURAM : Memory {
auto size() const -> uint;
auto read(uint24, uint8) -> uint8;
auto write(uint24, uint8) -> void;
};
//core.cpp
auto stop() -> void;
auto color(uint8 source) -> uint8;
auto plot(uint8 x, uint8 y) -> void;
auto rpix(uint8 x, uint8 y) -> uint8;
auto pixelcache_flush(pixelcache_t& cache) -> void;
//memory.cpp
auto bus_read(uint24 addr, uint8 data = 0x00) -> uint8 override;
auto bus_write(uint24 addr, uint8 data) -> void override;
auto op_read(uint16 addr) -> uint8;
alwaysinline auto peekpipe() -> uint8;
alwaysinline auto pipe() -> uint8;
auto cache_flush() -> void;
auto cache_mmio_read(uint16 addr) -> uint8;
auto cache_mmio_write(uint16 addr, uint8 data) -> void;
auto memory_reset() -> void;
//mmio.cpp
auto readIO(uint24 addr, uint8 data) -> uint8;
auto writeIO(uint24 addr, uint8 data) -> void;
//timing.cpp
auto step(uint clocks) -> void;
auto rombuffer_sync() -> void;
auto rombuffer_update() -> void;
auto rombuffer_read() -> uint8;
auto rambuffer_sync() -> void;
auto rambuffer_read(uint16 addr) -> uint8;
auto rambuffer_write(uint16 addr, uint8 data) -> void;
auto r14_modify(uint16) -> void;
auto r15_modify(uint16) -> void;
auto timing_reset() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
CPUROM cpurom;
CPURAM cpuram;
private:
uint rom_mask; //rom_size - 1
uint ram_mask; //ram_size - 1
bool r15_modified = false;
};
extern SuperFX superfx;

View File

@ -1,4 +1,4 @@
auto SuperFX::step(unsigned clocks) -> void {
auto SuperFX::step(uint clocks) -> void {
if(regs.romcl) {
regs.romcl -= min(clocks, regs.romcl);
if(regs.romcl == 0) {

View File

@ -1,16 +0,0 @@
bool r15_modified = false;
auto step(unsigned clocks) -> void;
auto rombuffer_sync() -> void;
auto rombuffer_update() -> void;
auto rombuffer_read() -> uint8;
auto rambuffer_sync() -> void;
auto rambuffer_read(uint16 addr) -> uint8;
auto rambuffer_write(uint16 addr, uint8 data) -> void;
auto r14_modify(uint16) -> void;
auto r15_modify(uint16) -> void;
auto timing_reset() -> void;

View File

@ -64,7 +64,7 @@ obj/ui-resource.o:
# targets
build: $(objects)
$(call unique,$(compiler) -o out/$(name) $(objects) $(link))
$(strip $(compiler) -o out/$(name) $(objects) $(link))
ifeq ($(platform),macosx)
@if [ -d out/$(name).app ]; then rm -r out/$(name).app; fi
mkdir -p out/$(name).app/Contents/MacOS/