mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
20ac95ee49
commit
3681961ca5
|
@ -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/";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;; }
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
|
@ -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);
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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);
|
|
@ -1,2 +0,0 @@
|
|||
auto mmio_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mmio_write(uint24 addr, uint8 data) -> void;
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
|
@ -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;
|
|
@ -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/
|
||||
|
|
Loading…
Reference in New Issue