diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 4961124a..b5886fb1 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -6,7 +6,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "097.28"; + static const string Version = "097.29"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/sfc/coprocessor/superfx/disassembler/disassembler.cpp b/higan/processor/gsu/disassembler.cpp similarity index 97% rename from higan/sfc/coprocessor/superfx/disassembler/disassembler.cpp rename to higan/processor/gsu/disassembler.cpp index 562e2969..73f31ad8 100644 --- a/higan/sfc/coprocessor/superfx/disassembler/disassembler.cpp +++ b/higan/processor/gsu/disassembler.cpp @@ -1,6 +1,4 @@ -//TODO: this belongs in processor/gsu - -auto SuperFX::disassemble_opcode(char* output) -> void { +auto GSU::disassemble_opcode(char* output) -> void { *output = 0; if(!regs.sfr.alt2) { @@ -39,7 +37,7 @@ auto SuperFX::disassemble_opcode(char* output) -> void { #define op1 bus_read((regs.pbr << 16) + regs.r[15] + 0) #define op2 bus_read((regs.pbr << 16) + regs.r[15] + 1) -auto SuperFX::disassemble_alt0(char* output) -> void { +auto GSU::disassemble_alt0(char* output) -> void { char t[256] = ""; switch(op0) { case (0x00): sprintf(t, "stop"); break; @@ -96,7 +94,7 @@ auto SuperFX::disassemble_alt0(char* output) -> void { strcat(output, t); } -auto SuperFX::disassemble_alt1(char* output) -> void { +auto GSU::disassemble_alt1(char* output) -> void { char t[256] = ""; switch(op0) { case (0x00): sprintf(t, "stop"); break; @@ -153,7 +151,7 @@ auto SuperFX::disassemble_alt1(char* output) -> void { strcat(output, t); } -auto SuperFX::disassemble_alt2(char* output) -> void { +auto GSU::disassemble_alt2(char* output) -> void { char t[256] = ""; switch(op0) { case (0x00): sprintf(t, "stop"); break; @@ -210,7 +208,7 @@ auto SuperFX::disassemble_alt2(char* output) -> void { strcat(output, t); } -auto SuperFX::disassemble_alt3(char* output) -> void { +auto GSU::disassemble_alt3(char* output) -> void { char t[256] = ""; switch(op0) { case (0x00): sprintf(t, "stop"); break; diff --git a/higan/processor/gsu/gsu.cpp b/higan/processor/gsu/gsu.cpp index 48281d21..03bbb0d3 100644 --- a/higan/processor/gsu/gsu.cpp +++ b/higan/processor/gsu/gsu.cpp @@ -10,6 +10,7 @@ namespace Processor { #include "instructions.cpp" #include "table.cpp" #include "serialization.cpp" +#include "disassembler.cpp" auto GSU::power() -> void { } diff --git a/higan/processor/gsu/gsu.hpp b/higan/processor/gsu/gsu.hpp index dbf146a8..3c517b78 100644 --- a/higan/processor/gsu/gsu.hpp +++ b/higan/processor/gsu/gsu.hpp @@ -20,6 +20,9 @@ struct GSU { virtual auto rambuffer_write(uint16 addr, uint8 data) -> void = 0; virtual auto cache_flush() -> void = 0; + virtual auto bus_read(uint24 addr, uint8 data = 0x00) -> uint8 = 0; + virtual auto bus_write(uint24 addr, uint8 data) -> void = 0; + //gsu.cpp auto power() -> void; auto reset() -> void; @@ -113,6 +116,13 @@ struct GSU { //serialization.cpp 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; }; } diff --git a/higan/processor/r65816/disassembler.cpp b/higan/processor/r65816/disassembler.cpp index 5c551273..2e93ad0c 100644 --- a/higan/processor/r65816/disassembler.cpp +++ b/higan/processor/r65816/disassembler.cpp @@ -1,123 +1,117 @@ -auto R65816::dreadb(uint32 addr) -> uint8 { +auto R65816::dreadb(uint24 addr) -> uint8 { if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) { - //$[00-3f|80-bf]:[2000-5fff] + //$00-3f|80-bf:2000-5fff //do not read MMIO registers within debugger return 0x00; } - return disassembler_read(addr); + return disassemblerRead(addr); } -auto R65816::dreadw(uint32 addr) -> uint16 { - uint16 r; - r = dreadb((addr + 0) & 0xffffff) << 0; - r |= dreadb((addr + 1) & 0xffffff) << 8; +auto R65816::dreadw(uint24 addr) -> uint16 { + uint16 data; + data.byte(0) = dreadb(addr++); + data.byte(1) = dreadb(addr++); + return data; +} + +auto R65816::dreadl(uint24 addr) -> uint24 { + uint24 data; + data.byte(0) = dreadb(addr++); + data.byte(1) = dreadb(addr++); + data.byte(2) = dreadb(addr++); + return data; +} + +auto R65816::decode(uint8 mode, uint24 addr) -> uint24 { + uint24 r = 0; + + switch(mode) { + case OPTYPE_DP: + r = (regs.d + (addr & 0xffff)) & 0xffff; + break; + case OPTYPE_DPX: + r = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; + break; + case OPTYPE_DPY: + r = (regs.d + regs.y + (addr & 0xffff)) & 0xffff; + break; + case OPTYPE_IDP: + addr = (regs.d + (addr & 0xffff)) & 0xffff; + r = (regs.db << 16) + dreadw(addr); + break; + case OPTYPE_IDPX: + addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; + r = (regs.db << 16) + dreadw(addr); + break; + case OPTYPE_IDPY: + addr = (regs.d + (addr & 0xffff)) & 0xffff; + r = (regs.db << 16) + dreadw(addr) + regs.y; + break; + case OPTYPE_ILDP: + addr = (regs.d + (addr & 0xffff)) & 0xffff; + r = dreadl(addr); + break; + case OPTYPE_ILDPY: + addr = (regs.d + (addr & 0xffff)) & 0xffff; + r = dreadl(addr) + regs.y; + break; + case OPTYPE_ADDR: + r = (regs.db << 16) + (addr & 0xffff); + break; + case OPTYPE_ADDR_PC: + r = (regs.pc.b << 16) + (addr & 0xffff); + break; + case OPTYPE_ADDRX: + r = (regs.db << 16) + (addr & 0xffff) + regs.x; + break; + case OPTYPE_ADDRY: + r = (regs.db << 16) + (addr & 0xffff) + regs.y; + break; + case OPTYPE_IADDR_PC: + r = (regs.pc.b << 16) + (addr & 0xffff); + break; + case OPTYPE_IADDRX: + r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff); + break; + case OPTYPE_ILADDR: + r = addr; + break; + case OPTYPE_LONG: + r = addr; + break; + case OPTYPE_LONGX: + r = (addr + regs.x); + break; + case OPTYPE_SR: + r = (regs.s + (addr & 0xff)) & 0xffff; + break; + case OPTYPE_ISRY: + addr = (regs.s + (addr & 0xff)) & 0xffff; + r = (regs.db << 16) + dreadw(addr) + regs.y; + break; + case OPTYPE_RELB: + r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff); + r += int8(addr); + break; + case OPTYPE_RELW: + r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff); + r += (int16)addr; + break; + } + return r; } -auto R65816::dreadl(uint32 addr) -> uint32 { - uint32 r; - r = dreadb((addr + 0) & 0xffffff) << 0; - r |= dreadb((addr + 1) & 0xffffff) << 8; - r |= dreadb((addr + 2) & 0xffffff) << 16; - return r; +auto R65816::disassemble() -> string { + return disassemble(regs.pc.d, regs.e, regs.p.m, regs.p.x); } -auto R65816::decode(uint8 offset_type, uint32 addr) -> uint32 { - uint32 r = 0; - - switch(offset_type) { - case OPTYPE_DP: - r = (regs.d + (addr & 0xffff)) & 0xffff; - break; - case OPTYPE_DPX: - r = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; - break; - case OPTYPE_DPY: - r = (regs.d + regs.y + (addr & 0xffff)) & 0xffff; - break; - case OPTYPE_IDP: - addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + dreadw(addr); - break; - case OPTYPE_IDPX: - addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + dreadw(addr); - break; - case OPTYPE_IDPY: - addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = (regs.db << 16) + dreadw(addr) + regs.y; - break; - case OPTYPE_ILDP: - addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = dreadl(addr); - break; - case OPTYPE_ILDPY: - addr = (regs.d + (addr & 0xffff)) & 0xffff; - r = dreadl(addr) + regs.y; - break; - case OPTYPE_ADDR: - r = (regs.db << 16) + (addr & 0xffff); - break; - case OPTYPE_ADDR_PC: - r = (regs.pc.b << 16) + (addr & 0xffff); - break; - case OPTYPE_ADDRX: - r = (regs.db << 16) + (addr & 0xffff) + regs.x; - break; - case OPTYPE_ADDRY: - r = (regs.db << 16) + (addr & 0xffff) + regs.y; - break; - case OPTYPE_IADDR_PC: - r = (regs.pc.b << 16) + (addr & 0xffff); - break; - case OPTYPE_IADDRX: - r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff); - break; - case OPTYPE_ILADDR: - r = addr; - break; - case OPTYPE_LONG: - r = addr; - break; - case OPTYPE_LONGX: - r = (addr + regs.x); - break; - case OPTYPE_SR: - r = (regs.s + (addr & 0xff)) & 0xffff; - break; - case OPTYPE_ISRY: - addr = (regs.s + (addr & 0xff)) & 0xffff; - r = (regs.db << 16) + dreadw(addr) + regs.y; - break; - case OPTYPE_RELB: - r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff); - r += int8(addr); - break; - case OPTYPE_RELW: - r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff); - r += int16(addr); - break; - } - - return(r & 0xffffff); -} - -auto R65816::disassemble_opcode(char* output) -> void { - return disassemble_opcode(output, regs.pc.d, regs.e, regs.p.m, regs.p.x); -} - -auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool x) -> void { - static reg24_t pc; - char t[256]; - char* s = output; - - if(false /* in_opcode() == true */) { - strcpy(s, "?????? "); - return; - } +auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string { + string s; + reg24_t pc; pc.d = addr; - sprintf(s, "%.6x ", (uint32)pc.d); + s = {hex(pc, 6), " "}; uint8 op = dreadb(pc.d); pc.w++; uint8 op0 = dreadb(pc.d); pc.w++; @@ -130,6 +124,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool #define a8 (e || m) #define x8 (e || x) + char t[256]; switch(op) { case 0x00: sprintf(t, "brk #$%.2x ", op8); break; case 0x01: sprintf(t, "ora ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; @@ -407,26 +402,26 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool #undef a8 #undef x8 - strcat(s, t); - strcat(s, " "); - - sprintf(t, "A:%.4x X:%.4x Y:%.4x S:%.4x D:%.4x B:%.2x ", - regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, (uint8_t)regs.db); - strcat(s, t); + s.append(t, " A:{0} X:{1} Y:{2} S:{3} D:{4} B:{5} ", format{ + hex(regs.a.w, 4), hex(regs.x.w, 4), hex(regs.y.w, 4), + hex(regs.s.w, 4), hex(regs.d.w, 4), hex(regs.db, 2) + }); if(regs.e) { - sprintf(t, "%c%c%c%c%c%c%c%c", + s.append( regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v', regs.p.m ? '1' : '0', regs.p.x ? 'B' : 'b', regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i', - regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c'); + regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c' + ); } else { - sprintf(t, "%c%c%c%c%c%c%c%c", + s.append( regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v', regs.p.m ? 'M' : 'm', regs.p.x ? 'X' : 'x', regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i', - regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c'); + regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c' + ); } - strcat(s, t); + return s; } diff --git a/higan/processor/r65816/disassembler.hpp b/higan/processor/r65816/disassembler.hpp index 4704456f..3d1e44da 100644 --- a/higan/processor/r65816/disassembler.hpp +++ b/higan/processor/r65816/disassembler.hpp @@ -1,4 +1,4 @@ -enum : unsigned { +enum : uint { OPTYPE_DP = 0, //dp OPTYPE_DPX, //dp,x OPTYPE_DPY, //dp,y @@ -22,9 +22,9 @@ enum : unsigned { OPTYPE_RELW, //relw }; -auto disassemble_opcode(char* output) -> void; -auto disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool x) -> void; -auto dreadb(uint32 addr) -> uint8; -auto dreadw(uint32 addr) -> uint16; -auto dreadl(uint32 addr) -> uint32; -auto decode(uint8 offset_type, uint32 addr) -> uint32; +auto disassemble() -> string; +auto disassemble(uint24 addr, bool e, bool m, bool x) -> string; +auto dreadb(uint24 addr) -> uint8; +auto dreadw(uint24 addr) -> uint16; +auto dreadl(uint24 addr) -> uint24; +auto decode(uint8 mode, uint24 addr) -> uint24; diff --git a/higan/processor/r65816/memory.hpp b/higan/processor/r65816/memory.hpp index 68cf6b9c..cd8301f5 100644 --- a/higan/processor/r65816/memory.hpp +++ b/higan/processor/r65816/memory.hpp @@ -1,77 +1,77 @@ -alwaysinline auto op_readpc() -> uint8 { - return op_read((regs.pc.b << 16) + regs.pc.w++); +alwaysinline auto readpc() -> uint8 { + return read((regs.pc.b << 16) + regs.pc.w++); } -alwaysinline auto op_readstack() -> uint8 { +alwaysinline auto readstack() -> uint8 { regs.e ? regs.s.l++ : regs.s.w++; - return op_read(regs.s.w); + return read(regs.s.w); } -alwaysinline auto op_readstackn() -> uint8 { - return op_read(++regs.s.w); +alwaysinline auto readstackn() -> uint8 { + return read(++regs.s.w); } -alwaysinline auto op_readaddr(uint32 addr) -> uint8 { - return op_read(addr & 0xffff); +alwaysinline auto readaddr(uint32 addr) -> uint8 { + return read(addr & 0xffff); } -alwaysinline auto op_readlong(uint32 addr) -> uint8 { - return op_read(addr & 0xffffff); +alwaysinline auto readlong(uint32 addr) -> uint8 { + return read(addr & 0xffffff); } -alwaysinline auto op_readdbr(uint32 addr) -> uint8 { - return op_read(((regs.db << 16) + addr) & 0xffffff); +alwaysinline auto readdbr(uint32 addr) -> uint8 { + return read(((regs.db << 16) + addr) & 0xffffff); } -alwaysinline auto op_readpbr(uint32 addr) -> uint8 { - return op_read((regs.pc.b << 16) + (addr & 0xffff)); +alwaysinline auto readpbr(uint32 addr) -> uint8 { + return read((regs.pc.b << 16) + (addr & 0xffff)); } -alwaysinline auto op_readdp(uint32 addr) -> uint8 { +alwaysinline auto readdp(uint32 addr) -> uint8 { if(regs.e && regs.d.l == 0x00) { - return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff)); + return read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff)); } else { - return op_read((regs.d + (addr & 0xffff)) & 0xffff); + return read((regs.d + (addr & 0xffff)) & 0xffff); } } -alwaysinline auto op_readsp(uint32 addr) -> uint8 { - return op_read((regs.s + (addr & 0xffff)) & 0xffff); +alwaysinline auto readsp(uint32 addr) -> uint8 { + return read((regs.s + (addr & 0xffff)) & 0xffff); } -alwaysinline auto op_writestack(uint8 data) -> void { - op_write(regs.s.w, data); +alwaysinline auto writestack(uint8 data) -> void { + write(regs.s.w, data); regs.e ? regs.s.l-- : regs.s.w--; } -alwaysinline auto op_writestackn(uint8 data) -> void { - op_write(regs.s.w--, data); +alwaysinline auto writestackn(uint8 data) -> void { + write(regs.s.w--, data); } -alwaysinline auto op_writeaddr(uint32 addr, uint8 data) -> void { - op_write(addr & 0xffff, data); +alwaysinline auto writeaddr(uint32 addr, uint8 data) -> void { + write(addr & 0xffff, data); } -alwaysinline auto op_writelong(uint32 addr, uint8 data) -> void { - op_write(addr & 0xffffff, data); +alwaysinline auto writelong(uint32 addr, uint8 data) -> void { + write(addr & 0xffffff, data); } -alwaysinline auto op_writedbr(uint32 addr, uint8 data) -> void { - op_write(((regs.db << 16) + addr) & 0xffffff, data); +alwaysinline auto writedbr(uint32 addr, uint8 data) -> void { + write(((regs.db << 16) + addr) & 0xffffff, data); } -alwaysinline auto op_writepbr(uint32 addr, uint8 data) -> void { - op_write((regs.pc.b << 16) + (addr & 0xffff), data); +alwaysinline auto writepbr(uint32 addr, uint8 data) -> void { + write((regs.pc.b << 16) + (addr & 0xffff), data); } -alwaysinline auto op_writedp(uint32 addr, uint8 data) -> void { +alwaysinline auto writedp(uint32 addr, uint8 data) -> void { if(regs.e && regs.d.l == 0x00) { - op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data); + write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data); } else { - op_write((regs.d + (addr & 0xffff)) & 0xffff, data); + write((regs.d + (addr & 0xffff)) & 0xffff, data); } } -alwaysinline auto op_writesp(uint32 addr, uint8 data) -> void { - op_write((regs.s + (addr & 0xffff)) & 0xffff, data); +alwaysinline auto writesp(uint32 addr, uint8 data) -> void { + write((regs.s + (addr & 0xffff)) & 0xffff, data); } diff --git a/higan/processor/r65816/opcode_misc.cpp b/higan/processor/r65816/opcode_misc.cpp index d1306f73..ba56b698 100644 --- a/higan/processor/r65816/opcode_misc.cpp +++ b/higan/processor/r65816/opcode_misc.cpp @@ -1,14 +1,14 @@ auto R65816::op_nop() { -L op_io_irq(); +L ioIRQ(); } auto R65816::op_wdm() { -L op_readpc(); +L readpc(); } auto R65816::op_xba() { - op_io(); -L op_io(); + io(); +L io(); regs.a.l ^= regs.a.h; regs.a.h ^= regs.a.l; regs.a.l ^= regs.a.h; @@ -17,74 +17,74 @@ L op_io(); } auto R65816::op_move_b(signed adjust) { - dp = op_readpc(); - sp = op_readpc(); + dp = readpc(); + sp = readpc(); regs.db = dp; - rd.l = op_readlong((sp << 16) | regs.x.w); - op_writelong((dp << 16) | regs.y.w, rd.l); - op_io(); + rd.l = readlong((sp << 16) | regs.x.w); + writelong((dp << 16) | regs.y.w, rd.l); + io(); regs.x.l += adjust; regs.y.l += adjust; -L op_io(); +L io(); if(regs.a.w--) regs.pc.w -= 3; } auto R65816::op_move_w(signed adjust) { - dp = op_readpc(); - sp = op_readpc(); + dp = readpc(); + sp = readpc(); regs.db = dp; - rd.l = op_readlong((sp << 16) | regs.x.w); - op_writelong((dp << 16) | regs.y.w, rd.l); - op_io(); + rd.l = readlong((sp << 16) | regs.x.w); + writelong((dp << 16) | regs.y.w, rd.l); + io(); regs.x.w += adjust; regs.y.w += adjust; -L op_io(); +L io(); if(regs.a.w--) regs.pc.w -= 3; } auto R65816::op_interrupt_e(uint16 vector) { - op_readpc(); - op_writestack(regs.pc.h); - op_writestack(regs.pc.l); - op_writestack(regs.p); - rd.l = op_readlong(vector + 0); + readpc(); + writestack(regs.pc.h); + writestack(regs.pc.l); + writestack(regs.p); + rd.l = readlong(vector + 0); regs.pc.b = 0; regs.p.i = 1; regs.p.d = 0; -L rd.h = op_readlong(vector + 1); +L rd.h = readlong(vector + 1); regs.pc.w = rd.w; } auto R65816::op_interrupt_n(uint16 vector) { - op_readpc(); - op_writestack(regs.pc.b); - op_writestack(regs.pc.h); - op_writestack(regs.pc.l); - op_writestack(regs.p); - rd.l = op_readlong(vector + 0); + readpc(); + writestack(regs.pc.b); + writestack(regs.pc.h); + writestack(regs.pc.l); + writestack(regs.p); + rd.l = readlong(vector + 0); regs.pc.b = 0x00; regs.p.i = 1; regs.p.d = 0; -L rd.h = op_readlong(vector + 1); +L rd.h = readlong(vector + 1); regs.pc.w = rd.w; } auto R65816::op_stp() { while(regs.wai = true) { -L op_io(); +L io(); } } auto R65816::op_wai() { regs.wai = true; while(regs.wai) { -L op_io(); +L io(); } - op_io(); + io(); } auto R65816::op_xce() { -L op_io_irq(); +L ioIRQ(); bool carry = regs.p.c; regs.p.c = regs.e; regs.e = carry; @@ -98,13 +98,13 @@ L op_io_irq(); } auto R65816::op_flag(bool& flag, bool value) { -L op_io_irq(); +L ioIRQ(); flag = value; } auto R65816::op_pflag_e(bool mode) { - rd.l = op_readpc(); -L op_io(); + rd.l = readpc(); +L io(); regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l); regs.p.m = 1; regs.p.x = 1; @@ -113,8 +113,8 @@ L op_io(); } auto R65816::op_pflag_n(bool mode) { - rd.l = op_readpc(); -L op_io(); + rd.l = readpc(); +L io(); regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l); if(regs.p.x) { regs.x.h = 0x00; @@ -123,140 +123,140 @@ L op_io(); } auto R65816::op_transfer_b(reg16_t& from, reg16_t& to) { -L op_io_irq(); +L ioIRQ(); to.l = from.l; regs.p.n = (to.l & 0x80); regs.p.z = (to.l == 0); } auto R65816::op_transfer_w(reg16_t& from, reg16_t& to) { -L op_io_irq(); +L ioIRQ(); to.w = from.w; regs.p.n = (to.w & 0x8000); regs.p.z = (to.w == 0); } auto R65816::op_tcs_e() { -L op_io_irq(); +L ioIRQ(); regs.s.l = regs.a.l; } auto R65816::op_tcs_n() { -L op_io_irq(); +L ioIRQ(); regs.s.w = regs.a.w; } auto R65816::op_tsx_b() { -L op_io_irq(); +L ioIRQ(); regs.x.l = regs.s.l; regs.p.n = (regs.x.l & 0x80); regs.p.z = (regs.x.l == 0); } auto R65816::op_tsx_w() { -L op_io_irq(); +L ioIRQ(); regs.x.w = regs.s.w; regs.p.n = (regs.x.w & 0x8000); regs.p.z = (regs.x.w == 0); } auto R65816::op_txs_e() { -L op_io_irq(); +L ioIRQ(); regs.s.l = regs.x.l; } auto R65816::op_txs_n() { -L op_io_irq(); +L ioIRQ(); regs.s.w = regs.x.w; } auto R65816::op_push_b(reg16_t& reg) { - op_io(); -L op_writestack(reg.l); + io(); +L writestack(reg.l); } auto R65816::op_push_w(reg16_t& reg) { - op_io(); - op_writestack(reg.h); -L op_writestack(reg.l); + io(); + writestack(reg.h); +L writestack(reg.l); } auto R65816::op_phd_e() { - op_io(); - op_writestackn(regs.d.h); -L op_writestackn(regs.d.l); + io(); + writestackn(regs.d.h); +L writestackn(regs.d.l); regs.s.h = 0x01; } auto R65816::op_phd_n() { - op_io(); - op_writestackn(regs.d.h); -L op_writestackn(regs.d.l); + io(); + writestackn(regs.d.h); +L writestackn(regs.d.l); } auto R65816::op_phb() { - op_io(); -L op_writestack(regs.db); + io(); +L writestack(regs.db); } auto R65816::op_phk() { - op_io(); -L op_writestack(regs.pc.b); + io(); +L writestack(regs.pc.b); } auto R65816::op_php() { - op_io(); -L op_writestack(regs.p); + io(); +L writestack(regs.p); } auto R65816::op_pull_b(reg16_t& reg) { - op_io(); - op_io(); -L reg.l = op_readstack(); + io(); + io(); +L reg.l = readstack(); regs.p.n = (reg.l & 0x80); regs.p.z = (reg.l == 0); } auto R65816::op_pull_w(reg16_t& reg) { - op_io(); - op_io(); - reg.l = op_readstack(); -L reg.h = op_readstack(); + io(); + io(); + reg.l = readstack(); +L reg.h = readstack(); regs.p.n = (reg.w & 0x8000); regs.p.z = (reg.w == 0); } auto R65816::op_pld_e() { - op_io(); - op_io(); - regs.d.l = op_readstackn(); -L regs.d.h = op_readstackn(); + io(); + io(); + regs.d.l = readstackn(); +L regs.d.h = readstackn(); regs.p.n = (regs.d.w & 0x8000); regs.p.z = (regs.d.w == 0); regs.s.h = 0x01; } auto R65816::op_pld_n() { - op_io(); - op_io(); - regs.d.l = op_readstackn(); -L regs.d.h = op_readstackn(); + io(); + io(); + regs.d.l = readstackn(); +L regs.d.h = readstackn(); regs.p.n = (regs.d.w & 0x8000); regs.p.z = (regs.d.w == 0); } auto R65816::op_plb() { - op_io(); - op_io(); -L regs.db = op_readstack(); + io(); + io(); +L regs.db = readstack(); regs.p.n = (regs.db & 0x80); regs.p.z = (regs.db == 0); } auto R65816::op_plp_e() { - op_io(); - op_io(); -L regs.p = op_readstack() | 0x30; + io(); + io(); +L regs.p = readstack() | 0x30; if(regs.p.x) { regs.x.h = 0x00; regs.y.h = 0x00; @@ -264,9 +264,9 @@ L regs.p = op_readstack() | 0x30; } auto R65816::op_plp_n() { - op_io(); - op_io(); -L regs.p = op_readstack(); + io(); + io(); +L regs.p = readstack(); if(regs.p.x) { regs.x.h = 0x00; regs.y.h = 0x00; @@ -274,54 +274,54 @@ L regs.p = op_readstack(); } auto R65816::op_pea_e() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writestackn(aa.h); -L op_writestackn(aa.l); + aa.l = readpc(); + aa.h = readpc(); + writestackn(aa.h); +L writestackn(aa.l); regs.s.h = 0x01; } auto R65816::op_pea_n() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writestackn(aa.h); -L op_writestackn(aa.l); + aa.l = readpc(); + aa.h = readpc(); + writestackn(aa.h); +L writestackn(aa.l); } auto R65816::op_pei_e() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_writestackn(aa.h); -L op_writestackn(aa.l); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + writestackn(aa.h); +L writestackn(aa.l); regs.s.h = 0x01; } auto R65816::op_pei_n() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_writestackn(aa.h); -L op_writestackn(aa.l); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + writestackn(aa.h); +L writestackn(aa.l); } auto R65816::op_per_e() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); + aa.l = readpc(); + aa.h = readpc(); + io(); rd.w = regs.pc.d + (int16)aa.w; - op_writestackn(rd.h); -L op_writestackn(rd.l); + writestackn(rd.h); +L writestackn(rd.l); regs.s.h = 0x01; } auto R65816::op_per_n() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); + aa.l = readpc(); + aa.h = readpc(); + io(); rd.w = regs.pc.d + (int16)aa.w; - op_writestackn(rd.h); -L op_writestackn(rd.l); + writestackn(rd.h); +L writestackn(rd.l); } diff --git a/higan/processor/r65816/opcode_pc.cpp b/higan/processor/r65816/opcode_pc.cpp index 0e4b2767..71c1fa8c 100644 --- a/higan/processor/r65816/opcode_pc.cpp +++ b/higan/processor/r65816/opcode_pc.cpp @@ -1,176 +1,176 @@ auto R65816::op_branch(bool flag, bool value) { if(flag != value) { -L rd.l = op_readpc(); +L rd.l = readpc(); } else { - rd.l = op_readpc(); + rd.l = readpc(); aa.w = regs.pc.d + (int8)rd.l; - op_io_cond6(aa.w); -L op_io(); + io6(aa.w); +L io(); regs.pc.w = aa.w; } } auto R65816::op_bra() { - rd.l = op_readpc(); + rd.l = readpc(); aa.w = regs.pc.d + (int8)rd.l; - op_io_cond6(aa.w); -L op_io(); + io6(aa.w); +L io(); regs.pc.w = aa.w; } auto R65816::op_brl() { - rd.l = op_readpc(); - rd.h = op_readpc(); -L op_io(); + rd.l = readpc(); + rd.h = readpc(); +L io(); regs.pc.w = regs.pc.d + (int16)rd.w; } auto R65816::op_jmp_addr() { - rd.l = op_readpc(); -L rd.h = op_readpc(); + rd.l = readpc(); +L rd.h = readpc(); regs.pc.w = rd.w; } auto R65816::op_jmp_long() { - rd.l = op_readpc(); - rd.h = op_readpc(); -L rd.b = op_readpc(); + rd.l = readpc(); + rd.h = readpc(); +L rd.b = readpc(); regs.pc.d = rd.d & 0xffffff; } auto R65816::op_jmp_iaddr() { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readaddr(aa.w + 0); -L rd.h = op_readaddr(aa.w + 1); + aa.l = readpc(); + aa.h = readpc(); + rd.l = readaddr(aa.w + 0); +L rd.h = readaddr(aa.w + 1); regs.pc.w = rd.w; } auto R65816::op_jmp_iaddrx() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - rd.l = op_readpbr(aa.w + regs.x.w + 0); -L rd.h = op_readpbr(aa.w + regs.x.w + 1); + aa.l = readpc(); + aa.h = readpc(); + io(); + rd.l = readpbr(aa.w + regs.x.w + 0); +L rd.h = readpbr(aa.w + regs.x.w + 1); regs.pc.w = rd.w; } auto R65816::op_jmp_iladdr() { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readaddr(aa.w + 0); - rd.h = op_readaddr(aa.w + 1); -L rd.b = op_readaddr(aa.w + 2); + aa.l = readpc(); + aa.h = readpc(); + rd.l = readaddr(aa.w + 0); + rd.h = readaddr(aa.w + 1); +L rd.b = readaddr(aa.w + 2); regs.pc.d = rd.d & 0xffffff; } auto R65816::op_jsr_addr() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); + aa.l = readpc(); + aa.h = readpc(); + io(); regs.pc.w--; - op_writestack(regs.pc.h); -L op_writestack(regs.pc.l); + writestack(regs.pc.h); +L writestack(regs.pc.l); regs.pc.w = aa.w; } auto R65816::op_jsr_long_e() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writestackn(regs.pc.b); - op_io(); - aa.b = op_readpc(); + aa.l = readpc(); + aa.h = readpc(); + writestackn(regs.pc.b); + io(); + aa.b = readpc(); regs.pc.w--; - op_writestackn(regs.pc.h); -L op_writestackn(regs.pc.l); + writestackn(regs.pc.h); +L writestackn(regs.pc.l); regs.pc.d = aa.d & 0xffffff; regs.s.h = 0x01; } auto R65816::op_jsr_long_n() { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writestackn(regs.pc.b); - op_io(); - aa.b = op_readpc(); + aa.l = readpc(); + aa.h = readpc(); + writestackn(regs.pc.b); + io(); + aa.b = readpc(); regs.pc.w--; - op_writestackn(regs.pc.h); -L op_writestackn(regs.pc.l); + writestackn(regs.pc.h); +L writestackn(regs.pc.l); regs.pc.d = aa.d & 0xffffff; } auto R65816::op_jsr_iaddrx_e() { - aa.l = op_readpc(); - op_writestackn(regs.pc.h); - op_writestackn(regs.pc.l); - aa.h = op_readpc(); - op_io(); - rd.l = op_readpbr(aa.w + regs.x.w + 0); -L rd.h = op_readpbr(aa.w + regs.x.w + 1); + aa.l = readpc(); + writestackn(regs.pc.h); + writestackn(regs.pc.l); + aa.h = readpc(); + io(); + rd.l = readpbr(aa.w + regs.x.w + 0); +L rd.h = readpbr(aa.w + regs.x.w + 1); regs.pc.w = rd.w; regs.s.h = 0x01; } auto R65816::op_jsr_iaddrx_n() { - aa.l = op_readpc(); - op_writestackn(regs.pc.h); - op_writestackn(regs.pc.l); - aa.h = op_readpc(); - op_io(); - rd.l = op_readpbr(aa.w + regs.x.w + 0); -L rd.h = op_readpbr(aa.w + regs.x.w + 1); + aa.l = readpc(); + writestackn(regs.pc.h); + writestackn(regs.pc.l); + aa.h = readpc(); + io(); + rd.l = readpbr(aa.w + regs.x.w + 0); +L rd.h = readpbr(aa.w + regs.x.w + 1); regs.pc.w = rd.w; } auto R65816::op_rti_e() { - op_io(); - op_io(); - regs.p = op_readstack() | 0x30; - rd.l = op_readstack(); -L rd.h = op_readstack(); + io(); + io(); + regs.p = readstack() | 0x30; + rd.l = readstack(); +L rd.h = readstack(); regs.pc.w = rd.w; } auto R65816::op_rti_n() { - op_io(); - op_io(); - regs.p = op_readstack(); + io(); + io(); + regs.p = readstack(); if(regs.p.x) { regs.x.h = 0x00; regs.y.h = 0x00; } - rd.l = op_readstack(); - rd.h = op_readstack(); -L rd.b = op_readstack(); + rd.l = readstack(); + rd.h = readstack(); +L rd.b = readstack(); regs.pc.d = rd.d & 0xffffff; } auto R65816::op_rts() { - op_io(); - op_io(); - rd.l = op_readstack(); - rd.h = op_readstack(); -L op_io(); + io(); + io(); + rd.l = readstack(); + rd.h = readstack(); +L io(); regs.pc.w = ++rd.w; } auto R65816::op_rtl_e() { - op_io(); - op_io(); - rd.l = op_readstackn(); - rd.h = op_readstackn(); -L rd.b = op_readstackn(); + io(); + io(); + rd.l = readstackn(); + rd.h = readstackn(); +L rd.b = readstackn(); regs.pc.b = rd.b; regs.pc.w = ++rd.w; regs.s.h = 0x01; } auto R65816::op_rtl_n() { - op_io(); - op_io(); - rd.l = op_readstackn(); - rd.h = op_readstackn(); -L rd.b = op_readstackn(); + io(); + io(); + rd.l = readstackn(); + rd.h = readstackn(); +L rd.b = readstackn(); regs.pc.b = rd.b; regs.pc.w = ++rd.w; } diff --git a/higan/processor/r65816/opcode_read.cpp b/higan/processor/r65816/opcode_read.cpp index 94072ad7..a9f0db53 100644 --- a/higan/processor/r65816/opcode_read.cpp +++ b/higan/processor/r65816/opcode_read.cpp @@ -1,275 +1,275 @@ auto R65816::op_read_const_b(fp op) { -L rd.l = op_readpc(); +L rd.l = readpc(); call(op); } auto R65816::op_read_const_w(fp op) { - rd.l = op_readpc(); -L rd.h = op_readpc(); + rd.l = readpc(); +L rd.h = readpc(); call(op); } auto R65816::op_read_bit_const_b() { -L rd.l = op_readpc(); +L rd.l = readpc(); regs.p.z = ((rd.l & regs.a.l) == 0); } auto R65816::op_read_bit_const_w() { - rd.l = op_readpc(); -L rd.h = op_readpc(); + rd.l = readpc(); +L rd.h = readpc(); regs.p.z = ((rd.w & regs.a.w) == 0); } auto R65816::op_read_addr_b(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); -L rd.l = op_readdbr(aa.w); + aa.l = readpc(); + aa.h = readpc(); +L rd.l = readdbr(aa.w); call(op); } auto R65816::op_read_addr_w(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readdbr(aa.w + 0); -L rd.h = op_readdbr(aa.w + 1); + aa.l = readpc(); + aa.h = readpc(); + rd.l = readdbr(aa.w + 0); +L rd.h = readdbr(aa.w + 1); call(op); } auto R65816::op_read_addrx_b(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io_cond4(aa.w, aa.w + regs.x.w); -L rd.l = op_readdbr(aa.w + regs.x.w); + aa.l = readpc(); + aa.h = readpc(); + io4(aa.w, aa.w + regs.x.w); +L rd.l = readdbr(aa.w + regs.x.w); call(op); } auto R65816::op_read_addrx_w(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io_cond4(aa.w, aa.w + regs.x.w); - rd.l = op_readdbr(aa.w + regs.x.w + 0); -L rd.h = op_readdbr(aa.w + regs.x.w + 1); + aa.l = readpc(); + aa.h = readpc(); + io4(aa.w, aa.w + regs.x.w); + rd.l = readdbr(aa.w + regs.x.w + 0); +L rd.h = readdbr(aa.w + regs.x.w + 1); call(op); } auto R65816::op_read_addry_b(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io_cond4(aa.w, aa.w + regs.y.w); -L rd.l = op_readdbr(aa.w + regs.y.w); + aa.l = readpc(); + aa.h = readpc(); + io4(aa.w, aa.w + regs.y.w); +L rd.l = readdbr(aa.w + regs.y.w); call(op); } auto R65816::op_read_addry_w(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io_cond4(aa.w, aa.w + regs.y.w); - rd.l = op_readdbr(aa.w + regs.y.w + 0); -L rd.h = op_readdbr(aa.w + regs.y.w + 1); + aa.l = readpc(); + aa.h = readpc(); + io4(aa.w, aa.w + regs.y.w); + rd.l = readdbr(aa.w + regs.y.w + 0); +L rd.h = readdbr(aa.w + regs.y.w + 1); call(op); } auto R65816::op_read_long_b(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); -L rd.l = op_readlong(aa.d); + aa.l = readpc(); + aa.h = readpc(); + aa.b = readpc(); +L rd.l = readlong(aa.d); call(op); } auto R65816::op_read_long_w(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); - rd.l = op_readlong(aa.d + 0); -L rd.h = op_readlong(aa.d + 1); + aa.l = readpc(); + aa.h = readpc(); + aa.b = readpc(); + rd.l = readlong(aa.d + 0); +L rd.h = readlong(aa.d + 1); call(op); } auto R65816::op_read_longx_b(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); -L rd.l = op_readlong(aa.d + regs.x.w); + aa.l = readpc(); + aa.h = readpc(); + aa.b = readpc(); +L rd.l = readlong(aa.d + regs.x.w); call(op); } auto R65816::op_read_longx_w(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); - rd.l = op_readlong(aa.d + regs.x.w + 0); -L rd.h = op_readlong(aa.d + regs.x.w + 1); + aa.l = readpc(); + aa.h = readpc(); + aa.b = readpc(); + rd.l = readlong(aa.d + regs.x.w + 0); +L rd.h = readlong(aa.d + regs.x.w + 1); call(op); } auto R65816::op_read_dp_b(fp op) { - dp = op_readpc(); - op_io_cond2(); -L rd.l = op_readdp(dp); + dp = readpc(); + io2(); +L rd.l = readdp(dp); call(op); } auto R65816::op_read_dp_w(fp op) { - dp = op_readpc(); - op_io_cond2(); - rd.l = op_readdp(dp + 0); -L rd.h = op_readdp(dp + 1); + dp = readpc(); + io2(); + rd.l = readdp(dp + 0); +L rd.h = readdp(dp + 1); call(op); } auto R65816::op_read_dpr_b(fp op, reg16_t& reg) { - dp = op_readpc(); - op_io_cond2(); - op_io(); -L rd.l = op_readdp(dp + reg.w); + dp = readpc(); + io2(); + io(); +L rd.l = readdp(dp + reg.w); call(op); } auto R65816::op_read_dpr_w(fp op, reg16_t& reg) { - dp = op_readpc(); - op_io_cond2(); - op_io(); - rd.l = op_readdp(dp + reg.w + 0); -L rd.h = op_readdp(dp + reg.w + 1); + dp = readpc(); + io2(); + io(); + rd.l = readdp(dp + reg.w + 0); +L rd.h = readdp(dp + reg.w + 1); call(op); } auto R65816::op_read_idp_b(fp op) { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); -L rd.l = op_readdbr(aa.w); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); +L rd.l = readdbr(aa.w); call(op); } auto R65816::op_read_idp_w(fp op) { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - rd.l = op_readdbr(aa.w + 0); -L rd.h = op_readdbr(aa.w + 1); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + rd.l = readdbr(aa.w + 0); +L rd.h = readdbr(aa.w + 1); call(op); } auto R65816::op_read_idpx_b(fp op) { - dp = op_readpc(); - op_io_cond2(); - op_io(); - aa.l = op_readdp(dp + regs.x.w + 0); - aa.h = op_readdp(dp + regs.x.w + 1); -L rd.l = op_readdbr(aa.w); + dp = readpc(); + io2(); + io(); + aa.l = readdp(dp + regs.x.w + 0); + aa.h = readdp(dp + regs.x.w + 1); +L rd.l = readdbr(aa.w); call(op); } auto R65816::op_read_idpx_w(fp op) { - dp = op_readpc(); - op_io_cond2(); - op_io(); - aa.l = op_readdp(dp + regs.x.w + 0); - aa.h = op_readdp(dp + regs.x.w + 1); - rd.l = op_readdbr(aa.w + 0); -L rd.h = op_readdbr(aa.w + 1); + dp = readpc(); + io2(); + io(); + aa.l = readdp(dp + regs.x.w + 0); + aa.h = readdp(dp + regs.x.w + 1); + rd.l = readdbr(aa.w + 0); +L rd.h = readdbr(aa.w + 1); call(op); } auto R65816::op_read_idpy_b(fp op) { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_io_cond4(aa.w, aa.w + regs.y.w); -L rd.l = op_readdbr(aa.w + regs.y.w); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + io4(aa.w, aa.w + regs.y.w); +L rd.l = readdbr(aa.w + regs.y.w); call(op); } auto R65816::op_read_idpy_w(fp op) { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_io_cond4(aa.w, aa.w + regs.y.w); - rd.l = op_readdbr(aa.w + regs.y.w + 0); -L rd.h = op_readdbr(aa.w + regs.y.w + 1); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + io4(aa.w, aa.w + regs.y.w); + rd.l = readdbr(aa.w + regs.y.w + 0); +L rd.h = readdbr(aa.w + regs.y.w + 1); call(op); } auto R65816::op_read_ildp_b(fp op) { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); -L rd.l = op_readlong(aa.d); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + aa.b = readdp(dp + 2); +L rd.l = readlong(aa.d); call(op); } auto R65816::op_read_ildp_w(fp op) { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); - rd.l = op_readlong(aa.d + 0); -L rd.h = op_readlong(aa.d + 1); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + aa.b = readdp(dp + 2); + rd.l = readlong(aa.d + 0); +L rd.h = readlong(aa.d + 1); call(op); } auto R65816::op_read_ildpy_b(fp op) { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); -L rd.l = op_readlong(aa.d + regs.y.w); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + aa.b = readdp(dp + 2); +L rd.l = readlong(aa.d + regs.y.w); call(op); } auto R65816::op_read_ildpy_w(fp op) { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); - rd.l = op_readlong(aa.d + regs.y.w + 0); -L rd.h = op_readlong(aa.d + regs.y.w + 1); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + aa.b = readdp(dp + 2); + rd.l = readlong(aa.d + regs.y.w + 0); +L rd.h = readlong(aa.d + regs.y.w + 1); call(op); } auto R65816::op_read_sr_b(fp op) { - sp = op_readpc(); - op_io(); -L rd.l = op_readsp(sp); + sp = readpc(); + io(); +L rd.l = readsp(sp); call(op); } auto R65816::op_read_sr_w(fp op) { - sp = op_readpc(); - op_io(); - rd.l = op_readsp(sp + 0); -L rd.h = op_readsp(sp + 1); + sp = readpc(); + io(); + rd.l = readsp(sp + 0); +L rd.h = readsp(sp + 1); call(op); } auto R65816::op_read_isry_b(fp op) { - sp = op_readpc(); - op_io(); - aa.l = op_readsp(sp + 0); - aa.h = op_readsp(sp + 1); - op_io(); -L rd.l = op_readdbr(aa.w + regs.y.w); + sp = readpc(); + io(); + aa.l = readsp(sp + 0); + aa.h = readsp(sp + 1); + io(); +L rd.l = readdbr(aa.w + regs.y.w); call(op); } auto R65816::op_read_isry_w(fp op) { - sp = op_readpc(); - op_io(); - aa.l = op_readsp(sp + 0); - aa.h = op_readsp(sp + 1); - op_io(); - rd.l = op_readdbr(aa.w + regs.y.w + 0); -L rd.h = op_readdbr(aa.w + regs.y.w + 1); + sp = readpc(); + io(); + aa.l = readsp(sp + 0); + aa.h = readsp(sp + 1); + io(); + rd.l = readdbr(aa.w + regs.y.w + 0); +L rd.h = readdbr(aa.w + regs.y.w + 1); call(op); } diff --git a/higan/processor/r65816/opcode_rmw.cpp b/higan/processor/r65816/opcode_rmw.cpp index 857e7407..bb274e7c 100644 --- a/higan/processor/r65816/opcode_rmw.cpp +++ b/higan/processor/r65816/opcode_rmw.cpp @@ -1,19 +1,19 @@ auto R65816::op_adjust_imm_b(reg16_t& reg, signed adjust) { -L op_io_irq(); +L ioIRQ(); reg.l += adjust; regs.p.n = (reg.l & 0x80); regs.p.z = (reg.l == 0); } auto R65816::op_adjust_imm_w(reg16_t& reg, signed adjust) { -L op_io_irq(); +L ioIRQ(); reg.w += adjust; regs.p.n = (reg.w & 0x8000); regs.p.z = (reg.w == 0); } auto R65816::op_asl_imm_b() { -L op_io_irq(); +L ioIRQ(); regs.p.c = (regs.a.l & 0x80); regs.a.l <<= 1; regs.p.n = (regs.a.l & 0x80); @@ -21,7 +21,7 @@ L op_io_irq(); } auto R65816::op_asl_imm_w() { -L op_io_irq(); +L ioIRQ(); regs.p.c = (regs.a.w & 0x8000); regs.a.w <<= 1; regs.p.n = (regs.a.w & 0x8000); @@ -29,7 +29,7 @@ L op_io_irq(); } auto R65816::op_lsr_imm_b() { -L op_io_irq(); +L ioIRQ(); regs.p.c = (regs.a.l & 0x01); regs.a.l >>= 1; regs.p.n = (regs.a.l & 0x80); @@ -37,7 +37,7 @@ L op_io_irq(); } auto R65816::op_lsr_imm_w() { -L op_io_irq(); +L ioIRQ(); regs.p.c = (regs.a.w & 0x0001); regs.a.w >>= 1; regs.p.n = (regs.a.w & 0x8000); @@ -45,7 +45,7 @@ L op_io_irq(); } auto R65816::op_rol_imm_b() { -L op_io_irq(); +L ioIRQ(); bool carry = regs.p.c; regs.p.c = (regs.a.l & 0x80); regs.a.l = (regs.a.l << 1) | carry; @@ -54,7 +54,7 @@ L op_io_irq(); } auto R65816::op_rol_imm_w() { -L op_io_irq(); +L ioIRQ(); bool carry = regs.p.c; regs.p.c = (regs.a.w & 0x8000); regs.a.w = (regs.a.w << 1) | carry; @@ -63,7 +63,7 @@ L op_io_irq(); } auto R65816::op_ror_imm_b() { -L op_io_irq(); +L ioIRQ(); bool carry = regs.p.c; regs.p.c = (regs.a.l & 0x01); regs.a.l = (carry << 7) | (regs.a.l >> 1); @@ -72,7 +72,7 @@ L op_io_irq(); } auto R65816::op_ror_imm_w() { -L op_io_irq(); +L ioIRQ(); bool carry = regs.p.c; regs.p.c = (regs.a.w & 0x0001); regs.a.w = (carry << 15) | (regs.a.w >> 1); @@ -81,85 +81,85 @@ L op_io_irq(); } auto R65816::op_adjust_addr_b(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readdbr(aa.w); - op_io(); + aa.l = readpc(); + aa.h = readpc(); + rd.l = readdbr(aa.w); + io(); call(op); -L op_writedbr(aa.w, rd.l); +L writedbr(aa.w, rd.l); } auto R65816::op_adjust_addr_w(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - rd.l = op_readdbr(aa.w + 0); - rd.h = op_readdbr(aa.w + 1); - op_io(); + aa.l = readpc(); + aa.h = readpc(); + rd.l = readdbr(aa.w + 0); + rd.h = readdbr(aa.w + 1); + io(); call(op); - op_writedbr(aa.w + 1, rd.h); -L op_writedbr(aa.w + 0, rd.l); + writedbr(aa.w + 1, rd.h); +L writedbr(aa.w + 0, rd.l); } auto R65816::op_adjust_addrx_b(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - rd.l = op_readdbr(aa.w + regs.x.w); - op_io(); + aa.l = readpc(); + aa.h = readpc(); + io(); + rd.l = readdbr(aa.w + regs.x.w); + io(); call(op); -L op_writedbr(aa.w + regs.x.w, rd.l); +L writedbr(aa.w + regs.x.w, rd.l); } auto R65816::op_adjust_addrx_w(fp op) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - rd.l = op_readdbr(aa.w + regs.x.w + 0); - rd.h = op_readdbr(aa.w + regs.x.w + 1); - op_io(); + aa.l = readpc(); + aa.h = readpc(); + io(); + rd.l = readdbr(aa.w + regs.x.w + 0); + rd.h = readdbr(aa.w + regs.x.w + 1); + io(); call(op); - op_writedbr(aa.w + regs.x.w + 1, rd.h); -L op_writedbr(aa.w + regs.x.w + 0, rd.l); + writedbr(aa.w + regs.x.w + 1, rd.h); +L writedbr(aa.w + regs.x.w + 0, rd.l); } auto R65816::op_adjust_dp_b(fp op) { - dp = op_readpc(); - op_io_cond2(); - rd.l = op_readdp(dp); - op_io(); + dp = readpc(); + io2(); + rd.l = readdp(dp); + io(); call(op); -L op_writedp(dp, rd.l); +L writedp(dp, rd.l); } auto R65816::op_adjust_dp_w(fp op) { - dp = op_readpc(); - op_io_cond2(); - rd.l = op_readdp(dp + 0); - rd.h = op_readdp(dp + 1); - op_io(); + dp = readpc(); + io2(); + rd.l = readdp(dp + 0); + rd.h = readdp(dp + 1); + io(); call(op); - op_writedp(dp + 1, rd.h); -L op_writedp(dp + 0, rd.l); + writedp(dp + 1, rd.h); +L writedp(dp + 0, rd.l); } auto R65816::op_adjust_dpx_b(fp op) { - dp = op_readpc(); - op_io_cond2(); - op_io(); - rd.l = op_readdp(dp + regs.x.w); - op_io(); + dp = readpc(); + io2(); + io(); + rd.l = readdp(dp + regs.x.w); + io(); call(op); -L op_writedp(dp + regs.x.w, rd.l); +L writedp(dp + regs.x.w, rd.l); } auto R65816::op_adjust_dpx_w(fp op) { - dp = op_readpc(); - op_io_cond2(); - op_io(); - rd.l = op_readdp(dp + regs.x.w + 0); - rd.h = op_readdp(dp + regs.x.w + 1); - op_io(); + dp = readpc(); + io2(); + io(); + rd.l = readdp(dp + regs.x.w + 0); + rd.h = readdp(dp + regs.x.w + 1); + io(); call(op); - op_writedp(dp + regs.x.w + 1, rd.h); -L op_writedp(dp + regs.x.w + 0, rd.l); + writedp(dp + regs.x.w + 1, rd.h); +L writedp(dp + regs.x.w + 0, rd.l); } diff --git a/higan/processor/r65816/opcode_write.cpp b/higan/processor/r65816/opcode_write.cpp index 69efe11e..cff5780c 100644 --- a/higan/processor/r65816/opcode_write.cpp +++ b/higan/processor/r65816/opcode_write.cpp @@ -1,195 +1,195 @@ auto R65816::op_write_addr_b(reg16_t& reg) { - aa.l = op_readpc(); - aa.h = op_readpc(); -L op_writedbr(aa.w, reg); + aa.l = readpc(); + aa.h = readpc(); +L writedbr(aa.w, reg); } auto R65816::op_write_addr_w(reg16_t& reg) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_writedbr(aa.w + 0, reg >> 0); -L op_writedbr(aa.w + 1, reg >> 8); + aa.l = readpc(); + aa.h = readpc(); + writedbr(aa.w + 0, reg >> 0); +L writedbr(aa.w + 1, reg >> 8); } auto R65816::op_write_addrr_b(reg16_t& reg, reg16_t& idx) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); -L op_writedbr(aa.w + idx, reg); + aa.l = readpc(); + aa.h = readpc(); + io(); +L writedbr(aa.w + idx, reg); } auto R65816::op_write_addrr_w(reg16_t& reg, reg16_t& idx) { - aa.l = op_readpc(); - aa.h = op_readpc(); - op_io(); - op_writedbr(aa.w + idx + 0, reg >> 0); -L op_writedbr(aa.w + idx + 1, reg >> 8); + aa.l = readpc(); + aa.h = readpc(); + io(); + writedbr(aa.w + idx + 0, reg >> 0); +L writedbr(aa.w + idx + 1, reg >> 8); } auto R65816::op_write_longr_b(reg16_t& idx) { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); -L op_writelong(aa.d + idx, regs.a.l); + aa.l = readpc(); + aa.h = readpc(); + aa.b = readpc(); +L writelong(aa.d + idx, regs.a.l); } auto R65816::op_write_longr_w(reg16_t& idx) { - aa.l = op_readpc(); - aa.h = op_readpc(); - aa.b = op_readpc(); - op_writelong(aa.d + idx + 0, regs.a.l); -L op_writelong(aa.d + idx + 1, regs.a.h); + aa.l = readpc(); + aa.h = readpc(); + aa.b = readpc(); + writelong(aa.d + idx + 0, regs.a.l); +L writelong(aa.d + idx + 1, regs.a.h); } auto R65816::op_write_dp_b(reg16_t& reg) { - dp = op_readpc(); - op_io_cond2(); -L op_writedp(dp, reg); + dp = readpc(); + io2(); +L writedp(dp, reg); } auto R65816::op_write_dp_w(reg16_t& reg) { - dp = op_readpc(); - op_io_cond2(); - op_writedp(dp + 0, reg >> 0); -L op_writedp(dp + 1, reg >> 8); + dp = readpc(); + io2(); + writedp(dp + 0, reg >> 0); +L writedp(dp + 1, reg >> 8); } auto R65816::op_write_dpr_b(reg16_t& reg, reg16_t& idx) { - dp = op_readpc(); - op_io_cond2(); - op_io(); -L op_writedp(dp + idx, reg); + dp = readpc(); + io2(); + io(); +L writedp(dp + idx, reg); } auto R65816::op_write_dpr_w(reg16_t& reg, reg16_t& idx) { - dp = op_readpc(); - op_io_cond2(); - op_io(); - op_writedp(dp + idx + 0, reg >> 0); -L op_writedp(dp + idx + 1, reg >> 8); + dp = readpc(); + io2(); + io(); + writedp(dp + idx + 0, reg >> 0); +L writedp(dp + idx + 1, reg >> 8); } auto R65816::op_sta_idp_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); -L op_writedbr(aa.w, regs.a.l); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); +L writedbr(aa.w, regs.a.l); } auto R65816::op_sta_idp_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_writedbr(aa.w + 0, regs.a.l); -L op_writedbr(aa.w + 1, regs.a.h); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + writedbr(aa.w + 0, regs.a.l); +L writedbr(aa.w + 1, regs.a.h); } auto R65816::op_sta_ildp_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); -L op_writelong(aa.d, regs.a.l); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + aa.b = readdp(dp + 2); +L writelong(aa.d, regs.a.l); } auto R65816::op_sta_ildp_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); - op_writelong(aa.d + 0, regs.a.l); -L op_writelong(aa.d + 1, regs.a.h); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + aa.b = readdp(dp + 2); + writelong(aa.d + 0, regs.a.l); +L writelong(aa.d + 1, regs.a.h); } auto R65816::op_sta_idpx_b() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - aa.l = op_readdp(dp + regs.x.w + 0); - aa.h = op_readdp(dp + regs.x.w + 1); -L op_writedbr(aa.w, regs.a.l); + dp = readpc(); + io2(); + io(); + aa.l = readdp(dp + regs.x.w + 0); + aa.h = readdp(dp + regs.x.w + 1); +L writedbr(aa.w, regs.a.l); } auto R65816::op_sta_idpx_w() { - dp = op_readpc(); - op_io_cond2(); - op_io(); - aa.l = op_readdp(dp + regs.x.w + 0); - aa.h = op_readdp(dp + regs.x.w + 1); - op_writedbr(aa.w + 0, regs.a.l); -L op_writedbr(aa.w + 1, regs.a.h); + dp = readpc(); + io2(); + io(); + aa.l = readdp(dp + regs.x.w + 0); + aa.h = readdp(dp + regs.x.w + 1); + writedbr(aa.w + 0, regs.a.l); +L writedbr(aa.w + 1, regs.a.h); } auto R65816::op_sta_idpy_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_io(); -L op_writedbr(aa.w + regs.y.w, regs.a.l); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + io(); +L writedbr(aa.w + regs.y.w, regs.a.l); } auto R65816::op_sta_idpy_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - op_io(); - op_writedbr(aa.w + regs.y.w + 0, regs.a.l); -L op_writedbr(aa.w + regs.y.w + 1, regs.a.h); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + io(); + writedbr(aa.w + regs.y.w + 0, regs.a.l); +L writedbr(aa.w + regs.y.w + 1, regs.a.h); } auto R65816::op_sta_ildpy_b() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); -L op_writelong(aa.d + regs.y.w, regs.a.l); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + aa.b = readdp(dp + 2); +L writelong(aa.d + regs.y.w, regs.a.l); } auto R65816::op_sta_ildpy_w() { - dp = op_readpc(); - op_io_cond2(); - aa.l = op_readdp(dp + 0); - aa.h = op_readdp(dp + 1); - aa.b = op_readdp(dp + 2); - op_writelong(aa.d + regs.y.w + 0, regs.a.l); -L op_writelong(aa.d + regs.y.w + 1, regs.a.h); + dp = readpc(); + io2(); + aa.l = readdp(dp + 0); + aa.h = readdp(dp + 1); + aa.b = readdp(dp + 2); + writelong(aa.d + regs.y.w + 0, regs.a.l); +L writelong(aa.d + regs.y.w + 1, regs.a.h); } auto R65816::op_sta_sr_b() { - sp = op_readpc(); - op_io(); -L op_writesp(sp, regs.a.l); + sp = readpc(); + io(); +L writesp(sp, regs.a.l); } auto R65816::op_sta_sr_w() { - sp = op_readpc(); - op_io(); - op_writesp(sp + 0, regs.a.l); -L op_writesp(sp + 1, regs.a.h); + sp = readpc(); + io(); + writesp(sp + 0, regs.a.l); +L writesp(sp + 1, regs.a.h); } auto R65816::op_sta_isry_b() { - sp = op_readpc(); - op_io(); - aa.l = op_readsp(sp + 0); - aa.h = op_readsp(sp + 1); - op_io(); -L op_writedbr(aa.w + regs.y.w, regs.a.l); + sp = readpc(); + io(); + aa.l = readsp(sp + 0); + aa.h = readsp(sp + 1); + io(); +L writedbr(aa.w + regs.y.w, regs.a.l); } auto R65816::op_sta_isry_w() { - sp = op_readpc(); - op_io(); - aa.l = op_readsp(sp + 0); - aa.h = op_readsp(sp + 1); - op_io(); - op_writedbr(aa.w + regs.y.w + 0, regs.a.l); -L op_writedbr(aa.w + regs.y.w + 1, regs.a.h); + sp = readpc(); + io(); + aa.l = readsp(sp + 0); + aa.h = readsp(sp + 1); + io(); + writedbr(aa.w + regs.y.w + 0, regs.a.l); +L writedbr(aa.w + regs.y.w + 1, regs.a.h); } diff --git a/higan/processor/r65816/r65816.cpp b/higan/processor/r65816/r65816.cpp index 3e76c828..323c9a6a 100644 --- a/higan/processor/r65816/r65816.cpp +++ b/higan/processor/r65816/r65816.cpp @@ -7,7 +7,7 @@ namespace Processor { #include "disassembler.cpp" #include "serialization.cpp" -#define L last_cycle(); +#define L lastCycle(); #define call(op) (this->*op)() #include "opcode_read.cpp" @@ -28,45 +28,45 @@ namespace Processor { // tcd, tcs, tdc, tsc, tsx, txs, // inc, inx, iny, dec, dex, dey, // asl, lsr, rol, ror, nop, xce. -auto R65816::op_io_irq() -> void { - if(interrupt_pending()) { +auto R65816::ioIRQ() -> void { + if(interruptPending()) { //modify I/O cycle to bus read cycle, do not increment PC - op_read(regs.pc.d); + read(regs.pc.d); } else { - op_io(); + io(); } } -auto R65816::op_io_cond2() -> void { +auto R65816::io2() -> void { if(regs.d.l != 0x00) { - op_io(); + io(); } } -auto R65816::op_io_cond4(uint16 x, uint16 y) -> void { +auto R65816::io4(uint16 x, uint16 y) -> void { if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) { - op_io(); + io(); } } -auto R65816::op_io_cond6(uint16 addr) -> void { +auto R65816::io6(uint16 addr) -> void { if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) { - op_io(); + io(); } } -auto R65816::op_irq() -> void { - op_read(regs.pc.d); - op_io(); - if(!regs.e) op_writestack(regs.pc.b); - op_writestack(regs.pc.h); - op_writestack(regs.pc.l); - op_writestack(regs.e ? (regs.p & ~0x10) : regs.p); - rd.l = op_read(regs.vector + 0); +auto R65816::interrupt() -> void { + read(regs.pc.d); + io(); + if(!regs.e) writestack(regs.pc.b); + writestack(regs.pc.h); + writestack(regs.pc.l); + writestack(regs.e ? (regs.p & ~0x10) : regs.p); + rd.l = read(regs.vector + 0); regs.pc.b = 0x00; regs.p.i = 1; regs.p.d = 0; - rd.h = op_read(regs.vector + 1); + rd.h = read(regs.vector + 1); regs.pc.w = rd.w; } diff --git a/higan/processor/r65816/r65816.hpp b/higan/processor/r65816/r65816.hpp index 2f8d82a6..6c42a011 100644 --- a/higan/processor/r65816/r65816.hpp +++ b/higan/processor/r65816/r65816.hpp @@ -13,20 +13,20 @@ struct R65816 { using fp = auto (R65816::*)() -> void; - virtual auto op_io() -> void = 0; - virtual auto op_read(uint24 addr) -> uint8 = 0; - virtual auto op_write(uint24 addr, uint8 data) -> void = 0; - virtual auto last_cycle() -> void = 0; - virtual auto interrupt_pending() -> bool = 0; - virtual auto op_irq() -> void; + virtual auto io() -> void = 0; + virtual auto read(uint24 addr) -> uint8 = 0; + virtual auto write(uint24 addr, uint8 data) -> void = 0; + virtual auto lastCycle() -> void = 0; + virtual auto interruptPending() const -> bool = 0; + virtual auto interrupt() -> void; - virtual auto disassembler_read(uint24 addr) -> uint8 { return 0u; } + virtual auto disassemblerRead(uint24 addr) -> uint8 { return 0u; } //r65816.cpp - alwaysinline auto op_io_irq() -> void; - alwaysinline auto op_io_cond2() -> void; - alwaysinline auto op_io_cond4(uint16 x, uint16 y) -> void; - alwaysinline auto op_io_cond6(uint16 addr) -> void; + alwaysinline auto ioIRQ() -> void; + alwaysinline auto io2() -> void; + alwaysinline auto io4(uint16 x, uint16 y) -> void; + alwaysinline auto io6(uint16 addr) -> void; //algorithms.cpp auto op_adc_b(); @@ -215,7 +215,7 @@ struct R65816 { auto op_per_n(); //switch.cpp - auto op_exec() -> void; + auto instruction() -> void; //serialization.cpp auto serialize(serializer&) -> void; diff --git a/higan/processor/r65816/switch.cpp b/higan/processor/r65816/switch.cpp index 4448244c..3af47143 100644 --- a/higan/processor/r65816/switch.cpp +++ b/higan/processor/r65816/switch.cpp @@ -1,4 +1,4 @@ -auto R65816::op_exec() -> void { +auto R65816::instruction() -> void { #define opA( n, o ) case n: return op_##o(); #define opAII(n, o, i, j) case n: return op_##o(i, j); #define opE( n, o ) case n: return regs.e ? op_##o##_e() : op_##o##_n(); @@ -15,7 +15,7 @@ auto R65816::op_exec() -> void { #define opXI( n, o, i ) case n: return regs.p.x ? op_##o##_b(i) : op_##o##_w(i); #define opXII(n, o, i, j) case n: return regs.p.x ? op_##o##_b(i, j) : op_##o##_w(i, j); - switch(op_readpc()) { + switch(readpc()) { opEII(0x00, interrupt, 0xfffe, 0xffe6) opMF (0x01, read_idpx, ora) opEII(0x02, interrupt, 0xfff4, 0xffe4) diff --git a/higan/processor/v30mz/disassembler.cpp b/higan/processor/v30mz/disassembler.cpp index 816eae3e..a8a2bbe8 100644 --- a/higan/processor/v30mz/disassembler.cpp +++ b/higan/processor/v30mz/disassembler.cpp @@ -1,3 +1,4 @@ +//todo: this is horribly broken in many cases; needs a total rewrite auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> string { string s; uint20 ea = cs * 16 + ip; diff --git a/higan/processor/v30mz/instructions-adjust.cpp b/higan/processor/v30mz/instructions-adjust.cpp index 60ac3b22..043d99a8 100644 --- a/higan/processor/v30mz/instructions-adjust.cpp +++ b/higan/processor/v30mz/instructions-adjust.cpp @@ -8,7 +8,7 @@ auto V30MZ::opDecimalAdjust(bool negate) { r.f.h = 1; } if(r.f.c || (al > 0x99)) { - r.al += negate ? -0x06 : 0x60; + r.al += negate ? -0x60 : 0x60; r.f.c = 1; } r.f.s = r.al & 0x80; diff --git a/higan/processor/v30mz/instructions-string.cpp b/higan/processor/v30mz/instructions-string.cpp index 58343e27..009b815b 100644 --- a/higan/processor/v30mz/instructions-string.cpp +++ b/higan/processor/v30mz/instructions-string.cpp @@ -51,8 +51,8 @@ auto V30MZ::opCompareString(Size size) { alSub(size, x, y); if(!repeat() || !--r.cx) return; - if(repeat() == RepeatWhileZero && r.f.z == 1) return; - if(repeat() == RepeatWhileNotZero && r.f.z == 0) return; + if(repeat() == RepeatWhileZero && r.f.z == 0) return; + if(repeat() == RepeatWhileNotZero && r.f.z == 1) return; state.prefix = true; r.ip--; @@ -98,8 +98,8 @@ auto V30MZ::opScanString(Size size) { alSub(size, x, y); if(!repeat() || !--r.cx) return; - if(repeat() == RepeatWhileZero && r.f.z == 1) return; - if(repeat() == RepeatWhileNotZero && r.f.z == 0) return; + if(repeat() == RepeatWhileZero && r.f.z == 0) return; + if(repeat() == RepeatWhileNotZero && r.f.z == 1) return; state.prefix = true; r.ip--; diff --git a/higan/processor/v30mz/v30mz.cpp b/higan/processor/v30mz/v30mz.cpp index 508297bb..0986f5bf 100644 --- a/higan/processor/v30mz/v30mz.cpp +++ b/higan/processor/v30mz/v30mz.cpp @@ -32,7 +32,7 @@ auto V30MZ::power() -> void { r.cx = 0x0000; r.dx = 0x0000; r.bx = 0x0000; - r.sp = 0x0000; + r.sp = 0x2000; r.bp = 0x0000; r.si = 0x0000; r.di = 0x0000; diff --git a/higan/sfc/coprocessor/sa1/memory/memory.cpp b/higan/sfc/coprocessor/sa1/memory/memory.cpp index b203912c..0a3f2fcb 100644 --- a/higan/sfc/coprocessor/sa1/memory/memory.cpp +++ b/higan/sfc/coprocessor/sa1/memory/memory.cpp @@ -108,17 +108,17 @@ auto SA1::vbr_read(uint24 addr, uint8 data) -> uint8 { //tick() == 2 clock ticks //note: bus conflict delays are not emulated at this time -auto SA1::op_io() -> void { +auto SA1::io() -> void { tick(); } -auto SA1::op_read(uint24 addr) -> uint8 { +auto SA1::read(uint24 addr) -> uint8 { tick(); if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); return bus_read(addr, regs.mdr); } -auto SA1::op_write(uint24 addr, uint8 data) -> void { +auto SA1::write(uint24 addr, uint8 data) -> void { tick(); if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); bus_write(addr, regs.mdr = data); diff --git a/higan/sfc/coprocessor/sa1/memory/memory.hpp b/higan/sfc/coprocessor/sa1/memory/memory.hpp index 9c1702b7..605f25c5 100644 --- a/higan/sfc/coprocessor/sa1/memory/memory.hpp +++ b/higan/sfc/coprocessor/sa1/memory/memory.hpp @@ -2,9 +2,9 @@ auto bus_read(uint24 addr, uint8 data) -> uint8; auto bus_write(uint24 addr, uint8 data) -> void; auto vbr_read(uint24 addr, uint8 data = 0) -> uint8; -alwaysinline auto op_io() -> void override; -alwaysinline auto op_read(uint24 addr) -> uint8 override; -alwaysinline auto op_write(uint24 addr, uint8 data) -> void override; +alwaysinline auto io() -> void override; +alwaysinline auto read(uint24 addr) -> uint8 override; +alwaysinline auto write(uint24 addr, uint8 data) -> void override; auto mmcrom_read(uint24 addr, uint8 data) -> uint8; auto mmcrom_write(uint24 addr, uint8 data) -> void; diff --git a/higan/sfc/coprocessor/sa1/sa1.cpp b/higan/sfc/coprocessor/sa1/sa1.cpp index efc22c2d..e7a240d0 100644 --- a/higan/sfc/coprocessor/sa1/sa1.cpp +++ b/higan/sfc/coprocessor/sa1/sa1.cpp @@ -24,27 +24,27 @@ auto SA1::main() -> void { if(status.interrupt_pending) { status.interrupt_pending = false; - op_irq(); + interrupt(); return; } - op_exec(); + instruction(); } -auto SA1::op_irq() -> void { - op_read(regs.pc.d); - op_io(); - if(!regs.e) op_writestack(regs.pc.b); - op_writestack(regs.pc.h); - op_writestack(regs.pc.l); - op_writestack(regs.e ? (regs.p & ~0x10) : regs.p); +auto SA1::interrupt() -> void { + read(regs.pc.d); + io(); + if(!regs.e) writestack(regs.pc.b); + writestack(regs.pc.h); + writestack(regs.pc.l); + writestack(regs.e ? (regs.p & ~0x10) : regs.p); regs.pc.w = regs.vector; regs.pc.b = 0x00; regs.p.i = 1; regs.p.d = 0; } -auto SA1::last_cycle() -> void { +auto SA1::lastCycle() -> void { if(mmio.sa1_nmi && !mmio.sa1_nmicl) { status.interrupt_pending = true; regs.vector = mmio.cnv; @@ -71,7 +71,7 @@ auto SA1::last_cycle() -> void { } } -auto SA1::interrupt_pending() -> bool { +auto SA1::interruptPending() const -> bool { return status.interrupt_pending; } diff --git a/higan/sfc/coprocessor/sa1/sa1.hpp b/higan/sfc/coprocessor/sa1/sa1.hpp index ed5dd4fb..76936820 100644 --- a/higan/sfc/coprocessor/sa1/sa1.hpp +++ b/higan/sfc/coprocessor/sa1/sa1.hpp @@ -17,11 +17,11 @@ struct SA1 : Processor::R65816, public Coprocessor { static auto Enter() -> void; auto main() -> void; auto tick() -> void; - auto op_irq() -> void override; + auto interrupt() -> void override; alwaysinline auto trigger_irq() -> void; - alwaysinline auto last_cycle() -> void override; - alwaysinline auto interrupt_pending() -> bool override; + alwaysinline auto lastCycle() -> void override; + alwaysinline auto interruptPending() const -> bool override; auto init() -> void; auto load() -> void; diff --git a/higan/sfc/coprocessor/sdd1/sdd1.cpp b/higan/sfc/coprocessor/sdd1/sdd1.cpp index 9768c33d..1bfbbfe1 100644 --- a/higan/sfc/coprocessor/sdd1/sdd1.cpp +++ b/higan/sfc/coprocessor/sdd1/sdd1.cpp @@ -69,7 +69,7 @@ auto SDD1::write(uint24 addr, uint8 data) -> void { } auto SDD1::dma_read(uint24 addr, uint8 data) -> uint8 { - return cpu.mmio_read(addr, data); + return cpu.dmaPortRead(addr, data); } auto SDD1::dma_write(uint24 addr, uint8 data) -> void { @@ -82,7 +82,7 @@ auto SDD1::dma_write(uint24 addr, uint8 data) -> void { case 5: dma[channel].size = (dma[channel].size & 0xff00) + (data << 0); break; case 6: dma[channel].size = (dma[channel].size & 0x00ff) + (data << 8); break; } - return cpu.mmio_write(addr, data); + return cpu.dmaPortWrite(addr, data); } auto SDD1::mmc_read(uint24 addr) -> uint8 { diff --git a/higan/sfc/coprocessor/superfx/disassembler/disassembler.hpp b/higan/sfc/coprocessor/superfx/disassembler/disassembler.hpp deleted file mode 100644 index 23b025e8..00000000 --- a/higan/sfc/coprocessor/superfx/disassembler/disassembler.hpp +++ /dev/null @@ -1,5 +0,0 @@ -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; diff --git a/higan/sfc/coprocessor/superfx/memory/memory.cpp b/higan/sfc/coprocessor/superfx/memory/memory.cpp index 2fff88de..5fcc6cff 100644 --- a/higan/sfc/coprocessor/superfx/memory/memory.cpp +++ b/higan/sfc/coprocessor/superfx/memory/memory.cpp @@ -1,4 +1,4 @@ -auto SuperFX::bus_read(unsigned addr) -> uint8 { +auto SuperFX::bus_read(uint24 addr, uint8 data) -> uint8 { if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff, $00-3f:8000-ffff while(!regs.scmr.ron && !scheduler.synchronizing()) { step(6); @@ -22,9 +22,11 @@ auto SuperFX::bus_read(unsigned addr) -> uint8 { } return ram.read(addr & ram_mask); } + + return data; } -auto SuperFX::bus_write(unsigned addr, uint8 data) -> void { +auto SuperFX::bus_write(uint24 addr, uint8 data) -> void { if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff while(!regs.scmr.ran && !scheduler.synchronizing()) { step(6); diff --git a/higan/sfc/coprocessor/superfx/memory/memory.hpp b/higan/sfc/coprocessor/superfx/memory/memory.hpp index 2c4046f3..7a3ab917 100644 --- a/higan/sfc/coprocessor/superfx/memory/memory.hpp +++ b/higan/sfc/coprocessor/superfx/memory/memory.hpp @@ -1,8 +1,8 @@ -unsigned rom_mask; //rom_size - 1 -unsigned ram_mask; //ram_size - 1 +uint rom_mask; //rom_size - 1 +uint ram_mask; //ram_size - 1 -auto bus_read(unsigned addr) -> uint8; -auto bus_write(unsigned addr, uint8 data) -> void; +auto bus_read(uint24 addr, uint8 data = 0x00) -> uint8 override; +auto bus_write(uint24 addr, uint8 data) -> void override; auto op_read(uint16 addr) -> uint8; alwaysinline auto peekpipe() -> uint8; diff --git a/higan/sfc/coprocessor/superfx/superfx.cpp b/higan/sfc/coprocessor/superfx/superfx.cpp index cb145575..4d56f935 100644 --- a/higan/sfc/coprocessor/superfx/superfx.cpp +++ b/higan/sfc/coprocessor/superfx/superfx.cpp @@ -8,7 +8,6 @@ namespace SuperFamicom { #include "memory/memory.cpp" #include "mmio/mmio.cpp" #include "timing/timing.cpp" -#include "disassembler/disassembler.cpp" SuperFX superfx; diff --git a/higan/sfc/coprocessor/superfx/superfx.hpp b/higan/sfc/coprocessor/superfx/superfx.hpp index 04ee9427..26fed300 100644 --- a/higan/sfc/coprocessor/superfx/superfx.hpp +++ b/higan/sfc/coprocessor/superfx/superfx.hpp @@ -7,7 +7,6 @@ struct SuperFX : Processor::GSU, Coprocessor { #include "memory/memory.hpp" #include "mmio/mmio.hpp" #include "timing/timing.hpp" - #include "disassembler/disassembler.hpp" //superfx.cpp static auto Enter() -> void; diff --git a/higan/sfc/cpu/cpu.cpp b/higan/sfc/cpu/cpu.cpp index e8499a0b..8a6b7882 100644 --- a/higan/sfc/cpu/cpu.cpp +++ b/higan/sfc/cpu/cpu.cpp @@ -3,12 +3,17 @@ namespace SuperFamicom { CPU cpu; - +#include "dma.cpp" +#include "memory.cpp" +#include "mmio.cpp" +#include "timing.cpp" +#include "irq.cpp" +#include "joypad.cpp" #include "serialization.cpp" -#include "dma/dma.cpp" -#include "memory/memory.cpp" -#include "mmio/mmio.cpp" -#include "timing/timing.cpp" + +auto CPU::interruptPending() const -> bool { return status.interrupt_pending; } +auto CPU::pio() const -> uint8 { return status.pio; } +auto CPU::joylatch() const -> bool { return status.joypad_strobe_latch; } CPU::CPU() { PPUcounter::scanline = {&CPU::scanline, this}; @@ -62,35 +67,38 @@ auto CPU::main() -> void { if(status.nmi_pending) { status.nmi_pending = false; regs.vector = (regs.e == false ? 0xffea : 0xfffa); - op_irq(); + interrupt(); debugger.op_nmi(); } else if(status.irq_pending) { status.irq_pending = false; regs.vector = (regs.e == false ? 0xffee : 0xfffe); - op_irq(); + interrupt(); debugger.op_irq(); } else if(status.reset_pending) { status.reset_pending = false; - add_clocks(186); + addClocks(186); regs.pc.l = bus.read(0xfffc, regs.mdr); regs.pc.h = bus.read(0xfffd, regs.mdr); } } - op_step(); -} - -auto CPU::op_step() -> void { debugger.op_exec(regs.pc.d); - op_exec(); + instruction(); } auto CPU::enable() -> void { - function uint8> reader{&CPU::mmio_read, (CPU*)&cpu}; - function void> writer{&CPU::mmio_write, (CPU*)&cpu}; + function uint8> reader; + function void> writer; - bus.map(reader, writer, 0x00, 0x3f, 0x2140, 0x2183); - bus.map(reader, writer, 0x80, 0xbf, 0x2140, 0x2183); + reader = {&CPU::apuPortRead, this}; + writer = {&CPU::apuPortWrite, this}; + bus.map(reader, writer, 0x00, 0x3f, 0x2140, 0x217f); + bus.map(reader, writer, 0x80, 0xbf, 0x2140, 0x217f); + + reader = {&CPU::cpuPortRead, this}; + writer = {&CPU::cpuPortWrite, this}; + bus.map(reader, writer, 0x00, 0x3f, 0x2180, 0x2183); + bus.map(reader, writer, 0x80, 0xbf, 0x2180, 0x2183); bus.map(reader, writer, 0x00, 0x3f, 0x4016, 0x4017); bus.map(reader, writer, 0x80, 0xbf, 0x4016, 0x4017); @@ -98,12 +106,13 @@ auto CPU::enable() -> void { bus.map(reader, writer, 0x00, 0x3f, 0x4200, 0x421f); bus.map(reader, writer, 0x80, 0xbf, 0x4200, 0x421f); + reader = {&CPU::dmaPortRead, this}; + writer = {&CPU::dmaPortWrite, this}; bus.map(reader, writer, 0x00, 0x3f, 0x4300, 0x437f); bus.map(reader, writer, 0x80, 0xbf, 0x4300, 0x437f); - reader = [](uint addr, uint8) -> uint8 { return cpu.wram[addr]; }; - writer = [](uint addr, uint8 data) -> void { cpu.wram[addr] = data; }; - + reader = [](uint24 addr, uint8) -> uint8 { return cpu.wram[addr]; }; + writer = [](uint24 addr, uint8 data) -> void { cpu.wram[addr] = data; }; bus.map(reader, writer, 0x00, 0x3f, 0x0000, 0x1fff, 0x002000); bus.map(reader, writer, 0x80, 0xbf, 0x0000, 0x1fff, 0x002000); bus.map(reader, writer, 0x7e, 0x7f, 0x0000, 0xffff, 0x020000); @@ -112,12 +121,31 @@ auto CPU::enable() -> void { auto CPU::power() -> void { for(auto& byte : wram) byte = random(0x55); + //CPU regs.a = regs.x = regs.y = 0x0000; regs.s = 0x01ff; - mmio_power(); - dma_power(); - timing_power(); + //DMA + for(auto& channel : this->channel) { + channel.direction = 1; + channel.indirect = true; + channel.unused = true; + channel.reverse_transfer = true; + channel.fixed_transfer = true; + channel.transfer_mode = 7; + + channel.dest_addr = 0xff; + + channel.source_addr = 0xffff; + channel.source_bank = 0xff; + + channel.transfer_size = 0xffff; + channel.indirect_bank = 0xff; + + channel.hdma_addr = 0xffff; + channel.line_counter = 0xff; + channel.unknown = 0xff; + } } auto CPU::reset() -> void { @@ -125,7 +153,7 @@ auto CPU::reset() -> void { coprocessors.reset(); PPUcounter::reset(); - //note: some registers are not fully reset by SNES + //CPU regs.pc = 0x000000; regs.x.h = 0x00; regs.y.h = 0x00; @@ -138,9 +166,109 @@ auto CPU::reset() -> void { regs.wai = false; regs.vector = 0xfffc; //reset vector address - mmio_reset(); - dma_reset(); - timing_reset(); + //$2140-217f + for(auto& port : status.port) port = 0x00; + + //$2181-$2183 + status.wram_addr = 0x000000; + + //$4016-$4017 + status.joypad_strobe_latch = 0; + status.joypad1_bits = ~0; + status.joypad2_bits = ~0; + + //$4200 + status.nmi_enabled = false; + status.hirq_enabled = false; + status.virq_enabled = false; + status.auto_joypad_poll = false; + + //$4201 + status.pio = 0xff; + + //$4202-$4203 + status.wrmpya = 0xff; + status.wrmpyb = 0xff; + + //$4204-$4206 + status.wrdiva = 0xffff; + status.wrdivb = 0xff; + + //$4207-$420a + status.hirq_pos = 0x01ff; + status.virq_pos = 0x01ff; + + //$420d + status.rom_speed = 8; + + //$4214-$4217 + status.rddiv = 0x0000; + status.rdmpy = 0x0000; + + //$4218-$421f + status.joy1 = 0x0000; + status.joy2 = 0x0000; + status.joy3 = 0x0000; + status.joy4 = 0x0000; + + //ALU + alu.mpyctr = 0; + alu.divctr = 0; + alu.shift = 0; + + //DMA + for(auto& channel : this->channel) { + channel.dma_enabled = false; + channel.hdma_enabled = false; + + channel.hdma_completed = false; + channel.hdma_do_transfer = false; + } + + pipe.valid = false; + pipe.addr = 0; + pipe.data = 0; + + //Timing + status.clock_count = 0; + status.line_clocks = lineclocks(); + + status.irq_lock = false; + status.dram_refresh_position = (cpu_version == 1 ? 530 : 538); + status.dram_refreshed = false; + + status.hdma_init_position = (cpu_version == 1 ? 12 + 8 - dmaCounter() : 12 + dmaCounter()); + status.hdma_init_triggered = false; + + status.hdma_position = 1104; + status.hdma_triggered = false; + + status.nmi_valid = false; + status.nmi_line = false; + status.nmi_transition = false; + status.nmi_pending = false; + status.nmi_hold = false; + + status.irq_valid = false; + status.irq_line = false; + status.irq_transition = false; + status.irq_pending = false; + status.irq_hold = false; + + status.reset_pending = true; + status.interrupt_pending = true; + + status.dma_active = false; + status.dma_counter = 0; + status.dma_clocks = 0; + status.dma_pending = false; + status.hdma_pending = false; + status.hdma_mode = 0; + + status.auto_joypad_active = false; + status.auto_joypad_latch = false; + status.auto_joypad_counter = 0; + status.auto_joypad_clock = 0; } } diff --git a/higan/sfc/cpu/cpu.hpp b/higan/sfc/cpu/cpu.hpp index 5b4ee8da..627b56e0 100644 --- a/higan/sfc/cpu/cpu.hpp +++ b/higan/sfc/cpu/cpu.hpp @@ -1,6 +1,10 @@ struct CPU : Processor::R65816, Thread, public PPUcounter { enum : bool { Threaded = true }; + auto interruptPending() const -> bool override; + auto pio() const -> uint8; + auto joylatch() const -> bool; + CPU(); alwaysinline auto step(uint clocks) -> void; @@ -12,15 +16,75 @@ struct CPU : Processor::R65816, Thread, public PPUcounter { auto portRead(uint2 port) const -> uint8; auto portWrite(uint2 port, uint8 data) -> void; - auto pio() -> uint8; - auto joylatch() -> bool; - alwaysinline auto interrupt_pending() -> bool { return status.interrupt_pending; } - + static auto Enter() -> void; auto main() -> void; auto enable() -> void; auto power() -> void; auto reset() -> void; + //dma.cpp + auto dmaAddClocks(uint clocks) -> void; + auto dmaTransferValid(uint8 bbus, uint24 abus) -> bool; + auto dmaAddressValid(uint24 abus) -> bool; + auto dmaRead(uint24 abus) -> uint8; + auto dmaWrite(bool valid, uint addr = 0, uint8 data = 0) -> void; + auto dmaTransfer(bool direction, uint8 bbus, uint24 abus) -> void; + + auto dmaAddressB(uint n, uint channel) -> uint8; + auto dmaAddress(uint n) -> uint24; + auto hdmaAddress(uint n) -> uint24; + auto hdmaIndirectAddress(uint n) -> uint24; + + auto dmaEnabledChannels() -> uint; + auto hdmaActive(uint n) -> bool; + auto hdmaActiveAfter(uint s) -> bool; + auto hdmaEnabledChannels() -> uint; + auto hdmaActiveChannels() -> uint; + + auto dmaRun() -> void; + auto hdmaUpdate(uint n) -> void; + auto hdmaRun() -> void; + auto hdmaInitReset() -> void; + auto hdmaInit() -> void; + + //memory.cpp + auto io() -> void override; + auto read(uint24 addr) -> uint8 override; + auto write(uint24 addr, uint8 data) -> void override; + alwaysinline auto speed(uint24 addr) const -> uint; + auto disassemblerRead(uint24 addr) -> uint8 override; + + //mmio.cpp + auto apuPortRead(uint24 addr, uint8 data) -> uint8; + auto cpuPortRead(uint24 addr, uint8 data) -> uint8; + auto dmaPortRead(uint24 addr, uint8 data) -> uint8; + auto apuPortWrite(uint24 addr, uint8 data) -> void; + auto cpuPortWrite(uint24 addr, uint8 data) -> void; + auto dmaPortWrite(uint24 addr, uint8 data) -> void; + + //timing.cpp + auto dmaCounter() const -> uint; + + auto addClocks(uint clocks) -> void; + auto scanline() -> void; + + alwaysinline auto aluEdge() -> void; + alwaysinline auto dmaEdge() -> void; + alwaysinline auto lastCycle() -> void; + + //irq.cpp + alwaysinline auto pollInterrupts() -> void; + auto nmitimenUpdate(uint8 data) -> void; + auto rdnmi() -> bool; + auto timeup() -> bool; + + alwaysinline auto nmiTest() -> bool; + alwaysinline auto irqTest() -> bool; + + //joypad.cpp + auto stepAutoJoypadPoll() -> void; + + //serialization.cpp auto serialize(serializer&) -> void; uint8 wram[128 * 1024]; @@ -29,11 +93,6 @@ struct CPU : Processor::R65816, Thread, public PPUcounter { privileged: uint cpu_version = 2; //allowed: 1, 2 - #include "dma/dma.hpp" - #include "memory/memory.hpp" - #include "mmio/mmio.hpp" - #include "timing/timing.hpp" - struct Status { bool interrupt_pending; @@ -132,15 +191,65 @@ privileged: uint shift; } alu; - static auto Enter() -> void; - auto op_step() -> void; + struct Channel { + //$420b + bool dma_enabled; + + //$420c + bool hdma_enabled; + + //$43x0 + bool direction; + bool indirect; + bool unused; + bool reverse_transfer; + bool fixed_transfer; + uint3 transfer_mode; + + //$43x1 + uint8 dest_addr; + + //$43x2-$43x3 + uint16 source_addr; + + //$43x4 + uint8 source_bank; + + //$43x5-$43x6 + union { + uint16_t transfer_size; + uint16_t indirect_addr; + }; + + //$43x7 + uint8 indirect_bank; + + //$43x8-$43x9 + uint16 hdma_addr; + + //$43xa + uint8 line_counter; + + //$43xb/$43xf + uint8 unknown; + + //internal state + bool hdma_completed; + bool hdma_do_transfer; + } channel[8]; + + struct Pipe { + bool valid; + uint addr; + uint8 data; + } pipe; struct Debugger { - hook op_exec; - hook op_read; - hook op_write; - hook op_nmi; - hook op_irq; + hook void> op_exec; + hook void> op_read; + hook void> op_write; + hook void> op_nmi; + hook void> op_irq; } debugger; }; diff --git a/higan/sfc/cpu/dma.cpp b/higan/sfc/cpu/dma.cpp new file mode 100644 index 00000000..65224322 --- /dev/null +++ b/higan/sfc/cpu/dma.cpp @@ -0,0 +1,238 @@ +auto CPU::dmaAddClocks(uint clocks) -> void { + status.dma_clocks += clocks; + addClocks(clocks); +} + +//============= +//memory access +//============= + +auto CPU::dmaTransferValid(uint8 bbus, uint24 abus) -> bool { + //transfers from WRAM to WRAM are invalid; chip only has one address bus + if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) return false; + return true; +} + +auto CPU::dmaAddressValid(uint24 abus) -> bool { + //A-bus access to B-bus or S-CPU registers are invalid + if((abus & 0x40ff00) == 0x2100) return false; //$00-3f,80-bf:2100-21ff + if((abus & 0x40fe00) == 0x4000) return false; //$00-3f,80-bf:4000-41ff + if((abus & 0x40ffe0) == 0x4200) return false; //$00-3f,80-bf:4200-421f + if((abus & 0x40ff80) == 0x4300) return false; //$00-3f,80-bf:4300-437f + return true; +} + +auto CPU::dmaRead(uint24 abus) -> uint8 { + if(!dmaAddressValid(abus)) return 0x00; + return bus.read(abus, regs.mdr); +} + +//simulate two-stage pipeline for DMA transfers; example: +//cycle 0: read N+0 +//cycle 1: write N+0 & read N+1 (parallel; one on A-bus, one on B-bus) +//cycle 2: write N+1 & read N+2 (parallel) +//cycle 3: write N+2 +auto CPU::dmaWrite(bool valid, uint addr, uint8 data) -> void { + if(pipe.valid) bus.write(pipe.addr, pipe.data); + pipe.valid = valid; + pipe.addr = addr; + pipe.data = data; +} + +auto CPU::dmaTransfer(bool direction, uint8 bbus, uint24 abus) -> void { + if(direction == 0) { + dmaAddClocks(4); + regs.mdr = dmaRead(abus); + dmaAddClocks(4); + dmaWrite(dmaTransferValid(bbus, abus), 0x2100 | bbus, regs.mdr); + } else { + dmaAddClocks(4); + regs.mdr = dmaTransferValid(bbus, abus) ? bus.read(0x2100 | bbus, regs.mdr) : (uint8)0x00; + dmaAddClocks(4); + dmaWrite(dmaAddressValid(abus), abus, regs.mdr); + } +} + +//=================== +//address calculation +//=================== + +auto CPU::dmaAddressB(uint n, uint index) -> uint8 { + switch(channel[n].transfer_mode) { default: + case 0: return (channel[n].dest_addr); //0 + case 1: return (channel[n].dest_addr + (index & 1)); //0,1 + case 2: return (channel[n].dest_addr); //0,0 + case 3: return (channel[n].dest_addr + ((index >> 1) & 1)); //0,0,1,1 + case 4: return (channel[n].dest_addr + (index & 3)); //0,1,2,3 + case 5: return (channel[n].dest_addr + (index & 1)); //0,1,0,1 + case 6: return (channel[n].dest_addr); //0,0 [2] + case 7: return (channel[n].dest_addr + ((index >> 1) & 1)); //0,0,1,1 [3] + } +} + +inline auto CPU::dmaAddress(uint n) -> uint24 { + uint24 addr = channel[n].source_bank << 16 | channel[n].source_addr; + + if(!channel[n].fixed_transfer) { + if(!channel[n].reverse_transfer) { + channel[n].source_addr++; + } else { + channel[n].source_addr--; + } + } + + return addr; +} + +inline auto CPU::hdmaAddress(uint n) -> uint24 { + return channel[n].source_bank << 16 | channel[n].hdma_addr++; +} + +inline auto CPU::hdmaIndirectAddress(uint n) -> uint24 { + return channel[n].indirect_bank << 16 | channel[n].indirect_addr++; +} + +//============== +//channel status +//============== + +auto CPU::dmaEnabledChannels() -> uint { + uint count = 0; + for(auto n : range(8)) count += channel[n].dma_enabled; + return count; +} + +inline auto CPU::hdmaActive(uint n) -> bool { + return channel[n].hdma_enabled && !channel[n].hdma_completed; +} + +inline auto CPU::hdmaActiveAfter(uint s) -> bool { + for(uint n = s + 1; n < 8; n++) { + if(hdmaActive(n)) return true; + } + return false; +} + +inline auto CPU::hdmaEnabledChannels() -> uint { + uint count = 0; + for(auto n : range(8)) count += channel[n].hdma_enabled; + return count; +} + +inline auto CPU::hdmaActiveChannels() -> uint { + uint count = 0; + for(auto n : range(8)) count += hdmaActive(n); + return count; +} + +//============== +//core functions +//============== + +auto CPU::dmaRun() -> void { + dmaAddClocks(8); + dmaWrite(false); + dmaEdge(); + + for(auto n : range(8)) { + if(!channel[n].dma_enabled) continue; + + uint index = 0; + do { + dmaTransfer(channel[n].direction, dmaAddressB(n, index++), dmaAddress(n)); + dmaEdge(); + } while(channel[n].dma_enabled && --channel[n].transfer_size); + + dmaAddClocks(8); + dmaWrite(false); + dmaEdge(); + + channel[n].dma_enabled = false; + } + + status.irq_lock = true; +} + +auto CPU::hdmaUpdate(uint n) -> void { + dmaAddClocks(4); + regs.mdr = dmaRead(channel[n].source_bank << 16 | channel[n].hdma_addr); + dmaAddClocks(4); + dmaWrite(false); + + if((channel[n].line_counter & 0x7f) == 0) { + channel[n].line_counter = regs.mdr; + channel[n].hdma_addr++; + + channel[n].hdma_completed = channel[n].line_counter == 0; + channel[n].hdma_do_transfer = !channel[n].hdma_completed; + + if(channel[n].indirect) { + dmaAddClocks(4); + regs.mdr = dmaRead(hdmaAddress(n)); + channel[n].indirect_addr = regs.mdr << 8; + dmaAddClocks(4); + dmaWrite(false); + + if(!channel[n].hdma_completed || hdmaActiveAfter(n)) { + dmaAddClocks(4); + regs.mdr = dmaRead(hdmaAddress(n)); + channel[n].indirect_addr >>= 8; + channel[n].indirect_addr |= regs.mdr << 8; + dmaAddClocks(4); + dmaWrite(false); + } + } + } +} + +auto CPU::hdmaRun() -> void { + dmaAddClocks(8); + dmaWrite(false); + + for(auto n : range(8)) { + if(!hdmaActive(n)) continue; + channel[n].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer + + if(channel[n].hdma_do_transfer) { + static const uint transferLength[8] = {1, 2, 2, 4, 4, 4, 2, 4}; + uint length = transferLength[channel[n].transfer_mode]; + for(auto index : range(length)) { + uint addr = !channel[n].indirect ? hdmaAddress(n) : hdmaIndirectAddress(n); + dmaTransfer(channel[n].direction, dmaAddressB(n, index), addr); + } + } + } + + for(auto n : range(8)) { + if(!hdmaActive(n)) continue; + + channel[n].line_counter--; + channel[n].hdma_do_transfer = channel[n].line_counter & 0x80; + hdmaUpdate(n); + } + + status.irq_lock = true; +} + +auto CPU::hdmaInitReset() -> void { + for(auto n : range(8)) { + channel[n].hdma_completed = false; + channel[n].hdma_do_transfer = false; + } +} + +auto CPU::hdmaInit() -> void { + dmaAddClocks(8); + dmaWrite(false); + + for(auto n : range(8)) { + if(!channel[n].hdma_enabled) continue; + channel[n].dma_enabled = false; //HDMA init during DMA will stop DMA mid-transfer + + channel[n].hdma_addr = channel[n].source_addr; + channel[n].line_counter = 0; + hdmaUpdate(n); + } + + status.irq_lock = true; +} diff --git a/higan/sfc/cpu/dma/dma.cpp b/higan/sfc/cpu/dma/dma.cpp deleted file mode 100644 index 95a324d1..00000000 --- a/higan/sfc/cpu/dma/dma.cpp +++ /dev/null @@ -1,285 +0,0 @@ -auto CPU::dma_add_clocks(uint clocks) -> void { - status.dma_clocks += clocks; - add_clocks(clocks); -} - -//============= -//memory access -//============= - -auto CPU::dma_transfer_valid(uint8 bbus, uint32 abus) -> bool { - //transfers from WRAM to WRAM are invalid; chip only has one address bus - if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) return false; - return true; -} - -auto CPU::dma_addr_valid(uint32 abus) -> bool { - //A-bus access to B-bus or S-CPU registers are invalid - if((abus & 0x40ff00) == 0x2100) return false; //$[00-3f|80-bf]:[2100-21ff] - if((abus & 0x40fe00) == 0x4000) return false; //$[00-3f|80-bf]:[4000-41ff] - if((abus & 0x40ffe0) == 0x4200) return false; //$[00-3f|80-bf]:[4200-421f] - if((abus & 0x40ff80) == 0x4300) return false; //$[00-3f|80-bf]:[4300-437f] - return true; -} - -auto CPU::dma_read(uint32 abus) -> uint8 { - if(dma_addr_valid(abus) == false) return 0x00; - return bus.read(abus, regs.mdr); -} - -//simulate two-stage pipeline for DMA transfers; example: -//cycle 0: read N+0 -//cycle 1: write N+0 & read N+1 (parallel; one on A-bus, one on B-bus) -//cycle 2: write N+1 & read N+2 (parallel) -//cycle 3: write N+2 -auto CPU::dma_write(bool valid, uint addr, uint8 data) -> void { - if(pipe.valid) bus.write(pipe.addr, pipe.data); - pipe.valid = valid; - pipe.addr = addr; - pipe.data = data; -} - -auto CPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) -> void { - if(direction == 0) { - dma_add_clocks(4); - regs.mdr = dma_read(abus); - dma_add_clocks(4); - dma_write(dma_transfer_valid(bbus, abus), 0x2100 | bbus, regs.mdr); - } else { - dma_add_clocks(4); - regs.mdr = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus, regs.mdr) : (uint8)0x00; - dma_add_clocks(4); - dma_write(dma_addr_valid(abus), abus, regs.mdr); - } -} - -//=================== -//address calculation -//=================== - -auto CPU::dma_bbus(uint i, uint index) -> uint8 { - switch(channel[i].transfer_mode) { default: - case 0: return (channel[i].dest_addr); //0 - case 1: return (channel[i].dest_addr + (index & 1)); //0,1 - case 2: return (channel[i].dest_addr); //0,0 - case 3: return (channel[i].dest_addr + ((index >> 1) & 1)); //0,0,1,1 - case 4: return (channel[i].dest_addr + (index & 3)); //0,1,2,3 - case 5: return (channel[i].dest_addr + (index & 1)); //0,1,0,1 - case 6: return (channel[i].dest_addr); //0,0 [2] - case 7: return (channel[i].dest_addr + ((index >> 1) & 1)); //0,0,1,1 [3] - } -} - -inline auto CPU::dma_addr(uint i) -> uint32 { - uint32 r = (channel[i].source_bank << 16) | (channel[i].source_addr); - - if(channel[i].fixed_transfer == false) { - if(channel[i].reverse_transfer == false) { - channel[i].source_addr++; - } else { - channel[i].source_addr--; - } - } - - return r; -} - -inline auto CPU::hdma_addr(uint i) -> uint32 { - return (channel[i].source_bank << 16) | (channel[i].hdma_addr++); -} - -inline auto CPU::hdma_iaddr(uint i) -> uint32 { - return (channel[i].indirect_bank << 16) | (channel[i].indirect_addr++); -} - -//============== -//channel status -//============== - -auto CPU::dma_enabled_channels() -> uint8 { - uint8 r = 0; - for(uint i = 0; i < 8; i++) { - if(channel[i].dma_enabled) r++; - } - return r; -} - -inline auto CPU::hdma_active(uint i) -> bool { - return (channel[i].hdma_enabled && !channel[i].hdma_completed); -} - -inline auto CPU::hdma_active_after(uint i) -> bool { - for(uint n = i + 1; n < 8; n++) { - if(hdma_active(n) == true) return true; - } - return false; -} - -inline auto CPU::hdma_enabled_channels() -> uint8 { - uint8 r = 0; - for(uint i = 0; i < 8; i++) { - if(channel[i].hdma_enabled) r++; - } - return r; -} - -inline auto CPU::hdma_active_channels() -> uint8 { - uint8 r = 0; - for(uint i = 0; i < 8; i++) { - if(hdma_active(i) == true) r++; - } - return r; -} - -//============== -//core functions -//============== - -auto CPU::dma_run() -> void { - dma_add_clocks(8); - dma_write(false); - dma_edge(); - - for(uint i = 0; i < 8; i++) { - if(channel[i].dma_enabled == false) continue; - - uint index = 0; - do { - dma_transfer(channel[i].direction, dma_bbus(i, index++), dma_addr(i)); - dma_edge(); - } while(channel[i].dma_enabled && --channel[i].transfer_size); - - dma_add_clocks(8); - dma_write(false); - dma_edge(); - - channel[i].dma_enabled = false; - } - - status.irq_lock = true; -} - -auto CPU::hdma_update(uint i) -> void { - dma_add_clocks(4); - regs.mdr = dma_read((channel[i].source_bank << 16) | channel[i].hdma_addr); - dma_add_clocks(4); - dma_write(false); - - if((channel[i].line_counter & 0x7f) == 0) { - channel[i].line_counter = regs.mdr; - channel[i].hdma_addr++; - - channel[i].hdma_completed = (channel[i].line_counter == 0); - channel[i].hdma_do_transfer = !channel[i].hdma_completed; - - if(channel[i].indirect) { - dma_add_clocks(4); - regs.mdr = dma_read(hdma_addr(i)); - channel[i].indirect_addr = regs.mdr << 8; - dma_add_clocks(4); - dma_write(false); - - if(!channel[i].hdma_completed || hdma_active_after(i)) { - dma_add_clocks(4); - regs.mdr = dma_read(hdma_addr(i)); - channel[i].indirect_addr >>= 8; - channel[i].indirect_addr |= regs.mdr << 8; - dma_add_clocks(4); - dma_write(false); - } - } - } -} - -auto CPU::hdma_run() -> void { - dma_add_clocks(8); - dma_write(false); - - for(uint i = 0; i < 8; i++) { - if(hdma_active(i) == false) continue; - channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer - - if(channel[i].hdma_do_transfer) { - static const uint transfer_length[8] = {1, 2, 2, 4, 4, 4, 2, 4}; - uint length = transfer_length[channel[i].transfer_mode]; - for(uint index = 0; index < length; index++) { - uint addr = channel[i].indirect == false ? hdma_addr(i) : hdma_iaddr(i); - dma_transfer(channel[i].direction, dma_bbus(i, index), addr); - } - } - } - - for(uint i = 0; i < 8; i++) { - if(hdma_active(i) == false) continue; - - channel[i].line_counter--; - channel[i].hdma_do_transfer = channel[i].line_counter & 0x80; - hdma_update(i); - } - - status.irq_lock = true; -} - -auto CPU::hdma_init_reset() -> void { - for(uint i = 0; i < 8; i++) { - channel[i].hdma_completed = false; - channel[i].hdma_do_transfer = false; - } -} - -auto CPU::hdma_init() -> void { - dma_add_clocks(8); - dma_write(false); - - for(uint i = 0; i < 8; i++) { - if(!channel[i].hdma_enabled) continue; - channel[i].dma_enabled = false; //HDMA init during DMA will stop DMA mid-transfer - - channel[i].hdma_addr = channel[i].source_addr; - channel[i].line_counter = 0; - hdma_update(i); - } - - status.irq_lock = true; -} - -//============== -//initialization -//============== - -auto CPU::dma_power() -> void { - for(uint i = 0; i < 8; i++) { - channel[i].direction = 1; - channel[i].indirect = true; - channel[i].unused = true; - channel[i].reverse_transfer = true; - channel[i].fixed_transfer = true; - channel[i].transfer_mode = 7; - - channel[i].dest_addr = 0xff; - - channel[i].source_addr = 0xffff; - channel[i].source_bank = 0xff; - - channel[i].transfer_size = 0xffff; - channel[i].indirect_bank = 0xff; - - channel[i].hdma_addr = 0xffff; - channel[i].line_counter = 0xff; - channel[i].unknown = 0xff; - } -} - -auto CPU::dma_reset() -> void { - for(uint i = 0; i < 8; i++) { - channel[i].dma_enabled = false; - channel[i].hdma_enabled = false; - - channel[i].hdma_completed = false; - channel[i].hdma_do_transfer = false; - } - - pipe.valid = false; - pipe.addr = 0; - pipe.data = 0; -} diff --git a/higan/sfc/cpu/dma/dma.hpp b/higan/sfc/cpu/dma/dma.hpp deleted file mode 100644 index a0a54f48..00000000 --- a/higan/sfc/cpu/dma/dma.hpp +++ /dev/null @@ -1,79 +0,0 @@ -struct { - //$420b - bool dma_enabled; - - //$420c - bool hdma_enabled; - - //$43x0 - bool direction; - bool indirect; - bool unused; - bool reverse_transfer; - bool fixed_transfer; - uint3 transfer_mode; - - //$43x1 - uint8 dest_addr; - - //$43x2-$43x3 - uint16 source_addr; - - //$43x4 - uint8 source_bank; - - //$43x5-$43x6 - union { - uint16_t transfer_size; - uint16_t indirect_addr; - }; - - //$43x7 - uint8 indirect_bank; - - //$43x8-$43x9 - uint16 hdma_addr; - - //$43xa - uint8 line_counter; - - //$43xb/$43xf - uint8 unknown; - - //internal state - bool hdma_completed; - bool hdma_do_transfer; -} channel[8]; - -struct { - bool valid; - uint addr; - uint8 data; -} pipe; - -auto dma_add_clocks(uint clocks) -> void; -auto dma_transfer_valid(uint8 bbus, uint32 abus) -> bool; -auto dma_addr_valid(uint32 abus) -> bool; -auto dma_read(uint32 abus) -> uint8; -auto dma_write(bool valid, uint addr = 0, uint8 data = 0) -> void; -auto dma_transfer(bool direction, uint8 bbus, uint32 abus) -> void; - -auto dma_bbus(uint i, uint channel) -> uint8; -auto dma_addr(uint i) -> uint32; -auto hdma_addr(uint i) -> uint32; -auto hdma_iaddr(uint i) -> uint32; - -auto dma_enabled_channels() -> uint8; -auto hdma_active(uint i) -> bool; -auto hdma_active_after(uint i) -> bool; -auto hdma_enabled_channels() -> uint8; -auto hdma_active_channels() -> uint8; - -auto dma_run() -> void; -auto hdma_update(uint i) -> void; -auto hdma_run() -> void; -auto hdma_init_reset() -> void; -auto hdma_init() -> void; - -auto dma_power() -> void; -auto dma_reset() -> void; diff --git a/higan/sfc/cpu/timing/irq.cpp b/higan/sfc/cpu/irq.cpp similarity index 94% rename from higan/sfc/cpu/timing/irq.cpp rename to higan/sfc/cpu/irq.cpp index f47b0326..b7e81973 100644 --- a/higan/sfc/cpu/timing/irq.cpp +++ b/higan/sfc/cpu/irq.cpp @@ -3,7 +3,7 @@ // //ppu.(vh)counter(n) returns the value of said counters n-clocks before current time; //it is used to emulate hardware communication delay between opcode and interrupt units. -auto CPU::poll_interrupts() -> void { +auto CPU::pollInterrupts() -> void { //NMI hold if(status.nmi_hold) { status.nmi_hold = false; @@ -44,7 +44,7 @@ auto CPU::poll_interrupts() -> void { status.irq_valid = irq_valid; } -auto CPU::nmitimen_update(uint8 data) -> void { +auto CPU::nmitimenUpdate(uint8 data) -> void { bool nmi_enabled = status.nmi_enabled; bool virq_enabled = status.virq_enabled; bool hirq_enabled = status.hirq_enabled; @@ -87,14 +87,14 @@ auto CPU::timeup() -> bool { return result; } -auto CPU::nmi_test() -> bool { +auto CPU::nmiTest() -> bool { if(!status.nmi_transition) return false; status.nmi_transition = false; regs.wai = false; return true; } -auto CPU::irq_test() -> bool { +auto CPU::irqTest() -> bool { if(!status.irq_transition && !regs.irq) return false; status.irq_transition = false; regs.wai = false; diff --git a/higan/sfc/cpu/timing/joypad.cpp b/higan/sfc/cpu/joypad.cpp similarity index 61% rename from higan/sfc/cpu/timing/joypad.cpp rename to higan/sfc/cpu/joypad.cpp index 0abf7afc..0d257b03 100644 --- a/higan/sfc/cpu/timing/joypad.cpp +++ b/higan/sfc/cpu/joypad.cpp @@ -1,6 +1,6 @@ -//called every 256 clocks; see CPU::add_clocks() -auto CPU::step_auto_joypad_poll() -> void { - if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) { +//called every 256 clocks; see CPU::addClocks() +auto CPU::stepAutoJoypadPoll() -> void { + if(vcounter() >= !ppu.overscan() ? 225 : 240) { //cache enable state at first iteration if(status.auto_joypad_counter == 0) status.auto_joypad_latch = status.auto_joypad_poll; status.auto_joypad_active = status.auto_joypad_counter <= 15; @@ -16,10 +16,10 @@ auto CPU::step_auto_joypad_poll() -> void { uint2 port0 = device.controllerPort1->data(); uint2 port1 = device.controllerPort2->data(); - status.joy1 = (status.joy1 << 1) | (bool)(port0 & 1); - status.joy2 = (status.joy2 << 1) | (bool)(port1 & 1); - status.joy3 = (status.joy3 << 1) | (bool)(port0 & 2); - status.joy4 = (status.joy4 << 1) | (bool)(port1 & 2); + status.joy1 = status.joy1 << 1 | port0.bit(0); + status.joy2 = status.joy2 << 1 | port1.bit(0); + status.joy3 = status.joy3 << 1 | port0.bit(1); + status.joy4 = status.joy4 << 1 | port1.bit(1); } status.auto_joypad_counter++; diff --git a/higan/sfc/cpu/memory/memory.cpp b/higan/sfc/cpu/memory.cpp similarity index 65% rename from higan/sfc/cpu/memory/memory.cpp rename to higan/sfc/cpu/memory.cpp index 05334adf..8a845806 100644 --- a/higan/sfc/cpu/memory/memory.cpp +++ b/higan/sfc/cpu/memory.cpp @@ -6,29 +6,29 @@ auto CPU::portWrite(uint2 port, uint8 data) -> void { status.port[port] = data; } -auto CPU::op_io() -> void { +auto CPU::io() -> void { status.clock_count = 6; - dma_edge(); - add_clocks(6); - alu_edge(); + dmaEdge(); + addClocks(6); + aluEdge(); } -auto CPU::op_read(uint24 addr) -> uint8 { +auto CPU::read(uint24 addr) -> uint8 { status.clock_count = speed(addr); - dma_edge(); - add_clocks(status.clock_count - 4); + dmaEdge(); + addClocks(status.clock_count - 4); regs.mdr = bus.read(addr, regs.mdr); - add_clocks(4); - alu_edge(); + addClocks(4); + aluEdge(); debugger.op_read(addr, regs.mdr); return regs.mdr; } -auto CPU::op_write(uint24 addr, uint8 data) -> void { - alu_edge(); +auto CPU::write(uint24 addr, uint8 data) -> void { + aluEdge(); status.clock_count = speed(addr); - dma_edge(); - add_clocks(status.clock_count); + dmaEdge(); + addClocks(status.clock_count); bus.write(addr, regs.mdr = data); debugger.op_write(addr, regs.mdr); } @@ -43,6 +43,6 @@ auto CPU::speed(uint24 addr) const -> uint { return 12; } -auto CPU::disassembler_read(uint24 addr) -> uint8 { +auto CPU::disassemblerRead(uint24 addr) -> uint8 { return bus.read(addr, regs.mdr); } diff --git a/higan/sfc/cpu/memory/memory.hpp b/higan/sfc/cpu/memory/memory.hpp deleted file mode 100644 index 9109f5e3..00000000 --- a/higan/sfc/cpu/memory/memory.hpp +++ /dev/null @@ -1,6 +0,0 @@ -auto op_io() -> void override; -auto op_read(uint24 addr) -> uint8 override; -auto op_write(uint24 addr, uint8 data) -> void override; -alwaysinline auto speed(uint24 addr) const -> uint; - -auto disassembler_read(uint24 addr) -> uint8 override; diff --git a/higan/sfc/cpu/mmio.cpp b/higan/sfc/cpu/mmio.cpp new file mode 100644 index 00000000..e3e068f4 --- /dev/null +++ b/higan/sfc/cpu/mmio.cpp @@ -0,0 +1,345 @@ +auto CPU::apuPortRead(uint24 addr, uint8 data) -> uint8 { + synchronizeSMP(); + return smp.portRead(addr.bits(0,1)); +} + +auto CPU::cpuPortRead(uint24 addr, uint8 data) -> uint8 { + addr &= 0xffff; + + //WMDATA + if(addr == 0x2180) { + return bus.read(0x7e0000 | status.wram_addr++, regs.mdr); + } + + //JOYSER0 + //7-2 = MDR + //1-0 = Joypad serial data + if(addr == 0x4016) { + uint8 r = regs.mdr & 0xfc; + r |= device.controllerPort1->data(); + return r; + } + + //JOYSER1 + if(addr == 0x4017) { + //7-5 = MDR + //4-2 = Always 1 (pins are connected to GND) + //1-0 = Joypad serial data + uint8 r = (regs.mdr & 0xe0) | 0x1c; + r |= device.controllerPort2->data(); + return r; + } + + //RDNMI + if(addr == 0x4210) { + //7 = NMI acknowledge + //6-4 = MDR + //3-0 = CPU (5a22) version + uint8 r = (regs.mdr & 0x70); + r |= (uint8)(rdnmi()) << 7; + r |= (cpu_version & 0x0f); + return r; + } + + //TIMEUP + if(addr == 0x4211) { + //7 = IRQ acknowledge + //6-0 = MDR + uint8 r = (regs.mdr & 0x7f); + r |= (uint8)(timeup()) << 7; + return r; + } + + //HVBJOY + if(addr == 0x4212) { + //7 = VBLANK acknowledge + //6 = HBLANK acknowledge + //5-1 = MDR + //0 = JOYPAD acknowledge + uint8 r = (regs.mdr & 0x3e); + if(status.auto_joypad_active) r |= 0x01; + if(hcounter() <= 2 || hcounter() >= 1096) r |= 0x40; //hblank + if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) r |= 0x80; //vblank + return r; + } + + //RDIO + if(addr == 0x4213) { + return status.pio; + } + + //RDDIVL + if(addr == 0x4214) { + return status.rddiv.byte(0); + } + + //RDDIVH + if(addr == 0x4215) { + return status.rddiv.byte(1); + } + + //RDMPYL + if(addr == 0x4216) { + return status.rdmpy.byte(0); + } + + //RDMPYH + if(addr == 0x4217) { + return status.rdmpy.byte(1); + } + + if(addr == 0x4218) return status.joy1.byte(0); //JOY1L + if(addr == 0x4219) return status.joy1.byte(1); //JOY1H + if(addr == 0x421a) return status.joy2.byte(0); //JOY2L + if(addr == 0x421b) return status.joy2.byte(1); //JOY2H + if(addr == 0x421c) return status.joy3.byte(0); //JOY3L + if(addr == 0x421d) return status.joy3.byte(1); //JOY3H + if(addr == 0x421e) return status.joy4.byte(0); //JOY4L + if(addr == 0x421f) return status.joy4.byte(1); //JOY4H + + return data; +} + +auto CPU::dmaPortRead(uint24 addr, uint8 data) -> uint8 { + auto& channel = this->channel[addr.bits(4,6)]; + addr &= 0xff0f; + + //DMAPx + if(addr == 0x4300) return ( + channel.direction << 7 + | channel.indirect << 6 + | channel.unused << 5 + | channel.reverse_transfer << 4 + | channel.fixed_transfer << 3 + | channel.transfer_mode << 0 + ); + + //BBADx + if(addr == 0x4301) return channel.dest_addr; + + //A1TxL + if(addr == 0x4302) return channel.source_addr >> 0; + + //A1TxH + if(addr == 0x4303) return channel.source_addr >> 8; + + //A1Bx + if(addr == 0x4304) return channel.source_bank; + + //DASxL -- union { uint16 transfer_size; uint16 indirect_addr; }; + if(addr == 0x4305) return channel.transfer_size >> 0; + + //DASxH -- union { uint16 transfer_size; uint16 indirect_addr; }; + if(addr == 0x4306) return channel.transfer_size >> 8; + + //DASBx + if(addr == 0x4307) return channel.indirect_bank; + + //A2AxL + if(addr == 0x4308) return channel.hdma_addr >> 0; + + //A2AxH + if(addr == 0x4309) return channel.hdma_addr >> 8; + + //NTRLx + if(addr == 0x430a) return channel.line_counter; + + //??? + if(addr == 0x430b || addr == 0x430f) return channel.unknown; + + return data; +} + +auto CPU::apuPortWrite(uint24 addr, uint8 data) -> void { + synchronizeSMP(); + return portWrite(addr.bits(0,1), data); +} + +auto CPU::cpuPortWrite(uint24 addr, uint8 data) -> void { + addr &= 0xffff; + + //WMDATA + if(addr == 0x2180) { + bus.write(0x7e0000 | status.wram_addr++, data); + } + + //WMADDL + if(addr == 0x2181) { + status.wram_addr.bits(0,7) = data; + } + + //WMADDM + if(addr == 0x2182) { + status.wram_addr.bits(8,15) = data; + } + + //WMADDH + if(addr == 0x2183) { + status.wram_addr.bit(16) = data.bit(0); + } + + //JOYSER0 + if(addr == 0x4016) { + //bit 0 is shared between JOYSER0 and JOYSER1, therefore + //strobing $4016.d0 affects both controller port latches. + //$4017 bit 0 writes are ignored. + device.controllerPort1->latch(data.bit(0)); + device.controllerPort2->latch(data.bit(0)); + } + + //NMITIMEN + if(addr == 0x4200) { + status.auto_joypad_poll = data.bit(0); + nmitimenUpdate(data); + } + + //WRIO + if(addr == 0x4201) { + if(status.pio.bit(7) && !data.bit(7)) ppu.latch_counters(); + status.pio = data; + } + + //WRMPYA + if(addr == 0x4202) { + status.wrmpya = data; + } + + //WRMPYB + if(addr == 0x4203) { + status.rdmpy = 0; + if(alu.mpyctr || alu.divctr) return; + + status.wrmpyb = data; + status.rddiv = (status.wrmpyb << 8) | status.wrmpya; + + alu.mpyctr = 8; //perform multiplication over the next eight cycles + alu.shift = status.wrmpyb; + } + + //WRDIVL + if(addr == 0x4204) { + status.wrdiva.byte(0) = data; + } + + //WRDIVH + if(addr == 0x4205) { + status.wrdiva.byte(1) = data; + } + + //WRDIVB + if(addr == 0x4206) { + status.rdmpy = status.wrdiva; + if(alu.mpyctr || alu.divctr) return; + + status.wrdivb = data; + + alu.divctr = 16; //perform division over the next sixteen cycles + alu.shift = status.wrdivb << 16; + } + + //HTIMEL + if(addr == 0x4207) { + status.hirq_pos.bits(0,7) = data; + } + + //HTIMEH + if(addr == 0x4208) { + status.hirq_pos.bit(8) = data.bit(0); + } + + //VTIMEL + if(addr == 0x4209) { + status.virq_pos.bits(0,7) = data; + } + + //VTIMEH + if(addr == 0x420a) { + status.virq_pos.bit(8) = data; + } + + //DMAEN + if(addr == 0x420b) { + for(auto n : range(8)) channel[n].dma_enabled = data.bit(n); + if(data) status.dma_pending = true; + } + + //HDMAEN + if(addr == 0x420c) { + for(auto n : range(8)) channel[n].hdma_enabled = data.bit(n); + } + + //MEMSEL + if(addr == 0x420d) { + status.rom_speed = data.bit(0) ? 6 : 8; + } +} + +auto CPU::dmaPortWrite(uint24 addr, uint8 data) -> void { + auto& channel = this->channel[addr.bits(4,6)]; + addr &= 0xff0f; + + //DMAPx + if(addr == 0x4300) { + channel.direction = data & 0x80; + channel.indirect = data & 0x40; + channel.unused = data & 0x20; + channel.reverse_transfer = data & 0x10; + channel.fixed_transfer = data & 0x08; + channel.transfer_mode = data & 0x07; + } + + //DDBADx + if(addr == 0x4301) { + channel.dest_addr = data; + } + + //A1TxL + if(addr == 0x4302) { + channel.source_addr = (channel.source_addr & 0xff00) | (data << 0); + } + + //A1TxH + if(addr == 0x4303) { + channel.source_addr = (channel.source_addr & 0x00ff) | (data << 8); + } + + //A1Bx + if(addr == 0x4304) { + channel.source_bank = data; + } + + //DASxL -- union { uint16 transfer_size; uint16 indirect_addr; }; + if(addr == 0x4305) { + channel.transfer_size = (channel.transfer_size & 0xff00) | (data << 0); + } + + //DASxH -- union { uint16 transfer_size; uint16 indirect_addr; }; + if(addr == 0x4306) { + channel.transfer_size = (channel.transfer_size & 0x00ff) | (data << 8); + } + + //DASBx + if(addr == 0x4307) { + channel.indirect_bank = data; + } + + //A2AxL + if(addr == 0x4308) { + channel.hdma_addr = (channel.hdma_addr & 0xff00) | (data << 0); + } + + //A2AxH + if(addr == 0x4309) { + channel.hdma_addr = (channel.hdma_addr & 0x00ff) | (data << 8); + } + + //NTRLx + if(addr == 0x430a) { + channel.line_counter = data; + } + + //??? + if(addr == 0x430b || addr == 0x430f) { + channel.unknown = data; + } +} diff --git a/higan/sfc/cpu/mmio/mmio.cpp b/higan/sfc/cpu/mmio/mmio.cpp deleted file mode 100644 index 3c43fd91..00000000 --- a/higan/sfc/cpu/mmio/mmio.cpp +++ /dev/null @@ -1,520 +0,0 @@ -auto CPU::pio() -> uint8 { - return status.pio; -} - -auto CPU::joylatch() -> bool { - return status.joypad_strobe_latch; -} - -//WMDATA -auto CPU::mmio_r2180() -> uint8 { - return bus.read(0x7e0000 | status.wram_addr++, regs.mdr); -} - -//WMDATA -auto CPU::mmio_w2180(uint8 data) -> void { - bus.write(0x7e0000 | status.wram_addr++, data); -} - -//WMADDL -auto CPU::mmio_w2181(uint8 data) -> void { - status.wram_addr = (status.wram_addr & 0x01ff00) | (data << 0); -} - -//WMADDM -auto CPU::mmio_w2182(uint8 data) -> void { - status.wram_addr = (status.wram_addr & 0x0100ff) | (data << 8); -} - -//WMADDH -auto CPU::mmio_w2183(uint8 data) -> void { - status.wram_addr = (status.wram_addr & 0x00ffff) | (data << 16); -} - -//JOYSER0 -//bit 0 is shared between JOYSER0 and JOYSER1, therefore -//strobing $4016.d0 affects both controller port latches. -//$4017 bit 0 writes are ignored. -auto CPU::mmio_w4016(uint8 data) -> void { - device.controllerPort1->latch(data & 1); - device.controllerPort2->latch(data & 1); -} - -//JOYSER0 -//7-2 = MDR -//1-0 = Joypad serial data -auto CPU::mmio_r4016() -> uint8 { - uint8 r = regs.mdr & 0xfc; - r |= device.controllerPort1->data(); - return r; -} - -//JOYSER1 -//7-5 = MDR -//4-2 = Always 1 (pins are connected to GND) -//1-0 = Joypad serial data -auto CPU::mmio_r4017() -> uint8 { - uint8 r = (regs.mdr & 0xe0) | 0x1c; - r |= device.controllerPort2->data(); - return r; -} - -//NMITIMEN -auto CPU::mmio_w4200(uint8 data) -> void { - status.auto_joypad_poll = data & 1; - nmitimen_update(data); -} - -//WRIO -auto CPU::mmio_w4201(uint8 data) -> void { - if((status.pio & 0x80) && !(data & 0x80)) ppu.latch_counters(); - status.pio = data; -} - -//WRMPYA -auto CPU::mmio_w4202(uint8 data) -> void { - status.wrmpya = data; -} - -//WRMPYB -auto CPU::mmio_w4203(uint8 data) -> void { - status.rdmpy = 0; - if(alu.mpyctr || alu.divctr) return; - - status.wrmpyb = data; - status.rddiv = (status.wrmpyb << 8) | status.wrmpya; - - alu.mpyctr = 8; //perform multiplication over the next eight cycles - alu.shift = status.wrmpyb; -} - -//WRDIVL -auto CPU::mmio_w4204(uint8 data) -> void { - status.wrdiva = (status.wrdiva & 0xff00) | (data << 0); -} - -//WRDIVH -auto CPU::mmio_w4205(uint8 data) -> void { - status.wrdiva = (status.wrdiva & 0x00ff) | (data << 8); -} - -//WRDIVB -auto CPU::mmio_w4206(uint8 data) -> void { - status.rdmpy = status.wrdiva; - if(alu.mpyctr || alu.divctr) return; - - status.wrdivb = data; - - alu.divctr = 16; //perform division over the next sixteen cycles - alu.shift = status.wrdivb << 16; -} - -//HTIMEL -auto CPU::mmio_w4207(uint8 data) -> void { - status.hirq_pos = (status.hirq_pos & 0x0100) | (data << 0); -} - -//HTIMEH -auto CPU::mmio_w4208(uint8 data) -> void { - status.hirq_pos = (status.hirq_pos & 0x00ff) | (data << 8); -} - -//VTIMEL -auto CPU::mmio_w4209(uint8 data) -> void { - status.virq_pos = (status.virq_pos & 0x0100) | (data << 0); -} - -//VTIMEH -auto CPU::mmio_w420a(uint8 data) -> void { - status.virq_pos = (status.virq_pos & 0x00ff) | (data << 8); -} - -//DMAEN -auto CPU::mmio_w420b(uint8 data) -> void { - for(unsigned i = 0; i < 8; i++) { - channel[i].dma_enabled = data & (1 << i); - } - if(data) status.dma_pending = true; -} - -//HDMAEN -auto CPU::mmio_w420c(uint8 data) -> void { - for(unsigned i = 0; i < 8; i++) { - channel[i].hdma_enabled = data & (1 << i); - } -} - -//MEMSEL -auto CPU::mmio_w420d(uint8 data) -> void { - status.rom_speed = (data & 1 ? 6 : 8); -} - -//RDNMI -//7 = NMI acknowledge -//6-4 = MDR -//3-0 = CPU (5a22) version -auto CPU::mmio_r4210() -> uint8 { - uint8 r = (regs.mdr & 0x70); - r |= (uint8)(rdnmi()) << 7; - r |= (cpu_version & 0x0f); - return r; -} - -//TIMEUP -//7 = IRQ acknowledge -//6-0 = MDR -auto CPU::mmio_r4211() -> uint8 { - uint8 r = (regs.mdr & 0x7f); - r |= (uint8)(timeup()) << 7; - return r; -} - -//HVBJOY -//7 = VBLANK acknowledge -//6 = HBLANK acknowledge -//5-1 = MDR -//0 = JOYPAD acknowledge -auto CPU::mmio_r4212() -> uint8 { - uint8 r = (regs.mdr & 0x3e); - if(status.auto_joypad_active) r |= 0x01; - if(hcounter() <= 2 || hcounter() >= 1096) r |= 0x40; //hblank - if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) r |= 0x80; //vblank - return r; -} - -//RDIO -auto CPU::mmio_r4213() -> uint8 { - return status.pio; -} - -//RDDIVL -auto CPU::mmio_r4214() -> uint8 { - return status.rddiv >> 0; -} - -//RDDIVH -auto CPU::mmio_r4215() -> uint8 { - return status.rddiv >> 8; -} - -//RDMPYL -auto CPU::mmio_r4216() -> uint8 { - return status.rdmpy >> 0; -} - -//RDMPYH -auto CPU::mmio_r4217() -> uint8 { - return status.rdmpy >> 8; -} - -auto CPU::mmio_r4218() -> uint8 { return status.joy1 >> 0; } //JOY1L -auto CPU::mmio_r4219() -> uint8 { return status.joy1 >> 8; } //JOY1H -auto CPU::mmio_r421a() -> uint8 { return status.joy2 >> 0; } //JOY2L -auto CPU::mmio_r421b() -> uint8 { return status.joy2 >> 8; } //JOY2H -auto CPU::mmio_r421c() -> uint8 { return status.joy3 >> 0; } //JOY3L -auto CPU::mmio_r421d() -> uint8 { return status.joy3 >> 8; } //JOY3H -auto CPU::mmio_r421e() -> uint8 { return status.joy4 >> 0; } //JOY4L -auto CPU::mmio_r421f() -> uint8 { return status.joy4 >> 8; } //JOY4H - -//DMAPx -auto CPU::mmio_r43x0(uint8 i) -> uint8 { - return (channel[i].direction << 7) - | (channel[i].indirect << 6) - | (channel[i].unused << 5) - | (channel[i].reverse_transfer << 4) - | (channel[i].fixed_transfer << 3) - | (channel[i].transfer_mode << 0); -} - -//BBADx -auto CPU::mmio_r43x1(uint8 i) -> uint8 { - return channel[i].dest_addr; -} - -//A1TxL -auto CPU::mmio_r43x2(uint8 i) -> uint8 { - return channel[i].source_addr >> 0; -} - -//A1TxH -auto CPU::mmio_r43x3(uint8 i) -> uint8 { - return channel[i].source_addr >> 8; -} - -//A1Bx -auto CPU::mmio_r43x4(uint8 i) -> uint8 { - return channel[i].source_bank; -} - -//DASxL -//union { uint16 transfer_size; uint16 indirect_addr; }; -auto CPU::mmio_r43x5(uint8 i) -> uint8 { - return channel[i].transfer_size >> 0; -} - -//DASxH -//union { uint16 transfer_size; uint16 indirect_addr; }; -auto CPU::mmio_r43x6(uint8 i) -> uint8 { - return channel[i].transfer_size >> 8; -} - -//DASBx -auto CPU::mmio_r43x7(uint8 i) -> uint8 { - return channel[i].indirect_bank; -} - -//A2AxL -auto CPU::mmio_r43x8(uint8 i) -> uint8 { - return channel[i].hdma_addr >> 0; -} - -//A2AxH -auto CPU::mmio_r43x9(uint8 i) -> uint8 { - return channel[i].hdma_addr >> 8; -} - -//NTRLx -auto CPU::mmio_r43xa(uint8 i) -> uint8 { - return channel[i].line_counter; -} - -//??? -auto CPU::mmio_r43xb(uint8 i) -> uint8 { - return channel[i].unknown; -} - -//DMAPx -auto CPU::mmio_w43x0(uint8 i, uint8 data) -> void { - channel[i].direction = data & 0x80; - channel[i].indirect = data & 0x40; - channel[i].unused = data & 0x20; - channel[i].reverse_transfer = data & 0x10; - channel[i].fixed_transfer = data & 0x08; - channel[i].transfer_mode = data & 0x07; -} - -//DDBADx -auto CPU::mmio_w43x1(uint8 i, uint8 data) -> void { - channel[i].dest_addr = data; -} - -//A1TxL -auto CPU::mmio_w43x2(uint8 i, uint8 data) -> void { - channel[i].source_addr = (channel[i].source_addr & 0xff00) | (data << 0); -} - -//A1TxH -auto CPU::mmio_w43x3(uint8 i, uint8 data) -> void { - channel[i].source_addr = (channel[i].source_addr & 0x00ff) | (data << 8); -} - -//A1Bx -auto CPU::mmio_w43x4(uint8 i, uint8 data) -> void { - channel[i].source_bank = data; -} - -//DASxL -//union { uint16 transfer_size; uint16 indirect_addr; }; -auto CPU::mmio_w43x5(uint8 i, uint8 data) -> void { - channel[i].transfer_size = (channel[i].transfer_size & 0xff00) | (data << 0); -} - -//DASxH -//union { uint16 transfer_size; uint16 indirect_addr; }; -auto CPU::mmio_w43x6(uint8 i, uint8 data) -> void { - channel[i].transfer_size = (channel[i].transfer_size & 0x00ff) | (data << 8); -} - -//DASBx -auto CPU::mmio_w43x7(uint8 i, uint8 data) -> void { - channel[i].indirect_bank = data; -} - -//A2AxL -auto CPU::mmio_w43x8(uint8 i, uint8 data) -> void { - channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data << 0); -} - -//A2AxH -auto CPU::mmio_w43x9(uint8 i, uint8 data) -> void { - channel[i].hdma_addr = (channel[i].hdma_addr & 0x00ff) | (data << 8); -} - -//NTRLx -auto CPU::mmio_w43xa(uint8 i, uint8 data) -> void { - channel[i].line_counter = data; -} - -//??? -auto CPU::mmio_w43xb(uint8 i, uint8 data) -> void { - channel[i].unknown = data; -} - -auto CPU::mmio_power() -> void { -} - -auto CPU::mmio_reset() -> void { - //$2140-217f - for(auto& port : status.port) port = 0x00; - - //$2181-$2183 - status.wram_addr = 0x000000; - - //$4016-$4017 - status.joypad_strobe_latch = 0; - status.joypad1_bits = ~0; - status.joypad2_bits = ~0; - - //$4200 - status.nmi_enabled = false; - status.hirq_enabled = false; - status.virq_enabled = false; - status.auto_joypad_poll = false; - - //$4201 - status.pio = 0xff; - - //$4202-$4203 - status.wrmpya = 0xff; - status.wrmpyb = 0xff; - - //$4204-$4206 - status.wrdiva = 0xffff; - status.wrdivb = 0xff; - - //$4207-$420a - status.hirq_pos = 0x01ff; - status.virq_pos = 0x01ff; - - //$420d - status.rom_speed = 8; - - //$4214-$4217 - status.rddiv = 0x0000; - status.rdmpy = 0x0000; - - //$4218-$421f - status.joy1 = 0x0000; - status.joy2 = 0x0000; - status.joy3 = 0x0000; - status.joy4 = 0x0000; - - //ALU - alu.mpyctr = 0; - alu.divctr = 0; - alu.shift = 0; -} - -auto CPU::mmio_read(uint addr, uint8 data) -> uint8 { - addr &= 0xffff; - - //APU - if((addr & 0xffc0) == 0x2140) { //$2140-$217f - synchronizeSMP(); - return smp.portRead(addr); - } - - //DMA - if((addr & 0xff80) == 0x4300) { //$4300-$437f - uint i = (addr >> 4) & 7; - switch(addr & 0xf) { - case 0x0: return mmio_r43x0(i); - case 0x1: return mmio_r43x1(i); - case 0x2: return mmio_r43x2(i); - case 0x3: return mmio_r43x3(i); - case 0x4: return mmio_r43x4(i); - case 0x5: return mmio_r43x5(i); - case 0x6: return mmio_r43x6(i); - case 0x7: return mmio_r43x7(i); - case 0x8: return mmio_r43x8(i); - case 0x9: return mmio_r43x9(i); - case 0xa: return mmio_r43xa(i); - case 0xb: return mmio_r43xb(i); - case 0xc: return regs.mdr; //unmapped - case 0xd: return regs.mdr; //unmapped - case 0xe: return regs.mdr; //unmapped - case 0xf: return mmio_r43xb(i); //mirror of $43xb - } - } - - switch(addr) { - case 0x2180: return mmio_r2180(); - case 0x4016: return mmio_r4016(); - case 0x4017: return mmio_r4017(); - case 0x4210: return mmio_r4210(); - case 0x4211: return mmio_r4211(); - case 0x4212: return mmio_r4212(); - case 0x4213: return mmio_r4213(); - case 0x4214: return mmio_r4214(); - case 0x4215: return mmio_r4215(); - case 0x4216: return mmio_r4216(); - case 0x4217: return mmio_r4217(); - case 0x4218: return mmio_r4218(); - case 0x4219: return mmio_r4219(); - case 0x421a: return mmio_r421a(); - case 0x421b: return mmio_r421b(); - case 0x421c: return mmio_r421c(); - case 0x421d: return mmio_r421d(); - case 0x421e: return mmio_r421e(); - case 0x421f: return mmio_r421f(); - } - - return data; -} - -auto CPU::mmio_write(uint addr, uint8 data) -> void { - addr &= 0xffff; - - //APU - if((addr & 0xffc0) == 0x2140) { //$2140-$217f - synchronizeSMP(); - portWrite(addr, data); - return; - } - - //DMA - if((addr & 0xff80) == 0x4300) { //$4300-$437f - uint i = (addr >> 4) & 7; - switch(addr & 0xf) { - case 0x0: mmio_w43x0(i, data); return; - case 0x1: mmio_w43x1(i, data); return; - case 0x2: mmio_w43x2(i, data); return; - case 0x3: mmio_w43x3(i, data); return; - case 0x4: mmio_w43x4(i, data); return; - case 0x5: mmio_w43x5(i, data); return; - case 0x6: mmio_w43x6(i, data); return; - case 0x7: mmio_w43x7(i, data); return; - case 0x8: mmio_w43x8(i, data); return; - case 0x9: mmio_w43x9(i, data); return; - case 0xa: mmio_w43xa(i, data); return; - case 0xb: mmio_w43xb(i, data); return; - case 0xc: return; //unmapped - case 0xd: return; //unmapped - case 0xe: return; //unmapped - case 0xf: mmio_w43xb(i, data); return; //mirror of $43xb - } - } - - switch(addr) { - case 0x2180: mmio_w2180(data); return; - case 0x2181: mmio_w2181(data); return; - case 0x2182: mmio_w2182(data); return; - case 0x2183: mmio_w2183(data); return; - case 0x4016: mmio_w4016(data); return; - case 0x4017: return; //unmapped - case 0x4200: mmio_w4200(data); return; - case 0x4201: mmio_w4201(data); return; - case 0x4202: mmio_w4202(data); return; - case 0x4203: mmio_w4203(data); return; - case 0x4204: mmio_w4204(data); return; - case 0x4205: mmio_w4205(data); return; - case 0x4206: mmio_w4206(data); return; - case 0x4207: mmio_w4207(data); return; - case 0x4208: mmio_w4208(data); return; - case 0x4209: mmio_w4209(data); return; - case 0x420a: mmio_w420a(data); return; - case 0x420b: mmio_w420b(data); return; - case 0x420c: mmio_w420c(data); return; - case 0x420d: mmio_w420d(data); return; - } -} diff --git a/higan/sfc/cpu/mmio/mmio.hpp b/higan/sfc/cpu/mmio/mmio.hpp deleted file mode 100644 index d25235ab..00000000 --- a/higan/sfc/cpu/mmio/mmio.hpp +++ /dev/null @@ -1,71 +0,0 @@ -public: -auto mmio_read(uint addr, uint8 data) -> uint8; -auto mmio_write(uint addr, uint8 data) -> void; - -privileged: -auto mmio_power() -> void; -auto mmio_reset() -> void; - -auto mmio_r2180() -> uint8; -auto mmio_r4016() -> uint8; -auto mmio_r4017() -> uint8; -auto mmio_r4210() -> uint8; -auto mmio_r4211() -> uint8; -auto mmio_r4212() -> uint8; -auto mmio_r4213() -> uint8; -auto mmio_r4214() -> uint8; -auto mmio_r4215() -> uint8; -auto mmio_r4216() -> uint8; -auto mmio_r4217() -> uint8; -auto mmio_r4218() -> uint8; -auto mmio_r4219() -> uint8; -auto mmio_r421a() -> uint8; -auto mmio_r421b() -> uint8; -auto mmio_r421c() -> uint8; -auto mmio_r421d() -> uint8; -auto mmio_r421e() -> uint8; -auto mmio_r421f() -> uint8; -auto mmio_r43x0(uint8 i) -> uint8; -auto mmio_r43x1(uint8 i) -> uint8; -auto mmio_r43x2(uint8 i) -> uint8; -auto mmio_r43x3(uint8 i) -> uint8; -auto mmio_r43x4(uint8 i) -> uint8; -auto mmio_r43x5(uint8 i) -> uint8; -auto mmio_r43x6(uint8 i) -> uint8; -auto mmio_r43x7(uint8 i) -> uint8; -auto mmio_r43x8(uint8 i) -> uint8; -auto mmio_r43x9(uint8 i) -> uint8; -auto mmio_r43xa(uint8 i) -> uint8; -auto mmio_r43xb(uint8 i) -> uint8; - -auto mmio_w2180(uint8 data) -> void; -auto mmio_w2181(uint8 data) -> void; -auto mmio_w2182(uint8 data) -> void; -auto mmio_w2183(uint8 data) -> void; -auto mmio_w4016(uint8 data) -> void; -auto mmio_w4200(uint8 data) -> void; -auto mmio_w4201(uint8 data) -> void; -auto mmio_w4202(uint8 data) -> void; -auto mmio_w4203(uint8 data) -> void; -auto mmio_w4204(uint8 data) -> void; -auto mmio_w4205(uint8 data) -> void; -auto mmio_w4206(uint8 data) -> void; -auto mmio_w4207(uint8 data) -> void; -auto mmio_w4208(uint8 data) -> void; -auto mmio_w4209(uint8 data) -> void; -auto mmio_w420a(uint8 data) -> void; -auto mmio_w420b(uint8 data) -> void; -auto mmio_w420c(uint8 data) -> void; -auto mmio_w420d(uint8 data) -> void; -auto mmio_w43x0(uint8 i, uint8 data) -> void; -auto mmio_w43x1(uint8 i, uint8 data) -> void; -auto mmio_w43x2(uint8 i, uint8 data) -> void; -auto mmio_w43x3(uint8 i, uint8 data) -> void; -auto mmio_w43x4(uint8 i, uint8 data) -> void; -auto mmio_w43x5(uint8 i, uint8 data) -> void; -auto mmio_w43x6(uint8 i, uint8 data) -> void; -auto mmio_w43x7(uint8 i, uint8 data) -> void; -auto mmio_w43x8(uint8 i, uint8 data) -> void; -auto mmio_w43x9(uint8 i, uint8 data) -> void; -auto mmio_w43xa(uint8 i, uint8 data) -> void; -auto mmio_w43xb(uint8 i, uint8 data) -> void; diff --git a/higan/sfc/cpu/timing/timing.cpp b/higan/sfc/cpu/timing.cpp similarity index 57% rename from higan/sfc/cpu/timing/timing.cpp rename to higan/sfc/cpu/timing.cpp index 801fd679..4ceeecab 100644 --- a/higan/sfc/cpu/timing/timing.cpp +++ b/higan/sfc/cpu/timing.cpp @@ -1,16 +1,13 @@ -#include "irq.cpp" -#include "joypad.cpp" - -auto CPU::dma_counter() -> uint { +auto CPU::dmaCounter() const -> uint { return (status.dma_counter + hcounter()) & 7; } -auto CPU::add_clocks(uint clocks) -> void { +auto CPU::addClocks(uint clocks) -> void { status.irq_lock = false; uint ticks = clocks >> 1; while(ticks--) { tick(); - if(hcounter() & 2) poll_interrupts(); + if(hcounter() & 2) pollInterrupts(); } step(clocks); @@ -18,12 +15,12 @@ auto CPU::add_clocks(uint clocks) -> void { status.auto_joypad_clock += clocks; if(status.auto_joypad_clock >= 256) { status.auto_joypad_clock -= 256; - step_auto_joypad_poll(); + stepAutoJoypadPoll(); } - if(status.dram_refreshed == false && hcounter() >= status.dram_refresh_position) { + if(!status.dram_refreshed && hcounter() >= status.dram_refresh_position) { status.dram_refreshed = true; - add_clocks(40); + addClocks(40); } #if defined(DEBUGGER) @@ -45,14 +42,14 @@ auto CPU::scanline() -> void { if(vcounter() == 0) { //HDMA init triggers once every frame - status.hdma_init_position = (cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter()); + status.hdma_init_position = (cpu_version == 1 ? 12 + 8 - dmaCounter() : 12 + dmaCounter()); status.hdma_init_triggered = false; status.auto_joypad_counter = 0; } //DRAM refresh occurs once every scanline - if(cpu_version == 2) status.dram_refresh_position = 530 + 8 - dma_counter(); + if(cpu_version == 2) status.dram_refresh_position = 530 + 8 - dmaCounter(); status.dram_refreshed = false; //HDMA triggers once every visible scanline @@ -62,7 +59,7 @@ auto CPU::scanline() -> void { } } -auto CPU::alu_edge() -> void { +auto CPU::aluEdge() -> void { if(alu.mpyctr) { alu.mpyctr--; if(status.rddiv & 1) status.rdmpy += alu.shift; @@ -81,7 +78,7 @@ auto CPU::alu_edge() -> void { } } -auto CPU::dma_edge() -> void { +auto CPU::dmaEdge() -> void { //H/DMA pending && DMA inactive? //.. Run one full CPU cycle //.. HDMA pending && HDMA enabled ? DMA sync + HDMA run @@ -93,13 +90,13 @@ auto CPU::dma_edge() -> void { if(status.dma_active == true) { if(status.hdma_pending) { status.hdma_pending = false; - if(hdma_enabled_channels()) { - if(!dma_enabled_channels()) { - dma_add_clocks(8 - dma_counter()); + if(hdmaEnabledChannels()) { + if(!dmaEnabledChannels()) { + dmaAddClocks(8 - dmaCounter()); } - status.hdma_mode == 0 ? hdma_init() : hdma_run(); - if(!dma_enabled_channels()) { - add_clocks(status.clock_count - (status.dma_clocks % status.clock_count)); + status.hdma_mode == 0 ? hdmaInit() : hdmaRun(); + if(!dmaEnabledChannels()) { + addClocks(status.clock_count - (status.dma_clocks % status.clock_count)); status.dma_active = false; } } @@ -107,10 +104,10 @@ auto CPU::dma_edge() -> void { if(status.dma_pending) { status.dma_pending = false; - if(dma_enabled_channels()) { - dma_add_clocks(8 - dma_counter()); - dma_run(); - add_clocks(status.clock_count - (status.dma_clocks % status.clock_count)); + if(dmaEnabledChannels()) { + dmaAddClocks(8 - dmaCounter()); + dmaRun(); + addClocks(status.clock_count - (status.dma_clocks % status.clock_count)); status.dma_active = false; } } @@ -118,8 +115,8 @@ auto CPU::dma_edge() -> void { if(status.hdma_init_triggered == false && hcounter() >= status.hdma_init_position) { status.hdma_init_triggered = true; - hdma_init_reset(); - if(hdma_enabled_channels()) { + hdmaInitReset(); + if(hdmaEnabledChannels()) { status.hdma_pending = true; status.hdma_mode = 0; } @@ -127,7 +124,7 @@ auto CPU::dma_edge() -> void { if(status.hdma_triggered == false && hcounter() >= status.hdma_position) { status.hdma_triggered = true; - if(hdma_active_channels()) { + if(hdmaActiveChannels()) { status.hdma_pending = true; status.hdma_mode = 1; } @@ -146,55 +143,10 @@ auto CPU::dma_edge() -> void { // //status.irq_lock is used to simulate hardware delay before interrupts can //trigger during certain events (immediately after DMA, writes to $4200, etc) -auto CPU::last_cycle() -> void { - if(status.irq_lock == false) { - status.nmi_pending |= nmi_test(); - status.irq_pending |= irq_test(); +auto CPU::lastCycle() -> void { + if(!status.irq_lock) { + status.nmi_pending |= nmiTest(); + status.irq_pending |= irqTest(); status.interrupt_pending = (status.nmi_pending || status.irq_pending); } } - -auto CPU::timing_power() -> void { -} - -auto CPU::timing_reset() -> void { - status.clock_count = 0; - status.line_clocks = lineclocks(); - - status.irq_lock = false; - status.dram_refresh_position = (cpu_version == 1 ? 530 : 538); - status.dram_refreshed = false; - - status.hdma_init_position = (cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter()); - status.hdma_init_triggered = false; - - status.hdma_position = 1104; - status.hdma_triggered = false; - - status.nmi_valid = false; - status.nmi_line = false; - status.nmi_transition = false; - status.nmi_pending = false; - status.nmi_hold = false; - - status.irq_valid = false; - status.irq_line = false; - status.irq_transition = false; - status.irq_pending = false; - status.irq_hold = false; - - status.reset_pending = true; - status.interrupt_pending = true; - - status.dma_active = false; - status.dma_counter = 0; - status.dma_clocks = 0; - status.dma_pending = false; - status.hdma_pending = false; - status.hdma_mode = 0; - - status.auto_joypad_active = false; - status.auto_joypad_latch = false; - status.auto_joypad_counter = 0; - status.auto_joypad_clock = 0; -} diff --git a/higan/sfc/cpu/timing/timing.hpp b/higan/sfc/cpu/timing/timing.hpp deleted file mode 100644 index 6d715ae1..00000000 --- a/higan/sfc/cpu/timing/timing.hpp +++ /dev/null @@ -1,24 +0,0 @@ -//timing.cpp -auto dma_counter() -> uint; - -auto add_clocks(uint clocks) -> void; -auto scanline() -> void; - -alwaysinline auto alu_edge() -> void; -alwaysinline auto dma_edge() -> void; -alwaysinline auto last_cycle() -> void; - -auto timing_power() -> void; -auto timing_reset() -> void; - -//irq.cpp -alwaysinline auto poll_interrupts() -> void; -auto nmitimen_update(uint8 data) -> void; -auto rdnmi() -> bool; -auto timeup() -> bool; - -alwaysinline auto nmi_test() -> bool; -alwaysinline auto irq_test() -> bool; - -//joypad.cpp -auto step_auto_joypad_poll() -> void; diff --git a/higan/ws/apu/serialization.cpp b/higan/ws/apu/serialization.cpp index 62d70e08..b850be8d 100644 --- a/higan/ws/apu/serialization.cpp +++ b/higan/ws/apu/serialization.cpp @@ -1,4 +1,6 @@ auto APU::serialize(serializer& s) -> void { + Thread::serialize(s); + s.integer(this->s.sweepClock); s.integer(r.waveBase); s.integer(r.speakerEnable); diff --git a/higan/ws/cartridge/cartridge.cpp b/higan/ws/cartridge/cartridge.cpp index 6c3c594e..43d3f6b1 100644 --- a/higan/ws/cartridge/cartridge.cpp +++ b/higan/ws/cartridge/cartridge.cpp @@ -31,6 +31,9 @@ auto Cartridge::power() -> void { bus.map(this, 0x00c0, 0x00c8); if(rtc.data) bus.map(this, 0x00ca, 0x00cb); + bus.map(this, 0x00cc, 0x00cd); + + memory::fill(&r, sizeof(Registers)); r.romBank0 = 0xff; r.romBank1 = 0xff; @@ -50,8 +53,11 @@ auto Cartridge::load() -> void { rom.name = node["name"].text(); rom.size = node["size"].natural(); rom.mask = bit::round(rom.size) - 1; - if(rom.size) rom.data = new uint8[rom.mask + 1](); - if(rom.name) interface->loadRequest(ID::ROM, rom.name, true); + if(rom.size) { + rom.data = new uint8[rom.mask + 1]; + memory::fill(rom.data, rom.mask + 1, 0xff); + if(rom.name) interface->loadRequest(ID::ROM, rom.name, true); + } } if(auto node = document["board/ram"]) { @@ -59,15 +65,20 @@ auto Cartridge::load() -> void { ram.name = node["name"].text(); ram.size = node["size"].natural(); ram.mask = bit::round(ram.size) - 1; - if(ram.size) ram.data = new uint8[ram.mask + 1](); - if(ram.name) interface->loadRequest(ID::RAM, ram.name, false); + if(ram.size) { + ram.data = new uint8[ram.mask + 1]; + memory::fill(ram.data, ram.mask + 1, 0xff); + if(ram.name) interface->loadRequest(ID::RAM, ram.name, false); + } } if(node["type"].text() == "eeprom") { eeprom.setName(node["name"].text()); eeprom.setSize(node["size"].natural() / sizeof(uint16)); - eeprom.erase(); - if(eeprom.name()) interface->loadRequest(ID::EEPROM, eeprom.name(), false); + if(eeprom.size()) { + eeprom.erase(); + if(eeprom.name()) interface->loadRequest(ID::EEPROM, eeprom.name(), false); + } } } @@ -75,8 +86,11 @@ auto Cartridge::load() -> void { rtc.name = node["name"].text(); rtc.size = node["size"].natural(); rtc.mask = bit::round(rtc.size) - 1; - if(rtc.size) rtc.data = new uint8[rtc.mask + 1](); - if(rtc.name) interface->loadRequest(ID::RTC, rtc.name, false); + if(rtc.size) { + rtc.data = new uint8[rtc.mask + 1]; + memory::fill(rtc.data, rtc.mask + 1, 0x00); + if(rtc.name) interface->loadRequest(ID::RTC, rtc.name, false); + } } information.title = document["information/title"].text(); diff --git a/higan/ws/cartridge/cartridge.hpp b/higan/ws/cartridge/cartridge.hpp index 70b04d34..33c8758e 100644 --- a/higan/ws/cartridge/cartridge.hpp +++ b/higan/ws/cartridge/cartridge.hpp @@ -31,11 +31,31 @@ struct Cartridge : Thread, IO { //serialization.cpp auto serialize(serializer&) -> void; + struct Information { + string manifest; + string title; + bool orientation; //0 = horizontal; 1 = vertical + string sha256; + } information; + struct Registers { - uint8 romBank0; - uint8 romBank1; + //$00c0 BANK_ROM2 uint8 romBank2; + + //$00c1 BANK_SRAM uint8 sramBank; + + //$00c2 BANK_ROM0 + uint8 romBank0; + + //$00c3 BANK_ROM1 + uint8 romBank1; + + //$00cc GPO_EN + uint8 gpoEnable; + + //$00cd GPO_DATA + uint8 gpoData; } r; struct Memory { @@ -66,13 +86,6 @@ struct Cartridge : Thread, IO { Memory ram; EEPROM eeprom; RTC rtc; - - struct Information { - string manifest; - string title; - bool orientation; //0 = horizontal; 1 = vertical - string sha256; - } information; }; extern Cartridge cartridge; diff --git a/higan/ws/cartridge/io.cpp b/higan/ws/cartridge/io.cpp index be4f6fce..f3a53f9f 100644 --- a/higan/ws/cartridge/io.cpp +++ b/higan/ws/cartridge/io.cpp @@ -28,6 +28,12 @@ auto Cartridge::portRead(uint16 addr) -> uint8 { //RTC_DATA if(addr == 0x00cb) return rtcRead(); + //GPO_EN + if(addr == 0x00cc) return r.gpoEnable; + + //GPO_DATA + if(addr == 0x00cd) return r.gpoData; + return 0x00; } @@ -60,4 +66,10 @@ auto Cartridge::portWrite(uint16 addr, uint8 data) -> void { //RTC_DATA if(addr == 0x00cb) rtcWrite(data); + + //GPO_EN + if(addr == 0x00cc) r.gpoEnable = data; + + //GPO_DATA + if(addr == 0x00cd) r.gpoData = data; } diff --git a/higan/ws/cartridge/rtc.cpp b/higan/ws/cartridge/rtc.cpp index a47e6719..0d4b7e42 100644 --- a/higan/ws/cartridge/rtc.cpp +++ b/higan/ws/cartridge/rtc.cpp @@ -122,6 +122,7 @@ auto Cartridge::rtcWrite(uint8 data) -> void { if(rtc.command == 0x12) { if(data.bit(6)) rtc.alarm = data; //todo: is bit6 really required to be set? rtc.command = 0; + rtcCheckAlarm(); } //SET_DATETIME diff --git a/higan/ws/cartridge/serialization.cpp b/higan/ws/cartridge/serialization.cpp index 6e9713d2..927952f0 100644 --- a/higan/ws/cartridge/serialization.cpp +++ b/higan/ws/cartridge/serialization.cpp @@ -1,4 +1,6 @@ auto Cartridge::serialize(serializer& s) -> void { + Thread::serialize(s); + if(ram.size) s.array(ram.data, ram.size); if(eeprom.size()) eeprom.serialize(s); if(rtc.size) s.array(rtc.data, rtc.size); @@ -15,4 +17,6 @@ auto Cartridge::serialize(serializer& s) -> void { s.integer(r.romBank1); s.integer(r.romBank2); s.integer(r.sramBank); + s.integer(r.gpoEnable); + s.integer(r.gpoData); } diff --git a/higan/ws/cpu/cpu.cpp b/higan/ws/cpu/cpu.cpp index 29c7ff3f..5837db61 100644 --- a/higan/ws/cpu/cpu.cpp +++ b/higan/ws/cpu/cpu.cpp @@ -53,26 +53,14 @@ auto CPU::power() -> void { create(CPU::Enter, 3'072'000); bus.map(this, 0x00a0); - bus.map(this, 0x00b0); - bus.map(this, 0x00b2); - bus.map(this, 0x00b4, 0x00b6); + bus.map(this, 0x00b0, 0x00b6); if(system.model() != Model::WonderSwan) { bus.map(this, 0x0040, 0x0049); bus.map(this, 0x0062); } - r.dmaSource = 0; - r.dmaTarget = 0; - r.dmaLength = 0; - r.dmaEnable = 0; - r.dmaMode = 0; - r.interruptBase = 0; - r.interruptEnable = 0; - r.interruptStatus = 0; - r.ypadEnable = 0; - r.xpadEnable = 0; - r.buttonEnable = 0; + memory::fill(&r, sizeof(Registers)); } } diff --git a/higan/ws/cpu/cpu.hpp b/higan/ws/cpu/cpu.hpp index c02c2c0c..1104a2b9 100644 --- a/higan/ws/cpu/cpu.hpp +++ b/higan/ws/cpu/cpu.hpp @@ -55,9 +55,16 @@ struct CPU : Processor::V30MZ, Thread, IO { //$00b0 INT_BASE uint8 interruptBase; + //$00b1 SER_DATA + uint8 serialData; + //$00b2 INT_ENABLE uint8 interruptEnable; + //$00b3 SER_STATUS + uint1 serialBaudRate; //0 = 9600; 1 = 38400 + uint1 serialEnable; + //$00b4 INT_STATUS uint8 interruptStatus; diff --git a/higan/ws/cpu/io.cpp b/higan/ws/cpu/io.cpp index 7eb75335..7ba8a580 100644 --- a/higan/ws/cpu/io.cpp +++ b/higan/ws/cpu/io.cpp @@ -63,9 +63,19 @@ auto CPU::portRead(uint16 addr) -> uint8 { return r.interruptBase; } + //SER_DATA + if(addr == 0x00b1) return r.serialData; + //INT_ENABLE if(addr == 0x00b2) return r.interruptEnable; + //SER_STATUS + if(addr == 0x00b3) return ( + 1 << 2 //hack: always report send buffer as empty + | r.serialBaudRate << 6 + | r.serialEnable << 7 + ); + //INT_STATUS if(addr == 0x00b4) return r.interruptStatus; @@ -120,23 +130,32 @@ auto CPU::portWrite(uint16 addr, uint8 data) -> void { return; } + //SER_DATA + if(addr == 0x00b1) r.serialData = data; + //INT_ENABLE if(addr == 0x00b2) { r.interruptEnable = data; return; } + //SER_STATUS + if(addr == 0x00b3) { + r.serialBaudRate = data.bit(6); + r.serialEnable = data.bit(7); + } + //KEYPAD if(addr == 0x00b5) { r.ypadEnable = data.bit(4); r.xpadEnable = data.bit(5); r.buttonEnable = data.bit(6); - return; } //INT_ACK if(addr == 0x00b6) { - r.interruptStatus &= ~data; + //acknowledge only edge-sensitive interrupts + r.interruptStatus &= ~(data & 0b11110010); return; } } diff --git a/higan/ws/cpu/serialization.cpp b/higan/ws/cpu/serialization.cpp index 51ce05bb..af269f95 100644 --- a/higan/ws/cpu/serialization.cpp +++ b/higan/ws/cpu/serialization.cpp @@ -1,5 +1,6 @@ auto CPU::serialize(serializer& s) -> void { V30MZ::serialize(s); + Thread::serialize(s); s.integer(r.dmaSource); s.integer(r.dmaTarget); @@ -7,7 +8,10 @@ auto CPU::serialize(serializer& s) -> void { s.integer(r.dmaEnable); s.integer(r.dmaMode); s.integer(r.interruptBase); + s.integer(r.serialData); s.integer(r.interruptEnable); + s.integer(r.serialBaudRate); + s.integer(r.serialEnable); s.integer(r.interruptStatus); s.integer(r.ypadEnable); s.integer(r.xpadEnable); diff --git a/higan/ws/eeprom/eeprom.cpp b/higan/ws/eeprom/eeprom.cpp index 28c15ed3..6d6ad4f6 100644 --- a/higan/ws/eeprom/eeprom.cpp +++ b/higan/ws/eeprom/eeprom.cpp @@ -26,9 +26,9 @@ auto EEPROM::power() -> void { r.unknown = false; r.writeRequested = false; r.readRequested = false; - r.writeCompleted = false; - r.readCompleted = false; - r.writeProtect = false; + r.writeCompleted = true; //hack: should require time to complete reads/writes + r.readCompleted = true; //instead; leave bits always set so games don't lock + r.writeProtect = true; } auto EEPROM::read(uint port) -> uint8 { @@ -134,4 +134,8 @@ auto EEPROM::execute() -> void { } } +auto EEPROM::operator[](uint10 addr) -> uint16& { + return _data[addr]; +} + } diff --git a/higan/ws/eeprom/eeprom.hpp b/higan/ws/eeprom/eeprom.hpp index e65c2ccc..182774e9 100644 --- a/higan/ws/eeprom/eeprom.hpp +++ b/higan/ws/eeprom/eeprom.hpp @@ -26,6 +26,8 @@ struct EEPROM { auto read(uint) -> uint8; auto write(uint, uint8) -> void; + auto operator[](uint10 addr) -> uint16&; + //serialization.cpp auto serialize(serializer&) -> void; diff --git a/higan/ws/ppu/io.cpp b/higan/ws/ppu/io.cpp index a11e2f24..c4117710 100644 --- a/higan/ws/ppu/io.cpp +++ b/higan/ws/ppu/io.cpp @@ -262,19 +262,17 @@ auto PPU::portWrite(uint16 addr, uint8 data) -> void { if(addr == 0x00a4) r.htimerFrequency.byte(0) = data; if(addr == 0x00a5) r.htimerFrequency.byte(1) = data; - //VTMR_FREQ - if(addr == 0x00a6) r.vtimerFrequency.byte(0) = data; - if(addr == 0x00a7) r.vtimerFrequency.byte(1) = data; - - //todo: is this correct? - if(addr == 0x00a5) { + if(addr == 0x00a4 || addr == 0x00a5) { r.htimerEnable = true; r.htimerRepeat = true; r.htimerCounter = 0; } - //todo: is this correct? - if(addr == 0x00a7) { + //VTMR_FREQ + if(addr == 0x00a6) r.vtimerFrequency.byte(0) = data; + if(addr == 0x00a7) r.vtimerFrequency.byte(1) = data; + + if(addr == 0x00a6 || addr == 0x00a7) { r.vtimerEnable = true; r.vtimerRepeat = true; r.vtimerCounter = 0; diff --git a/higan/ws/ppu/serialization.cpp b/higan/ws/ppu/serialization.cpp index b3f96f55..33ea78c0 100644 --- a/higan/ws/ppu/serialization.cpp +++ b/higan/ws/ppu/serialization.cpp @@ -1,4 +1,6 @@ auto PPU::serialize(serializer& s) -> void { + Thread::serialize(s); + s.integer(this->s.field); s.integer(this->s.vclk); s.integer(this->s.hclk); diff --git a/higan/ws/system/system.cpp b/higan/ws/system/system.cpp index 861f2100..77efad86 100644 --- a/higan/ws/system/system.cpp +++ b/higan/ws/system/system.cpp @@ -33,6 +33,8 @@ auto System::load(Model model) -> void { eeprom.setName(node["name"].text()); eeprom.setSize(node["size"].natural() / sizeof(uint16)); eeprom.erase(); + //initialize user-data section + for(uint addr = 0x0030; addr <= 0x003a; addr++) eeprom[addr] = 0x0000; interface->loadRequest(ID::SystemEEPROM, eeprom.name(), false); } diff --git a/higan/ws/ws.hpp b/higan/ws/ws.hpp index e513b1cb..f6144de3 100644 --- a/higan/ws/ws.hpp +++ b/higan/ws/ws.hpp @@ -6,7 +6,7 @@ namespace WonderSwan { namespace Info { static const string Name = "bws"; - static const uint SerializerVersion = 0; + static const uint SerializerVersion = 1; } }