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 {
|
||||
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 License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -14,10 +14,10 @@ auto CPU::Enter() -> void {
|
|||
|
||||
auto CPU::main() -> void {
|
||||
interrupt_test();
|
||||
exec();
|
||||
instruction();
|
||||
}
|
||||
|
||||
auto CPU::interrupt_raise(CPU::Interrupt id) -> void {
|
||||
auto CPU::raise(CPU::Interrupt id) -> void {
|
||||
if(id == Interrupt::Vblank) {
|
||||
status.interrupt_request_vblank = 1;
|
||||
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 {
|
||||
if(!r.ime) return;
|
||||
|
||||
if(status.interrupt_request_vblank && status.interrupt_enable_vblank) {
|
||||
status.interrupt_request_vblank = 0;
|
||||
return interrupt_exec(0x0040);
|
||||
return interrupt(0x0040);
|
||||
}
|
||||
|
||||
if(status.interrupt_request_stat && status.interrupt_enable_stat) {
|
||||
status.interrupt_request_stat = 0;
|
||||
return interrupt_exec(0x0048);
|
||||
return interrupt(0x0048);
|
||||
}
|
||||
|
||||
if(status.interrupt_request_timer && status.interrupt_enable_timer) {
|
||||
status.interrupt_request_timer = 0;
|
||||
return interrupt_exec(0x0050);
|
||||
return interrupt(0x0050);
|
||||
}
|
||||
|
||||
if(status.interrupt_request_serial && status.interrupt_enable_serial) {
|
||||
status.interrupt_request_serial = 0;
|
||||
return interrupt_exec(0x0058);
|
||||
return interrupt(0x0058);
|
||||
}
|
||||
|
||||
if(status.interrupt_request_joypad && status.interrupt_enable_joypad) {
|
||||
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 {
|
||||
if(status.speed_switch) {
|
||||
status.speed_switch = 0;
|
||||
|
|
|
@ -3,10 +3,8 @@ struct CPU : Processor::LR35902, Thread, MMIO {
|
|||
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto interrupt_raise(Interrupt id) -> void;
|
||||
auto interrupt_lower(Interrupt id) -> void;
|
||||
auto raise(Interrupt id) -> void;
|
||||
auto interrupt_test() -> void;
|
||||
auto interrupt_exec(uint16 pc) -> void;
|
||||
auto stop() -> bool;
|
||||
auto power() -> void;
|
||||
|
||||
|
@ -19,9 +17,9 @@ struct CPU : Processor::LR35902, Thread, MMIO {
|
|||
auto mmio_write(uint16 addr, uint8 data) -> void;
|
||||
|
||||
//memory.cpp
|
||||
auto op_io() -> void;
|
||||
auto op_read(uint16 addr) -> uint8;
|
||||
auto op_write(uint16 addr, uint8 data) -> void;
|
||||
auto io() -> void override;
|
||||
auto read(uint16 addr) -> uint8 override;
|
||||
auto write(uint16 addr, uint8 data) -> void override;
|
||||
auto cycle_edge() -> void;
|
||||
auto dma_read(uint16 addr) -> uint8;
|
||||
auto dma_write(uint16 addr, uint8 data) -> void;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
auto CPU::op_io() -> void {
|
||||
auto CPU::io() -> void {
|
||||
cycle_edge();
|
||||
add_clocks(4);
|
||||
}
|
||||
|
||||
auto CPU::op_read(uint16 addr) -> uint8 {
|
||||
auto CPU::read(uint16 addr) -> uint8 {
|
||||
cycle_edge();
|
||||
add_clocks(4);
|
||||
return bus.read(addr);
|
||||
}
|
||||
|
||||
auto CPU::op_write(uint16 addr, uint8 data) -> void {
|
||||
auto CPU::write(uint16 addr, uint8 data) -> void {
|
||||
cycle_edge();
|
||||
add_clocks(4);
|
||||
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 == 0) status.joyp &= button ^ 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 {
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
// 154 scanlines/frame
|
||||
|
||||
auto CPU::add_clocks(uint clocks) -> void {
|
||||
if(system.sgb()) system._clocksExecuted += clocks;
|
||||
|
||||
while(clocks--) {
|
||||
for(auto n : range(clocks)) {
|
||||
if(++status.clock == 0) {
|
||||
cartridge.mbc3.second();
|
||||
}
|
||||
|
@ -25,14 +23,17 @@ auto CPU::add_clocks(uint clocks) -> void {
|
|||
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 {
|
||||
if(status.timer_enable && status.timer_clock == 1) {
|
||||
if(++status.tima == 0) {
|
||||
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.tima == 0) {
|
||||
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.tima == 0) {
|
||||
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_bits == 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.tima == 0) {
|
||||
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 {
|
||||
px = 0;
|
||||
if(!enabled()) return;
|
||||
|
||||
const uint Height = (status.ob_size == 0 ? 8 : 16);
|
||||
sprites = 0;
|
||||
|
@ -68,7 +69,7 @@ auto PPU::cgb_run() -> void {
|
|||
ob.priority = 0;
|
||||
|
||||
uint color = 0x7fff;
|
||||
if(status.display_enable) {
|
||||
if(enabled()) {
|
||||
cgb_run_bg();
|
||||
if(status.window_display_enable) cgb_run_window();
|
||||
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 {
|
||||
px = 0;
|
||||
if(!enabled()) return;
|
||||
|
||||
const uint Height = (status.ob_size == 0 ? 8 : 16);
|
||||
sprites = 0;
|
||||
|
@ -59,7 +60,7 @@ auto PPU::dmg_run() -> void {
|
|||
ob.palette = 0;
|
||||
|
||||
uint color = 0;
|
||||
if(status.display_enable) {
|
||||
if(enabled()) {
|
||||
if(status.bg_enable) dmg_run_bg();
|
||||
if(status.window_display_enable) dmg_run_window();
|
||||
if(status.ob_enable) dmg_run_ob();
|
||||
|
|
|
@ -8,6 +8,8 @@ PPU ppu;
|
|||
#include "cgb.cpp"
|
||||
#include "serialization.cpp"
|
||||
|
||||
auto PPU::enabled() const -> bool { return status.display_enable; }
|
||||
|
||||
auto PPU::Enter() -> void {
|
||||
while(true) scheduler.synchronize(), ppu.main();
|
||||
}
|
||||
|
@ -16,7 +18,7 @@ auto PPU::main() -> void {
|
|||
status.lx = 0;
|
||||
interface->lcdScanline(); //Super Game Boy notification
|
||||
|
||||
if(status.display_enable && status.ly <= 143) {
|
||||
if(status.ly <= 143) {
|
||||
mode(2);
|
||||
scanline();
|
||||
wait(92);
|
||||
|
@ -28,7 +30,7 @@ auto PPU::main() -> void {
|
|||
}
|
||||
|
||||
mode(0);
|
||||
cpu.hblank();
|
||||
if(enabled()) cpu.hblank();
|
||||
wait(204);
|
||||
} else {
|
||||
mode(1);
|
||||
|
@ -38,7 +40,7 @@ auto PPU::main() -> void {
|
|||
status.ly++;
|
||||
|
||||
if(status.ly == 144) {
|
||||
cpu.interrupt_raise(CPU::Interrupt::Vblank);
|
||||
if(enabled()) cpu.raise(CPU::Interrupt::Vblank);
|
||||
scheduler.exit(Scheduler::Event::Frame);
|
||||
}
|
||||
|
||||
|
@ -48,35 +50,25 @@ auto PPU::main() -> void {
|
|||
}
|
||||
|
||||
auto PPU::mode(uint mode) -> void {
|
||||
if(!enabled()) mode = 1; //force blank
|
||||
status.mode = mode;
|
||||
}
|
||||
|
||||
auto PPU::stat() -> void {
|
||||
bool irq = status.irq;
|
||||
|
||||
if(status.mode == 0) { //hblank
|
||||
status.irq = status.interrupt_hblank;
|
||||
}
|
||||
status.irq = status.interrupt_hblank && status.mode == 0;
|
||||
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
|
||||
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);
|
||||
}
|
||||
if(!irq && status.irq) cpu.raise(CPU::Interrupt::Stat);
|
||||
}
|
||||
|
||||
auto PPU::coincidence() -> bool {
|
||||
//LYC of zero triggers on LYC=153
|
||||
return (status.lyc && status.ly == status.lyc) || (!status.lyc && status.ly == 153);
|
||||
uint ly = status.ly;
|
||||
if(ly == 153 && status.lx >= 92) ly = 0; //LYC=0 triggers early during LY=153
|
||||
return ly == status.lyc;
|
||||
}
|
||||
|
||||
auto PPU::refresh() -> void {
|
||||
|
@ -85,6 +77,7 @@ auto PPU::refresh() -> void {
|
|||
|
||||
auto PPU::wait(uint clocks) -> void {
|
||||
while(clocks--) {
|
||||
stat();
|
||||
if(status.dma_active) {
|
||||
uint hi = status.dma_clock++;
|
||||
uint lo = hi & (cpu.status.speed_double ? 1 : 3);
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
struct PPU : Thread, MMIO {
|
||||
auto enabled() const -> bool;
|
||||
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto mode(uint) -> void;
|
||||
auto stat() -> void;
|
||||
auto coincidence() -> bool;
|
||||
auto refresh() -> 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;
|
||||
|
||||
if(!regs.sfr.alt2) {
|
||||
if(!regs.sfr.alt1) {
|
||||
disassemble_alt0(output);
|
||||
} else {
|
||||
disassemble_alt1(output);
|
||||
}
|
||||
} else {
|
||||
if(!regs.sfr.alt1) {
|
||||
disassemble_alt2(output);
|
||||
} else {
|
||||
disassemble_alt3(output);
|
||||
}
|
||||
switch(regs.sfr.alt2 << 1 | regs.sfr.alt1 << 0) {
|
||||
case 0: disassembleAlt0(output); break;
|
||||
case 1: disassembleAlt1(output); break;
|
||||
case 2: disassembleAlt2(output); break;
|
||||
case 3: disassembleAlt3(output); break;
|
||||
}
|
||||
|
||||
unsigned length = strlen(output);
|
||||
uint length = strlen(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
|
||||
|
||||
#define op0 regs.pipeline
|
||||
#define op1 bus_read((regs.pbr << 16) + regs.r[15] + 0)
|
||||
#define op2 bus_read((regs.pbr << 16) + regs.r[15] + 1)
|
||||
#define op1 read((regs.pbr << 16) + regs.r[15] + 0)
|
||||
#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] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
|
@ -94,7 +87,7 @@ auto GSU::disassemble_alt0(char* output) -> void {
|
|||
strcat(output, t);
|
||||
}
|
||||
|
||||
auto GSU::disassemble_alt1(char* output) -> void {
|
||||
auto GSU::disassembleAlt1(char* output) -> void {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
|
@ -151,7 +144,7 @@ auto GSU::disassemble_alt1(char* output) -> void {
|
|||
strcat(output, t);
|
||||
}
|
||||
|
||||
auto GSU::disassemble_alt2(char* output) -> void {
|
||||
auto GSU::disassembleAlt2(char* output) -> void {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
|
@ -208,7 +201,7 @@ auto GSU::disassemble_alt2(char* output) -> void {
|
|||
strcat(output, t);
|
||||
}
|
||||
|
||||
auto GSU::disassemble_alt3(char* output) -> void {
|
||||
auto GSU::disassembleAlt3(char* output) -> void {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
|
|
|
@ -16,7 +16,11 @@ auto GSU::power() -> 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.pbr = 0x00;
|
||||
regs.rombr = 0x00;
|
||||
|
|
|
@ -13,15 +13,15 @@ struct GSU {
|
|||
virtual auto rpix(uint8 x, uint8 y) -> uint8 = 0;
|
||||
|
||||
virtual auto pipe() -> uint8 = 0;
|
||||
virtual auto rombuffer_sync() -> void = 0;
|
||||
virtual auto rombuffer_read() -> uint8 = 0;
|
||||
virtual auto rambuffer_sync() -> void = 0;
|
||||
virtual auto rambuffer_read(uint16 addr) -> uint8 = 0;
|
||||
virtual auto rambuffer_write(uint16 addr, uint8 data) -> void = 0;
|
||||
virtual auto cache_flush() -> void = 0;
|
||||
virtual auto syncROMBuffer() -> void = 0;
|
||||
virtual auto readROMBuffer() -> uint8 = 0;
|
||||
virtual auto syncRAMBuffer() -> void = 0;
|
||||
virtual auto readRAMBuffer(uint16 addr) -> uint8 = 0;
|
||||
virtual auto writeRAMBuffer(uint16 addr, uint8 data) -> void = 0;
|
||||
virtual auto flushCache() -> void = 0;
|
||||
|
||||
virtual auto bus_read(uint24 addr, uint8 data = 0x00) -> uint8 = 0;
|
||||
virtual auto bus_write(uint24 addr, uint8 data) -> void = 0;
|
||||
virtual auto read(uint24 addr, uint8 data = 0x00) -> uint8 = 0;
|
||||
virtual auto write(uint24 addr, uint8 data) -> void = 0;
|
||||
|
||||
//gsu.cpp
|
||||
auto power() -> void;
|
||||
|
@ -76,11 +76,11 @@ struct GSU {
|
|||
auto serialize(serializer&) -> void;
|
||||
|
||||
//disassembler.cpp
|
||||
auto disassemble_opcode(char* output) -> void;
|
||||
auto disassemble_alt0(char* output) -> void;
|
||||
auto disassemble_alt1(char* output) -> void;
|
||||
auto disassemble_alt2(char* output) -> void;
|
||||
auto disassemble_alt3(char* output) -> void;
|
||||
auto disassembleOpcode(char* output) -> void;
|
||||
auto disassembleAlt0(char* output) -> void;
|
||||
auto disassembleAlt1(char* output) -> void;
|
||||
auto disassembleAlt2(char* output) -> void;
|
||||
auto disassembleAlt3(char* output) -> void;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ auto GSU::op_nop() {
|
|||
auto GSU::op_cache() {
|
||||
if(regs.cbr != (regs.r[15] & 0xfff0)) {
|
||||
regs.cbr = regs.r[15] & 0xfff0;
|
||||
cache_flush();
|
||||
flushCache();
|
||||
}
|
||||
regs.reset();
|
||||
}
|
||||
|
@ -80,8 +80,8 @@ auto GSU::op_with(uint n) {
|
|||
//$30-3b(alt1) stb (rN)
|
||||
auto GSU::op_store(uint n) {
|
||||
regs.ramaddr = regs.r[n];
|
||||
rambuffer_write(regs.ramaddr, regs.sr());
|
||||
if(!regs.sfr.alt1) rambuffer_write(regs.ramaddr ^ 1, regs.sr() >> 8);
|
||||
writeRAMBuffer(regs.ramaddr, regs.sr());
|
||||
if(!regs.sfr.alt1) writeRAMBuffer(regs.ramaddr ^ 1, regs.sr() >> 8);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,8 @@ auto GSU::op_alt3() {
|
|||
//$40-4b(alt1) ldb (rN)
|
||||
auto GSU::op_load(uint n) {
|
||||
regs.ramaddr = regs.r[n];
|
||||
regs.dr() = rambuffer_read(regs.ramaddr);
|
||||
if(!regs.sfr.alt1) regs.dr() |= rambuffer_read(regs.ramaddr ^ 1) << 8;
|
||||
regs.dr() = readRAMBuffer(regs.ramaddr);
|
||||
if(!regs.sfr.alt1) regs.dr() |= readRAMBuffer(regs.ramaddr ^ 1) << 8;
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
|
@ -230,8 +230,8 @@ auto GSU::op_mult_umult(uint n) {
|
|||
|
||||
//$90 sbk
|
||||
auto GSU::op_sbk() {
|
||||
rambuffer_write(regs.ramaddr ^ 0, regs.sr() >> 0);
|
||||
rambuffer_write(regs.ramaddr ^ 1, regs.sr() >> 8);
|
||||
writeRAMBuffer(regs.ramaddr ^ 0, regs.sr() >> 0);
|
||||
writeRAMBuffer(regs.ramaddr ^ 1, regs.sr() >> 8);
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ auto GSU::op_jmp_ljmp(uint n) {
|
|||
regs.pbr = regs.r[n] & 0x7f;
|
||||
regs.r[15] = regs.sr();
|
||||
regs.cbr = regs.r[15] & 0xfff0;
|
||||
cache_flush();
|
||||
flushCache();
|
||||
}
|
||||
regs.reset();
|
||||
}
|
||||
|
@ -310,12 +310,12 @@ auto GSU::op_fmult_lmult() {
|
|||
auto GSU::op_ibt_lms_sms(uint n) {
|
||||
if(regs.sfr.alt1) {
|
||||
regs.ramaddr = pipe() << 1;
|
||||
uint8 lo = rambuffer_read(regs.ramaddr ^ 0) << 0;
|
||||
regs.r[n] = rambuffer_read(regs.ramaddr ^ 1) << 8 | lo;
|
||||
uint8 lo = readRAMBuffer(regs.ramaddr ^ 0) << 0;
|
||||
regs.r[n] = readRAMBuffer(regs.ramaddr ^ 1) << 8 | lo;
|
||||
} else if(regs.sfr.alt2) {
|
||||
regs.ramaddr = pipe() << 1;
|
||||
rambuffer_write(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
||||
rambuffer_write(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
||||
writeRAMBuffer(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
||||
writeRAMBuffer(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
||||
} else {
|
||||
regs.r[n] = (int8)pipe();
|
||||
}
|
||||
|
@ -369,12 +369,12 @@ auto GSU::op_inc(uint n) {
|
|||
//$df(alt3) romb
|
||||
auto GSU::op_getc_ramb_romb() {
|
||||
if(!regs.sfr.alt2) {
|
||||
regs.colr = color(rombuffer_read());
|
||||
regs.colr = color(readROMBuffer());
|
||||
} else if(!regs.sfr.alt1) {
|
||||
rambuffer_sync();
|
||||
syncRAMBuffer();
|
||||
regs.rambr = regs.sr() & 0x01;
|
||||
} else {
|
||||
rombuffer_sync();
|
||||
syncROMBuffer();
|
||||
regs.rombr = regs.sr() & 0x7f;
|
||||
}
|
||||
regs.reset();
|
||||
|
@ -394,10 +394,10 @@ auto GSU::op_dec(uint n) {
|
|||
//$ef(alt3) getbs
|
||||
auto GSU::op_getb() {
|
||||
switch(regs.sfr.alt2 << 1 | regs.sfr.alt1 << 0) {
|
||||
case 0: regs.dr() = rombuffer_read(); break;
|
||||
case 1: regs.dr() = rombuffer_read() << 8 | (uint8)regs.sr(); break;
|
||||
case 2: regs.dr() = (regs.sr() & 0xff00) | rombuffer_read(); break;
|
||||
case 3: regs.dr() = (int8)rombuffer_read(); break;
|
||||
case 0: regs.dr() = readROMBuffer(); break;
|
||||
case 1: regs.dr() = readROMBuffer() << 8 | (uint8)regs.sr(); break;
|
||||
case 2: regs.dr() = (regs.sr() & 0xff00) | readROMBuffer(); break;
|
||||
case 3: regs.dr() = (int8)readROMBuffer(); break;
|
||||
}
|
||||
regs.reset();
|
||||
}
|
||||
|
@ -409,13 +409,13 @@ auto GSU::op_iwt_lm_sm(uint n) {
|
|||
if(regs.sfr.alt1) {
|
||||
regs.ramaddr = pipe() << 0;
|
||||
regs.ramaddr |= pipe() << 8;
|
||||
uint8 lo = rambuffer_read(regs.ramaddr ^ 0) << 0;
|
||||
regs.r[n] = rambuffer_read(regs.ramaddr ^ 1) << 8 | lo;
|
||||
uint8 lo = readRAMBuffer(regs.ramaddr ^ 0) << 0;
|
||||
regs.r[n] = readRAMBuffer(regs.ramaddr ^ 1) << 8 | lo;
|
||||
} else if(regs.sfr.alt2) {
|
||||
regs.ramaddr = pipe() << 0;
|
||||
regs.ramaddr |= pipe() << 8;
|
||||
rambuffer_write(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
||||
rambuffer_write(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
||||
writeRAMBuffer(regs.ramaddr ^ 0, regs.r[n] >> 0);
|
||||
writeRAMBuffer(regs.ramaddr ^ 1, regs.r[n] >> 8);
|
||||
} else {
|
||||
uint8 lo = pipe();
|
||||
regs.r[n] = pipe() << 8 | lo;
|
||||
|
|
|
@ -1,41 +1,39 @@
|
|||
//accepts a callback binding so r14 writes can trigger ROM buffering transparently
|
||||
struct reg16_t {
|
||||
struct Register {
|
||||
uint16 data = 0;
|
||||
function<auto (uint16) -> void> modify;
|
||||
bool modified = false;
|
||||
|
||||
inline operator unsigned() const {
|
||||
inline operator uint() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
inline auto assign(uint16 i) -> uint16 {
|
||||
if(modify) modify(i);
|
||||
else data = i;
|
||||
return data;
|
||||
inline auto assign(uint value) -> uint16 {
|
||||
modified = true;
|
||||
return data = value;
|
||||
}
|
||||
|
||||
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) { unsigned r = data; assign(data - 1); return r; }
|
||||
inline auto operator = (unsigned i) { return assign(i); }
|
||||
inline auto operator |= (unsigned i) { return assign(data | i); }
|
||||
inline auto operator ^= (unsigned i) { return assign(data ^ i); }
|
||||
inline auto operator &= (unsigned i) { return assign(data & i); }
|
||||
inline auto operator <<= (unsigned i) { return assign(data << i); }
|
||||
inline auto operator >>= (unsigned i) { return assign(data >> i); }
|
||||
inline auto operator += (unsigned i) { return assign(data + i); }
|
||||
inline auto operator -= (unsigned i) { return assign(data - i); }
|
||||
inline auto operator *= (unsigned i) { return assign(data * i); }
|
||||
inline auto operator /= (unsigned i) { return assign(data / i); }
|
||||
inline auto operator %= (unsigned i) { return assign(data % i); }
|
||||
inline auto operator++(int) { uint r = data; assign(data + 1); return r; }
|
||||
inline auto operator--(int) { uint r = data; assign(data - 1); return r; }
|
||||
inline auto operator = (uint i) { return assign(i); }
|
||||
inline auto operator |= (uint i) { return assign(data | i); }
|
||||
inline auto operator ^= (uint i) { return assign(data ^ i); }
|
||||
inline auto operator &= (uint i) { return assign(data & i); }
|
||||
inline auto operator <<= (uint i) { return assign(data << i); }
|
||||
inline auto operator >>= (uint i) { return assign(data >> i); }
|
||||
inline auto operator += (uint i) { return assign(data + i); }
|
||||
inline auto operator -= (uint i) { return assign(data - i); }
|
||||
inline auto operator *= (uint i) { return assign(data * i); }
|
||||
inline auto operator /= (uint 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;
|
||||
reg16_t(const reg16_t&) = delete;
|
||||
Register() = default;
|
||||
Register(const Register&) = delete;
|
||||
};
|
||||
|
||||
struct sfr_t {
|
||||
struct SFR {
|
||||
bool irq; //interrupt flag
|
||||
bool b; //WITH flag
|
||||
bool ih; //immediate higher 8-bit flag
|
||||
|
@ -49,12 +47,12 @@ struct sfr_t {
|
|||
bool cy; //carry flag
|
||||
bool z; //zero flag
|
||||
|
||||
operator unsigned() const {
|
||||
operator uint() const {
|
||||
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);
|
||||
}
|
||||
|
||||
auto& operator=(uint16_t data) {
|
||||
auto& operator=(uint data) {
|
||||
irq = data & 0x8000;
|
||||
b = data & 0x1000;
|
||||
ih = data & 0x0800;
|
||||
|
@ -71,17 +69,17 @@ struct sfr_t {
|
|||
}
|
||||
};
|
||||
|
||||
struct scmr_t {
|
||||
unsigned ht;
|
||||
struct SCMR {
|
||||
uint ht;
|
||||
bool ron;
|
||||
bool ran;
|
||||
unsigned md;
|
||||
uint md;
|
||||
|
||||
operator unsigned() const {
|
||||
operator uint() const {
|
||||
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 & 0x04) << 0;
|
||||
ron = data & 0x10;
|
||||
|
@ -91,18 +89,18 @@ struct scmr_t {
|
|||
}
|
||||
};
|
||||
|
||||
struct por_t {
|
||||
struct POR {
|
||||
bool obj;
|
||||
bool freezehigh;
|
||||
bool highnibble;
|
||||
bool dither;
|
||||
bool transparent;
|
||||
|
||||
operator unsigned() const {
|
||||
operator uint() const {
|
||||
return (obj << 4) | (freezehigh << 3) | (highnibble << 2) | (dither << 1) | (transparent);
|
||||
}
|
||||
|
||||
auto& operator=(uint8 data) {
|
||||
auto& operator=(uint data) {
|
||||
obj = data & 0x10;
|
||||
freezehigh = data & 0x08;
|
||||
highnibble = data & 0x04;
|
||||
|
@ -112,48 +110,49 @@ struct por_t {
|
|||
}
|
||||
};
|
||||
|
||||
struct cfgr_t {
|
||||
struct CFGR {
|
||||
bool irq;
|
||||
bool ms0;
|
||||
|
||||
operator unsigned() const {
|
||||
operator uint() const {
|
||||
return (irq << 7) | (ms0 << 5);
|
||||
}
|
||||
|
||||
auto& operator=(uint8 data) {
|
||||
auto& operator=(uint data) {
|
||||
irq = data & 0x80;
|
||||
ms0 = data & 0x20;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct regs_t {
|
||||
struct Registers {
|
||||
uint8 pipeline;
|
||||
uint16 ramaddr;
|
||||
|
||||
reg16_t r[16]; //general purpose registers
|
||||
sfr_t sfr; //status flag register
|
||||
Register r[16]; //general purpose registers
|
||||
SFR sfr; //status flag register
|
||||
uint8 pbr; //program bank register
|
||||
uint8 rombr; //game pack ROM bank register
|
||||
bool rambr; //game pack RAM bank register
|
||||
uint16 cbr; //cache base register
|
||||
uint8 scbr; //screen base register
|
||||
scmr_t scmr; //screen mode register
|
||||
SCMR scmr; //screen mode register
|
||||
uint8 colr; //color register
|
||||
por_t por; //plot option register
|
||||
POR por; //plot option register
|
||||
bool bramr; //back-up RAM register
|
||||
uint8 vcr; //version code register
|
||||
cfgr_t cfgr; //config register
|
||||
CFGR cfgr; //config 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
|
||||
|
||||
unsigned ramcl; //clock ticks until ramdr is valid
|
||||
uint ramcl; //clock ticks until ramdr is valid
|
||||
uint16 ramar; //RAM buffer address register
|
||||
uint8 ramdr; //RAM buffer data register
|
||||
|
||||
unsigned sreg, dreg;
|
||||
uint sreg;
|
||||
uint dreg;
|
||||
auto& sr() { return r[sreg]; } //source register (from)
|
||||
auto& dr() { return r[dreg]; } //destination register (to)
|
||||
|
||||
|
@ -167,12 +166,12 @@ struct regs_t {
|
|||
}
|
||||
} regs;
|
||||
|
||||
struct cache_t {
|
||||
struct Cache {
|
||||
uint8 buffer[512];
|
||||
bool valid[32];
|
||||
} cache;
|
||||
|
||||
struct pixelcache_t {
|
||||
struct PixelCache {
|
||||
uint16 offset;
|
||||
uint8 bitpend;
|
||||
uint8 data[8];
|
||||
|
|
|
@ -2,22 +2,10 @@ auto GSU::serialize(serializer& s) -> void {
|
|||
s.integer(regs.pipeline);
|
||||
s.integer(regs.ramaddr);
|
||||
|
||||
s.integer(regs.r[ 0].data);
|
||||
s.integer(regs.r[ 1].data);
|
||||
s.integer(regs.r[ 2].data);
|
||||
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);
|
||||
for(auto n : range(16)) {
|
||||
s.integer(regs.r[n].data);
|
||||
s.integer(regs.r[n].modified);
|
||||
}
|
||||
|
||||
s.integer(regs.sfr.irq);
|
||||
s.integer(regs.sfr.b);
|
||||
|
@ -72,9 +60,9 @@ auto GSU::serialize(serializer& s) -> void {
|
|||
s.array(cache.buffer);
|
||||
s.array(cache.valid);
|
||||
|
||||
for(unsigned i = 0; i < 2; i++) {
|
||||
s.integer(pixelcache[i].offset);
|
||||
s.integer(pixelcache[i].bitpend);
|
||||
s.array(pixelcache[i].data);
|
||||
for(uint n : range(2)) {
|
||||
s.integer(pixelcache[n].offset);
|
||||
s.integer(pixelcache[n].bitpend);
|
||||
s.array(pixelcache[n].data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@ auto LR35902::disassemble(uint16 pc) -> string {
|
|||
}
|
||||
|
||||
auto LR35902::disassembleOpcode(uint16 pc) -> string {
|
||||
uint8 opcode = debugger_read(pc);
|
||||
uint8 p0 = debugger_read(pc + 1);
|
||||
uint8 p1 = debugger_read(pc + 2);
|
||||
uint8 p2 = debugger_read(pc + 3);
|
||||
uint8 opcode = debuggerRead(pc);
|
||||
uint8 p0 = debuggerRead(pc + 1);
|
||||
uint8 p1 = debuggerRead(pc + 2);
|
||||
uint8 p2 = debuggerRead(pc + 3);
|
||||
|
||||
switch(opcode) {
|
||||
case 0x00: return { "nop" };
|
||||
|
@ -288,10 +288,10 @@ auto LR35902::disassembleOpcode(uint16 pc) -> string {
|
|||
}
|
||||
|
||||
auto LR35902::disassembleOpcodeCB(uint16 pc) -> string {
|
||||
uint8 opcode = debugger_read(pc);
|
||||
uint8 p0 = debugger_read(pc + 1);
|
||||
uint8 p1 = debugger_read(pc + 2);
|
||||
uint8 p2 = debugger_read(pc + 3);
|
||||
uint8 opcode = debuggerRead(pc);
|
||||
uint8 p0 = debuggerRead(pc + 1);
|
||||
uint8 p1 = debuggerRead(pc + 2);
|
||||
uint8 p2 = debuggerRead(pc + 3);
|
||||
|
||||
switch(opcode) {
|
||||
case 0x00: return { "rlc b" };
|
||||
|
|
|
@ -2,7 +2,7 @@ auto LR35902::op_xx() {
|
|||
}
|
||||
|
||||
auto LR35902::op_cb() {
|
||||
execCB();
|
||||
instructionCB();
|
||||
}
|
||||
|
||||
//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) {
|
||||
r[x] = op_read(r[PC]++);
|
||||
r[x] = read(r[PC]++);
|
||||
}
|
||||
|
||||
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) {
|
||||
op_write(r[HL], r[x]);
|
||||
write(r[HL], r[x]);
|
||||
}
|
||||
|
||||
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) {
|
||||
r[A] = op_read(r[x]);
|
||||
r[A] = read(r[x]);
|
||||
}
|
||||
|
||||
auto LR35902::op_ld_a_nn() {
|
||||
uint8 lo = op_read(r[PC]++);
|
||||
uint8 hi = op_read(r[PC]++);
|
||||
r[A] = op_read((hi << 8) | (lo << 0));
|
||||
uint8 lo = read(r[PC]++);
|
||||
uint8 hi = read(r[PC]++);
|
||||
r[A] = read((hi << 8) | (lo << 0));
|
||||
}
|
||||
|
||||
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() {
|
||||
uint8 lo = op_read(r[PC]++);
|
||||
uint8 hi = op_read(r[PC]++);
|
||||
op_write((hi << 8) | (lo << 0), r[A]);
|
||||
uint8 lo = read(r[PC]++);
|
||||
uint8 hi = read(r[PC]++);
|
||||
write((hi << 8) | (lo << 0), r[A]);
|
||||
}
|
||||
|
||||
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() {
|
||||
op_write(0xff00 + op_read(r[PC]++), r[A]);
|
||||
write(0xff00 + read(r[PC]++), r[A]);
|
||||
}
|
||||
|
||||
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() {
|
||||
op_write(0xff00 + r[C], r[A]);
|
||||
write(0xff00 + r[C], r[A]);
|
||||
}
|
||||
|
||||
auto LR35902::op_ldi_hl_a() {
|
||||
op_write(r[HL], r[A]);
|
||||
write(r[HL], r[A]);
|
||||
r[HL]++;
|
||||
}
|
||||
|
||||
auto LR35902::op_ldi_a_hl() {
|
||||
r[A] = op_read(r[HL]);
|
||||
r[A] = read(r[HL]);
|
||||
r[HL]++;
|
||||
}
|
||||
|
||||
auto LR35902::op_ldd_hl_a() {
|
||||
op_write(r[HL], r[A]);
|
||||
write(r[HL], r[A]);
|
||||
r[HL]--;
|
||||
}
|
||||
|
||||
auto LR35902::op_ldd_a_hl() {
|
||||
r[A] = op_read(r[HL]);
|
||||
r[A] = read(r[HL]);
|
||||
r[HL]--;
|
||||
}
|
||||
|
||||
//16-bit load commands
|
||||
|
||||
auto LR35902::op_ld_rr_nn(uint x) {
|
||||
r[x] = op_read(r[PC]++) << 0;
|
||||
r[x] |= op_read(r[PC]++) << 8;
|
||||
r[x] = read(r[PC]++) << 0;
|
||||
r[x] |= read(r[PC]++) << 8;
|
||||
}
|
||||
|
||||
auto LR35902::op_ld_nn_sp() {
|
||||
uint16 addr = op_read(r[PC]++) << 0;
|
||||
addr |= op_read(r[PC]++) << 8;
|
||||
op_write(addr + 0, r[SP] >> 0);
|
||||
op_write(addr + 1, r[SP] >> 8);
|
||||
uint16 addr = read(r[PC]++) << 0;
|
||||
addr |= read(r[PC]++) << 8;
|
||||
write(addr + 0, r[SP] >> 0);
|
||||
write(addr + 1, r[SP] >> 8);
|
||||
}
|
||||
|
||||
auto LR35902::op_ld_sp_hl() {
|
||||
r[SP] = r[HL];
|
||||
op_io();
|
||||
io();
|
||||
}
|
||||
|
||||
auto LR35902::op_push_rr(uint x) {
|
||||
op_io();
|
||||
op_write(--r[SP], r[x] >> 8);
|
||||
op_write(--r[SP], r[x] >> 0);
|
||||
io();
|
||||
write(--r[SP], r[x] >> 8);
|
||||
write(--r[SP], r[x] >> 0);
|
||||
}
|
||||
|
||||
auto LR35902::op_pop_rr(uint x) {
|
||||
r[x] = op_read(r[SP]++) << 0;
|
||||
r[x] |= op_read(r[SP]++) << 8;
|
||||
r[x] = read(r[SP]++) << 0;
|
||||
r[x] |= read(r[SP]++) << 8;
|
||||
}
|
||||
|
||||
//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_n() { opi_add_a(op_read(r[PC]++)); }
|
||||
auto LR35902::op_add_a_hl() { opi_add_a(op_read(r[HL])); }
|
||||
auto LR35902::op_add_a_n() { opi_add_a(read(r[PC]++)); }
|
||||
auto LR35902::op_add_a_hl() { opi_add_a(read(r[HL])); }
|
||||
|
||||
auto LR35902::opi_adc_a(uint8 x) {
|
||||
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_n() { opi_adc_a(op_read(r[PC]++)); }
|
||||
auto LR35902::op_adc_a_hl() { opi_adc_a(op_read(r[HL])); }
|
||||
auto LR35902::op_adc_a_n() { opi_adc_a(read(r[PC]++)); }
|
||||
auto LR35902::op_adc_a_hl() { opi_adc_a(read(r[HL])); }
|
||||
|
||||
auto LR35902::opi_sub_a(uint8 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_n() { opi_sub_a(op_read(r[PC]++)); }
|
||||
auto LR35902::op_sub_a_hl() { opi_sub_a(op_read(r[HL])); }
|
||||
auto LR35902::op_sub_a_n() { opi_sub_a(read(r[PC]++)); }
|
||||
auto LR35902::op_sub_a_hl() { opi_sub_a(read(r[HL])); }
|
||||
|
||||
auto LR35902::opi_sbc_a(uint8 x) {
|
||||
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_n() { opi_sbc_a(op_read(r[PC]++)); }
|
||||
auto LR35902::op_sbc_a_hl() { opi_sbc_a(op_read(r[HL])); }
|
||||
auto LR35902::op_sbc_a_n() { opi_sbc_a(read(r[PC]++)); }
|
||||
auto LR35902::op_sbc_a_hl() { opi_sbc_a(read(r[HL])); }
|
||||
|
||||
auto LR35902::opi_and_a(uint8 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_n() { opi_and_a(op_read(r[PC]++)); }
|
||||
auto LR35902::op_and_a_hl() { opi_and_a(op_read(r[HL])); }
|
||||
auto LR35902::op_and_a_n() { opi_and_a(read(r[PC]++)); }
|
||||
auto LR35902::op_and_a_hl() { opi_and_a(read(r[HL])); }
|
||||
|
||||
auto LR35902::opi_xor_a(uint8 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_n() { opi_xor_a(op_read(r[PC]++)); }
|
||||
auto LR35902::op_xor_a_hl() { opi_xor_a(op_read(r[HL])); }
|
||||
auto LR35902::op_xor_a_n() { opi_xor_a(read(r[PC]++)); }
|
||||
auto LR35902::op_xor_a_hl() { opi_xor_a(read(r[HL])); }
|
||||
|
||||
auto LR35902::opi_or_a(uint8 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_n() { opi_or_a(op_read(r[PC]++)); }
|
||||
auto LR35902::op_or_a_hl() { opi_or_a(op_read(r[HL])); }
|
||||
auto LR35902::op_or_a_n() { opi_or_a(read(r[PC]++)); }
|
||||
auto LR35902::op_or_a_hl() { opi_or_a(read(r[HL])); }
|
||||
|
||||
auto LR35902::opi_cp_a(uint8 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_n() { opi_cp_a(op_read(r[PC]++)); }
|
||||
auto LR35902::op_cp_a_hl() { opi_cp_a(op_read(r[HL])); }
|
||||
auto LR35902::op_cp_a_n() { opi_cp_a(read(r[PC]++)); }
|
||||
auto LR35902::op_cp_a_hl() { opi_cp_a(read(r[HL])); }
|
||||
|
||||
auto LR35902::op_inc_r(uint x) {
|
||||
r[x]++;
|
||||
|
@ -228,8 +228,8 @@ auto LR35902::op_inc_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_inc_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
op_write(r[HL], ++n);
|
||||
uint8 n = read(r[HL]);
|
||||
write(r[HL], ++n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 0;
|
||||
r.f.h = (n & 0x0f) == 0x00;
|
||||
|
@ -243,8 +243,8 @@ auto LR35902::op_dec_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_dec_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
op_write(r[HL], --n);
|
||||
uint8 n = read(r[HL]);
|
||||
write(r[HL], --n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 1;
|
||||
r.f.h = (n & 0x0f) == 0x0f;
|
||||
|
@ -277,7 +277,7 @@ auto LR35902::op_cpl() {
|
|||
//16-bit arithmetic commands
|
||||
|
||||
auto LR35902::op_add_hl_rr(uint x) {
|
||||
op_io();
|
||||
io();
|
||||
uint32 rb = (r[HL] + r[x]);
|
||||
uint32 rn = (r[HL] & 0xfff) + (r[x] & 0xfff);
|
||||
r[HL] = rb;
|
||||
|
@ -287,34 +287,34 @@ auto LR35902::op_add_hl_rr(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_inc_rr(uint x) {
|
||||
op_io();
|
||||
io();
|
||||
r[x]++;
|
||||
}
|
||||
|
||||
auto LR35902::op_dec_rr(uint x) {
|
||||
op_io();
|
||||
io();
|
||||
r[x]--;
|
||||
}
|
||||
|
||||
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.n = 0;
|
||||
r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f;
|
||||
r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff;
|
||||
r[SP] += n;
|
||||
op_io();
|
||||
op_io();
|
||||
io();
|
||||
io();
|
||||
}
|
||||
|
||||
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.n = 0;
|
||||
r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f;
|
||||
r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff;
|
||||
r[HL] = r[SP] + n;
|
||||
op_io();
|
||||
io();
|
||||
}
|
||||
|
||||
//rotate/shift commands
|
||||
|
@ -362,9 +362,9 @@ auto LR35902::op_rlc_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_rlc_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
n = (n << 1) | (n >> 7);
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 0;
|
||||
r.f.h = 0;
|
||||
|
@ -381,10 +381,10 @@ auto LR35902::op_rl_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_rl_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
bool c = n & 0x80;
|
||||
n = (n << 1) | (r.f.c << 0);
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 0;
|
||||
r.f.h = 0;
|
||||
|
@ -400,9 +400,9 @@ auto LR35902::op_rrc_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_rrc_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
n = (n >> 1) | (n << 7);
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 0;
|
||||
r.f.h = 0;
|
||||
|
@ -419,10 +419,10 @@ auto LR35902::op_rr_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_rr_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
bool c = n & 0x01;
|
||||
n = (n >> 1) | (r.f.c << 7);
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 0;
|
||||
r.f.h = 0;
|
||||
|
@ -439,10 +439,10 @@ auto LR35902::op_sla_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_sla_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
bool c = n & 0x80;
|
||||
n <<= 1;
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 0;
|
||||
r.f.h = 0;
|
||||
|
@ -458,9 +458,9 @@ auto LR35902::op_swap_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_swap_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
n = (n << 4) | (n >> 4);
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 0;
|
||||
r.f.h = 0;
|
||||
|
@ -477,10 +477,10 @@ auto LR35902::op_sra_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_sra_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
bool c = n & 0x01;
|
||||
n = (int8)n >> 1;
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 0;
|
||||
r.f.h = 0;
|
||||
|
@ -497,10 +497,10 @@ auto LR35902::op_srl_r(uint x) {
|
|||
}
|
||||
|
||||
auto LR35902::op_srl_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
bool c = n & 0x01;
|
||||
n >>= 1;
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
r.f.z = n == 0;
|
||||
r.f.n = 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) {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
r.f.z = (n & (1 << b)) == 0;
|
||||
r.f.n = 0;
|
||||
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) {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint8 n = read(r[HL]);
|
||||
n |= 1 << b;
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
}
|
||||
|
||||
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) {
|
||||
uint n = op_read(r[HL]);
|
||||
uint n = read(r[HL]);
|
||||
n &= ~(1 << b);
|
||||
op_write(r[HL], n);
|
||||
write(r[HL], n);
|
||||
}
|
||||
|
||||
//control commands
|
||||
|
@ -561,13 +561,13 @@ auto LR35902::op_nop() {
|
|||
|
||||
auto LR35902::op_halt() {
|
||||
r.halt = true;
|
||||
while(r.halt == true) op_io();
|
||||
while(r.halt) io();
|
||||
}
|
||||
|
||||
auto LR35902::op_stop() {
|
||||
if(stop()) return;
|
||||
r.stop = true;
|
||||
while(r.stop == true) op_io();
|
||||
while(r.stop) io();
|
||||
}
|
||||
|
||||
auto LR35902::op_di() {
|
||||
|
@ -582,10 +582,10 @@ auto LR35902::op_ei() {
|
|||
//jump commands
|
||||
|
||||
auto LR35902::op_jp_nn() {
|
||||
uint8 lo = op_read(r[PC]++);
|
||||
uint8 hi = op_read(r[PC]++);
|
||||
uint8 lo = read(r[PC]++);
|
||||
uint8 hi = read(r[PC]++);
|
||||
r[PC] = (hi << 8) | (lo << 0);
|
||||
op_io();
|
||||
io();
|
||||
}
|
||||
|
||||
auto LR35902::op_jp_hl() {
|
||||
|
@ -593,76 +593,76 @@ auto LR35902::op_jp_hl() {
|
|||
}
|
||||
|
||||
auto LR35902::op_jp_f_nn(uint x, bool y) {
|
||||
uint8 lo = op_read(r[PC]++);
|
||||
uint8 hi = op_read(r[PC]++);
|
||||
uint8 lo = read(r[PC]++);
|
||||
uint8 hi = read(r[PC]++);
|
||||
if(r.f[x] == y) {
|
||||
r[PC] = (hi << 8) | (lo << 0);
|
||||
op_io();
|
||||
io();
|
||||
}
|
||||
}
|
||||
|
||||
auto LR35902::op_jr_n() {
|
||||
int8 n = op_read(r[PC]++);
|
||||
int8 n = read(r[PC]++);
|
||||
r[PC] += n;
|
||||
op_io();
|
||||
io();
|
||||
}
|
||||
|
||||
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) {
|
||||
r[PC] += n;
|
||||
op_io();
|
||||
io();
|
||||
}
|
||||
}
|
||||
|
||||
auto LR35902::op_call_nn() {
|
||||
uint8 lo = op_read(r[PC]++);
|
||||
uint8 hi = op_read(r[PC]++);
|
||||
op_io();
|
||||
op_write(--r[SP], r[PC] >> 8);
|
||||
op_write(--r[SP], r[PC] >> 0);
|
||||
uint8 lo = read(r[PC]++);
|
||||
uint8 hi = read(r[PC]++);
|
||||
io();
|
||||
write(--r[SP], r[PC] >> 8);
|
||||
write(--r[SP], r[PC] >> 0);
|
||||
r[PC] = (hi << 8) | (lo << 0);
|
||||
}
|
||||
|
||||
auto LR35902::op_call_f_nn(uint x, bool y) {
|
||||
uint8 lo = op_read(r[PC]++);
|
||||
uint8 hi = op_read(r[PC]++);
|
||||
uint8 lo = read(r[PC]++);
|
||||
uint8 hi = read(r[PC]++);
|
||||
if(r.f[x] == y) {
|
||||
op_io();
|
||||
op_write(--r[SP], r[PC] >> 8);
|
||||
op_write(--r[SP], r[PC] >> 0);
|
||||
io();
|
||||
write(--r[SP], r[PC] >> 8);
|
||||
write(--r[SP], r[PC] >> 0);
|
||||
r[PC] = (hi << 8) | (lo << 0);
|
||||
}
|
||||
}
|
||||
|
||||
auto LR35902::op_ret() {
|
||||
uint8 lo = op_read(r[SP]++);
|
||||
uint8 hi = op_read(r[SP]++);
|
||||
uint8 lo = read(r[SP]++);
|
||||
uint8 hi = read(r[SP]++);
|
||||
r[PC] = (hi << 8) | (lo << 0);
|
||||
op_io();
|
||||
io();
|
||||
}
|
||||
|
||||
auto LR35902::op_ret_f(uint x, bool y) {
|
||||
op_io();
|
||||
io();
|
||||
if(r.f[x] == y) {
|
||||
uint8 lo = op_read(r[SP]++);
|
||||
uint8 hi = op_read(r[SP]++);
|
||||
uint8 lo = read(r[SP]++);
|
||||
uint8 hi = read(r[SP]++);
|
||||
r[PC] = (hi << 8) | (lo << 0);
|
||||
op_io();
|
||||
io();
|
||||
}
|
||||
}
|
||||
|
||||
auto LR35902::op_reti() {
|
||||
uint8 lo = op_read(r[SP]++);
|
||||
uint8 hi = op_read(r[SP]++);
|
||||
uint8 lo = read(r[SP]++);
|
||||
uint8 hi = read(r[SP]++);
|
||||
r[PC] = (hi << 8) | (lo << 0);
|
||||
op_io();
|
||||
io();
|
||||
r.ime = 1;
|
||||
}
|
||||
|
||||
auto LR35902::op_rst_n(uint n) {
|
||||
op_io();
|
||||
op_write(--r[SP], r[PC] >> 8);
|
||||
op_write(--r[SP], r[PC] >> 0);
|
||||
io();
|
||||
write(--r[SP], r[PC] >> 8);
|
||||
write(--r[SP], r[PC] >> 0);
|
||||
r[PC] = n;
|
||||
}
|
||||
|
|
|
@ -14,9 +14,18 @@ auto LR35902::power() -> void {
|
|||
r.ime = false;
|
||||
}
|
||||
|
||||
auto LR35902::exec() -> void {
|
||||
uint8 opcode = op_read(r[PC]++);
|
||||
switch(opcode) {
|
||||
auto LR35902::interrupt(uint16 vector) -> void {
|
||||
io();
|
||||
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 0x01: return op_ld_rr_nn(BC);
|
||||
case 0x02: return op_ld_rr_a(BC);
|
||||
|
@ -276,9 +285,8 @@ auto LR35902::exec() -> void {
|
|||
}
|
||||
}
|
||||
|
||||
auto LR35902::execCB() -> void {
|
||||
uint8 opcode = op_read(r[PC]++);
|
||||
switch(opcode) {
|
||||
auto LR35902::instructionCB() -> void {
|
||||
switch(auto opcode = read(r[PC]++)) {
|
||||
case 0x00: return op_rlc_r(B);
|
||||
case 0x01: return op_rlc_r(C);
|
||||
case 0x02: return op_rlc_r(D);
|
||||
|
|
|
@ -5,15 +5,16 @@
|
|||
namespace Processor {
|
||||
|
||||
struct LR35902 {
|
||||
virtual auto op_io() -> void = 0;
|
||||
virtual auto op_read(uint16 addr) -> uint8 = 0;
|
||||
virtual auto op_write(uint16 addr, uint8 data) -> void = 0;
|
||||
virtual auto io() -> void = 0;
|
||||
virtual auto read(uint16 addr) -> uint8 = 0;
|
||||
virtual auto write(uint16 addr, uint8 data) -> void = 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 exec() -> void;
|
||||
auto execCB() -> void;
|
||||
auto interrupt(uint16 vector) -> void;
|
||||
auto instruction() -> void;
|
||||
auto instructionCB() -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#define call (this->*op)
|
||||
|
||||
auto SPC700::op_adjust(fps op, uint8_t& r) -> void {
|
||||
auto SPC700::op_adjust(fps op, uint8_t& r) {
|
||||
io();
|
||||
r = call(r);
|
||||
}
|
||||
|
||||
auto SPC700::op_adjust_addr(fps op) -> void {
|
||||
auto SPC700::op_adjust_addr(fps op) {
|
||||
dp.l = readPC();
|
||||
dp.h = readPC();
|
||||
rd = read(dp);
|
||||
|
@ -13,14 +13,14 @@ auto SPC700::op_adjust_addr(fps op) -> void {
|
|||
write(dp, rd);
|
||||
}
|
||||
|
||||
auto SPC700::op_adjust_dp(fps op) -> void {
|
||||
auto SPC700::op_adjust_dp(fps op) {
|
||||
dp = readPC();
|
||||
rd = readDP(dp);
|
||||
rd = call(rd);
|
||||
writeDP(dp, rd);
|
||||
}
|
||||
|
||||
auto SPC700::op_adjust_dpw(int n) -> void {
|
||||
auto SPC700::op_adjust_dpw(int n) {
|
||||
dp = readPC();
|
||||
rd.w = readDP(dp) + n;
|
||||
writeDP(dp++, rd.l);
|
||||
|
@ -30,7 +30,7 @@ auto SPC700::op_adjust_dpw(int n) -> void {
|
|||
regs.p.z = rd == 0;
|
||||
}
|
||||
|
||||
auto SPC700::op_adjust_dpx(fps op) -> void {
|
||||
auto SPC700::op_adjust_dpx(fps op) {
|
||||
dp = readPC();
|
||||
io();
|
||||
rd = readDP(dp + regs.x);
|
||||
|
@ -38,7 +38,7 @@ auto SPC700::op_adjust_dpx(fps op) -> void {
|
|||
writeDP(dp + regs.x, rd);
|
||||
}
|
||||
|
||||
auto SPC700::op_branch(bool condition) -> void {
|
||||
auto SPC700::op_branch(bool condition) {
|
||||
rd = readPC();
|
||||
if(!condition) return;
|
||||
io();
|
||||
|
@ -46,7 +46,7 @@ auto SPC700::op_branch(bool condition) -> void {
|
|||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_branch_bit() -> void {
|
||||
auto SPC700::op_branch_bit() {
|
||||
dp = readPC();
|
||||
sp = readDP(dp);
|
||||
rd = readPC();
|
||||
|
@ -57,26 +57,26 @@ auto SPC700::op_branch_bit() -> void {
|
|||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_pull(uint8_t& r) -> void {
|
||||
auto SPC700::op_pull(uint8_t& r) {
|
||||
io();
|
||||
io();
|
||||
r = readSP();
|
||||
}
|
||||
|
||||
auto SPC700::op_push(uint8 r) -> void {
|
||||
auto SPC700::op_push(uint8 r) {
|
||||
io();
|
||||
io();
|
||||
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.h = readPC();
|
||||
rd = read(dp);
|
||||
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.h = readPC();
|
||||
io();
|
||||
|
@ -84,25 +84,25 @@ auto SPC700::op_read_addri(fpb op, uint8_t& r) -> void {
|
|||
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();
|
||||
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();
|
||||
rd = readDP(dp);
|
||||
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();
|
||||
io();
|
||||
rd = readDP(dp + i);
|
||||
r = call(r, rd);
|
||||
}
|
||||
|
||||
auto SPC700::op_read_dpw(fpw op) -> void {
|
||||
auto SPC700::op_read_dpw(fpw op) {
|
||||
dp = readPC();
|
||||
rd.l = readDP(dp++);
|
||||
if(op != &SPC700::op_cpw) io();
|
||||
|
@ -110,7 +110,7 @@ auto SPC700::op_read_dpw(fpw op) -> void {
|
|||
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;
|
||||
io();
|
||||
sp.l = readDP(dp++);
|
||||
|
@ -119,7 +119,7 @@ auto SPC700::op_read_idpx(fpb op) -> void {
|
|||
regs.a = call(regs.a, rd);
|
||||
}
|
||||
|
||||
auto SPC700::op_read_idpy(fpb op) -> void {
|
||||
auto SPC700::op_read_idpy(fpb op) {
|
||||
dp = readPC();
|
||||
io();
|
||||
sp.l = readDP(dp++);
|
||||
|
@ -128,13 +128,13 @@ auto SPC700::op_read_idpy(fpb op) -> void {
|
|||
regs.a = call(regs.a, rd);
|
||||
}
|
||||
|
||||
auto SPC700::op_read_ix(fpb op) -> void {
|
||||
auto SPC700::op_read_ix(fpb op) {
|
||||
io();
|
||||
rd = readDP(regs.x);
|
||||
regs.a = call(regs.a, rd);
|
||||
}
|
||||
|
||||
auto SPC700::op_set_addr_bit() -> void {
|
||||
auto SPC700::op_set_addr_bit() {
|
||||
dp.l = readPC();
|
||||
dp.h = readPC();
|
||||
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();
|
||||
rd = readDP(dp) & ~(1 << (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();
|
||||
if(&flag == ®s.p.i) io();
|
||||
flag = data;
|
||||
}
|
||||
|
||||
auto SPC700::op_test_addr(bool set) -> void {
|
||||
auto SPC700::op_test_addr(bool set) {
|
||||
dp.l = readPC();
|
||||
dp.h = readPC();
|
||||
rd = read(dp);
|
||||
|
@ -191,7 +191,7 @@ auto SPC700::op_test_addr(bool set) -> void {
|
|||
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();
|
||||
to = from;
|
||||
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);
|
||||
}
|
||||
|
||||
auto SPC700::op_write_addr(uint8_t& r) -> void {
|
||||
auto SPC700::op_write_addr(uint8_t& r) {
|
||||
dp.l = readPC();
|
||||
dp.h = readPC();
|
||||
read(dp);
|
||||
write(dp, r);
|
||||
}
|
||||
|
||||
auto SPC700::op_write_addri(uint8_t& i) -> void {
|
||||
auto SPC700::op_write_addri(uint8_t& i) {
|
||||
dp.l = readPC();
|
||||
dp.h = readPC();
|
||||
io();
|
||||
|
@ -215,20 +215,20 @@ auto SPC700::op_write_addri(uint8_t& i) -> void {
|
|||
write(dp, regs.a);
|
||||
}
|
||||
|
||||
auto SPC700::op_write_dp(uint8_t& r) -> void {
|
||||
auto SPC700::op_write_dp(uint8_t& r) {
|
||||
dp = readPC();
|
||||
readDP(dp);
|
||||
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;
|
||||
io();
|
||||
readDP(dp);
|
||||
writeDP(dp, r);
|
||||
}
|
||||
|
||||
auto SPC700::op_write_dp_const(fpb op) -> void {
|
||||
auto SPC700::op_write_dp_const(fpb op) {
|
||||
rd = readPC();
|
||||
dp = readPC();
|
||||
wr = readDP(dp);
|
||||
|
@ -236,7 +236,7 @@ auto SPC700::op_write_dp_const(fpb op) -> void {
|
|||
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();
|
||||
rd = readDP(sp);
|
||||
dp = readPC();
|
||||
|
@ -245,7 +245,7 @@ auto SPC700::op_write_dp_dp(fpb op) -> void {
|
|||
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();
|
||||
rd = readDP(regs.y);
|
||||
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();
|
||||
sp = readDP(dp);
|
||||
rd = readPC();
|
||||
|
@ -266,7 +266,7 @@ auto SPC700::op_bne_dp() -> void {
|
|||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_bne_dpdec() -> void {
|
||||
auto SPC700::op_bne_dpdec() {
|
||||
dp = readPC();
|
||||
wr = readDP(dp);
|
||||
writeDP(dp, --wr);
|
||||
|
@ -277,7 +277,7 @@ auto SPC700::op_bne_dpdec() -> void {
|
|||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_bne_dpx() -> void {
|
||||
auto SPC700::op_bne_dpx() {
|
||||
dp = readPC();
|
||||
io();
|
||||
sp = readDP(dp + regs.x);
|
||||
|
@ -289,7 +289,7 @@ auto SPC700::op_bne_dpx() -> void {
|
|||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_bne_ydec() -> void {
|
||||
auto SPC700::op_bne_ydec() {
|
||||
rd = readPC();
|
||||
io();
|
||||
io();
|
||||
|
@ -299,7 +299,7 @@ auto SPC700::op_bne_ydec() -> void {
|
|||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_brk() -> void {
|
||||
auto SPC700::op_brk() {
|
||||
rd.l = read(0xffde);
|
||||
rd.h = read(0xffdf);
|
||||
io();
|
||||
|
@ -312,19 +312,19 @@ auto SPC700::op_brk() -> void {
|
|||
regs.p.i = 0;
|
||||
}
|
||||
|
||||
auto SPC700::op_clv() -> void {
|
||||
auto SPC700::op_clv() {
|
||||
io();
|
||||
regs.p.v = 0;
|
||||
regs.p.h = 0;
|
||||
}
|
||||
|
||||
auto SPC700::op_cmc() -> void {
|
||||
auto SPC700::op_cmc() {
|
||||
io();
|
||||
io();
|
||||
regs.p.c = !regs.p.c;
|
||||
}
|
||||
|
||||
auto SPC700::op_daa() -> void {
|
||||
auto SPC700::op_daa() {
|
||||
io();
|
||||
io();
|
||||
if(regs.p.c || (regs.a) > 0x99) {
|
||||
|
@ -338,7 +338,7 @@ auto SPC700::op_daa() -> void {
|
|||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
auto SPC700::op_das() -> void {
|
||||
auto SPC700::op_das() {
|
||||
io();
|
||||
io();
|
||||
if(!regs.p.c || (regs.a) > 0x99) {
|
||||
|
@ -352,7 +352,7 @@ auto SPC700::op_das() -> void {
|
|||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
auto SPC700::op_div_ya_x() -> void {
|
||||
auto SPC700::op_div_ya_x() {
|
||||
io();
|
||||
io();
|
||||
io();
|
||||
|
@ -383,13 +383,13 @@ auto SPC700::op_div_ya_x() -> void {
|
|||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
auto SPC700::op_jmp_addr() -> void {
|
||||
auto SPC700::op_jmp_addr() {
|
||||
rd.l = readPC();
|
||||
rd.h = readPC();
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_jmp_iaddrx() -> void {
|
||||
auto SPC700::op_jmp_iaddrx() {
|
||||
dp.l = readPC();
|
||||
dp.h = readPC();
|
||||
io();
|
||||
|
@ -399,7 +399,7 @@ auto SPC700::op_jmp_iaddrx() -> void {
|
|||
regs.pc = rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_jsp_dp() -> void {
|
||||
auto SPC700::op_jsp_dp() {
|
||||
rd = readPC();
|
||||
io();
|
||||
io();
|
||||
|
@ -408,7 +408,7 @@ auto SPC700::op_jsp_dp() -> void {
|
|||
regs.pc = 0xff00 | rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_jsr_addr() -> void {
|
||||
auto SPC700::op_jsr_addr() {
|
||||
rd.l = readPC();
|
||||
rd.h = readPC();
|
||||
io();
|
||||
|
@ -419,7 +419,7 @@ auto SPC700::op_jsr_addr() -> void {
|
|||
regs.pc = rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_jst() -> void {
|
||||
auto SPC700::op_jst() {
|
||||
dp = 0xffde - ((opcode >> 4) << 1);
|
||||
rd.l = read(dp++);
|
||||
rd.h = read(dp++);
|
||||
|
@ -431,7 +431,7 @@ auto SPC700::op_jst() -> void {
|
|||
regs.pc = rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_lda_ixinc() -> void {
|
||||
auto SPC700::op_lda_ixinc() {
|
||||
io();
|
||||
regs.a = readDP(regs.x++);
|
||||
io();
|
||||
|
@ -439,7 +439,7 @@ auto SPC700::op_lda_ixinc() -> void {
|
|||
regs.p.z = regs.a == 0;
|
||||
}
|
||||
|
||||
auto SPC700::op_mul_ya() -> void {
|
||||
auto SPC700::op_mul_ya() {
|
||||
io();
|
||||
io();
|
||||
io();
|
||||
|
@ -456,17 +456,17 @@ auto SPC700::op_mul_ya() -> void {
|
|||
regs.p.z = (regs.y == 0);
|
||||
}
|
||||
|
||||
auto SPC700::op_nop() -> void {
|
||||
auto SPC700::op_nop() {
|
||||
io();
|
||||
}
|
||||
|
||||
auto SPC700::op_plp() -> void {
|
||||
auto SPC700::op_plp() {
|
||||
io();
|
||||
io();
|
||||
regs.p = readSP();
|
||||
}
|
||||
|
||||
auto SPC700::op_rti() -> void {
|
||||
auto SPC700::op_rti() {
|
||||
regs.p = readSP();
|
||||
rd.l = readSP();
|
||||
rd.h = readSP();
|
||||
|
@ -475,7 +475,7 @@ auto SPC700::op_rti() -> void {
|
|||
regs.pc = rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_rts() -> void {
|
||||
auto SPC700::op_rts() {
|
||||
rd.l = readSP();
|
||||
rd.h = readSP();
|
||||
io();
|
||||
|
@ -483,7 +483,7 @@ auto SPC700::op_rts() -> void {
|
|||
regs.pc = rd;
|
||||
}
|
||||
|
||||
auto SPC700::op_sta_idpx() -> void {
|
||||
auto SPC700::op_sta_idpx() {
|
||||
sp = readPC() + regs.x;
|
||||
io();
|
||||
dp.l = readDP(sp++);
|
||||
|
@ -492,7 +492,7 @@ auto SPC700::op_sta_idpx() -> void {
|
|||
write(dp, regs.a);
|
||||
}
|
||||
|
||||
auto SPC700::op_sta_idpy() -> void {
|
||||
auto SPC700::op_sta_idpy() {
|
||||
sp = readPC();
|
||||
dp.l = readDP(sp++);
|
||||
dp.h = readDP(sp++);
|
||||
|
@ -502,33 +502,33 @@ auto SPC700::op_sta_idpy() -> void {
|
|||
write(dp, regs.a);
|
||||
}
|
||||
|
||||
auto SPC700::op_sta_ix() -> void {
|
||||
auto SPC700::op_sta_ix() {
|
||||
io();
|
||||
readDP(regs.x);
|
||||
writeDP(regs.x, regs.a);
|
||||
}
|
||||
|
||||
auto SPC700::op_sta_ixinc() -> void {
|
||||
auto SPC700::op_sta_ixinc() {
|
||||
io();
|
||||
io();
|
||||
writeDP(regs.x++, regs.a);
|
||||
}
|
||||
|
||||
auto SPC700::op_stw_dp() -> void {
|
||||
auto SPC700::op_stw_dp() {
|
||||
dp = readPC();
|
||||
readDP(dp);
|
||||
writeDP(dp++, regs.a);
|
||||
writeDP(dp++, regs.y);
|
||||
}
|
||||
|
||||
auto SPC700::op_wait() -> void {
|
||||
auto SPC700::op_wait() {
|
||||
while(true) {
|
||||
io();
|
||||
io();
|
||||
}
|
||||
}
|
||||
|
||||
auto SPC700::op_xcn() -> void {
|
||||
auto SPC700::op_xcn() {
|
||||
io();
|
||||
io();
|
||||
io();
|
||||
|
|
|
@ -45,65 +45,65 @@ protected:
|
|||
auto op_ldw(uint16, uint16) -> uint16;
|
||||
auto op_sbw(uint16, uint16) -> uint16;
|
||||
|
||||
auto op_adjust(fps, uint8_t&) -> void;
|
||||
auto op_adjust_addr(fps) -> void;
|
||||
auto op_adjust_dp(fps) -> void;
|
||||
auto op_adjust_dpw(int) -> void;
|
||||
auto op_adjust_dpx(fps) -> void;
|
||||
auto op_branch(bool) -> void;
|
||||
auto op_branch_bit() -> void;
|
||||
auto op_pull(uint8_t&) -> void;
|
||||
auto op_push(uint8) -> void;
|
||||
auto op_read_addr(fpb, uint8_t&) -> void;
|
||||
auto op_read_addri(fpb, uint8_t&) -> void;
|
||||
auto op_read_const(fpb, uint8_t&) -> void;
|
||||
auto op_read_dp(fpb, uint8_t&) -> void;
|
||||
auto op_read_dpi(fpb, uint8_t&, uint8_t&) -> void;
|
||||
auto op_read_dpw(fpw) -> void;
|
||||
auto op_read_idpx(fpb) -> void;
|
||||
auto op_read_idpy(fpb) -> void;
|
||||
auto op_read_ix(fpb) -> void;
|
||||
auto op_set_addr_bit() -> void;
|
||||
auto op_set_bit() -> void;
|
||||
auto op_set_flag(bool&, bool) -> void;
|
||||
auto op_test_addr(bool) -> void;
|
||||
auto op_transfer(uint8_t&, uint8_t&) -> void;
|
||||
auto op_write_addr(uint8_t&) -> void;
|
||||
auto op_write_addri(uint8_t&) -> void;
|
||||
auto op_write_dp(uint8_t&) -> void;
|
||||
auto op_write_dpi(uint8_t&, uint8_t&) -> void;
|
||||
auto op_write_dp_const(fpb) -> void;
|
||||
auto op_write_dp_dp(fpb) -> void;
|
||||
auto op_write_ix_iy(fpb) -> void;
|
||||
auto op_adjust(fps, uint8_t&);
|
||||
auto op_adjust_addr(fps);
|
||||
auto op_adjust_dp(fps);
|
||||
auto op_adjust_dpw(int);
|
||||
auto op_adjust_dpx(fps);
|
||||
auto op_branch(bool);
|
||||
auto op_branch_bit();
|
||||
auto op_pull(uint8_t&);
|
||||
auto op_push(uint8);
|
||||
auto op_read_addr(fpb, uint8_t&);
|
||||
auto op_read_addri(fpb, uint8_t&);
|
||||
auto op_read_const(fpb, uint8_t&);
|
||||
auto op_read_dp(fpb, uint8_t&);
|
||||
auto op_read_dpi(fpb, uint8_t&, uint8_t&);
|
||||
auto op_read_dpw(fpw);
|
||||
auto op_read_idpx(fpb);
|
||||
auto op_read_idpy(fpb);
|
||||
auto op_read_ix(fpb);
|
||||
auto op_set_addr_bit();
|
||||
auto op_set_bit();
|
||||
auto op_set_flag(bool&, bool);
|
||||
auto op_test_addr(bool);
|
||||
auto op_transfer(uint8_t&, uint8_t&);
|
||||
auto op_write_addr(uint8_t&);
|
||||
auto op_write_addri(uint8_t&);
|
||||
auto op_write_dp(uint8_t&);
|
||||
auto op_write_dpi(uint8_t&, uint8_t&);
|
||||
auto op_write_dp_const(fpb);
|
||||
auto op_write_dp_dp(fpb);
|
||||
auto op_write_ix_iy(fpb);
|
||||
|
||||
auto op_bne_dp() -> void;
|
||||
auto op_bne_dpdec() -> void;
|
||||
auto op_bne_dpx() -> void;
|
||||
auto op_bne_ydec() -> void;
|
||||
auto op_brk() -> void;
|
||||
auto op_clv() -> void;
|
||||
auto op_cmc() -> void;
|
||||
auto op_daa() -> void;
|
||||
auto op_das() -> void;
|
||||
auto op_div_ya_x() -> void;
|
||||
auto op_jmp_addr() -> void;
|
||||
auto op_jmp_iaddrx() -> void;
|
||||
auto op_jsp_dp() -> void;
|
||||
auto op_jsr_addr() -> void;
|
||||
auto op_jst() -> void;
|
||||
auto op_lda_ixinc() -> void;
|
||||
auto op_mul_ya() -> void;
|
||||
auto op_nop() -> void;
|
||||
auto op_plp() -> void;
|
||||
auto op_rti() -> void;
|
||||
auto op_rts() -> void;
|
||||
auto op_sta_idpx() -> void;
|
||||
auto op_sta_idpy() -> void;
|
||||
auto op_sta_ix() -> void;
|
||||
auto op_sta_ixinc() -> void;
|
||||
auto op_stw_dp() -> void;
|
||||
auto op_wait() -> void;
|
||||
auto op_xcn() -> void;
|
||||
auto op_bne_dp();
|
||||
auto op_bne_dpdec();
|
||||
auto op_bne_dpx();
|
||||
auto op_bne_ydec();
|
||||
auto op_brk();
|
||||
auto op_clv();
|
||||
auto op_cmc();
|
||||
auto op_daa();
|
||||
auto op_das();
|
||||
auto op_div_ya_x();
|
||||
auto op_jmp_addr();
|
||||
auto op_jmp_iaddrx();
|
||||
auto op_jsp_dp();
|
||||
auto op_jsr_addr();
|
||||
auto op_jst();
|
||||
auto op_lda_ixinc();
|
||||
auto op_mul_ya();
|
||||
auto op_nop();
|
||||
auto op_plp();
|
||||
auto op_rti();
|
||||
auto op_rts();
|
||||
auto op_sta_idpx();
|
||||
auto op_sta_idpy();
|
||||
auto op_sta_ix();
|
||||
auto op_sta_ixinc();
|
||||
auto op_stw_dp();
|
||||
auto op_wait();
|
||||
auto op_xcn();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ auto SuperFX::plot(uint8 x, uint8 y) -> void {
|
|||
|
||||
uint16 offset = (y << 5) + (x >> 3);
|
||||
if(offset != pixelcache[0].offset) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
flushPixelCache(pixelcache[1]);
|
||||
pixelcache[1] = pixelcache[0];
|
||||
pixelcache[0].bitpend = 0x00;
|
||||
pixelcache[0].offset = offset;
|
||||
|
@ -40,64 +40,64 @@ auto SuperFX::plot(uint8 x, uint8 y) -> void {
|
|||
pixelcache[0].data[x] = color;
|
||||
pixelcache[0].bitpend |= 1 << x;
|
||||
if(pixelcache[0].bitpend == 0xff) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
flushPixelCache(pixelcache[1]);
|
||||
pixelcache[1] = pixelcache[0];
|
||||
pixelcache[0].bitpend = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
auto SuperFX::rpix(uint8 x, uint8 y) -> uint8 {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
pixelcache_flush(pixelcache[0]);
|
||||
flushPixelCache(pixelcache[1]);
|
||||
flushPixelCache(pixelcache[0]);
|
||||
|
||||
unsigned cn; //character number
|
||||
uint cn; //character number
|
||||
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
||||
case 0: cn = ((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 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 };
|
||||
unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||
uint bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
||||
uint addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||
uint8 data = 0x00;
|
||||
x = (x & 7) ^ 7;
|
||||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
for(uint n : range(bpp)) {
|
||||
uint byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
step(regs.clsr ? 5 : 6);
|
||||
data |= ((bus_read(addr + byte) >> x) & 1) << n;
|
||||
data |= ((read(addr + byte) >> x) & 1) << n;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
auto SuperFX::pixelcache_flush(pixelcache_t& cache) -> void {
|
||||
auto SuperFX::flushPixelCache(PixelCache& cache) -> void {
|
||||
if(cache.bitpend == 0x00) return;
|
||||
|
||||
uint8 x = cache.offset << 3;
|
||||
uint8 y = cache.offset >> 5;
|
||||
|
||||
unsigned cn; //character number
|
||||
uint cn; //character number
|
||||
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
||||
case 0: cn = ((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 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 };
|
||||
unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||
uint bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
||||
uint addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
for(uint n : range(bpp)) {
|
||||
uint byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
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) {
|
||||
step(regs.clsr ? 5 : 6);
|
||||
data &= cache.bitpend;
|
||||
data |= bus_read(addr + byte) & ~cache.bitpend;
|
||||
data |= read(addr + byte) & ~cache.bitpend;
|
||||
}
|
||||
step(regs.clsr ? 5 : 6);
|
||||
bus_write(addr + byte, data);
|
||||
write(addr + byte, data);
|
||||
}
|
||||
|
||||
cache.bitpend = 0x00;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
auto SuperFX::bus_read(uint24 addr, uint8 data) -> uint8 {
|
||||
if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff, $00-3f:8000-ffff
|
||||
auto SuperFX::read(uint24 addr, uint8 data) -> uint8 {
|
||||
if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff,:8000-ffff
|
||||
while(!regs.scmr.ron && !scheduler.synchronizing()) {
|
||||
step(6);
|
||||
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
|
||||
|
@ -12,7 +12,7 @@ auto SuperFX::bus_read(uint24 addr, uint8 data) -> uint8 {
|
|||
step(6);
|
||||
synchronizeCPU();
|
||||
}
|
||||
return rom.read(addr & rom_mask);
|
||||
return rom.read(addr & romMask);
|
||||
}
|
||||
|
||||
if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
|
||||
|
@ -20,31 +20,31 @@ auto SuperFX::bus_read(uint24 addr, uint8 data) -> uint8 {
|
|||
step(6);
|
||||
synchronizeCPU();
|
||||
}
|
||||
return ram.read(addr & ram_mask);
|
||||
return ram.read(addr & ramMask);
|
||||
}
|
||||
|
||||
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
|
||||
while(!regs.scmr.ran && !scheduler.synchronizing()) {
|
||||
step(6);
|
||||
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;
|
||||
if(offset < 512) {
|
||||
if(cache.valid[offset >> 4] == false) {
|
||||
unsigned dp = offset & 0xfff0;
|
||||
unsigned sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0);
|
||||
for(unsigned n = 0; n < 16; n++) {
|
||||
uint dp = offset & 0xfff0;
|
||||
uint sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0);
|
||||
for(uint n : range(16)) {
|
||||
step(regs.clsr ? 5 : 6);
|
||||
cache.buffer[dp++] = bus_read(sp++);
|
||||
cache.buffer[dp++] = read(sp++);
|
||||
}
|
||||
cache.valid[offset >> 4] = true;
|
||||
} else {
|
||||
|
@ -54,55 +54,43 @@ auto SuperFX::op_read(uint16 addr) -> uint8 {
|
|||
}
|
||||
|
||||
if(regs.pbr <= 0x5f) {
|
||||
//$[00-5f]:[0000-ffff] ROM
|
||||
rombuffer_sync();
|
||||
//$00-5f:0000-ffff ROM
|
||||
syncROMBuffer();
|
||||
step(regs.clsr ? 5 : 6);
|
||||
return bus_read((regs.pbr << 16) + addr);
|
||||
return read(regs.pbr << 16 | addr);
|
||||
} else {
|
||||
//$[60-7f]:[0000-ffff] RAM
|
||||
rambuffer_sync();
|
||||
//$60-7f:0000-ffff RAM
|
||||
syncRAMBuffer();
|
||||
step(regs.clsr ? 5 : 6);
|
||||
return bus_read((regs.pbr << 16) + addr);
|
||||
return read(regs.pbr << 16 | addr);
|
||||
}
|
||||
}
|
||||
|
||||
auto SuperFX::peekpipe() -> uint8 {
|
||||
uint8 result = regs.pipeline;
|
||||
regs.pipeline = op_read(regs.r[15]);
|
||||
r15_modified = false;
|
||||
regs.pipeline = readOpcode(regs.r[15]);
|
||||
regs.r[15].modified = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto SuperFX::pipe() -> uint8 {
|
||||
uint8 result = regs.pipeline;
|
||||
regs.pipeline = op_read(++regs.r[15]);
|
||||
r15_modified = false;
|
||||
regs.pipeline = readOpcode(++regs.r[15]);
|
||||
regs.r[15].modified = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto SuperFX::cache_flush() -> void {
|
||||
for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
|
||||
auto SuperFX::flushCache() -> void {
|
||||
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;
|
||||
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;
|
||||
cache.buffer[addr] = data;
|
||||
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);
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
return cache_mmio_read(addr - 0x3100);
|
||||
return readCache(addr - 0x3100);
|
||||
}
|
||||
|
||||
if(addr >= 0x3000 && addr <= 0x301f) {
|
||||
|
@ -55,7 +55,7 @@ auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
|
|||
addr = 0x3000 | addr.bits(0,9);
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
return cache_mmio_write(addr - 0x3100, data);
|
||||
return writeCache(addr - 0x3100, data);
|
||||
}
|
||||
|
||||
if(addr >= 0x3000 && addr <= 0x301f) {
|
||||
|
@ -65,6 +65,7 @@ auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
|
|||
} else {
|
||||
regs.r[n] = (data << 8) | (regs.r[n] & 0xff);
|
||||
}
|
||||
if(n == 14) updateROMBuffer();
|
||||
|
||||
if(addr == 0x301f) regs.sfr.g = 1;
|
||||
return;
|
||||
|
@ -76,7 +77,7 @@ auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
|
|||
regs.sfr = (regs.sfr & 0xff00) | (data << 0);
|
||||
if(g == 1 && regs.sfr.g == 0) {
|
||||
regs.cbr = 0x0000;
|
||||
cache_flush();
|
||||
flushCache();
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -90,7 +91,7 @@ auto SuperFX::writeIO(uint24 addr, uint8 data) -> void {
|
|||
|
||||
case 0x3034: {
|
||||
regs.pbr = data & 0x7f;
|
||||
cache_flush();
|
||||
flushCache();
|
||||
} break;
|
||||
|
||||
case 0x3037: {
|
||||
|
|
|
@ -3,5 +3,4 @@ auto SuperFX::serialize(serializer& s) -> void {
|
|||
Thread::serialize(s);
|
||||
|
||||
s.array(ram.data(), ram.size());
|
||||
s.integer(r15_modified);
|
||||
}
|
||||
|
|
|
@ -16,13 +16,22 @@ auto SuperFX::Enter() -> void {
|
|||
|
||||
auto SuperFX::main() -> void {
|
||||
if(regs.sfr.g == 0) return step(6);
|
||||
|
||||
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 {
|
||||
regs.r[14].modify = {&SuperFX::r14_modify, this};
|
||||
regs.r[15].modify = {&SuperFX::r15_modify, this};
|
||||
}
|
||||
|
||||
auto SuperFX::load() -> void {
|
||||
|
@ -40,8 +49,23 @@ auto SuperFX::power() -> void {
|
|||
auto SuperFX::reset() -> void {
|
||||
GSU::reset();
|
||||
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
|
||||
auto stop() -> void;
|
||||
auto color(uint8 source) -> uint8;
|
||||
auto plot(uint8 x, uint8 y) -> void;
|
||||
auto rpix(uint8 x, uint8 y) -> uint8;
|
||||
auto pixelcache_flush(pixelcache_t& cache) -> void;
|
||||
auto stop() -> void override;
|
||||
auto color(uint8 source) -> uint8 override;
|
||||
auto plot(uint8 x, uint8 y) -> void override;
|
||||
auto rpix(uint8 x, uint8 y) -> uint8 override;
|
||||
|
||||
auto flushPixelCache(PixelCache& cache) -> void;
|
||||
|
||||
//memory.cpp
|
||||
auto bus_read(uint24 addr, uint8 data = 0x00) -> uint8 override;
|
||||
auto bus_write(uint24 addr, uint8 data) -> void override;
|
||||
auto read(uint24 addr, uint8 data = 0x00) -> uint8 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 pipe() -> uint8;
|
||||
alwaysinline auto pipe() -> uint8 override;
|
||||
|
||||
auto cache_flush() -> void;
|
||||
auto cache_mmio_read(uint16 addr) -> uint8;
|
||||
auto cache_mmio_write(uint16 addr, uint8 data) -> void;
|
||||
|
||||
auto memory_reset() -> void;
|
||||
auto flushCache() -> void override;
|
||||
auto readCache(uint16 addr) -> uint8;
|
||||
auto writeCache(uint16 addr, uint8 data) -> void;
|
||||
|
||||
//mmio.cpp
|
||||
auto readIO(uint24 addr, uint8 data) -> uint8;
|
||||
auto writeIO(uint24 addr, uint8 data) -> void;
|
||||
|
||||
//timing.cpp
|
||||
auto step(uint clocks) -> void;
|
||||
auto step(uint clocks) -> void override;
|
||||
|
||||
auto rombuffer_sync() -> void;
|
||||
auto rombuffer_update() -> void;
|
||||
auto rombuffer_read() -> uint8;
|
||||
auto syncROMBuffer() -> void override;
|
||||
auto readROMBuffer() -> uint8 override;
|
||||
auto updateROMBuffer() -> void;
|
||||
|
||||
auto rambuffer_sync() -> void;
|
||||
auto rambuffer_read(uint16 addr) -> uint8;
|
||||
auto rambuffer_write(uint16 addr, uint8 data) -> void;
|
||||
|
||||
auto r14_modify(uint16) -> void;
|
||||
auto r15_modify(uint16) -> void;
|
||||
|
||||
auto timing_reset() -> void;
|
||||
auto syncRAMBuffer() -> void override;
|
||||
auto readRAMBuffer(uint16 addr) -> uint8 override;
|
||||
auto writeRAMBuffer(uint16 addr, uint8 data) -> void override;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
@ -72,10 +66,8 @@ struct SuperFX : Processor::GSU, Cothread {
|
|||
CPURAM cpuram;
|
||||
|
||||
private:
|
||||
uint rom_mask; //rom_size - 1
|
||||
uint ram_mask; //ram_size - 1
|
||||
|
||||
bool r15_modified = false;
|
||||
uint romMask;
|
||||
uint ramMask;
|
||||
};
|
||||
|
||||
extern SuperFX superfx;
|
||||
|
|
|
@ -3,14 +3,14 @@ auto SuperFX::step(uint clocks) -> void {
|
|||
regs.romcl -= min(clocks, regs.romcl);
|
||||
if(regs.romcl == 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) {
|
||||
regs.ramcl -= min(clocks, regs.ramcl);
|
||||
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();
|
||||
}
|
||||
|
||||
auto SuperFX::rombuffer_sync() -> void {
|
||||
auto SuperFX::syncROMBuffer() -> void {
|
||||
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.romcl = regs.clsr ? 5 : 6;
|
||||
}
|
||||
|
||||
auto SuperFX::rombuffer_read() -> uint8 {
|
||||
rombuffer_sync();
|
||||
return regs.romdr;
|
||||
}
|
||||
|
||||
auto SuperFX::rambuffer_sync() -> void {
|
||||
auto SuperFX::syncRAMBuffer() -> void {
|
||||
if(regs.ramcl) step(regs.ramcl);
|
||||
}
|
||||
|
||||
auto SuperFX::rambuffer_read(uint16 addr) -> uint8 {
|
||||
rambuffer_sync();
|
||||
return bus_read(0x700000 + (regs.rambr << 16) + addr);
|
||||
auto SuperFX::readRAMBuffer(uint16 addr) -> uint8 {
|
||||
syncRAMBuffer();
|
||||
return read(0x700000 + (regs.rambr << 16) + addr);
|
||||
}
|
||||
|
||||
auto SuperFX::rambuffer_write(uint16 addr, uint8 data) -> void {
|
||||
rambuffer_sync();
|
||||
auto SuperFX::writeRAMBuffer(uint16 addr, uint8 data) -> void {
|
||||
syncRAMBuffer();
|
||||
regs.ramcl = regs.clsr ? 5 : 6;
|
||||
regs.ramar = addr;
|
||||
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