mirror of https://github.com/bsnes-emu/bsnes.git
Update to v098r17 release.
byuu says: Changelog: - fixed Super Game Boy regression from v096r04 with bottom tile row flickering - fixed GB STAT IRQ regression from previous WIP - Altered Space is now playable - GBVideoPlayer isn't; but nobody seems to know exactly what weird hardware quirk that one relies on to work - ~3-4% speed improvement in SuperFX games by eliminating function<> callback on register assignments - most noticeable in Doom in-game; least noticeable on Yoshi's Island title screen (darn) - finished GSU core and SuperFX coprocessor code cleanups - did some more work cleaning up the LR35902 core and GB CPU code Just a fair warning: don't get your hopes up on these GB fixes. Cliffhanger now hangs completely (har har), and none of the other bugs are fixed. We pretty much did all this work just for Altered Space. So, I hope you like playing Altered Space.
This commit is contained in:
parent
3681961ca5
commit
9b452c9f5f
|
@ -9,7 +9,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "098.16";
|
static const string Version = "098.17";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -14,10 +14,10 @@ auto CPU::Enter() -> void {
|
||||||
|
|
||||||
auto CPU::main() -> void {
|
auto CPU::main() -> void {
|
||||||
interrupt_test();
|
interrupt_test();
|
||||||
exec();
|
instruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::interrupt_raise(CPU::Interrupt id) -> void {
|
auto CPU::raise(CPU::Interrupt id) -> void {
|
||||||
if(id == Interrupt::Vblank) {
|
if(id == Interrupt::Vblank) {
|
||||||
status.interrupt_request_vblank = 1;
|
status.interrupt_request_vblank = 1;
|
||||||
if(status.interrupt_enable_vblank) r.halt = false;
|
if(status.interrupt_enable_vblank) r.halt = false;
|
||||||
|
@ -44,51 +44,35 @@ 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 {
|
auto CPU::interrupt_test() -> void {
|
||||||
if(!r.ime) return;
|
if(!r.ime) return;
|
||||||
|
|
||||||
if(status.interrupt_request_vblank && status.interrupt_enable_vblank) {
|
if(status.interrupt_request_vblank && status.interrupt_enable_vblank) {
|
||||||
status.interrupt_request_vblank = 0;
|
status.interrupt_request_vblank = 0;
|
||||||
return interrupt_exec(0x0040);
|
return interrupt(0x0040);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.interrupt_request_stat && status.interrupt_enable_stat) {
|
if(status.interrupt_request_stat && status.interrupt_enable_stat) {
|
||||||
status.interrupt_request_stat = 0;
|
status.interrupt_request_stat = 0;
|
||||||
return interrupt_exec(0x0048);
|
return interrupt(0x0048);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.interrupt_request_timer && status.interrupt_enable_timer) {
|
if(status.interrupt_request_timer && status.interrupt_enable_timer) {
|
||||||
status.interrupt_request_timer = 0;
|
status.interrupt_request_timer = 0;
|
||||||
return interrupt_exec(0x0050);
|
return interrupt(0x0050);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.interrupt_request_serial && status.interrupt_enable_serial) {
|
if(status.interrupt_request_serial && status.interrupt_enable_serial) {
|
||||||
status.interrupt_request_serial = 0;
|
status.interrupt_request_serial = 0;
|
||||||
return interrupt_exec(0x0058);
|
return interrupt(0x0058);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.interrupt_request_joypad && status.interrupt_enable_joypad) {
|
if(status.interrupt_request_joypad && status.interrupt_enable_joypad) {
|
||||||
status.interrupt_request_joypad = 0;
|
status.interrupt_request_joypad = 0;
|
||||||
return interrupt_exec(0x0060);
|
return interrupt(0x0060);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::interrupt_exec(uint16 pc) -> void {
|
|
||||||
op_io();
|
|
||||||
op_io();
|
|
||||||
op_io();
|
|
||||||
r.ime = 0;
|
|
||||||
op_write(--r[SP], r[PC] >> 8);
|
|
||||||
op_write(--r[SP], r[PC] >> 0);
|
|
||||||
r[PC] = pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto CPU::stop() -> bool {
|
auto CPU::stop() -> bool {
|
||||||
if(status.speed_switch) {
|
if(status.speed_switch) {
|
||||||
status.speed_switch = 0;
|
status.speed_switch = 0;
|
||||||
|
|
|
@ -3,10 +3,8 @@ struct CPU : Processor::LR35902, Thread, MMIO {
|
||||||
|
|
||||||
static auto Enter() -> void;
|
static auto Enter() -> void;
|
||||||
auto main() -> void;
|
auto main() -> void;
|
||||||
auto interrupt_raise(Interrupt id) -> void;
|
auto raise(Interrupt id) -> void;
|
||||||
auto interrupt_lower(Interrupt id) -> void;
|
|
||||||
auto interrupt_test() -> void;
|
auto interrupt_test() -> void;
|
||||||
auto interrupt_exec(uint16 pc) -> void;
|
|
||||||
auto stop() -> bool;
|
auto stop() -> bool;
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
|
|
||||||
|
@ -19,9 +17,9 @@ struct CPU : Processor::LR35902, Thread, MMIO {
|
||||||
auto mmio_write(uint16 addr, uint8 data) -> void;
|
auto mmio_write(uint16 addr, uint8 data) -> void;
|
||||||
|
|
||||||
//memory.cpp
|
//memory.cpp
|
||||||
auto op_io() -> void;
|
auto io() -> void override;
|
||||||
auto op_read(uint16 addr) -> uint8;
|
auto read(uint16 addr) -> uint8 override;
|
||||||
auto op_write(uint16 addr, uint8 data) -> void;
|
auto write(uint16 addr, uint8 data) -> void override;
|
||||||
auto cycle_edge() -> void;
|
auto cycle_edge() -> void;
|
||||||
auto dma_read(uint16 addr) -> uint8;
|
auto dma_read(uint16 addr) -> uint8;
|
||||||
auto dma_write(uint16 addr, uint8 data) -> void;
|
auto dma_write(uint16 addr, uint8 data) -> void;
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
auto CPU::op_io() -> void {
|
auto CPU::io() -> void {
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
add_clocks(4);
|
add_clocks(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::op_read(uint16 addr) -> uint8 {
|
auto CPU::read(uint16 addr) -> uint8 {
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
add_clocks(4);
|
add_clocks(4);
|
||||||
return bus.read(addr);
|
return bus.read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::op_write(uint16 addr, uint8 data) -> void {
|
auto CPU::write(uint16 addr, uint8 data) -> void {
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
add_clocks(4);
|
add_clocks(4);
|
||||||
bus.write(addr, data);
|
bus.write(addr, data);
|
||||||
|
|
|
@ -29,7 +29,7 @@ auto CPU::mmio_joyp_poll() -> void {
|
||||||
if(status.p15 == 1 && status.p14 == 1) status.joyp -= status.mlt_req;
|
if(status.p15 == 1 && status.p14 == 1) status.joyp -= status.mlt_req;
|
||||||
if(status.p15 == 0) status.joyp &= button ^ 0x0f;
|
if(status.p15 == 0) status.joyp &= button ^ 0x0f;
|
||||||
if(status.p14 == 0) status.joyp &= dpad ^ 0x0f;
|
if(status.p14 == 0) status.joyp &= dpad ^ 0x0f;
|
||||||
if(status.joyp != 0x0f) interrupt_raise(Interrupt::Joypad);
|
if(status.joyp != 0x0f) raise(Interrupt::Joypad);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::mmio_read(uint16 addr) -> uint8 {
|
auto CPU::mmio_read(uint16 addr) -> uint8 {
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
// 154 scanlines/frame
|
// 154 scanlines/frame
|
||||||
|
|
||||||
auto CPU::add_clocks(uint clocks) -> void {
|
auto CPU::add_clocks(uint clocks) -> void {
|
||||||
if(system.sgb()) system._clocksExecuted += clocks;
|
for(auto n : range(clocks)) {
|
||||||
|
|
||||||
while(clocks--) {
|
|
||||||
if(++status.clock == 0) {
|
if(++status.clock == 0) {
|
||||||
cartridge.mbc3.second();
|
cartridge.mbc3.second();
|
||||||
}
|
}
|
||||||
|
@ -25,14 +23,17 @@ auto CPU::add_clocks(uint clocks) -> void {
|
||||||
if(apu.clock < 0) co_switch(apu.thread);
|
if(apu.clock < 0) co_switch(apu.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(system.sgb()) scheduler.exit(Scheduler::Event::Step);
|
if(system.sgb()) {
|
||||||
|
system._clocksExecuted += clocks;
|
||||||
|
scheduler.exit(Scheduler::Event::Step);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::timer_262144hz() -> void {
|
auto CPU::timer_262144hz() -> void {
|
||||||
if(status.timer_enable && status.timer_clock == 1) {
|
if(status.timer_enable && status.timer_clock == 1) {
|
||||||
if(++status.tima == 0) {
|
if(++status.tima == 0) {
|
||||||
status.tima = status.tma;
|
status.tima = status.tma;
|
||||||
interrupt_raise(Interrupt::Timer);
|
raise(Interrupt::Timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +42,7 @@ auto CPU::timer_65536hz() -> void {
|
||||||
if(status.timer_enable && status.timer_clock == 2) {
|
if(status.timer_enable && status.timer_clock == 2) {
|
||||||
if(++status.tima == 0) {
|
if(++status.tima == 0) {
|
||||||
status.tima = status.tma;
|
status.tima = status.tma;
|
||||||
interrupt_raise(Interrupt::Timer);
|
raise(Interrupt::Timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +51,7 @@ auto CPU::timer_16384hz() -> void {
|
||||||
if(status.timer_enable && status.timer_clock == 3) {
|
if(status.timer_enable && status.timer_clock == 3) {
|
||||||
if(++status.tima == 0) {
|
if(++status.tima == 0) {
|
||||||
status.tima = status.tma;
|
status.tima = status.tma;
|
||||||
interrupt_raise(Interrupt::Timer);
|
raise(Interrupt::Timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +60,7 @@ auto CPU::timer_8192hz() -> void {
|
||||||
if(status.serial_transfer && status.serial_clock) {
|
if(status.serial_transfer && status.serial_clock) {
|
||||||
if(--status.serial_bits == 0) {
|
if(--status.serial_bits == 0) {
|
||||||
status.serial_transfer = 0;
|
status.serial_transfer = 0;
|
||||||
interrupt_raise(Interrupt::Serial);
|
raise(Interrupt::Serial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +69,7 @@ auto CPU::timer_4096hz() -> void {
|
||||||
if(status.timer_enable && status.timer_clock == 0) {
|
if(status.timer_enable && status.timer_clock == 0) {
|
||||||
if(++status.tima == 0) {
|
if(++status.tima == 0) {
|
||||||
status.tima = status.tma;
|
status.tima = status.tma;
|
||||||
interrupt_raise(Interrupt::Timer);
|
raise(Interrupt::Timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ auto PPU::cgb_read_tile(bool select, uint x, uint y, uint& attr, uint& data) ->
|
||||||
|
|
||||||
auto PPU::cgb_scanline() -> void {
|
auto PPU::cgb_scanline() -> void {
|
||||||
px = 0;
|
px = 0;
|
||||||
|
if(!enabled()) return;
|
||||||
|
|
||||||
const uint Height = (status.ob_size == 0 ? 8 : 16);
|
const uint Height = (status.ob_size == 0 ? 8 : 16);
|
||||||
sprites = 0;
|
sprites = 0;
|
||||||
|
@ -68,7 +69,7 @@ auto PPU::cgb_run() -> void {
|
||||||
ob.priority = 0;
|
ob.priority = 0;
|
||||||
|
|
||||||
uint color = 0x7fff;
|
uint color = 0x7fff;
|
||||||
if(status.display_enable) {
|
if(enabled()) {
|
||||||
cgb_run_bg();
|
cgb_run_bg();
|
||||||
if(status.window_display_enable) cgb_run_window();
|
if(status.window_display_enable) cgb_run_window();
|
||||||
if(status.ob_enable) cgb_run_ob();
|
if(status.ob_enable) cgb_run_ob();
|
||||||
|
|
|
@ -19,6 +19,7 @@ auto PPU::dmg_read_tile(bool select, uint x, uint y, uint& data) -> void {
|
||||||
|
|
||||||
auto PPU::dmg_scanline() -> void {
|
auto PPU::dmg_scanline() -> void {
|
||||||
px = 0;
|
px = 0;
|
||||||
|
if(!enabled()) return;
|
||||||
|
|
||||||
const uint Height = (status.ob_size == 0 ? 8 : 16);
|
const uint Height = (status.ob_size == 0 ? 8 : 16);
|
||||||
sprites = 0;
|
sprites = 0;
|
||||||
|
@ -59,7 +60,7 @@ auto PPU::dmg_run() -> void {
|
||||||
ob.palette = 0;
|
ob.palette = 0;
|
||||||
|
|
||||||
uint color = 0;
|
uint color = 0;
|
||||||
if(status.display_enable) {
|
if(enabled()) {
|
||||||
if(status.bg_enable) dmg_run_bg();
|
if(status.bg_enable) dmg_run_bg();
|
||||||
if(status.window_display_enable) dmg_run_window();
|
if(status.window_display_enable) dmg_run_window();
|
||||||
if(status.ob_enable) dmg_run_ob();
|
if(status.ob_enable) dmg_run_ob();
|
||||||
|
|
|
@ -8,6 +8,8 @@ PPU ppu;
|
||||||
#include "cgb.cpp"
|
#include "cgb.cpp"
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
|
|
||||||
|
auto PPU::enabled() const -> bool { return status.display_enable; }
|
||||||
|
|
||||||
auto PPU::Enter() -> void {
|
auto PPU::Enter() -> void {
|
||||||
while(true) scheduler.synchronize(), ppu.main();
|
while(true) scheduler.synchronize(), ppu.main();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +18,7 @@ auto PPU::main() -> void {
|
||||||
status.lx = 0;
|
status.lx = 0;
|
||||||
interface->lcdScanline(); //Super Game Boy notification
|
interface->lcdScanline(); //Super Game Boy notification
|
||||||
|
|
||||||
if(status.display_enable && status.ly <= 143) {
|
if(status.ly <= 143) {
|
||||||
mode(2);
|
mode(2);
|
||||||
scanline();
|
scanline();
|
||||||
wait(92);
|
wait(92);
|
||||||
|
@ -28,7 +30,7 @@ auto PPU::main() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
mode(0);
|
mode(0);
|
||||||
cpu.hblank();
|
if(enabled()) cpu.hblank();
|
||||||
wait(204);
|
wait(204);
|
||||||
} else {
|
} else {
|
||||||
mode(1);
|
mode(1);
|
||||||
|
@ -38,7 +40,7 @@ auto PPU::main() -> void {
|
||||||
status.ly++;
|
status.ly++;
|
||||||
|
|
||||||
if(status.ly == 144) {
|
if(status.ly == 144) {
|
||||||
cpu.interrupt_raise(CPU::Interrupt::Vblank);
|
if(enabled()) cpu.raise(CPU::Interrupt::Vblank);
|
||||||
scheduler.exit(Scheduler::Event::Frame);
|
scheduler.exit(Scheduler::Event::Frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,35 +50,25 @@ auto PPU::main() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::mode(uint mode) -> void {
|
auto PPU::mode(uint mode) -> void {
|
||||||
|
if(!enabled()) mode = 1; //force blank
|
||||||
status.mode = mode;
|
status.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PPU::stat() -> void {
|
||||||
bool irq = status.irq;
|
bool irq = status.irq;
|
||||||
|
|
||||||
if(status.mode == 0) { //hblank
|
status.irq = status.interrupt_hblank && status.mode == 0;
|
||||||
status.irq = status.interrupt_hblank;
|
status.irq |= status.interrupt_vblank && status.mode == 1;
|
||||||
}
|
status.irq |= status.interrupt_oam && status.mode == 2;
|
||||||
|
status.irq |= status.interrupt_lyc && coincidence();
|
||||||
|
|
||||||
if(status.mode == 1) { //vblank
|
if(!irq && status.irq) cpu.raise(CPU::Interrupt::Stat);
|
||||||
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 {
|
auto PPU::coincidence() -> bool {
|
||||||
//LYC of zero triggers on LYC=153
|
uint ly = status.ly;
|
||||||
return (status.lyc && status.ly == status.lyc) || (!status.lyc && status.ly == 153);
|
if(ly == 153 && status.lx >= 92) ly = 0; //LYC=0 triggers early during LY=153
|
||||||
|
return ly == status.lyc;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::refresh() -> void {
|
auto PPU::refresh() -> void {
|
||||||
|
@ -85,6 +77,7 @@ auto PPU::refresh() -> void {
|
||||||
|
|
||||||
auto PPU::wait(uint clocks) -> void {
|
auto PPU::wait(uint clocks) -> void {
|
||||||
while(clocks--) {
|
while(clocks--) {
|
||||||
|
stat();
|
||||||
if(status.dma_active) {
|
if(status.dma_active) {
|
||||||
uint hi = status.dma_clock++;
|
uint hi = status.dma_clock++;
|
||||||
uint lo = hi & (cpu.status.speed_double ? 1 : 3);
|
uint lo = hi & (cpu.status.speed_double ? 1 : 3);
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
struct PPU : Thread, MMIO {
|
struct PPU : Thread, MMIO {
|
||||||
|
auto enabled() const -> bool;
|
||||||
|
|
||||||
static auto Enter() -> void;
|
static auto Enter() -> void;
|
||||||
auto main() -> void;
|
auto main() -> void;
|
||||||
auto mode(uint) -> void;
|
auto mode(uint) -> void;
|
||||||
|
auto stat() -> void;
|
||||||
auto coincidence() -> bool;
|
auto coincidence() -> bool;
|
||||||
auto refresh() -> void;
|
auto refresh() -> void;
|
||||||
auto wait(uint clocks) -> void;
|
auto wait(uint clocks) -> void;
|
||||||
|
|
|
@ -1,21 +1,14 @@
|
||||||
auto GSU::disassemble_opcode(char* output) -> void {
|
auto GSU::disassembleOpcode(char* output) -> void {
|
||||||
*output = 0;
|
*output = 0;
|
||||||
|
|
||||||
if(!regs.sfr.alt2) {
|
switch(regs.sfr.alt2 << 1 | regs.sfr.alt1 << 0) {
|
||||||
if(!regs.sfr.alt1) {
|
case 0: disassembleAlt0(output); break;
|
||||||
disassemble_alt0(output);
|
case 1: disassembleAlt1(output); break;
|
||||||
} else {
|
case 2: disassembleAlt2(output); break;
|
||||||
disassemble_alt1(output);
|
case 3: disassembleAlt3(output); break;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(!regs.sfr.alt1) {
|
|
||||||
disassemble_alt2(output);
|
|
||||||
} else {
|
|
||||||
disassemble_alt3(output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned length = strlen(output);
|
uint length = strlen(output);
|
||||||
while(length++ < 20) strcat(output, " ");
|
while(length++ < 20) strcat(output, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +27,10 @@ auto GSU::disassemble_opcode(char* output) -> void {
|
||||||
case id+ 8: case id+ 9: case id+10: case id+11: case id+12: case id+13: case id+14: case id+15
|
case id+ 8: case id+ 9: case id+10: case id+11: case id+12: case id+13: case id+14: case id+15
|
||||||
|
|
||||||
#define op0 regs.pipeline
|
#define op0 regs.pipeline
|
||||||
#define op1 bus_read((regs.pbr << 16) + regs.r[15] + 0)
|
#define op1 read((regs.pbr << 16) + regs.r[15] + 0)
|
||||||
#define op2 bus_read((regs.pbr << 16) + regs.r[15] + 1)
|
#define op2 read((regs.pbr << 16) + regs.r[15] + 1)
|
||||||
|
|
||||||
auto GSU::disassemble_alt0(char* output) -> void {
|
auto GSU::disassembleAlt0(char* output) -> void {
|
||||||
char t[256] = "";
|
char t[256] = "";
|
||||||
switch(op0) {
|
switch(op0) {
|
||||||
case (0x00): sprintf(t, "stop"); break;
|
case (0x00): sprintf(t, "stop"); break;
|
||||||
|
@ -94,7 +87,7 @@ auto GSU::disassemble_alt0(char* output) -> void {
|
||||||
strcat(output, t);
|
strcat(output, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GSU::disassemble_alt1(char* output) -> void {
|
auto GSU::disassembleAlt1(char* output) -> void {
|
||||||
char t[256] = "";
|
char t[256] = "";
|
||||||
switch(op0) {
|
switch(op0) {
|
||||||
case (0x00): sprintf(t, "stop"); break;
|
case (0x00): sprintf(t, "stop"); break;
|
||||||
|
@ -151,7 +144,7 @@ auto GSU::disassemble_alt1(char* output) -> void {
|
||||||
strcat(output, t);
|
strcat(output, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GSU::disassemble_alt2(char* output) -> void {
|
auto GSU::disassembleAlt2(char* output) -> void {
|
||||||
char t[256] = "";
|
char t[256] = "";
|
||||||
switch(op0) {
|
switch(op0) {
|
||||||
case (0x00): sprintf(t, "stop"); break;
|
case (0x00): sprintf(t, "stop"); break;
|
||||||
|
@ -208,7 +201,7 @@ auto GSU::disassemble_alt2(char* output) -> void {
|
||||||
strcat(output, t);
|
strcat(output, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GSU::disassemble_alt3(char* output) -> void {
|
auto GSU::disassembleAlt3(char* output) -> void {
|
||||||
char t[256] = "";
|
char t[256] = "";
|
||||||
switch(op0) {
|
switch(op0) {
|
||||||
case (0x00): sprintf(t, "stop"); break;
|
case (0x00): sprintf(t, "stop"); break;
|
||||||
|
|
|
@ -16,7 +16,11 @@ auto GSU::power() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GSU::reset() -> void {
|
auto GSU::reset() -> void {
|
||||||
for(auto& r : regs.r) r = 0x0000;
|
for(auto& r : regs.r) {
|
||||||
|
r.data = 0x0000;
|
||||||
|
r.modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
regs.sfr = 0x0000;
|
regs.sfr = 0x0000;
|
||||||
regs.pbr = 0x00;
|
regs.pbr = 0x00;
|
||||||
regs.rombr = 0x00;
|
regs.rombr = 0x00;
|
||||||
|
|
|
@ -13,15 +13,15 @@ struct GSU {
|
||||||
virtual auto rpix(uint8 x, uint8 y) -> uint8 = 0;
|
virtual auto rpix(uint8 x, uint8 y) -> uint8 = 0;
|
||||||
|
|
||||||
virtual auto pipe() -> uint8 = 0;
|
virtual auto pipe() -> uint8 = 0;
|
||||||
virtual auto rombuffer_sync() -> void = 0;
|
virtual auto syncROMBuffer() -> void = 0;
|
||||||
virtual auto rombuffer_read() -> uint8 = 0;
|
virtual auto readROMBuffer() -> uint8 = 0;
|
||||||
virtual auto rambuffer_sync() -> void = 0;
|
virtual auto syncRAMBuffer() -> void = 0;
|
||||||
virtual auto rambuffer_read(uint16 addr) -> uint8 = 0;
|
virtual auto readRAMBuffer(uint16 addr) -> uint8 = 0;
|
||||||
virtual auto rambuffer_write(uint16 addr, uint8 data) -> void = 0;
|
virtual auto writeRAMBuffer(uint16 addr, uint8 data) -> void = 0;
|
||||||
virtual auto cache_flush() -> void = 0;
|
virtual auto flushCache() -> void = 0;
|
||||||
|
|
||||||
virtual auto bus_read(uint24 addr, uint8 data = 0x00) -> uint8 = 0;
|
virtual auto read(uint24 addr, uint8 data = 0x00) -> uint8 = 0;
|
||||||
virtual auto bus_write(uint24 addr, uint8 data) -> void = 0;
|
virtual auto write(uint24 addr, uint8 data) -> void = 0;
|
||||||
|
|
||||||
//gsu.cpp
|
//gsu.cpp
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
|
@ -76,11 +76,11 @@ struct GSU {
|
||||||
auto serialize(serializer&) -> void;
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
//disassembler.cpp
|
//disassembler.cpp
|
||||||
auto disassemble_opcode(char* output) -> void;
|
auto disassembleOpcode(char* output) -> void;
|
||||||
auto disassemble_alt0(char* output) -> void;
|
auto disassembleAlt0(char* output) -> void;
|
||||||
auto disassemble_alt1(char* output) -> void;
|
auto disassembleAlt1(char* output) -> void;
|
||||||
auto disassemble_alt2(char* output) -> void;
|
auto disassembleAlt2(char* output) -> void;
|
||||||
auto disassemble_alt3(char* output) -> void;
|
auto disassembleAlt3(char* output) -> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ auto GSU::op_nop() {
|
||||||
auto GSU::op_cache() {
|
auto GSU::op_cache() {
|
||||||
if(regs.cbr != (regs.r[15] & 0xfff0)) {
|
if(regs.cbr != (regs.r[15] & 0xfff0)) {
|
||||||
regs.cbr = regs.r[15] & 0xfff0;
|
regs.cbr = regs.r[15] & 0xfff0;
|
||||||
cache_flush();
|
flushCache();
|
||||||
}
|
}
|
||||||
regs.reset();
|
regs.reset();
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ auto GSU::op_with(uint n) {
|
||||||
//$30-3b(alt1) stb (rN)
|
//$30-3b(alt1) stb (rN)
|
||||||
auto GSU::op_store(uint n) {
|
auto GSU::op_store(uint n) {
|
||||||
regs.ramaddr = regs.r[n];
|
regs.ramaddr = regs.r[n];
|
||||||
rambuffer_write(regs.ramaddr, regs.sr());
|
writeRAMBuffer(regs.ramaddr, regs.sr());
|
||||||
if(!regs.sfr.alt1) rambuffer_write(regs.ramaddr ^ 1, regs.sr() >> 8);
|
if(!regs.sfr.alt1) writeRAMBuffer(regs.ramaddr ^ 1, regs.sr() >> 8);
|
||||||
regs.reset();
|
regs.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,8 +117,8 @@ auto GSU::op_alt3() {
|
||||||
//$40-4b(alt1) ldb (rN)
|
//$40-4b(alt1) ldb (rN)
|
||||||
auto GSU::op_load(uint n) {
|
auto GSU::op_load(uint n) {
|
||||||
regs.ramaddr = regs.r[n];
|
regs.ramaddr = regs.r[n];
|
||||||
regs.dr() = rambuffer_read(regs.ramaddr);
|
regs.dr() = readRAMBuffer(regs.ramaddr);
|
||||||
if(!regs.sfr.alt1) regs.dr() |= rambuffer_read(regs.ramaddr ^ 1) << 8;
|
if(!regs.sfr.alt1) regs.dr() |= readRAMBuffer(regs.ramaddr ^ 1) << 8;
|
||||||
regs.reset();
|
regs.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,8 +230,8 @@ auto GSU::op_mult_umult(uint n) {
|
||||||
|
|
||||||
//$90 sbk
|
//$90 sbk
|
||||||
auto GSU::op_sbk() {
|
auto GSU::op_sbk() {
|
||||||
rambuffer_write(regs.ramaddr ^ 0, regs.sr() >> 0);
|
writeRAMBuffer(regs.ramaddr ^ 0, regs.sr() >> 0);
|
||||||
rambuffer_write(regs.ramaddr ^ 1, regs.sr() >> 8);
|
writeRAMBuffer(regs.ramaddr ^ 1, regs.sr() >> 8);
|
||||||
regs.reset();
|
regs.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ auto GSU::op_jmp_ljmp(uint n) {
|
||||||
regs.pbr = regs.r[n] & 0x7f;
|
regs.pbr = regs.r[n] & 0x7f;
|
||||||
regs.r[15] = regs.sr();
|
regs.r[15] = regs.sr();
|
||||||
regs.cbr = regs.r[15] & 0xfff0;
|
regs.cbr = regs.r[15] & 0xfff0;
|
||||||
cache_flush();
|
flushCache();
|
||||||
}
|
}
|
||||||
regs.reset();
|
regs.reset();
|
||||||
}
|
}
|
||||||
|
@ -310,12 +310,12 @@ auto GSU::op_fmult_lmult() {
|
||||||
auto GSU::op_ibt_lms_sms(uint n) {
|
auto GSU::op_ibt_lms_sms(uint n) {
|
||||||
if(regs.sfr.alt1) {
|
if(regs.sfr.alt1) {
|
||||||
regs.ramaddr = pipe() << 1;
|
regs.ramaddr = pipe() << 1;
|
||||||
uint8 lo = rambuffer_read(regs.ramaddr ^ 0) << 0;
|
uint8 lo = readRAMBuffer(regs.ramaddr ^ 0) << 0;
|
||||||
regs.r[n] = rambuffer_read(regs.ramaddr ^ 1) << 8 | lo;
|
regs.r[n] = readRAMBuffer(regs.ramaddr ^ 1) << 8 | lo;
|
||||||
} else if(regs.sfr.alt2) {
|
} else if(regs.sfr.alt2) {
|
||||||
regs.ramaddr = pipe() << 1;
|
regs.ramaddr = pipe() << 1;
|
||||||
rambuffer_write(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
writeRAMBuffer(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
||||||
rambuffer_write(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
writeRAMBuffer(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
||||||
} else {
|
} else {
|
||||||
regs.r[n] = (int8)pipe();
|
regs.r[n] = (int8)pipe();
|
||||||
}
|
}
|
||||||
|
@ -369,12 +369,12 @@ auto GSU::op_inc(uint n) {
|
||||||
//$df(alt3) romb
|
//$df(alt3) romb
|
||||||
auto GSU::op_getc_ramb_romb() {
|
auto GSU::op_getc_ramb_romb() {
|
||||||
if(!regs.sfr.alt2) {
|
if(!regs.sfr.alt2) {
|
||||||
regs.colr = color(rombuffer_read());
|
regs.colr = color(readROMBuffer());
|
||||||
} else if(!regs.sfr.alt1) {
|
} else if(!regs.sfr.alt1) {
|
||||||
rambuffer_sync();
|
syncRAMBuffer();
|
||||||
regs.rambr = regs.sr() & 0x01;
|
regs.rambr = regs.sr() & 0x01;
|
||||||
} else {
|
} else {
|
||||||
rombuffer_sync();
|
syncROMBuffer();
|
||||||
regs.rombr = regs.sr() & 0x7f;
|
regs.rombr = regs.sr() & 0x7f;
|
||||||
}
|
}
|
||||||
regs.reset();
|
regs.reset();
|
||||||
|
@ -394,10 +394,10 @@ auto GSU::op_dec(uint n) {
|
||||||
//$ef(alt3) getbs
|
//$ef(alt3) getbs
|
||||||
auto GSU::op_getb() {
|
auto GSU::op_getb() {
|
||||||
switch(regs.sfr.alt2 << 1 | regs.sfr.alt1 << 0) {
|
switch(regs.sfr.alt2 << 1 | regs.sfr.alt1 << 0) {
|
||||||
case 0: regs.dr() = rombuffer_read(); break;
|
case 0: regs.dr() = readROMBuffer(); break;
|
||||||
case 1: regs.dr() = rombuffer_read() << 8 | (uint8)regs.sr(); break;
|
case 1: regs.dr() = readROMBuffer() << 8 | (uint8)regs.sr(); break;
|
||||||
case 2: regs.dr() = (regs.sr() & 0xff00) | rombuffer_read(); break;
|
case 2: regs.dr() = (regs.sr() & 0xff00) | readROMBuffer(); break;
|
||||||
case 3: regs.dr() = (int8)rombuffer_read(); break;
|
case 3: regs.dr() = (int8)readROMBuffer(); break;
|
||||||
}
|
}
|
||||||
regs.reset();
|
regs.reset();
|
||||||
}
|
}
|
||||||
|
@ -409,13 +409,13 @@ auto GSU::op_iwt_lm_sm(uint n) {
|
||||||
if(regs.sfr.alt1) {
|
if(regs.sfr.alt1) {
|
||||||
regs.ramaddr = pipe() << 0;
|
regs.ramaddr = pipe() << 0;
|
||||||
regs.ramaddr |= pipe() << 8;
|
regs.ramaddr |= pipe() << 8;
|
||||||
uint8 lo = rambuffer_read(regs.ramaddr ^ 0) << 0;
|
uint8 lo = readRAMBuffer(regs.ramaddr ^ 0) << 0;
|
||||||
regs.r[n] = rambuffer_read(regs.ramaddr ^ 1) << 8 | lo;
|
regs.r[n] = readRAMBuffer(regs.ramaddr ^ 1) << 8 | lo;
|
||||||
} else if(regs.sfr.alt2) {
|
} else if(regs.sfr.alt2) {
|
||||||
regs.ramaddr = pipe() << 0;
|
regs.ramaddr = pipe() << 0;
|
||||||
regs.ramaddr |= pipe() << 8;
|
regs.ramaddr |= pipe() << 8;
|
||||||
rambuffer_write(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
writeRAMBuffer(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
||||||
rambuffer_write(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
writeRAMBuffer(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
||||||
} else {
|
} else {
|
||||||
uint8 lo = pipe();
|
uint8 lo = pipe();
|
||||||
regs.r[n] = pipe() << 8 | lo;
|
regs.r[n] = pipe() << 8 | lo;
|
||||||
|
|
|
@ -1,41 +1,39 @@
|
||||||
//accepts a callback binding so r14 writes can trigger ROM buffering transparently
|
struct Register {
|
||||||
struct reg16_t {
|
|
||||||
uint16 data = 0;
|
uint16 data = 0;
|
||||||
function<auto (uint16) -> void> modify;
|
bool modified = false;
|
||||||
|
|
||||||
inline operator unsigned() const {
|
inline operator uint() const {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto assign(uint16 i) -> uint16 {
|
inline auto assign(uint value) -> uint16 {
|
||||||
if(modify) modify(i);
|
modified = true;
|
||||||
else data = i;
|
return data = value;
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto operator++() { return assign(data + 1); }
|
inline auto operator++() { return assign(data + 1); }
|
||||||
inline auto operator--() { return assign(data - 1); }
|
inline auto operator--() { return assign(data - 1); }
|
||||||
inline auto operator++(int) { unsigned r = data; assign(data + 1); return r; }
|
inline auto operator++(int) { uint r = data; assign(data + 1); return r; }
|
||||||
inline auto operator--(int) { unsigned r = data; assign(data - 1); return r; }
|
inline auto operator--(int) { uint r = data; assign(data - 1); return r; }
|
||||||
inline auto operator = (unsigned i) { return assign(i); }
|
inline auto operator = (uint i) { return assign(i); }
|
||||||
inline auto operator |= (unsigned i) { return assign(data | i); }
|
inline auto operator |= (uint i) { return assign(data | i); }
|
||||||
inline auto operator ^= (unsigned i) { return assign(data ^ i); }
|
inline auto operator ^= (uint i) { return assign(data ^ i); }
|
||||||
inline auto operator &= (unsigned i) { return assign(data & i); }
|
inline auto operator &= (uint i) { return assign(data & i); }
|
||||||
inline auto operator <<= (unsigned i) { return assign(data << i); }
|
inline auto operator <<= (uint i) { return assign(data << i); }
|
||||||
inline auto operator >>= (unsigned i) { return assign(data >> i); }
|
inline auto operator >>= (uint i) { return assign(data >> i); }
|
||||||
inline auto operator += (unsigned i) { return assign(data + i); }
|
inline auto operator += (uint i) { return assign(data + i); }
|
||||||
inline auto operator -= (unsigned i) { return assign(data - i); }
|
inline auto operator -= (uint i) { return assign(data - i); }
|
||||||
inline auto operator *= (unsigned i) { return assign(data * i); }
|
inline auto operator *= (uint i) { return assign(data * i); }
|
||||||
inline auto operator /= (unsigned i) { return assign(data / i); }
|
inline auto operator /= (uint i) { return assign(data / i); }
|
||||||
inline auto operator %= (unsigned i) { return assign(data % i); }
|
inline auto operator %= (uint i) { return assign(data % i); }
|
||||||
|
|
||||||
inline auto operator = (const reg16_t& i) { return assign(i); }
|
inline auto operator = (const Register& value) { return assign(value); }
|
||||||
|
|
||||||
reg16_t() = default;
|
Register() = default;
|
||||||
reg16_t(const reg16_t&) = delete;
|
Register(const Register&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sfr_t {
|
struct SFR {
|
||||||
bool irq; //interrupt flag
|
bool irq; //interrupt flag
|
||||||
bool b; //WITH flag
|
bool b; //WITH flag
|
||||||
bool ih; //immediate higher 8-bit flag
|
bool ih; //immediate higher 8-bit flag
|
||||||
|
@ -49,12 +47,12 @@ struct sfr_t {
|
||||||
bool cy; //carry flag
|
bool cy; //carry flag
|
||||||
bool z; //zero flag
|
bool z; //zero flag
|
||||||
|
|
||||||
operator unsigned() const {
|
operator uint() const {
|
||||||
return (irq << 15) | (b << 12) | (ih << 11) | (il << 10) | (alt2 << 9) | (alt1 << 8)
|
return (irq << 15) | (b << 12) | (ih << 11) | (il << 10) | (alt2 << 9) | (alt1 << 8)
|
||||||
| (r << 6) | (g << 5) | (ov << 4) | (s << 3) | (cy << 2) | (z << 1);
|
| (r << 6) | (g << 5) | (ov << 4) | (s << 3) | (cy << 2) | (z << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& operator=(uint16_t data) {
|
auto& operator=(uint data) {
|
||||||
irq = data & 0x8000;
|
irq = data & 0x8000;
|
||||||
b = data & 0x1000;
|
b = data & 0x1000;
|
||||||
ih = data & 0x0800;
|
ih = data & 0x0800;
|
||||||
|
@ -71,17 +69,17 @@ struct sfr_t {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scmr_t {
|
struct SCMR {
|
||||||
unsigned ht;
|
uint ht;
|
||||||
bool ron;
|
bool ron;
|
||||||
bool ran;
|
bool ran;
|
||||||
unsigned md;
|
uint md;
|
||||||
|
|
||||||
operator unsigned() const {
|
operator uint() const {
|
||||||
return ((ht >> 1) << 5) | (ron << 4) | (ran << 3) | ((ht & 1) << 2) | (md);
|
return ((ht >> 1) << 5) | (ron << 4) | (ran << 3) | ((ht & 1) << 2) | (md);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& operator=(uint8 data) {
|
auto& operator=(uint data) {
|
||||||
ht = (bool)(data & 0x20) << 1;
|
ht = (bool)(data & 0x20) << 1;
|
||||||
ht |= (bool)(data & 0x04) << 0;
|
ht |= (bool)(data & 0x04) << 0;
|
||||||
ron = data & 0x10;
|
ron = data & 0x10;
|
||||||
|
@ -91,18 +89,18 @@ struct scmr_t {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct por_t {
|
struct POR {
|
||||||
bool obj;
|
bool obj;
|
||||||
bool freezehigh;
|
bool freezehigh;
|
||||||
bool highnibble;
|
bool highnibble;
|
||||||
bool dither;
|
bool dither;
|
||||||
bool transparent;
|
bool transparent;
|
||||||
|
|
||||||
operator unsigned() const {
|
operator uint() const {
|
||||||
return (obj << 4) | (freezehigh << 3) | (highnibble << 2) | (dither << 1) | (transparent);
|
return (obj << 4) | (freezehigh << 3) | (highnibble << 2) | (dither << 1) | (transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& operator=(uint8 data) {
|
auto& operator=(uint data) {
|
||||||
obj = data & 0x10;
|
obj = data & 0x10;
|
||||||
freezehigh = data & 0x08;
|
freezehigh = data & 0x08;
|
||||||
highnibble = data & 0x04;
|
highnibble = data & 0x04;
|
||||||
|
@ -112,48 +110,49 @@ struct por_t {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cfgr_t {
|
struct CFGR {
|
||||||
bool irq;
|
bool irq;
|
||||||
bool ms0;
|
bool ms0;
|
||||||
|
|
||||||
operator unsigned() const {
|
operator uint() const {
|
||||||
return (irq << 7) | (ms0 << 5);
|
return (irq << 7) | (ms0 << 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& operator=(uint8 data) {
|
auto& operator=(uint data) {
|
||||||
irq = data & 0x80;
|
irq = data & 0x80;
|
||||||
ms0 = data & 0x20;
|
ms0 = data & 0x20;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct regs_t {
|
struct Registers {
|
||||||
uint8 pipeline;
|
uint8 pipeline;
|
||||||
uint16 ramaddr;
|
uint16 ramaddr;
|
||||||
|
|
||||||
reg16_t r[16]; //general purpose registers
|
Register r[16]; //general purpose registers
|
||||||
sfr_t sfr; //status flag register
|
SFR sfr; //status flag register
|
||||||
uint8 pbr; //program bank register
|
uint8 pbr; //program bank register
|
||||||
uint8 rombr; //game pack ROM bank register
|
uint8 rombr; //game pack ROM bank register
|
||||||
bool rambr; //game pack RAM bank register
|
bool rambr; //game pack RAM bank register
|
||||||
uint16 cbr; //cache base register
|
uint16 cbr; //cache base register
|
||||||
uint8 scbr; //screen base register
|
uint8 scbr; //screen base register
|
||||||
scmr_t scmr; //screen mode register
|
SCMR scmr; //screen mode register
|
||||||
uint8 colr; //color register
|
uint8 colr; //color register
|
||||||
por_t por; //plot option register
|
POR por; //plot option register
|
||||||
bool bramr; //back-up RAM register
|
bool bramr; //back-up RAM register
|
||||||
uint8 vcr; //version code register
|
uint8 vcr; //version code register
|
||||||
cfgr_t cfgr; //config register
|
CFGR cfgr; //config register
|
||||||
bool clsr; //clock select register
|
bool clsr; //clock select register
|
||||||
|
|
||||||
unsigned romcl; //clock ticks until romdr is valid
|
uint romcl; //clock ticks until romdr is valid
|
||||||
uint8 romdr; //ROM buffer data register
|
uint8 romdr; //ROM buffer data register
|
||||||
|
|
||||||
unsigned ramcl; //clock ticks until ramdr is valid
|
uint ramcl; //clock ticks until ramdr is valid
|
||||||
uint16 ramar; //RAM buffer address register
|
uint16 ramar; //RAM buffer address register
|
||||||
uint8 ramdr; //RAM buffer data register
|
uint8 ramdr; //RAM buffer data register
|
||||||
|
|
||||||
unsigned sreg, dreg;
|
uint sreg;
|
||||||
|
uint dreg;
|
||||||
auto& sr() { return r[sreg]; } //source register (from)
|
auto& sr() { return r[sreg]; } //source register (from)
|
||||||
auto& dr() { return r[dreg]; } //destination register (to)
|
auto& dr() { return r[dreg]; } //destination register (to)
|
||||||
|
|
||||||
|
@ -167,12 +166,12 @@ struct regs_t {
|
||||||
}
|
}
|
||||||
} regs;
|
} regs;
|
||||||
|
|
||||||
struct cache_t {
|
struct Cache {
|
||||||
uint8 buffer[512];
|
uint8 buffer[512];
|
||||||
bool valid[32];
|
bool valid[32];
|
||||||
} cache;
|
} cache;
|
||||||
|
|
||||||
struct pixelcache_t {
|
struct PixelCache {
|
||||||
uint16 offset;
|
uint16 offset;
|
||||||
uint8 bitpend;
|
uint8 bitpend;
|
||||||
uint8 data[8];
|
uint8 data[8];
|
||||||
|
|
|
@ -2,22 +2,10 @@ auto GSU::serialize(serializer& s) -> void {
|
||||||
s.integer(regs.pipeline);
|
s.integer(regs.pipeline);
|
||||||
s.integer(regs.ramaddr);
|
s.integer(regs.ramaddr);
|
||||||
|
|
||||||
s.integer(regs.r[ 0].data);
|
for(auto n : range(16)) {
|
||||||
s.integer(regs.r[ 1].data);
|
s.integer(regs.r[n].data);
|
||||||
s.integer(regs.r[ 2].data);
|
s.integer(regs.r[n].modified);
|
||||||
s.integer(regs.r[ 3].data);
|
}
|
||||||
s.integer(regs.r[ 4].data);
|
|
||||||
s.integer(regs.r[ 5].data);
|
|
||||||
s.integer(regs.r[ 6].data);
|
|
||||||
s.integer(regs.r[ 7].data);
|
|
||||||
s.integer(regs.r[ 8].data);
|
|
||||||
s.integer(regs.r[ 9].data);
|
|
||||||
s.integer(regs.r[10].data);
|
|
||||||
s.integer(regs.r[11].data);
|
|
||||||
s.integer(regs.r[12].data);
|
|
||||||
s.integer(regs.r[13].data);
|
|
||||||
s.integer(regs.r[14].data);
|
|
||||||
s.integer(regs.r[15].data);
|
|
||||||
|
|
||||||
s.integer(regs.sfr.irq);
|
s.integer(regs.sfr.irq);
|
||||||
s.integer(regs.sfr.b);
|
s.integer(regs.sfr.b);
|
||||||
|
@ -72,9 +60,9 @@ auto GSU::serialize(serializer& s) -> void {
|
||||||
s.array(cache.buffer);
|
s.array(cache.buffer);
|
||||||
s.array(cache.valid);
|
s.array(cache.valid);
|
||||||
|
|
||||||
for(unsigned i = 0; i < 2; i++) {
|
for(uint n : range(2)) {
|
||||||
s.integer(pixelcache[i].offset);
|
s.integer(pixelcache[n].offset);
|
||||||
s.integer(pixelcache[i].bitpend);
|
s.integer(pixelcache[n].bitpend);
|
||||||
s.array(pixelcache[i].data);
|
s.array(pixelcache[n].data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,10 @@ auto LR35902::disassemble(uint16 pc) -> string {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::disassembleOpcode(uint16 pc) -> string {
|
auto LR35902::disassembleOpcode(uint16 pc) -> string {
|
||||||
uint8 opcode = debugger_read(pc);
|
uint8 opcode = debuggerRead(pc);
|
||||||
uint8 p0 = debugger_read(pc + 1);
|
uint8 p0 = debuggerRead(pc + 1);
|
||||||
uint8 p1 = debugger_read(pc + 2);
|
uint8 p1 = debuggerRead(pc + 2);
|
||||||
uint8 p2 = debugger_read(pc + 3);
|
uint8 p2 = debuggerRead(pc + 3);
|
||||||
|
|
||||||
switch(opcode) {
|
switch(opcode) {
|
||||||
case 0x00: return { "nop" };
|
case 0x00: return { "nop" };
|
||||||
|
@ -288,10 +288,10 @@ auto LR35902::disassembleOpcode(uint16 pc) -> string {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::disassembleOpcodeCB(uint16 pc) -> string {
|
auto LR35902::disassembleOpcodeCB(uint16 pc) -> string {
|
||||||
uint8 opcode = debugger_read(pc);
|
uint8 opcode = debuggerRead(pc);
|
||||||
uint8 p0 = debugger_read(pc + 1);
|
uint8 p0 = debuggerRead(pc + 1);
|
||||||
uint8 p1 = debugger_read(pc + 2);
|
uint8 p1 = debuggerRead(pc + 2);
|
||||||
uint8 p2 = debugger_read(pc + 3);
|
uint8 p2 = debuggerRead(pc + 3);
|
||||||
|
|
||||||
switch(opcode) {
|
switch(opcode) {
|
||||||
case 0x00: return { "rlc b" };
|
case 0x00: return { "rlc b" };
|
||||||
|
|
|
@ -2,7 +2,7 @@ auto LR35902::op_xx() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_cb() {
|
auto LR35902::op_cb() {
|
||||||
execCB();
|
instructionCB();
|
||||||
}
|
}
|
||||||
|
|
||||||
//8-bit load commands
|
//8-bit load commands
|
||||||
|
@ -12,105 +12,105 @@ auto LR35902::op_ld_r_r(uint x, uint y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_r_n(uint x) {
|
auto LR35902::op_ld_r_n(uint x) {
|
||||||
r[x] = op_read(r[PC]++);
|
r[x] = read(r[PC]++);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_r_hl(uint x) {
|
auto LR35902::op_ld_r_hl(uint x) {
|
||||||
r[x] = op_read(r[HL]);
|
r[x] = read(r[HL]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_hl_r(uint x) {
|
auto LR35902::op_ld_hl_r(uint x) {
|
||||||
op_write(r[HL], r[x]);
|
write(r[HL], r[x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_hl_n() {
|
auto LR35902::op_ld_hl_n() {
|
||||||
op_write(r[HL], op_read(r[PC]++));
|
write(r[HL], read(r[PC]++));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_a_rr(uint x) {
|
auto LR35902::op_ld_a_rr(uint x) {
|
||||||
r[A] = op_read(r[x]);
|
r[A] = read(r[x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_a_nn() {
|
auto LR35902::op_ld_a_nn() {
|
||||||
uint8 lo = op_read(r[PC]++);
|
uint8 lo = read(r[PC]++);
|
||||||
uint8 hi = op_read(r[PC]++);
|
uint8 hi = read(r[PC]++);
|
||||||
r[A] = op_read((hi << 8) | (lo << 0));
|
r[A] = read((hi << 8) | (lo << 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_rr_a(uint x) {
|
auto LR35902::op_ld_rr_a(uint x) {
|
||||||
op_write(r[x], r[A]);
|
write(r[x], r[A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_nn_a() {
|
auto LR35902::op_ld_nn_a() {
|
||||||
uint8 lo = op_read(r[PC]++);
|
uint8 lo = read(r[PC]++);
|
||||||
uint8 hi = op_read(r[PC]++);
|
uint8 hi = read(r[PC]++);
|
||||||
op_write((hi << 8) | (lo << 0), r[A]);
|
write((hi << 8) | (lo << 0), r[A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_a_ffn() {
|
auto LR35902::op_ld_a_ffn() {
|
||||||
r[A] = op_read(0xff00 + op_read(r[PC]++));
|
r[A] = read(0xff00 + read(r[PC]++));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_ffn_a() {
|
auto LR35902::op_ld_ffn_a() {
|
||||||
op_write(0xff00 + op_read(r[PC]++), r[A]);
|
write(0xff00 + read(r[PC]++), r[A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_a_ffc() {
|
auto LR35902::op_ld_a_ffc() {
|
||||||
r[A] = op_read(0xff00 + r[C]);
|
r[A] = read(0xff00 + r[C]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_ffc_a() {
|
auto LR35902::op_ld_ffc_a() {
|
||||||
op_write(0xff00 + r[C], r[A]);
|
write(0xff00 + r[C], r[A]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ldi_hl_a() {
|
auto LR35902::op_ldi_hl_a() {
|
||||||
op_write(r[HL], r[A]);
|
write(r[HL], r[A]);
|
||||||
r[HL]++;
|
r[HL]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ldi_a_hl() {
|
auto LR35902::op_ldi_a_hl() {
|
||||||
r[A] = op_read(r[HL]);
|
r[A] = read(r[HL]);
|
||||||
r[HL]++;
|
r[HL]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ldd_hl_a() {
|
auto LR35902::op_ldd_hl_a() {
|
||||||
op_write(r[HL], r[A]);
|
write(r[HL], r[A]);
|
||||||
r[HL]--;
|
r[HL]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ldd_a_hl() {
|
auto LR35902::op_ldd_a_hl() {
|
||||||
r[A] = op_read(r[HL]);
|
r[A] = read(r[HL]);
|
||||||
r[HL]--;
|
r[HL]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
//16-bit load commands
|
//16-bit load commands
|
||||||
|
|
||||||
auto LR35902::op_ld_rr_nn(uint x) {
|
auto LR35902::op_ld_rr_nn(uint x) {
|
||||||
r[x] = op_read(r[PC]++) << 0;
|
r[x] = read(r[PC]++) << 0;
|
||||||
r[x] |= op_read(r[PC]++) << 8;
|
r[x] |= read(r[PC]++) << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_nn_sp() {
|
auto LR35902::op_ld_nn_sp() {
|
||||||
uint16 addr = op_read(r[PC]++) << 0;
|
uint16 addr = read(r[PC]++) << 0;
|
||||||
addr |= op_read(r[PC]++) << 8;
|
addr |= read(r[PC]++) << 8;
|
||||||
op_write(addr + 0, r[SP] >> 0);
|
write(addr + 0, r[SP] >> 0);
|
||||||
op_write(addr + 1, r[SP] >> 8);
|
write(addr + 1, r[SP] >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_sp_hl() {
|
auto LR35902::op_ld_sp_hl() {
|
||||||
r[SP] = r[HL];
|
r[SP] = r[HL];
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_push_rr(uint x) {
|
auto LR35902::op_push_rr(uint x) {
|
||||||
op_io();
|
io();
|
||||||
op_write(--r[SP], r[x] >> 8);
|
write(--r[SP], r[x] >> 8);
|
||||||
op_write(--r[SP], r[x] >> 0);
|
write(--r[SP], r[x] >> 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_pop_rr(uint x) {
|
auto LR35902::op_pop_rr(uint x) {
|
||||||
r[x] = op_read(r[SP]++) << 0;
|
r[x] = read(r[SP]++) << 0;
|
||||||
r[x] |= op_read(r[SP]++) << 8;
|
r[x] |= read(r[SP]++) << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
//8-bit arithmetic commands
|
//8-bit arithmetic commands
|
||||||
|
@ -126,8 +126,8 @@ auto LR35902::opi_add_a(uint8 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_add_a_r(uint x) { 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_n() { opi_add_a(read(r[PC]++)); }
|
||||||
auto LR35902::op_add_a_hl() { opi_add_a(op_read(r[HL])); }
|
auto LR35902::op_add_a_hl() { opi_add_a(read(r[HL])); }
|
||||||
|
|
||||||
auto LR35902::opi_adc_a(uint8 x) {
|
auto LR35902::opi_adc_a(uint8 x) {
|
||||||
uint16 rh = r[A] + x + r.f.c;
|
uint16 rh = r[A] + x + r.f.c;
|
||||||
|
@ -140,8 +140,8 @@ auto LR35902::opi_adc_a(uint8 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_adc_a_r(uint x) { 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_n() { opi_adc_a(read(r[PC]++)); }
|
||||||
auto LR35902::op_adc_a_hl() { opi_adc_a(op_read(r[HL])); }
|
auto LR35902::op_adc_a_hl() { opi_adc_a(read(r[HL])); }
|
||||||
|
|
||||||
auto LR35902::opi_sub_a(uint8 x) {
|
auto LR35902::opi_sub_a(uint8 x) {
|
||||||
uint16 rh = r[A] - x;
|
uint16 rh = r[A] - x;
|
||||||
|
@ -154,8 +154,8 @@ auto LR35902::opi_sub_a(uint8 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_sub_a_r(uint x) { 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_n() { opi_sub_a(read(r[PC]++)); }
|
||||||
auto LR35902::op_sub_a_hl() { opi_sub_a(op_read(r[HL])); }
|
auto LR35902::op_sub_a_hl() { opi_sub_a(read(r[HL])); }
|
||||||
|
|
||||||
auto LR35902::opi_sbc_a(uint8 x) {
|
auto LR35902::opi_sbc_a(uint8 x) {
|
||||||
uint16 rh = r[A] - x - r.f.c;
|
uint16 rh = r[A] - x - r.f.c;
|
||||||
|
@ -168,8 +168,8 @@ auto LR35902::opi_sbc_a(uint8 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_sbc_a_r(uint x) { 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_n() { opi_sbc_a(read(r[PC]++)); }
|
||||||
auto LR35902::op_sbc_a_hl() { opi_sbc_a(op_read(r[HL])); }
|
auto LR35902::op_sbc_a_hl() { opi_sbc_a(read(r[HL])); }
|
||||||
|
|
||||||
auto LR35902::opi_and_a(uint8 x) {
|
auto LR35902::opi_and_a(uint8 x) {
|
||||||
r[A] &= x;
|
r[A] &= x;
|
||||||
|
@ -180,8 +180,8 @@ auto LR35902::opi_and_a(uint8 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_and_a_r(uint x) { 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_n() { opi_and_a(read(r[PC]++)); }
|
||||||
auto LR35902::op_and_a_hl() { opi_and_a(op_read(r[HL])); }
|
auto LR35902::op_and_a_hl() { opi_and_a(read(r[HL])); }
|
||||||
|
|
||||||
auto LR35902::opi_xor_a(uint8 x) {
|
auto LR35902::opi_xor_a(uint8 x) {
|
||||||
r[A] ^= x;
|
r[A] ^= x;
|
||||||
|
@ -192,8 +192,8 @@ auto LR35902::opi_xor_a(uint8 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_xor_a_r(uint x) { 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_n() { opi_xor_a(read(r[PC]++)); }
|
||||||
auto LR35902::op_xor_a_hl() { opi_xor_a(op_read(r[HL])); }
|
auto LR35902::op_xor_a_hl() { opi_xor_a(read(r[HL])); }
|
||||||
|
|
||||||
auto LR35902::opi_or_a(uint8 x) {
|
auto LR35902::opi_or_a(uint8 x) {
|
||||||
r[A] |= x;
|
r[A] |= x;
|
||||||
|
@ -204,8 +204,8 @@ auto LR35902::opi_or_a(uint8 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_or_a_r(uint x) { 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_n() { opi_or_a(read(r[PC]++)); }
|
||||||
auto LR35902::op_or_a_hl() { opi_or_a(op_read(r[HL])); }
|
auto LR35902::op_or_a_hl() { opi_or_a(read(r[HL])); }
|
||||||
|
|
||||||
auto LR35902::opi_cp_a(uint8 x) {
|
auto LR35902::opi_cp_a(uint8 x) {
|
||||||
uint16 rh = r[A] - x;
|
uint16 rh = r[A] - x;
|
||||||
|
@ -217,8 +217,8 @@ auto LR35902::opi_cp_a(uint8 x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_cp_a_r(uint x) { 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_n() { opi_cp_a(read(r[PC]++)); }
|
||||||
auto LR35902::op_cp_a_hl() { opi_cp_a(op_read(r[HL])); }
|
auto LR35902::op_cp_a_hl() { opi_cp_a(read(r[HL])); }
|
||||||
|
|
||||||
auto LR35902::op_inc_r(uint x) {
|
auto LR35902::op_inc_r(uint x) {
|
||||||
r[x]++;
|
r[x]++;
|
||||||
|
@ -228,8 +228,8 @@ auto LR35902::op_inc_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_inc_hl() {
|
auto LR35902::op_inc_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
op_write(r[HL], ++n);
|
write(r[HL], ++n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = (n & 0x0f) == 0x00;
|
r.f.h = (n & 0x0f) == 0x00;
|
||||||
|
@ -243,8 +243,8 @@ auto LR35902::op_dec_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_dec_hl() {
|
auto LR35902::op_dec_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
op_write(r[HL], --n);
|
write(r[HL], --n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 1;
|
r.f.n = 1;
|
||||||
r.f.h = (n & 0x0f) == 0x0f;
|
r.f.h = (n & 0x0f) == 0x0f;
|
||||||
|
@ -277,7 +277,7 @@ auto LR35902::op_cpl() {
|
||||||
//16-bit arithmetic commands
|
//16-bit arithmetic commands
|
||||||
|
|
||||||
auto LR35902::op_add_hl_rr(uint x) {
|
auto LR35902::op_add_hl_rr(uint x) {
|
||||||
op_io();
|
io();
|
||||||
uint32 rb = (r[HL] + r[x]);
|
uint32 rb = (r[HL] + r[x]);
|
||||||
uint32 rn = (r[HL] & 0xfff) + (r[x] & 0xfff);
|
uint32 rn = (r[HL] & 0xfff) + (r[x] & 0xfff);
|
||||||
r[HL] = rb;
|
r[HL] = rb;
|
||||||
|
@ -287,34 +287,34 @@ auto LR35902::op_add_hl_rr(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_inc_rr(uint x) {
|
auto LR35902::op_inc_rr(uint x) {
|
||||||
op_io();
|
io();
|
||||||
r[x]++;
|
r[x]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_dec_rr(uint x) {
|
auto LR35902::op_dec_rr(uint x) {
|
||||||
op_io();
|
io();
|
||||||
r[x]--;
|
r[x]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_add_sp_n() {
|
auto LR35902::op_add_sp_n() {
|
||||||
int n = (int8)op_read(r[PC]++);
|
int n = (int8)read(r[PC]++);
|
||||||
r.f.z = 0;
|
r.f.z = 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f;
|
r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f;
|
||||||
r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff;
|
r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff;
|
||||||
r[SP] += n;
|
r[SP] += n;
|
||||||
op_io();
|
io();
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ld_hl_sp_n() {
|
auto LR35902::op_ld_hl_sp_n() {
|
||||||
int n = (int8)op_read(r[PC]++);
|
int n = (int8)read(r[PC]++);
|
||||||
r.f.z = 0;
|
r.f.z = 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f;
|
r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f;
|
||||||
r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff;
|
r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff;
|
||||||
r[HL] = r[SP] + n;
|
r[HL] = r[SP] + n;
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
|
|
||||||
//rotate/shift commands
|
//rotate/shift commands
|
||||||
|
@ -362,9 +362,9 @@ auto LR35902::op_rlc_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_rlc_hl() {
|
auto LR35902::op_rlc_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
n = (n << 1) | (n >> 7);
|
n = (n << 1) | (n >> 7);
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 0;
|
r.f.h = 0;
|
||||||
|
@ -381,10 +381,10 @@ auto LR35902::op_rl_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_rl_hl() {
|
auto LR35902::op_rl_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
bool c = n & 0x80;
|
bool c = n & 0x80;
|
||||||
n = (n << 1) | (r.f.c << 0);
|
n = (n << 1) | (r.f.c << 0);
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 0;
|
r.f.h = 0;
|
||||||
|
@ -400,9 +400,9 @@ auto LR35902::op_rrc_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_rrc_hl() {
|
auto LR35902::op_rrc_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
n = (n >> 1) | (n << 7);
|
n = (n >> 1) | (n << 7);
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 0;
|
r.f.h = 0;
|
||||||
|
@ -419,10 +419,10 @@ auto LR35902::op_rr_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_rr_hl() {
|
auto LR35902::op_rr_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
bool c = n & 0x01;
|
bool c = n & 0x01;
|
||||||
n = (n >> 1) | (r.f.c << 7);
|
n = (n >> 1) | (r.f.c << 7);
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 0;
|
r.f.h = 0;
|
||||||
|
@ -439,10 +439,10 @@ auto LR35902::op_sla_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_sla_hl() {
|
auto LR35902::op_sla_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
bool c = n & 0x80;
|
bool c = n & 0x80;
|
||||||
n <<= 1;
|
n <<= 1;
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 0;
|
r.f.h = 0;
|
||||||
|
@ -458,9 +458,9 @@ auto LR35902::op_swap_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_swap_hl() {
|
auto LR35902::op_swap_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
n = (n << 4) | (n >> 4);
|
n = (n << 4) | (n >> 4);
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 0;
|
r.f.h = 0;
|
||||||
|
@ -477,10 +477,10 @@ auto LR35902::op_sra_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_sra_hl() {
|
auto LR35902::op_sra_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
bool c = n & 0x01;
|
bool c = n & 0x01;
|
||||||
n = (int8)n >> 1;
|
n = (int8)n >> 1;
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 0;
|
r.f.h = 0;
|
||||||
|
@ -497,10 +497,10 @@ auto LR35902::op_srl_r(uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_srl_hl() {
|
auto LR35902::op_srl_hl() {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
bool c = n & 0x01;
|
bool c = n & 0x01;
|
||||||
n >>= 1;
|
n >>= 1;
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
r.f.z = n == 0;
|
r.f.z = n == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 0;
|
r.f.h = 0;
|
||||||
|
@ -516,7 +516,7 @@ auto LR35902::op_bit_n_r(uint b, uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_bit_n_hl(uint b) {
|
auto LR35902::op_bit_n_hl(uint b) {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
r.f.z = (n & (1 << b)) == 0;
|
r.f.z = (n & (1 << b)) == 0;
|
||||||
r.f.n = 0;
|
r.f.n = 0;
|
||||||
r.f.h = 1;
|
r.f.h = 1;
|
||||||
|
@ -527,9 +527,9 @@ auto LR35902::op_set_n_r(uint b, uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_set_n_hl(uint b) {
|
auto LR35902::op_set_n_hl(uint b) {
|
||||||
uint8 n = op_read(r[HL]);
|
uint8 n = read(r[HL]);
|
||||||
n |= 1 << b;
|
n |= 1 << b;
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_res_n_r(uint b, uint x) {
|
auto LR35902::op_res_n_r(uint b, uint x) {
|
||||||
|
@ -537,9 +537,9 @@ auto LR35902::op_res_n_r(uint b, uint x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_res_n_hl(uint b) {
|
auto LR35902::op_res_n_hl(uint b) {
|
||||||
uint n = op_read(r[HL]);
|
uint n = read(r[HL]);
|
||||||
n &= ~(1 << b);
|
n &= ~(1 << b);
|
||||||
op_write(r[HL], n);
|
write(r[HL], n);
|
||||||
}
|
}
|
||||||
|
|
||||||
//control commands
|
//control commands
|
||||||
|
@ -561,13 +561,13 @@ auto LR35902::op_nop() {
|
||||||
|
|
||||||
auto LR35902::op_halt() {
|
auto LR35902::op_halt() {
|
||||||
r.halt = true;
|
r.halt = true;
|
||||||
while(r.halt == true) op_io();
|
while(r.halt) io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_stop() {
|
auto LR35902::op_stop() {
|
||||||
if(stop()) return;
|
if(stop()) return;
|
||||||
r.stop = true;
|
r.stop = true;
|
||||||
while(r.stop == true) op_io();
|
while(r.stop) io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_di() {
|
auto LR35902::op_di() {
|
||||||
|
@ -582,10 +582,10 @@ auto LR35902::op_ei() {
|
||||||
//jump commands
|
//jump commands
|
||||||
|
|
||||||
auto LR35902::op_jp_nn() {
|
auto LR35902::op_jp_nn() {
|
||||||
uint8 lo = op_read(r[PC]++);
|
uint8 lo = read(r[PC]++);
|
||||||
uint8 hi = op_read(r[PC]++);
|
uint8 hi = read(r[PC]++);
|
||||||
r[PC] = (hi << 8) | (lo << 0);
|
r[PC] = (hi << 8) | (lo << 0);
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_jp_hl() {
|
auto LR35902::op_jp_hl() {
|
||||||
|
@ -593,76 +593,76 @@ auto LR35902::op_jp_hl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_jp_f_nn(uint x, bool y) {
|
auto LR35902::op_jp_f_nn(uint x, bool y) {
|
||||||
uint8 lo = op_read(r[PC]++);
|
uint8 lo = read(r[PC]++);
|
||||||
uint8 hi = op_read(r[PC]++);
|
uint8 hi = read(r[PC]++);
|
||||||
if(r.f[x] == y) {
|
if(r.f[x] == y) {
|
||||||
r[PC] = (hi << 8) | (lo << 0);
|
r[PC] = (hi << 8) | (lo << 0);
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_jr_n() {
|
auto LR35902::op_jr_n() {
|
||||||
int8 n = op_read(r[PC]++);
|
int8 n = read(r[PC]++);
|
||||||
r[PC] += n;
|
r[PC] += n;
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_jr_f_n(uint x, bool y) {
|
auto LR35902::op_jr_f_n(uint x, bool y) {
|
||||||
int8 n = op_read(r[PC]++);
|
int8 n = read(r[PC]++);
|
||||||
if(r.f[x] == y) {
|
if(r.f[x] == y) {
|
||||||
r[PC] += n;
|
r[PC] += n;
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_call_nn() {
|
auto LR35902::op_call_nn() {
|
||||||
uint8 lo = op_read(r[PC]++);
|
uint8 lo = read(r[PC]++);
|
||||||
uint8 hi = op_read(r[PC]++);
|
uint8 hi = read(r[PC]++);
|
||||||
op_io();
|
io();
|
||||||
op_write(--r[SP], r[PC] >> 8);
|
write(--r[SP], r[PC] >> 8);
|
||||||
op_write(--r[SP], r[PC] >> 0);
|
write(--r[SP], r[PC] >> 0);
|
||||||
r[PC] = (hi << 8) | (lo << 0);
|
r[PC] = (hi << 8) | (lo << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_call_f_nn(uint x, bool y) {
|
auto LR35902::op_call_f_nn(uint x, bool y) {
|
||||||
uint8 lo = op_read(r[PC]++);
|
uint8 lo = read(r[PC]++);
|
||||||
uint8 hi = op_read(r[PC]++);
|
uint8 hi = read(r[PC]++);
|
||||||
if(r.f[x] == y) {
|
if(r.f[x] == y) {
|
||||||
op_io();
|
io();
|
||||||
op_write(--r[SP], r[PC] >> 8);
|
write(--r[SP], r[PC] >> 8);
|
||||||
op_write(--r[SP], r[PC] >> 0);
|
write(--r[SP], r[PC] >> 0);
|
||||||
r[PC] = (hi << 8) | (lo << 0);
|
r[PC] = (hi << 8) | (lo << 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ret() {
|
auto LR35902::op_ret() {
|
||||||
uint8 lo = op_read(r[SP]++);
|
uint8 lo = read(r[SP]++);
|
||||||
uint8 hi = op_read(r[SP]++);
|
uint8 hi = read(r[SP]++);
|
||||||
r[PC] = (hi << 8) | (lo << 0);
|
r[PC] = (hi << 8) | (lo << 0);
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_ret_f(uint x, bool y) {
|
auto LR35902::op_ret_f(uint x, bool y) {
|
||||||
op_io();
|
io();
|
||||||
if(r.f[x] == y) {
|
if(r.f[x] == y) {
|
||||||
uint8 lo = op_read(r[SP]++);
|
uint8 lo = read(r[SP]++);
|
||||||
uint8 hi = op_read(r[SP]++);
|
uint8 hi = read(r[SP]++);
|
||||||
r[PC] = (hi << 8) | (lo << 0);
|
r[PC] = (hi << 8) | (lo << 0);
|
||||||
op_io();
|
io();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_reti() {
|
auto LR35902::op_reti() {
|
||||||
uint8 lo = op_read(r[SP]++);
|
uint8 lo = read(r[SP]++);
|
||||||
uint8 hi = op_read(r[SP]++);
|
uint8 hi = read(r[SP]++);
|
||||||
r[PC] = (hi << 8) | (lo << 0);
|
r[PC] = (hi << 8) | (lo << 0);
|
||||||
op_io();
|
io();
|
||||||
r.ime = 1;
|
r.ime = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::op_rst_n(uint n) {
|
auto LR35902::op_rst_n(uint n) {
|
||||||
op_io();
|
io();
|
||||||
op_write(--r[SP], r[PC] >> 8);
|
write(--r[SP], r[PC] >> 8);
|
||||||
op_write(--r[SP], r[PC] >> 0);
|
write(--r[SP], r[PC] >> 0);
|
||||||
r[PC] = n;
|
r[PC] = n;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,18 @@ auto LR35902::power() -> void {
|
||||||
r.ime = false;
|
r.ime = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::exec() -> void {
|
auto LR35902::interrupt(uint16 vector) -> void {
|
||||||
uint8 opcode = op_read(r[PC]++);
|
io();
|
||||||
switch(opcode) {
|
io();
|
||||||
|
io();
|
||||||
|
r.ime = 0;
|
||||||
|
write(--r[SP], r[PC] >> 8);
|
||||||
|
write(--r[SP], r[PC] >> 0);
|
||||||
|
r[PC] = vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto LR35902::instruction() -> void {
|
||||||
|
switch(auto opcode = read(r[PC]++)) {
|
||||||
case 0x00: return op_nop();
|
case 0x00: return op_nop();
|
||||||
case 0x01: return op_ld_rr_nn(BC);
|
case 0x01: return op_ld_rr_nn(BC);
|
||||||
case 0x02: return op_ld_rr_a(BC);
|
case 0x02: return op_ld_rr_a(BC);
|
||||||
|
@ -276,9 +285,8 @@ auto LR35902::exec() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto LR35902::execCB() -> void {
|
auto LR35902::instructionCB() -> void {
|
||||||
uint8 opcode = op_read(r[PC]++);
|
switch(auto opcode = read(r[PC]++)) {
|
||||||
switch(opcode) {
|
|
||||||
case 0x00: return op_rlc_r(B);
|
case 0x00: return op_rlc_r(B);
|
||||||
case 0x01: return op_rlc_r(C);
|
case 0x01: return op_rlc_r(C);
|
||||||
case 0x02: return op_rlc_r(D);
|
case 0x02: return op_rlc_r(D);
|
||||||
|
|
|
@ -5,15 +5,16 @@
|
||||||
namespace Processor {
|
namespace Processor {
|
||||||
|
|
||||||
struct LR35902 {
|
struct LR35902 {
|
||||||
virtual auto op_io() -> void = 0;
|
virtual auto io() -> void = 0;
|
||||||
virtual auto op_read(uint16 addr) -> uint8 = 0;
|
virtual auto read(uint16 addr) -> uint8 = 0;
|
||||||
virtual auto op_write(uint16 addr, uint8 data) -> void = 0;
|
virtual auto write(uint16 addr, uint8 data) -> void = 0;
|
||||||
virtual auto stop() -> bool = 0;
|
virtual auto stop() -> bool = 0;
|
||||||
virtual auto debugger_read(uint16 addr) -> uint8 { return 0; }
|
virtual auto debuggerRead(uint16 addr) -> uint8 { return 0; }
|
||||||
|
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
auto exec() -> void;
|
auto interrupt(uint16 vector) -> void;
|
||||||
auto execCB() -> void;
|
auto instruction() -> void;
|
||||||
|
auto instructionCB() -> void;
|
||||||
|
|
||||||
auto serialize(serializer&) -> void;
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#define call (this->*op)
|
#define call (this->*op)
|
||||||
|
|
||||||
auto SPC700::op_adjust(fps op, uint8_t& r) -> void {
|
auto SPC700::op_adjust(fps op, uint8_t& r) {
|
||||||
io();
|
io();
|
||||||
r = call(r);
|
r = call(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_adjust_addr(fps op) -> void {
|
auto SPC700::op_adjust_addr(fps op) {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
rd = read(dp);
|
rd = read(dp);
|
||||||
|
@ -13,14 +13,14 @@ auto SPC700::op_adjust_addr(fps op) -> void {
|
||||||
write(dp, rd);
|
write(dp, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_adjust_dp(fps op) -> void {
|
auto SPC700::op_adjust_dp(fps op) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
rd = readDP(dp);
|
rd = readDP(dp);
|
||||||
rd = call(rd);
|
rd = call(rd);
|
||||||
writeDP(dp, rd);
|
writeDP(dp, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_adjust_dpw(int n) -> void {
|
auto SPC700::op_adjust_dpw(int n) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
rd.w = readDP(dp) + n;
|
rd.w = readDP(dp) + n;
|
||||||
writeDP(dp++, rd.l);
|
writeDP(dp++, rd.l);
|
||||||
|
@ -30,7 +30,7 @@ auto SPC700::op_adjust_dpw(int n) -> void {
|
||||||
regs.p.z = rd == 0;
|
regs.p.z = rd == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_adjust_dpx(fps op) -> void {
|
auto SPC700::op_adjust_dpx(fps op) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
io();
|
io();
|
||||||
rd = readDP(dp + regs.x);
|
rd = readDP(dp + regs.x);
|
||||||
|
@ -38,7 +38,7 @@ auto SPC700::op_adjust_dpx(fps op) -> void {
|
||||||
writeDP(dp + regs.x, rd);
|
writeDP(dp + regs.x, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_branch(bool condition) -> void {
|
auto SPC700::op_branch(bool condition) {
|
||||||
rd = readPC();
|
rd = readPC();
|
||||||
if(!condition) return;
|
if(!condition) return;
|
||||||
io();
|
io();
|
||||||
|
@ -46,7 +46,7 @@ auto SPC700::op_branch(bool condition) -> void {
|
||||||
regs.pc += (int8)rd;
|
regs.pc += (int8)rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_branch_bit() -> void {
|
auto SPC700::op_branch_bit() {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
sp = readDP(dp);
|
sp = readDP(dp);
|
||||||
rd = readPC();
|
rd = readPC();
|
||||||
|
@ -57,26 +57,26 @@ auto SPC700::op_branch_bit() -> void {
|
||||||
regs.pc += (int8)rd;
|
regs.pc += (int8)rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_pull(uint8_t& r) -> void {
|
auto SPC700::op_pull(uint8_t& r) {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
r = readSP();
|
r = readSP();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_push(uint8 r) -> void {
|
auto SPC700::op_push(uint8 r) {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
writeSP(r);
|
writeSP(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_addr(fpb op, uint8_t& r) -> void {
|
auto SPC700::op_read_addr(fpb op, uint8_t& r) {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
rd = read(dp);
|
rd = read(dp);
|
||||||
r = call(r, rd);
|
r = call(r, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_addri(fpb op, uint8_t& r) -> void {
|
auto SPC700::op_read_addri(fpb op, uint8_t& r) {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
io();
|
io();
|
||||||
|
@ -84,25 +84,25 @@ auto SPC700::op_read_addri(fpb op, uint8_t& r) -> void {
|
||||||
regs.a = call(regs.a, rd);
|
regs.a = call(regs.a, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_const(fpb op, uint8_t& r) -> void {
|
auto SPC700::op_read_const(fpb op, uint8_t& r) {
|
||||||
rd = readPC();
|
rd = readPC();
|
||||||
r = call(r, rd);
|
r = call(r, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_dp(fpb op, uint8_t& r) -> void {
|
auto SPC700::op_read_dp(fpb op, uint8_t& r) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
rd = readDP(dp);
|
rd = readDP(dp);
|
||||||
r = call(r, rd);
|
r = call(r, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_dpi(fpb op, uint8_t& r, uint8_t& i) -> void {
|
auto SPC700::op_read_dpi(fpb op, uint8_t& r, uint8_t& i) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
io();
|
io();
|
||||||
rd = readDP(dp + i);
|
rd = readDP(dp + i);
|
||||||
r = call(r, rd);
|
r = call(r, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_dpw(fpw op) -> void {
|
auto SPC700::op_read_dpw(fpw op) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
rd.l = readDP(dp++);
|
rd.l = readDP(dp++);
|
||||||
if(op != &SPC700::op_cpw) io();
|
if(op != &SPC700::op_cpw) io();
|
||||||
|
@ -110,7 +110,7 @@ auto SPC700::op_read_dpw(fpw op) -> void {
|
||||||
regs.ya = call(regs.ya, rd);
|
regs.ya = call(regs.ya, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_idpx(fpb op) -> void {
|
auto SPC700::op_read_idpx(fpb op) {
|
||||||
dp = readPC() + regs.x;
|
dp = readPC() + regs.x;
|
||||||
io();
|
io();
|
||||||
sp.l = readDP(dp++);
|
sp.l = readDP(dp++);
|
||||||
|
@ -119,7 +119,7 @@ auto SPC700::op_read_idpx(fpb op) -> void {
|
||||||
regs.a = call(regs.a, rd);
|
regs.a = call(regs.a, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_idpy(fpb op) -> void {
|
auto SPC700::op_read_idpy(fpb op) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
io();
|
io();
|
||||||
sp.l = readDP(dp++);
|
sp.l = readDP(dp++);
|
||||||
|
@ -128,13 +128,13 @@ auto SPC700::op_read_idpy(fpb op) -> void {
|
||||||
regs.a = call(regs.a, rd);
|
regs.a = call(regs.a, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_read_ix(fpb op) -> void {
|
auto SPC700::op_read_ix(fpb op) {
|
||||||
io();
|
io();
|
||||||
rd = readDP(regs.x);
|
rd = readDP(regs.x);
|
||||||
regs.a = call(regs.a, rd);
|
regs.a = call(regs.a, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_set_addr_bit() -> void {
|
auto SPC700::op_set_addr_bit() {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
bit = dp >> 13;
|
bit = dp >> 13;
|
||||||
|
@ -169,19 +169,19 @@ auto SPC700::op_set_addr_bit() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_set_bit() -> void {
|
auto SPC700::op_set_bit() {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
rd = readDP(dp) & ~(1 << (opcode >> 5));
|
rd = readDP(dp) & ~(1 << (opcode >> 5));
|
||||||
writeDP(dp, rd | (!(opcode & 0x10) << (opcode >> 5)));
|
writeDP(dp, rd | (!(opcode & 0x10) << (opcode >> 5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_set_flag(bool& flag, bool data) -> void {
|
auto SPC700::op_set_flag(bool& flag, bool data) {
|
||||||
io();
|
io();
|
||||||
if(&flag == ®s.p.i) io();
|
if(&flag == ®s.p.i) io();
|
||||||
flag = data;
|
flag = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_test_addr(bool set) -> void {
|
auto SPC700::op_test_addr(bool set) {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
rd = read(dp);
|
rd = read(dp);
|
||||||
|
@ -191,7 +191,7 @@ auto SPC700::op_test_addr(bool set) -> void {
|
||||||
write(dp, set ? rd | regs.a : rd & ~regs.a);
|
write(dp, set ? rd | regs.a : rd & ~regs.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_transfer(uint8_t& from, uint8_t& to) -> void {
|
auto SPC700::op_transfer(uint8_t& from, uint8_t& to) {
|
||||||
io();
|
io();
|
||||||
to = from;
|
to = from;
|
||||||
if(&to == ®s.s) return;
|
if(&to == ®s.s) return;
|
||||||
|
@ -199,14 +199,14 @@ auto SPC700::op_transfer(uint8_t& from, uint8_t& to) -> void {
|
||||||
regs.p.z = (to == 0);
|
regs.p.z = (to == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_addr(uint8_t& r) -> void {
|
auto SPC700::op_write_addr(uint8_t& r) {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
read(dp);
|
read(dp);
|
||||||
write(dp, r);
|
write(dp, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_addri(uint8_t& i) -> void {
|
auto SPC700::op_write_addri(uint8_t& i) {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
io();
|
io();
|
||||||
|
@ -215,20 +215,20 @@ auto SPC700::op_write_addri(uint8_t& i) -> void {
|
||||||
write(dp, regs.a);
|
write(dp, regs.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_dp(uint8_t& r) -> void {
|
auto SPC700::op_write_dp(uint8_t& r) {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
readDP(dp);
|
readDP(dp);
|
||||||
writeDP(dp, r);
|
writeDP(dp, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_dpi(uint8_t& r, uint8_t& i) -> void {
|
auto SPC700::op_write_dpi(uint8_t& r, uint8_t& i) {
|
||||||
dp = readPC() + i;
|
dp = readPC() + i;
|
||||||
io();
|
io();
|
||||||
readDP(dp);
|
readDP(dp);
|
||||||
writeDP(dp, r);
|
writeDP(dp, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_dp_const(fpb op) -> void {
|
auto SPC700::op_write_dp_const(fpb op) {
|
||||||
rd = readPC();
|
rd = readPC();
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
wr = readDP(dp);
|
wr = readDP(dp);
|
||||||
|
@ -236,7 +236,7 @@ auto SPC700::op_write_dp_const(fpb op) -> void {
|
||||||
op != &SPC700::op_cmp ? writeDP(dp, wr) : io();
|
op != &SPC700::op_cmp ? writeDP(dp, wr) : io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_dp_dp(fpb op) -> void {
|
auto SPC700::op_write_dp_dp(fpb op) {
|
||||||
sp = readPC();
|
sp = readPC();
|
||||||
rd = readDP(sp);
|
rd = readDP(sp);
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
|
@ -245,7 +245,7 @@ auto SPC700::op_write_dp_dp(fpb op) -> void {
|
||||||
op != &SPC700::op_cmp ? writeDP(dp, wr) : io();
|
op != &SPC700::op_cmp ? writeDP(dp, wr) : io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_write_ix_iy(fpb op) -> void {
|
auto SPC700::op_write_ix_iy(fpb op) {
|
||||||
io();
|
io();
|
||||||
rd = readDP(regs.y);
|
rd = readDP(regs.y);
|
||||||
wr = readDP(regs.x);
|
wr = readDP(regs.x);
|
||||||
|
@ -255,7 +255,7 @@ auto SPC700::op_write_ix_iy(fpb op) -> void {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
auto SPC700::op_bne_dp() -> void {
|
auto SPC700::op_bne_dp() {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
sp = readDP(dp);
|
sp = readDP(dp);
|
||||||
rd = readPC();
|
rd = readPC();
|
||||||
|
@ -266,7 +266,7 @@ auto SPC700::op_bne_dp() -> void {
|
||||||
regs.pc += (int8)rd;
|
regs.pc += (int8)rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_bne_dpdec() -> void {
|
auto SPC700::op_bne_dpdec() {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
wr = readDP(dp);
|
wr = readDP(dp);
|
||||||
writeDP(dp, --wr);
|
writeDP(dp, --wr);
|
||||||
|
@ -277,7 +277,7 @@ auto SPC700::op_bne_dpdec() -> void {
|
||||||
regs.pc += (int8)rd;
|
regs.pc += (int8)rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_bne_dpx() -> void {
|
auto SPC700::op_bne_dpx() {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
io();
|
io();
|
||||||
sp = readDP(dp + regs.x);
|
sp = readDP(dp + regs.x);
|
||||||
|
@ -289,7 +289,7 @@ auto SPC700::op_bne_dpx() -> void {
|
||||||
regs.pc += (int8)rd;
|
regs.pc += (int8)rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_bne_ydec() -> void {
|
auto SPC700::op_bne_ydec() {
|
||||||
rd = readPC();
|
rd = readPC();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
|
@ -299,7 +299,7 @@ auto SPC700::op_bne_ydec() -> void {
|
||||||
regs.pc += (int8)rd;
|
regs.pc += (int8)rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_brk() -> void {
|
auto SPC700::op_brk() {
|
||||||
rd.l = read(0xffde);
|
rd.l = read(0xffde);
|
||||||
rd.h = read(0xffdf);
|
rd.h = read(0xffdf);
|
||||||
io();
|
io();
|
||||||
|
@ -312,19 +312,19 @@ auto SPC700::op_brk() -> void {
|
||||||
regs.p.i = 0;
|
regs.p.i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_clv() -> void {
|
auto SPC700::op_clv() {
|
||||||
io();
|
io();
|
||||||
regs.p.v = 0;
|
regs.p.v = 0;
|
||||||
regs.p.h = 0;
|
regs.p.h = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_cmc() -> void {
|
auto SPC700::op_cmc() {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
regs.p.c = !regs.p.c;
|
regs.p.c = !regs.p.c;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_daa() -> void {
|
auto SPC700::op_daa() {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
if(regs.p.c || (regs.a) > 0x99) {
|
if(regs.p.c || (regs.a) > 0x99) {
|
||||||
|
@ -338,7 +338,7 @@ auto SPC700::op_daa() -> void {
|
||||||
regs.p.z = (regs.a == 0);
|
regs.p.z = (regs.a == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_das() -> void {
|
auto SPC700::op_das() {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
if(!regs.p.c || (regs.a) > 0x99) {
|
if(!regs.p.c || (regs.a) > 0x99) {
|
||||||
|
@ -352,7 +352,7 @@ auto SPC700::op_das() -> void {
|
||||||
regs.p.z = (regs.a == 0);
|
regs.p.z = (regs.a == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_div_ya_x() -> void {
|
auto SPC700::op_div_ya_x() {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
|
@ -383,13 +383,13 @@ auto SPC700::op_div_ya_x() -> void {
|
||||||
regs.p.z = (regs.a == 0);
|
regs.p.z = (regs.a == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_jmp_addr() -> void {
|
auto SPC700::op_jmp_addr() {
|
||||||
rd.l = readPC();
|
rd.l = readPC();
|
||||||
rd.h = readPC();
|
rd.h = readPC();
|
||||||
regs.pc = rd;
|
regs.pc = rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_jmp_iaddrx() -> void {
|
auto SPC700::op_jmp_iaddrx() {
|
||||||
dp.l = readPC();
|
dp.l = readPC();
|
||||||
dp.h = readPC();
|
dp.h = readPC();
|
||||||
io();
|
io();
|
||||||
|
@ -399,7 +399,7 @@ auto SPC700::op_jmp_iaddrx() -> void {
|
||||||
regs.pc = rd;
|
regs.pc = rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_jsp_dp() -> void {
|
auto SPC700::op_jsp_dp() {
|
||||||
rd = readPC();
|
rd = readPC();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
|
@ -408,7 +408,7 @@ auto SPC700::op_jsp_dp() -> void {
|
||||||
regs.pc = 0xff00 | rd;
|
regs.pc = 0xff00 | rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_jsr_addr() -> void {
|
auto SPC700::op_jsr_addr() {
|
||||||
rd.l = readPC();
|
rd.l = readPC();
|
||||||
rd.h = readPC();
|
rd.h = readPC();
|
||||||
io();
|
io();
|
||||||
|
@ -419,7 +419,7 @@ auto SPC700::op_jsr_addr() -> void {
|
||||||
regs.pc = rd;
|
regs.pc = rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_jst() -> void {
|
auto SPC700::op_jst() {
|
||||||
dp = 0xffde - ((opcode >> 4) << 1);
|
dp = 0xffde - ((opcode >> 4) << 1);
|
||||||
rd.l = read(dp++);
|
rd.l = read(dp++);
|
||||||
rd.h = read(dp++);
|
rd.h = read(dp++);
|
||||||
|
@ -431,7 +431,7 @@ auto SPC700::op_jst() -> void {
|
||||||
regs.pc = rd;
|
regs.pc = rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_lda_ixinc() -> void {
|
auto SPC700::op_lda_ixinc() {
|
||||||
io();
|
io();
|
||||||
regs.a = readDP(regs.x++);
|
regs.a = readDP(regs.x++);
|
||||||
io();
|
io();
|
||||||
|
@ -439,7 +439,7 @@ auto SPC700::op_lda_ixinc() -> void {
|
||||||
regs.p.z = regs.a == 0;
|
regs.p.z = regs.a == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_mul_ya() -> void {
|
auto SPC700::op_mul_ya() {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
|
@ -456,17 +456,17 @@ auto SPC700::op_mul_ya() -> void {
|
||||||
regs.p.z = (regs.y == 0);
|
regs.p.z = (regs.y == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_nop() -> void {
|
auto SPC700::op_nop() {
|
||||||
io();
|
io();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_plp() -> void {
|
auto SPC700::op_plp() {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
regs.p = readSP();
|
regs.p = readSP();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_rti() -> void {
|
auto SPC700::op_rti() {
|
||||||
regs.p = readSP();
|
regs.p = readSP();
|
||||||
rd.l = readSP();
|
rd.l = readSP();
|
||||||
rd.h = readSP();
|
rd.h = readSP();
|
||||||
|
@ -475,7 +475,7 @@ auto SPC700::op_rti() -> void {
|
||||||
regs.pc = rd;
|
regs.pc = rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_rts() -> void {
|
auto SPC700::op_rts() {
|
||||||
rd.l = readSP();
|
rd.l = readSP();
|
||||||
rd.h = readSP();
|
rd.h = readSP();
|
||||||
io();
|
io();
|
||||||
|
@ -483,7 +483,7 @@ auto SPC700::op_rts() -> void {
|
||||||
regs.pc = rd;
|
regs.pc = rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_sta_idpx() -> void {
|
auto SPC700::op_sta_idpx() {
|
||||||
sp = readPC() + regs.x;
|
sp = readPC() + regs.x;
|
||||||
io();
|
io();
|
||||||
dp.l = readDP(sp++);
|
dp.l = readDP(sp++);
|
||||||
|
@ -492,7 +492,7 @@ auto SPC700::op_sta_idpx() -> void {
|
||||||
write(dp, regs.a);
|
write(dp, regs.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_sta_idpy() -> void {
|
auto SPC700::op_sta_idpy() {
|
||||||
sp = readPC();
|
sp = readPC();
|
||||||
dp.l = readDP(sp++);
|
dp.l = readDP(sp++);
|
||||||
dp.h = readDP(sp++);
|
dp.h = readDP(sp++);
|
||||||
|
@ -502,33 +502,33 @@ auto SPC700::op_sta_idpy() -> void {
|
||||||
write(dp, regs.a);
|
write(dp, regs.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_sta_ix() -> void {
|
auto SPC700::op_sta_ix() {
|
||||||
io();
|
io();
|
||||||
readDP(regs.x);
|
readDP(regs.x);
|
||||||
writeDP(regs.x, regs.a);
|
writeDP(regs.x, regs.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_sta_ixinc() -> void {
|
auto SPC700::op_sta_ixinc() {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
writeDP(regs.x++, regs.a);
|
writeDP(regs.x++, regs.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_stw_dp() -> void {
|
auto SPC700::op_stw_dp() {
|
||||||
dp = readPC();
|
dp = readPC();
|
||||||
readDP(dp);
|
readDP(dp);
|
||||||
writeDP(dp++, regs.a);
|
writeDP(dp++, regs.a);
|
||||||
writeDP(dp++, regs.y);
|
writeDP(dp++, regs.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_wait() -> void {
|
auto SPC700::op_wait() {
|
||||||
while(true) {
|
while(true) {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SPC700::op_xcn() -> void {
|
auto SPC700::op_xcn() {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
|
|
|
@ -45,65 +45,65 @@ protected:
|
||||||
auto op_ldw(uint16, uint16) -> uint16;
|
auto op_ldw(uint16, uint16) -> uint16;
|
||||||
auto op_sbw(uint16, uint16) -> uint16;
|
auto op_sbw(uint16, uint16) -> uint16;
|
||||||
|
|
||||||
auto op_adjust(fps, uint8_t&) -> void;
|
auto op_adjust(fps, uint8_t&);
|
||||||
auto op_adjust_addr(fps) -> void;
|
auto op_adjust_addr(fps);
|
||||||
auto op_adjust_dp(fps) -> void;
|
auto op_adjust_dp(fps);
|
||||||
auto op_adjust_dpw(int) -> void;
|
auto op_adjust_dpw(int);
|
||||||
auto op_adjust_dpx(fps) -> void;
|
auto op_adjust_dpx(fps);
|
||||||
auto op_branch(bool) -> void;
|
auto op_branch(bool);
|
||||||
auto op_branch_bit() -> void;
|
auto op_branch_bit();
|
||||||
auto op_pull(uint8_t&) -> void;
|
auto op_pull(uint8_t&);
|
||||||
auto op_push(uint8) -> void;
|
auto op_push(uint8);
|
||||||
auto op_read_addr(fpb, uint8_t&) -> void;
|
auto op_read_addr(fpb, uint8_t&);
|
||||||
auto op_read_addri(fpb, uint8_t&) -> void;
|
auto op_read_addri(fpb, uint8_t&);
|
||||||
auto op_read_const(fpb, uint8_t&) -> void;
|
auto op_read_const(fpb, uint8_t&);
|
||||||
auto op_read_dp(fpb, uint8_t&) -> void;
|
auto op_read_dp(fpb, uint8_t&);
|
||||||
auto op_read_dpi(fpb, uint8_t&, uint8_t&) -> void;
|
auto op_read_dpi(fpb, uint8_t&, uint8_t&);
|
||||||
auto op_read_dpw(fpw) -> void;
|
auto op_read_dpw(fpw);
|
||||||
auto op_read_idpx(fpb) -> void;
|
auto op_read_idpx(fpb);
|
||||||
auto op_read_idpy(fpb) -> void;
|
auto op_read_idpy(fpb);
|
||||||
auto op_read_ix(fpb) -> void;
|
auto op_read_ix(fpb);
|
||||||
auto op_set_addr_bit() -> void;
|
auto op_set_addr_bit();
|
||||||
auto op_set_bit() -> void;
|
auto op_set_bit();
|
||||||
auto op_set_flag(bool&, bool) -> void;
|
auto op_set_flag(bool&, bool);
|
||||||
auto op_test_addr(bool) -> void;
|
auto op_test_addr(bool);
|
||||||
auto op_transfer(uint8_t&, uint8_t&) -> void;
|
auto op_transfer(uint8_t&, uint8_t&);
|
||||||
auto op_write_addr(uint8_t&) -> void;
|
auto op_write_addr(uint8_t&);
|
||||||
auto op_write_addri(uint8_t&) -> void;
|
auto op_write_addri(uint8_t&);
|
||||||
auto op_write_dp(uint8_t&) -> void;
|
auto op_write_dp(uint8_t&);
|
||||||
auto op_write_dpi(uint8_t&, uint8_t&) -> void;
|
auto op_write_dpi(uint8_t&, uint8_t&);
|
||||||
auto op_write_dp_const(fpb) -> void;
|
auto op_write_dp_const(fpb);
|
||||||
auto op_write_dp_dp(fpb) -> void;
|
auto op_write_dp_dp(fpb);
|
||||||
auto op_write_ix_iy(fpb) -> void;
|
auto op_write_ix_iy(fpb);
|
||||||
|
|
||||||
auto op_bne_dp() -> void;
|
auto op_bne_dp();
|
||||||
auto op_bne_dpdec() -> void;
|
auto op_bne_dpdec();
|
||||||
auto op_bne_dpx() -> void;
|
auto op_bne_dpx();
|
||||||
auto op_bne_ydec() -> void;
|
auto op_bne_ydec();
|
||||||
auto op_brk() -> void;
|
auto op_brk();
|
||||||
auto op_clv() -> void;
|
auto op_clv();
|
||||||
auto op_cmc() -> void;
|
auto op_cmc();
|
||||||
auto op_daa() -> void;
|
auto op_daa();
|
||||||
auto op_das() -> void;
|
auto op_das();
|
||||||
auto op_div_ya_x() -> void;
|
auto op_div_ya_x();
|
||||||
auto op_jmp_addr() -> void;
|
auto op_jmp_addr();
|
||||||
auto op_jmp_iaddrx() -> void;
|
auto op_jmp_iaddrx();
|
||||||
auto op_jsp_dp() -> void;
|
auto op_jsp_dp();
|
||||||
auto op_jsr_addr() -> void;
|
auto op_jsr_addr();
|
||||||
auto op_jst() -> void;
|
auto op_jst();
|
||||||
auto op_lda_ixinc() -> void;
|
auto op_lda_ixinc();
|
||||||
auto op_mul_ya() -> void;
|
auto op_mul_ya();
|
||||||
auto op_nop() -> void;
|
auto op_nop();
|
||||||
auto op_plp() -> void;
|
auto op_plp();
|
||||||
auto op_rti() -> void;
|
auto op_rti();
|
||||||
auto op_rts() -> void;
|
auto op_rts();
|
||||||
auto op_sta_idpx() -> void;
|
auto op_sta_idpx();
|
||||||
auto op_sta_idpy() -> void;
|
auto op_sta_idpy();
|
||||||
auto op_sta_ix() -> void;
|
auto op_sta_ix();
|
||||||
auto op_sta_ixinc() -> void;
|
auto op_sta_ixinc();
|
||||||
auto op_stw_dp() -> void;
|
auto op_stw_dp();
|
||||||
auto op_wait() -> void;
|
auto op_wait();
|
||||||
auto op_xcn() -> void;
|
auto op_xcn();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ auto SuperFX::plot(uint8 x, uint8 y) -> void {
|
||||||
|
|
||||||
uint16 offset = (y << 5) + (x >> 3);
|
uint16 offset = (y << 5) + (x >> 3);
|
||||||
if(offset != pixelcache[0].offset) {
|
if(offset != pixelcache[0].offset) {
|
||||||
pixelcache_flush(pixelcache[1]);
|
flushPixelCache(pixelcache[1]);
|
||||||
pixelcache[1] = pixelcache[0];
|
pixelcache[1] = pixelcache[0];
|
||||||
pixelcache[0].bitpend = 0x00;
|
pixelcache[0].bitpend = 0x00;
|
||||||
pixelcache[0].offset = offset;
|
pixelcache[0].offset = offset;
|
||||||
|
@ -40,64 +40,64 @@ auto SuperFX::plot(uint8 x, uint8 y) -> void {
|
||||||
pixelcache[0].data[x] = color;
|
pixelcache[0].data[x] = color;
|
||||||
pixelcache[0].bitpend |= 1 << x;
|
pixelcache[0].bitpend |= 1 << x;
|
||||||
if(pixelcache[0].bitpend == 0xff) {
|
if(pixelcache[0].bitpend == 0xff) {
|
||||||
pixelcache_flush(pixelcache[1]);
|
flushPixelCache(pixelcache[1]);
|
||||||
pixelcache[1] = pixelcache[0];
|
pixelcache[1] = pixelcache[0];
|
||||||
pixelcache[0].bitpend = 0x00;
|
pixelcache[0].bitpend = 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::rpix(uint8 x, uint8 y) -> uint8 {
|
auto SuperFX::rpix(uint8 x, uint8 y) -> uint8 {
|
||||||
pixelcache_flush(pixelcache[1]);
|
flushPixelCache(pixelcache[1]);
|
||||||
pixelcache_flush(pixelcache[0]);
|
flushPixelCache(pixelcache[0]);
|
||||||
|
|
||||||
unsigned cn; //character number
|
uint cn; //character number
|
||||||
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
||||||
case 0: cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3); break;
|
case 0: cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3); break;
|
||||||
case 1: cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3); break;
|
case 1: cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3); break;
|
||||||
case 2: cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3); break;
|
case 2: cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3); break;
|
||||||
case 3: cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break;
|
case 3: cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break;
|
||||||
}
|
}
|
||||||
unsigned bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
uint bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
||||||
unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
uint addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||||
uint8 data = 0x00;
|
uint8 data = 0x00;
|
||||||
x = (x & 7) ^ 7;
|
x = (x & 7) ^ 7;
|
||||||
|
|
||||||
for(unsigned n = 0; n < bpp; n++) {
|
for(uint n : range(bpp)) {
|
||||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
uint byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||||
step(regs.clsr ? 5 : 6);
|
step(regs.clsr ? 5 : 6);
|
||||||
data |= ((bus_read(addr + byte) >> x) & 1) << n;
|
data |= ((read(addr + byte) >> x) & 1) << n;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::pixelcache_flush(pixelcache_t& cache) -> void {
|
auto SuperFX::flushPixelCache(PixelCache& cache) -> void {
|
||||||
if(cache.bitpend == 0x00) return;
|
if(cache.bitpend == 0x00) return;
|
||||||
|
|
||||||
uint8 x = cache.offset << 3;
|
uint8 x = cache.offset << 3;
|
||||||
uint8 y = cache.offset >> 5;
|
uint8 y = cache.offset >> 5;
|
||||||
|
|
||||||
unsigned cn; //character number
|
uint cn; //character number
|
||||||
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
||||||
case 0: cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3); break;
|
case 0: cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3); break;
|
||||||
case 1: cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3); break;
|
case 1: cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3); break;
|
||||||
case 2: cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3); break;
|
case 2: cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3); break;
|
||||||
case 3: cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break;
|
case 3: cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break;
|
||||||
}
|
}
|
||||||
unsigned bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
uint bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
||||||
unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
uint addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||||
|
|
||||||
for(unsigned n = 0; n < bpp; n++) {
|
for(uint n : range(bpp)) {
|
||||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
uint byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||||
uint8 data = 0x00;
|
uint8 data = 0x00;
|
||||||
for(unsigned x = 0; x < 8; x++) data |= ((cache.data[x] >> n) & 1) << x;
|
for(uint x : range(8)) data |= ((cache.data[x] >> n) & 1) << x;
|
||||||
if(cache.bitpend != 0xff) {
|
if(cache.bitpend != 0xff) {
|
||||||
step(regs.clsr ? 5 : 6);
|
step(regs.clsr ? 5 : 6);
|
||||||
data &= cache.bitpend;
|
data &= cache.bitpend;
|
||||||
data |= bus_read(addr + byte) & ~cache.bitpend;
|
data |= read(addr + byte) & ~cache.bitpend;
|
||||||
}
|
}
|
||||||
step(regs.clsr ? 5 : 6);
|
step(regs.clsr ? 5 : 6);
|
||||||
bus_write(addr + byte, data);
|
write(addr + byte, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.bitpend = 0x00;
|
cache.bitpend = 0x00;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
auto SuperFX::bus_read(uint24 addr, uint8 data) -> uint8 {
|
auto SuperFX::read(uint24 addr, uint8 data) -> uint8 {
|
||||||
if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff, $00-3f:8000-ffff
|
if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff,:8000-ffff
|
||||||
while(!regs.scmr.ron && !scheduler.synchronizing()) {
|
while(!regs.scmr.ron && !scheduler.synchronizing()) {
|
||||||
step(6);
|
step(6);
|
||||||
synchronizeCPU();
|
synchronizeCPU();
|
||||||
}
|
}
|
||||||
return rom.read((((addr & 0x3f0000) >> 1) | (addr & 0x7fff)) & rom_mask);
|
return rom.read((((addr & 0x3f0000) >> 1) | (addr & 0x7fff)) & romMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((addr & 0xe00000) == 0x400000) { //$40-5f:0000-ffff
|
if((addr & 0xe00000) == 0x400000) { //$40-5f:0000-ffff
|
||||||
|
@ -12,7 +12,7 @@ auto SuperFX::bus_read(uint24 addr, uint8 data) -> uint8 {
|
||||||
step(6);
|
step(6);
|
||||||
synchronizeCPU();
|
synchronizeCPU();
|
||||||
}
|
}
|
||||||
return rom.read(addr & rom_mask);
|
return rom.read(addr & romMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
|
if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
|
||||||
|
@ -20,31 +20,31 @@ auto SuperFX::bus_read(uint24 addr, uint8 data) -> uint8 {
|
||||||
step(6);
|
step(6);
|
||||||
synchronizeCPU();
|
synchronizeCPU();
|
||||||
}
|
}
|
||||||
return ram.read(addr & ram_mask);
|
return ram.read(addr & ramMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::bus_write(uint24 addr, uint8 data) -> void {
|
auto SuperFX::write(uint24 addr, uint8 data) -> void {
|
||||||
if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
|
if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
|
||||||
while(!regs.scmr.ran && !scheduler.synchronizing()) {
|
while(!regs.scmr.ran && !scheduler.synchronizing()) {
|
||||||
step(6);
|
step(6);
|
||||||
synchronizeCPU();
|
synchronizeCPU();
|
||||||
}
|
}
|
||||||
return ram.write(addr & ram_mask, data);
|
return ram.write(addr & ramMask, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::op_read(uint16 addr) -> uint8 {
|
auto SuperFX::readOpcode(uint16 addr) -> uint8 {
|
||||||
uint16 offset = addr - regs.cbr;
|
uint16 offset = addr - regs.cbr;
|
||||||
if(offset < 512) {
|
if(offset < 512) {
|
||||||
if(cache.valid[offset >> 4] == false) {
|
if(cache.valid[offset >> 4] == false) {
|
||||||
unsigned dp = offset & 0xfff0;
|
uint dp = offset & 0xfff0;
|
||||||
unsigned sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0);
|
uint sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0);
|
||||||
for(unsigned n = 0; n < 16; n++) {
|
for(uint n : range(16)) {
|
||||||
step(regs.clsr ? 5 : 6);
|
step(regs.clsr ? 5 : 6);
|
||||||
cache.buffer[dp++] = bus_read(sp++);
|
cache.buffer[dp++] = read(sp++);
|
||||||
}
|
}
|
||||||
cache.valid[offset >> 4] = true;
|
cache.valid[offset >> 4] = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -54,55 +54,43 @@ auto SuperFX::op_read(uint16 addr) -> uint8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.pbr <= 0x5f) {
|
if(regs.pbr <= 0x5f) {
|
||||||
//$[00-5f]:[0000-ffff] ROM
|
//$00-5f:0000-ffff ROM
|
||||||
rombuffer_sync();
|
syncROMBuffer();
|
||||||
step(regs.clsr ? 5 : 6);
|
step(regs.clsr ? 5 : 6);
|
||||||
return bus_read((regs.pbr << 16) + addr);
|
return read(regs.pbr << 16 | addr);
|
||||||
} else {
|
} else {
|
||||||
//$[60-7f]:[0000-ffff] RAM
|
//$60-7f:0000-ffff RAM
|
||||||
rambuffer_sync();
|
syncRAMBuffer();
|
||||||
step(regs.clsr ? 5 : 6);
|
step(regs.clsr ? 5 : 6);
|
||||||
return bus_read((regs.pbr << 16) + addr);
|
return read(regs.pbr << 16 | addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::peekpipe() -> uint8 {
|
auto SuperFX::peekpipe() -> uint8 {
|
||||||
uint8 result = regs.pipeline;
|
uint8 result = regs.pipeline;
|
||||||
regs.pipeline = op_read(regs.r[15]);
|
regs.pipeline = readOpcode(regs.r[15]);
|
||||||
r15_modified = false;
|
regs.r[15].modified = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::pipe() -> uint8 {
|
auto SuperFX::pipe() -> uint8 {
|
||||||
uint8 result = regs.pipeline;
|
uint8 result = regs.pipeline;
|
||||||
regs.pipeline = op_read(++regs.r[15]);
|
regs.pipeline = readOpcode(++regs.r[15]);
|
||||||
r15_modified = false;
|
regs.r[15].modified = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::cache_flush() -> void {
|
auto SuperFX::flushCache() -> void {
|
||||||
for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
|
for(uint n : range(32)) cache.valid[n] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::cache_mmio_read(uint16 addr) -> uint8 {
|
auto SuperFX::readCache(uint16 addr) -> uint8 {
|
||||||
addr = (addr + regs.cbr) & 511;
|
addr = (addr + regs.cbr) & 511;
|
||||||
return cache.buffer[addr];
|
return cache.buffer[addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::cache_mmio_write(uint16 addr, uint8 data) -> void {
|
auto SuperFX::writeCache(uint16 addr, uint8 data) -> void {
|
||||||
addr = (addr + regs.cbr) & 511;
|
addr = (addr + regs.cbr) & 511;
|
||||||
cache.buffer[addr] = data;
|
cache.buffer[addr] = data;
|
||||||
if((addr & 15) == 15) cache.valid[addr >> 4] = true;
|
if((addr & 15) == 15) cache.valid[addr >> 4] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::memory_reset() -> void {
|
|
||||||
rom_mask = rom.size() - 1;
|
|
||||||
ram_mask = ram.size() - 1;
|
|
||||||
|
|
||||||
for(unsigned n = 0; n < 512; n++) cache.buffer[n] = 0x00;
|
|
||||||
for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
|
|
||||||
for(unsigned n = 0; n < 2; n++) {
|
|
||||||
pixelcache[n].offset = ~0;
|
|
||||||
pixelcache[n].bitpend = 0x00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ auto SuperFX::readIO(uint24 addr, uint8) -> uint8 {
|
||||||
addr = 0x3000 | addr.bits(0,9);
|
addr = 0x3000 | addr.bits(0,9);
|
||||||
|
|
||||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||||
return cache_mmio_read(addr - 0x3100);
|
return readCache(addr - 0x3100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(addr >= 0x3000 && addr <= 0x301f) {
|
if(addr >= 0x3000 && addr <= 0x301f) {
|
||||||
|
@ -55,7 +55,7 @@ auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
|
||||||
addr = 0x3000 | addr.bits(0,9);
|
addr = 0x3000 | addr.bits(0,9);
|
||||||
|
|
||||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||||
return cache_mmio_write(addr - 0x3100, data);
|
return writeCache(addr - 0x3100, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(addr >= 0x3000 && addr <= 0x301f) {
|
if(addr >= 0x3000 && addr <= 0x301f) {
|
||||||
|
@ -65,6 +65,7 @@ auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
|
||||||
} else {
|
} else {
|
||||||
regs.r[n] = (data << 8) | (regs.r[n] & 0xff);
|
regs.r[n] = (data << 8) | (regs.r[n] & 0xff);
|
||||||
}
|
}
|
||||||
|
if(n == 14) updateROMBuffer();
|
||||||
|
|
||||||
if(addr == 0x301f) regs.sfr.g = 1;
|
if(addr == 0x301f) regs.sfr.g = 1;
|
||||||
return;
|
return;
|
||||||
|
@ -76,7 +77,7 @@ auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
|
||||||
regs.sfr = (regs.sfr & 0xff00) | (data << 0);
|
regs.sfr = (regs.sfr & 0xff00) | (data << 0);
|
||||||
if(g == 1 && regs.sfr.g == 0) {
|
if(g == 1 && regs.sfr.g == 0) {
|
||||||
regs.cbr = 0x0000;
|
regs.cbr = 0x0000;
|
||||||
cache_flush();
|
flushCache();
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
|
||||||
|
|
||||||
case 0x3034: {
|
case 0x3034: {
|
||||||
regs.pbr = data & 0x7f;
|
regs.pbr = data & 0x7f;
|
||||||
cache_flush();
|
flushCache();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case 0x3037: {
|
case 0x3037: {
|
||||||
|
|
|
@ -3,5 +3,4 @@ auto SuperFX::serialize(serializer& s) -> void {
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
|
|
||||||
s.array(ram.data(), ram.size());
|
s.array(ram.data(), ram.size());
|
||||||
s.integer(r15_modified);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,22 @@ auto SuperFX::Enter() -> void {
|
||||||
|
|
||||||
auto SuperFX::main() -> void {
|
auto SuperFX::main() -> void {
|
||||||
if(regs.sfr.g == 0) return step(6);
|
if(regs.sfr.g == 0) return step(6);
|
||||||
|
|
||||||
instruction(peekpipe());
|
instruction(peekpipe());
|
||||||
if(!r15_modified) regs.r[15]++;
|
|
||||||
|
if(regs.r[14].modified) {
|
||||||
|
regs.r[14].modified = false;
|
||||||
|
updateROMBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(regs.r[15].modified) {
|
||||||
|
regs.r[15].modified = false;
|
||||||
|
} else {
|
||||||
|
regs.r[15]++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::init() -> void {
|
auto SuperFX::init() -> void {
|
||||||
regs.r[14].modify = {&SuperFX::r14_modify, this};
|
|
||||||
regs.r[15].modify = {&SuperFX::r15_modify, this};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::load() -> void {
|
auto SuperFX::load() -> void {
|
||||||
|
@ -40,8 +49,23 @@ auto SuperFX::power() -> void {
|
||||||
auto SuperFX::reset() -> void {
|
auto SuperFX::reset() -> void {
|
||||||
GSU::reset();
|
GSU::reset();
|
||||||
create(SuperFX::Enter, system.cpuFrequency());
|
create(SuperFX::Enter, system.cpuFrequency());
|
||||||
memory_reset();
|
|
||||||
timing_reset();
|
romMask = rom.size() - 1;
|
||||||
|
ramMask = ram.size() - 1;
|
||||||
|
|
||||||
|
for(uint n : range(512)) cache.buffer[n] = 0x00;
|
||||||
|
for(uint n : range(32)) cache.valid[n] = false;
|
||||||
|
for(uint n : range(2)) {
|
||||||
|
pixelcache[n].offset = ~0;
|
||||||
|
pixelcache[n].bitpend = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.romcl = 0;
|
||||||
|
regs.romdr = 0;
|
||||||
|
|
||||||
|
regs.ramcl = 0;
|
||||||
|
regs.ramar = 0;
|
||||||
|
regs.ramdr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,45 +25,39 @@ struct SuperFX : Processor::GSU, Cothread {
|
||||||
};
|
};
|
||||||
|
|
||||||
//core.cpp
|
//core.cpp
|
||||||
auto stop() -> void;
|
auto stop() -> void override;
|
||||||
auto color(uint8 source) -> uint8;
|
auto color(uint8 source) -> uint8 override;
|
||||||
auto plot(uint8 x, uint8 y) -> void;
|
auto plot(uint8 x, uint8 y) -> void override;
|
||||||
auto rpix(uint8 x, uint8 y) -> uint8;
|
auto rpix(uint8 x, uint8 y) -> uint8 override;
|
||||||
auto pixelcache_flush(pixelcache_t& cache) -> void;
|
|
||||||
|
auto flushPixelCache(PixelCache& cache) -> void;
|
||||||
|
|
||||||
//memory.cpp
|
//memory.cpp
|
||||||
auto bus_read(uint24 addr, uint8 data = 0x00) -> uint8 override;
|
auto read(uint24 addr, uint8 data = 0x00) -> uint8 override;
|
||||||
auto bus_write(uint24 addr, uint8 data) -> void override;
|
auto write(uint24 addr, uint8 data) -> void override;
|
||||||
|
|
||||||
auto op_read(uint16 addr) -> uint8;
|
auto readOpcode(uint16 addr) -> uint8;
|
||||||
alwaysinline auto peekpipe() -> uint8;
|
alwaysinline auto peekpipe() -> uint8;
|
||||||
alwaysinline auto pipe() -> uint8;
|
alwaysinline auto pipe() -> uint8 override;
|
||||||
|
|
||||||
auto cache_flush() -> void;
|
auto flushCache() -> void override;
|
||||||
auto cache_mmio_read(uint16 addr) -> uint8;
|
auto readCache(uint16 addr) -> uint8;
|
||||||
auto cache_mmio_write(uint16 addr, uint8 data) -> void;
|
auto writeCache(uint16 addr, uint8 data) -> void;
|
||||||
|
|
||||||
auto memory_reset() -> void;
|
|
||||||
|
|
||||||
//mmio.cpp
|
//mmio.cpp
|
||||||
auto readIO(uint24 addr, uint8 data) -> uint8;
|
auto readIO(uint24 addr, uint8 data) -> uint8;
|
||||||
auto writeIO(uint24 addr, uint8 data) -> void;
|
auto writeIO(uint24 addr, uint8 data) -> void;
|
||||||
|
|
||||||
//timing.cpp
|
//timing.cpp
|
||||||
auto step(uint clocks) -> void;
|
auto step(uint clocks) -> void override;
|
||||||
|
|
||||||
auto rombuffer_sync() -> void;
|
auto syncROMBuffer() -> void override;
|
||||||
auto rombuffer_update() -> void;
|
auto readROMBuffer() -> uint8 override;
|
||||||
auto rombuffer_read() -> uint8;
|
auto updateROMBuffer() -> void;
|
||||||
|
|
||||||
auto rambuffer_sync() -> void;
|
auto syncRAMBuffer() -> void override;
|
||||||
auto rambuffer_read(uint16 addr) -> uint8;
|
auto readRAMBuffer(uint16 addr) -> uint8 override;
|
||||||
auto rambuffer_write(uint16 addr, uint8 data) -> void;
|
auto writeRAMBuffer(uint16 addr, uint8 data) -> void override;
|
||||||
|
|
||||||
auto r14_modify(uint16) -> void;
|
|
||||||
auto r15_modify(uint16) -> void;
|
|
||||||
|
|
||||||
auto timing_reset() -> void;
|
|
||||||
|
|
||||||
//serialization.cpp
|
//serialization.cpp
|
||||||
auto serialize(serializer&) -> void;
|
auto serialize(serializer&) -> void;
|
||||||
|
@ -72,10 +66,8 @@ struct SuperFX : Processor::GSU, Cothread {
|
||||||
CPURAM cpuram;
|
CPURAM cpuram;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint rom_mask; //rom_size - 1
|
uint romMask;
|
||||||
uint ram_mask; //ram_size - 1
|
uint ramMask;
|
||||||
|
|
||||||
bool r15_modified = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SuperFX superfx;
|
extern SuperFX superfx;
|
||||||
|
|
|
@ -3,14 +3,14 @@ auto SuperFX::step(uint clocks) -> void {
|
||||||
regs.romcl -= min(clocks, regs.romcl);
|
regs.romcl -= min(clocks, regs.romcl);
|
||||||
if(regs.romcl == 0) {
|
if(regs.romcl == 0) {
|
||||||
regs.sfr.r = 0;
|
regs.sfr.r = 0;
|
||||||
regs.romdr = bus_read((regs.rombr << 16) + regs.r[14]);
|
regs.romdr = read((regs.rombr << 16) + regs.r[14]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.ramcl) {
|
if(regs.ramcl) {
|
||||||
regs.ramcl -= min(clocks, regs.ramcl);
|
regs.ramcl -= min(clocks, regs.ramcl);
|
||||||
if(regs.ramcl == 0) {
|
if(regs.ramcl == 0) {
|
||||||
bus_write(0x700000 + (regs.rambr << 16) + regs.ramar, regs.ramdr);
|
write(0x700000 + (regs.rambr << 16) + regs.ramar, regs.ramdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,53 +18,32 @@ auto SuperFX::step(uint clocks) -> void {
|
||||||
synchronizeCPU();
|
synchronizeCPU();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::rombuffer_sync() -> void {
|
auto SuperFX::syncROMBuffer() -> void {
|
||||||
if(regs.romcl) step(regs.romcl);
|
if(regs.romcl) step(regs.romcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::rombuffer_update() -> void {
|
auto SuperFX::readROMBuffer() -> uint8 {
|
||||||
|
syncROMBuffer();
|
||||||
|
return regs.romdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SuperFX::updateROMBuffer() -> void {
|
||||||
regs.sfr.r = 1;
|
regs.sfr.r = 1;
|
||||||
regs.romcl = regs.clsr ? 5 : 6;
|
regs.romcl = regs.clsr ? 5 : 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::rombuffer_read() -> uint8 {
|
auto SuperFX::syncRAMBuffer() -> void {
|
||||||
rombuffer_sync();
|
|
||||||
return regs.romdr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperFX::rambuffer_sync() -> void {
|
|
||||||
if(regs.ramcl) step(regs.ramcl);
|
if(regs.ramcl) step(regs.ramcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::rambuffer_read(uint16 addr) -> uint8 {
|
auto SuperFX::readRAMBuffer(uint16 addr) -> uint8 {
|
||||||
rambuffer_sync();
|
syncRAMBuffer();
|
||||||
return bus_read(0x700000 + (regs.rambr << 16) + addr);
|
return read(0x700000 + (regs.rambr << 16) + addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::rambuffer_write(uint16 addr, uint8 data) -> void {
|
auto SuperFX::writeRAMBuffer(uint16 addr, uint8 data) -> void {
|
||||||
rambuffer_sync();
|
syncRAMBuffer();
|
||||||
regs.ramcl = regs.clsr ? 5 : 6;
|
regs.ramcl = regs.clsr ? 5 : 6;
|
||||||
regs.ramar = addr;
|
regs.ramar = addr;
|
||||||
regs.ramdr = data;
|
regs.ramdr = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SuperFX::r14_modify(uint16 data) -> void {
|
|
||||||
regs.r[14].data = data;
|
|
||||||
rombuffer_update();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperFX::r15_modify(uint16 data) -> void {
|
|
||||||
regs.r[15].data = data;
|
|
||||||
r15_modified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto SuperFX::timing_reset() -> void {
|
|
||||||
r15_modified = false;
|
|
||||||
|
|
||||||
regs.romcl = 0;
|
|
||||||
regs.romdr = 0;
|
|
||||||
|
|
||||||
regs.ramcl = 0;
|
|
||||||
regs.ramar = 0;
|
|
||||||
regs.ramdr = 0;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue