diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 823cc30c..445f56d4 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "101.35"; + static const string Version = "102"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/pce/vdc/background.cpp b/higan/pce/vdc/background.cpp index 9fa364d3..1cf35491 100644 --- a/higan/pce/vdc/background.cpp +++ b/higan/pce/vdc/background.cpp @@ -1,14 +1,20 @@ auto VDC::Background::scanline(uint y) -> void { + hoffset = hscroll; + if(y == 0) { + voffset = vscroll; + } else { + voffset++; + } } auto VDC::Background::run(uint x, uint y) -> void { color = nothing; -//if(blank) return; - uint10 hoffset = x + hscroll; - uint9 voffset = y + vscroll; + uint16 batAddress; + batAddress = (voffset >> 3) & (height - 1); + batAddress *= width; + batAddress += (hoffset >> 3) & (width - 1); - uint16 batAddress = (voffset >> 3) * width + (hoffset >> 3); uint16 tiledata = vdc.vramRead(batAddress); uint16 patternAddress = tiledata.bits(0,11) << 4; patternAddress += (voffset & 7); @@ -24,6 +30,6 @@ auto VDC::Background::run(uint x, uint y) -> void { output.bit(2) = d1.bit(0 + index); output.bit(3) = d1.bit(8 + index); - if(output == 0) return; - color = vdc.cram[palette << 4 | output]; + if(enable && output) color = vdc.cram[palette << 4 | output]; + hoffset++; } diff --git a/higan/pce/vdc/io.cpp b/higan/pce/vdc/io.cpp index 52eca957..9b779acb 100644 --- a/higan/pce/vdc/io.cpp +++ b/higan/pce/vdc/io.cpp @@ -99,8 +99,8 @@ auto VDC::write(uint11 addr, uint8 data) -> void { irq.enableLineCoincidence = data.bit(2); irq.enableVblank = data.bit(3); io.externalSync = data.bits(4,5); - sprite.blank = data.bit(6); - background.blank = data.bit(7); + sprite.enable = data.bit(6); + background.enable = data.bit(7); } else { io.displayOutput = data.bits(0,1); io.dramRefresh = data.bit(2); @@ -127,6 +127,7 @@ auto VDC::write(uint11 addr, uint8 data) -> void { if(io.address == 0x08) { //BYR background.vscroll.byte(a0) = data; + background.voffset = background.vscroll; return; } diff --git a/higan/pce/vdc/sprite.cpp b/higan/pce/vdc/sprite.cpp index c87f2eb3..000c6463 100644 --- a/higan/pce/vdc/sprite.cpp +++ b/higan/pce/vdc/sprite.cpp @@ -39,7 +39,9 @@ auto VDC::Sprite::scanline(uint y) -> void { auto VDC::Sprite::run(uint x, uint y) -> void { x += 32; y += 64; + color = nothing; + if(!enable) return; bool zero = 0; uint index = 0; @@ -58,10 +60,11 @@ auto VDC::Sprite::run(uint x, uint y) -> void { if(object.height == 31) pattern.bit(1) = 0; if(object.height == 63) pattern.bits(1,2) = 0; - uint16 patternAddress = pattern << 6; - patternAddress += (voffset >> 4) << (6 + (object.height == 31)); - patternAddress += (hoffset >> 4) << 6; - patternAddress += (voffset & 15); + uint16 patternAddress = pattern; + patternAddress += (voffset >> 4) << 1; + patternAddress += (hoffset >> 4); + patternAddress <<= 6; + patternAddress += (voffset & 15); uint16 d0 = vdc.vramRead(patternAddress + 0); uint16 d1 = vdc.vramRead(patternAddress + 16); diff --git a/higan/pce/vdc/vdc.cpp b/higan/pce/vdc/vdc.cpp index fd8a8375..6d6d52ef 100644 --- a/higan/pce/vdc/vdc.cpp +++ b/higan/pce/vdc/vdc.cpp @@ -15,6 +15,7 @@ auto VDC::Enter() -> void { auto VDC::main() -> void { //1365 cycles/scanline + state.x = 0; uint y = state.y; auto output = buffer + y * 512; background.scanline(y); @@ -37,11 +38,7 @@ auto VDC::main() -> void { step(4); } step(341); - scanline(); -} -auto VDC::scanline() -> void { - state.x = 0; if(++state.y == 262) { state.y = 0; } diff --git a/higan/pce/vdc/vdc.hpp b/higan/pce/vdc/vdc.hpp index ee9709a8..703b44c9 100644 --- a/higan/pce/vdc/vdc.hpp +++ b/higan/pce/vdc/vdc.hpp @@ -4,7 +4,6 @@ struct VDC : Thread { static auto Enter() -> void; auto main() -> void; - auto scanline() -> void; auto step(uint clocks) -> void; auto refresh() -> void; @@ -85,12 +84,15 @@ private: auto scanline(uint y) -> void; auto run(uint x, uint y) -> void; - bool blank; + bool enable; uint10 hscroll; uint9 vscroll; uint8 width; uint8 height; + uint10 hoffset; + uint9 voffset; + maybe color; } background; @@ -99,7 +101,7 @@ private: auto scanline(uint y) -> void; auto run(uint x, uint y) -> void; - bool blank; + bool enable; struct Object { uint10 y; diff --git a/higan/processor/huc6280/huc6280.hpp b/higan/processor/huc6280/huc6280.hpp index d6abdeff..eb5d1121 100644 --- a/higan/processor/huc6280/huc6280.hpp +++ b/higan/processor/huc6280/huc6280.hpp @@ -14,8 +14,11 @@ struct HuC6280 { //memory.cpp inline auto mmu(uint16) const -> uint21; - inline auto load(uint16) -> uint8; - inline auto store(uint16, uint8) -> void; + inline auto load8(uint8) -> uint8; + inline auto load16(uint16) -> uint8; + inline auto store8(uint8, uint8) -> void; + inline auto store16(uint16, uint8) -> void; + inline auto store21(uint21, uint8) -> void; auto io() -> uint8; auto opcode() -> uint8; @@ -49,12 +52,12 @@ struct HuC6280 { auto TRB(uint8) -> uint8; auto TSB(uint8) -> uint8; - using bp = auto (HuC6280::*)(uint16&, uint16&) -> void; - auto TAI(uint16&, uint16&) -> void; - auto TDD(uint16&, uint16&) -> void; - auto TIA(uint16&, uint16&) -> void; - auto TII(uint16&, uint16&) -> void; - auto TIN(uint16&, uint16&) -> void; + using bp = auto (HuC6280::*)(uint16&, uint16&, bool) -> void; + auto TAI(uint16&, uint16&, bool) -> void; + auto TDD(uint16&, uint16&, bool) -> void; + auto TIA(uint16&, uint16&, bool) -> void; + auto TII(uint16&, uint16&, bool) -> void; + auto TIN(uint16&, uint16&, bool) -> void; auto instruction_absoluteLoad(fp, uint8&, uint8 = 0) -> void; auto instruction_absoluteModify(fp, uint8 = 0) -> void; diff --git a/higan/processor/huc6280/instruction.cpp b/higan/processor/huc6280/instruction.cpp index 0d95b63e..a288d85a 100644 --- a/higan/processor/huc6280/instruction.cpp +++ b/higan/processor/huc6280/instruction.cpp @@ -9,8 +9,8 @@ auto HuC6280::interrupt(uint16 vector) -> void { push(P); D = 0; I = 1; - PC.byte(0) = load(vector + 0); -L PC.byte(1) = load(vector + 1); + PC.byte(0) = load16(vector + 0); +L PC.byte(1) = load16(vector + 1); } auto HuC6280::instruction() -> void { diff --git a/higan/processor/huc6280/instructions.cpp b/higan/processor/huc6280/instructions.cpp index 04bbbc69..03751557 100644 --- a/higan/processor/huc6280/instructions.cpp +++ b/higan/processor/huc6280/instructions.cpp @@ -1,8 +1,18 @@ auto HuC6280::ADC(uint8 i) -> uint8 { - uint9 o = A + i + C; + int16 o; + if(!D) { + o = A + i + C; + V = ~(A ^ i) & (A ^ o) & 0x80; + } else { + o = (A & 0x0f) + (i & 0x0f) + (C << 0); + if(o > 0x09) o += 0x06; + C = o > 0x0f; + o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f); + V = ~(A ^ i) & (A ^ o) & 0x80; + if(o > 0x9f) o += 0x60; + } C = o.bit(8); Z = uint8(o) == 0; - V = ~(A ^ i) & (A ^ o) & 0x80; N = o.bit(7); return o; } @@ -114,10 +124,21 @@ auto HuC6280::ROR(uint8 i) -> uint8 { } auto HuC6280::SBC(uint8 i) -> uint8 { - uint9 o = A - i - !C; - C = !o.bit(8); + i ^= 0xff; + int16 o; + if(!D) { + o = A + i + C; + V = ~(A ^ i) & (A ^ o) & 0x80; + } else { + o = (A & 0x0f) + (i & 0x0f) + (C << 0); + if(o <= 0x0f) o -= 0x06; + C = o > 0x0f; + o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f); + V = ~(A ^ i) & (A ^ o) & 0x80; + if(o <= 0xff) o -= 0x60; + } + C = o.bit(8); Z = uint8(o) == 0; - V = (A ^ i) & (A ^ o) & 0x80; N = o.bit(7); return o; } @@ -138,27 +159,27 @@ auto HuC6280::TSB(uint8 i) -> uint8 { // -auto HuC6280::TAI(uint16& source, uint16& target) -> void { - source ^= 1; +auto HuC6280::TAI(uint16& source, uint16& target, bool alternate) -> void { + !alternate ? source++ : source--; target++; } -auto HuC6280::TDD(uint16& source, uint16& target) -> void { +auto HuC6280::TDD(uint16& source, uint16& target, bool) -> void { source--; target--; } -auto HuC6280::TIA(uint16& source, uint16& target) -> void { +auto HuC6280::TIA(uint16& source, uint16& target, bool alternate) -> void { source++; - target ^= 1; + !alternate ? target++ : target--; } -auto HuC6280::TII(uint16& source, uint16& target) -> void { +auto HuC6280::TII(uint16& source, uint16& target, bool) -> void { source++; target++; } -auto HuC6280::TIN(uint16& source, uint16& target) -> void { +auto HuC6280::TIN(uint16& source, uint16& target, bool) -> void { source++; } @@ -168,7 +189,7 @@ auto HuC6280::instruction_absoluteLoad(fp alu, uint8& data, uint8 index) -> void uint16 absolute = operand(); absolute |= operand() << 8; io(); -L data = ALU(load(absolute + index)); +L data = ALU(load16(absolute + index)); } auto HuC6280::instruction_absoluteModify(fp alu, uint8 index) -> void { @@ -176,44 +197,46 @@ auto HuC6280::instruction_absoluteModify(fp alu, uint8 index) -> void { absolute |= operand() << 8; io(); io(); - auto data = ALU(load(absolute + index)); -L store(absolute + index, data); + auto data = ALU(load16(absolute + index)); +L store16(absolute + index, data); } auto HuC6280::instruction_absoluteStore(uint8 data, uint8 index) -> void { uint16 absolute = operand(); absolute |= operand() << 8; io(); -L store(absolute + index, data); +L store16(absolute + index, data); } auto HuC6280::instruction_blockmove(bp alu) -> void { uint16 source = operand(); source |= operand() << 8; - io(); - io(); - io(); uint16 target = operand(); target |= operand() << 8; - io(); - io(); - io(); uint16 length = operand(); length |= operand() << 8; + push(Y); + push(A); + push(X); io(); io(); io(); + io(); + io(); + bool alternate = 0; do { - auto data = load(source); - store(target, data); - ALU(source, target); + auto data = load16(source); + store16(target, data); + ALU(source, target, alternate); + alternate ^= 1; io(); io(); io(); io(); } while(--length); - io(); -L io(); + X = pull(); + A = pull(); +L Y = pull(); } auto HuC6280::instruction_branch(bool take) -> void { @@ -249,41 +272,41 @@ L io(); auto HuC6280::instruction_indirectLoad(fp alu, uint8& data, uint8 index) -> void { auto zeropage = operand(); io(); - uint16 absolute = load(0x2000 + zeropage + index); - absolute |= load(0x2001 + zeropage + index) << 8; + uint16 absolute = load8(zeropage + index + 0); + absolute |= load8(zeropage + index + 1) << 8; io(); -L data = ALU(load(absolute)); +L data = ALU(load16(absolute)); } auto HuC6280::instruction_indirectStore(uint8 data, uint8 index) -> void { auto zeropage = operand(); io(); - uint16 absolute = load(0x2000 + zeropage + index); - absolute |= load(0x2001 + zeropage + index) << 8; -L store(absolute, data); + uint16 absolute = load8(zeropage + index + 0); + absolute |= load8(zeropage + index + 1) << 8; +L store16(absolute, data); } auto HuC6280::instruction_indirectYLoad(fp alu, uint8& data) -> void { auto zeropage = operand(); io(); - uint16 absolute = load(0x2000 + zeropage); - absolute |= load(0x2001 + zeropage) << 8; + uint16 absolute = load8(zeropage + 0); + absolute |= load8(zeropage + 1) << 8; io(); -L data = ALU(load(absolute + Y)); +L data = ALU(load16(absolute + Y)); } auto HuC6280::instruction_indirectYStore(uint8 data) -> void { auto zeropage = operand(); io(); - uint16 absolute = load(0x2000 + zeropage); - absolute |= load(0x2001 + zeropage) << 8; -L store(absolute + Y, data); + uint16 absolute = load8(zeropage + 0); + absolute |= load8(zeropage + 1) << 8; +L store16(absolute + Y, data); } auto HuC6280::instruction_memory(fp alu) -> void { auto a = A; - A = ALU(load(0x2000 + X)); -L store(0x2000 + X, A); + A = ALU(load8(X)); +L store8(X, A); A = a; } @@ -325,21 +348,21 @@ L io(); auto HuC6280::instruction_zeropageLoad(fp alu, uint8& data, uint8 index) -> void { auto zeropage = operand(); io(); -L data = ALU(load(0x2000 + zeropage + index)); +L data = ALU(load8(zeropage + index)); } auto HuC6280::instruction_zeropageModify(fp alu, uint8 index) -> void { auto zeropage = operand(); io(); io(); - auto data = ALU(load(0x2000 + zeropage + index)); -L store(0x2000 + zeropage + index, data); + auto data = ALU(load8(zeropage + index)); +L store8(zeropage + index, data); } auto HuC6280::instruction_zeropageStore(uint8 data, uint8 index) -> void { auto zeropage = operand(); io(); -L store(0x2000 + zeropage + index, data); +L store8(zeropage + index, data); } // @@ -349,7 +372,7 @@ auto HuC6280::instruction_BBR(uint3 index) -> void { auto displacement = operand(); io(); io(); -L auto data = load(0x2000 + zeropage); +L auto data = load8(zeropage); if(data.bit(index) == 0) { PC += (int8)displacement; } @@ -360,7 +383,7 @@ auto HuC6280::instruction_BBS(uint3 index) -> void { auto displacement = operand(); io(); io(); -L auto data = load(0x2000 + zeropage); +L auto data = load8(zeropage); if(data.bit(index) == 1) { PC += (int8)displacement; } @@ -375,8 +398,8 @@ auto HuC6280::instruction_BRK() -> void { push(p | 0x10); //B flag set on push D = 0; I = 1; - PC.byte(0) = load(0xfff6); -L PC.byte(1) = load(0xfff7); + PC.byte(0) = load16(0xfff6); +L PC.byte(1) = load16(0xfff7); } auto HuC6280::instruction_BSR() -> void { @@ -412,8 +435,8 @@ auto HuC6280::instruction_JMP_indirect(uint8 index) -> void { address |= operand() << 8; io(); io(); - PC.byte(0) = load(address + index + 0); -L PC.byte(1) = load(address + index + 1); + PC.byte(0) = load16(address + index + 0); +L PC.byte(1) = load16(address + index + 1); } auto HuC6280::instruction_JSR() -> void { @@ -435,9 +458,9 @@ auto HuC6280::instruction_RMB(uint3 index) -> void { io(); io(); io(); - auto data = load(0x2000 + zeropage); + auto data = load8(zeropage); data.bit(index) = 0; -L store(0x2000 + zeropage, data); +L store8(zeropage, data); } auto HuC6280::instruction_RTI() -> void { @@ -464,16 +487,15 @@ auto HuC6280::instruction_SMB(uint3 index) -> void { io(); io(); io(); - auto data = load(0x2000 + zeropage); + auto data = load8(zeropage); data.bit(index) = 1; -L store(0x2000 + zeropage, data); +L store8(zeropage, data); } auto HuC6280::instruction_ST(uint2 index) -> void { auto data = operand(); io(); -L io(); - write(0x1fe000 + index, data); +L store21(0x1fe000 + index, data); } auto HuC6280::instruction_TAM() -> void { @@ -502,7 +524,7 @@ auto HuC6280::instruction_TST_absolute(uint8 index) -> void { io(); io(); io(); -L uint8 data = load(absolute + index); +L uint8 data = load16(absolute + index); Z = (data & mask) == 0; V = data.bit(6); N = data.bit(7); @@ -514,7 +536,7 @@ auto HuC6280::instruction_TST_zeropage(uint8 index) -> void { io(); io(); io(); -L uint8 data = load(0x2000 + zeropage + index); +L uint8 data = load8(zeropage + index); Z = (data & mask) == 0; V = data.bit(6); N = data.bit(7); diff --git a/higan/processor/huc6280/memory.cpp b/higan/processor/huc6280/memory.cpp index 126c0226..cabb0d76 100644 --- a/higan/processor/huc6280/memory.cpp +++ b/higan/processor/huc6280/memory.cpp @@ -4,36 +4,58 @@ auto HuC6280::mmu(uint16 addr) const -> uint21 { // -auto HuC6280::load(uint16 addr) -> uint8 { +auto HuC6280::load8(uint8 addr) -> uint8 { + step(r.cs); + return read(mmu(0x2000 + addr)); +} + +auto HuC6280::load16(uint16 addr) -> uint8 { step(r.cs); return read(mmu(addr)); } -auto HuC6280::store(uint16 addr, uint8 data) -> void { +auto HuC6280::store8(uint8 addr, uint8 data) -> void { + step(r.cs); + return write(mmu(0x2000 + addr), data); +} + +auto HuC6280::store16(uint16 addr, uint8 data) -> void { step(r.cs); return write(mmu(addr), data); } +auto HuC6280::store21(uint21 addr, uint8 data) -> void { + step(r.cs); + return write(addr, data); +} + // auto HuC6280::io() -> uint8 { - return load(r.pc); + step(r.cs); + return read(mmu(PC)); } auto HuC6280::opcode() -> uint8 { - return load(r.pc++); + step(r.cs); + return read(mmu(PC++)); } auto HuC6280::operand() -> uint8 { - return load(r.pc++); + step(r.cs); + return read(mmu(PC++)); } // auto HuC6280::push(uint8 data) -> void { - store(0x2100 + (S--), data); + step(r.cs); + write(mmu(0x2100 + S), data); + S--; } auto HuC6280::pull() -> uint8 { - return load(0x2100 + (++S)); + step(r.cs); + S++; + return read(mmu(0x2100 + S)); }