Update to v101r35 release.

byuu says:

Changelog:
  - PCE: added 384KB HuCard ROM mirroring mode
  - PCE: corrected D-pad polling order
  - PCE: corrected palette color ordering (GRB, not RGB -- yes,
    seriously)
  - PCE: corrected SATB DMA -- should write to SATB, not to VRAM
  - PCE: broke out Background, Sprite VDC settings to separate
    subclasses
  - PCE: emulated VDC backgrounds
  - PCE: emulated VDC sprites
  - PCE: emulated VDC sprite overflow, collision interrupts
  - HuC6280: fixed disassembler output for STi instructions
  - HuC6280: added missing LastCycle check to interrupt()
  - HuC6280: fixed BIT, CMP, CPX, CPY, TRB, TSB, TST flag testing and
    result
  - HuC6280: added extra cycle delays to the block move instructions
  - HuC6280: fixed ordering for flag set/clear instructions (happens
    after LastCycle check)
  - HuC6280: removed extra cycle from immediate instructions
  - HuC6280: fixed indirectLoad, indirectYStore absolute addressing
  - HuC6280: fixed BBR, BBS zeropage value testing
  - HuC6280: fixed stack push/pull direction

Neutopia looks okay until the main title screen, then there's some
gibberish on the bottom. The game also locks up with some gibberish once
you actually start a new game. So, still not playable just yet =(
This commit is contained in:
Tim Allen
2017-01-19 19:38:57 +11:00
parent f500426158
commit b03563426f
15 changed files with 287 additions and 97 deletions

View File

@@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; static const string Name = "higan";
static const string Version = "101.34"; static const string Version = "101.35";
static const string Author = "byuu"; static const string Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

@@ -54,6 +54,12 @@ auto Cartridge::write(uint20 addr, uint8 data) -> void {
} }
auto Cartridge::mirror(uint addr, uint size) -> uint { auto Cartridge::mirror(uint addr, uint size) -> uint {
//384KB games have unusual mirroring (only second ROM repeats)
if(size == 0x60000) {
if(addr <= 0x3ffff) return addr;
return 0x40000 + (addr & 0x1ffff);
}
uint base = 0; uint base = 0;
uint mask = 1 << 20; uint mask = 1 << 20;
while(addr >= size) { while(addr >= size) {

View File

@@ -7,17 +7,23 @@ auto Gamepad::readData() -> uint4 {
uint4 data; uint4 data;
if(sel) { if(sel) {
data.bit(0) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Up); bool up = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Up);
data.bit(1) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Down); bool right = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Right);
data.bit(2) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Right); bool down = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Down);
data.bit(3) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Left); bool left = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Left);
if(data.bits(0,1) == 0) data.bits(0,1) = 3; //disallow up+down at the same time data.bit(0) = !(up & !down);
if(data.bits(2,3) == 0) data.bits(2,3) = 3; //disallow left+right at the same time data.bit(1) = !(right & !left);
data.bit(2) = !(down & !up);
data.bit(3) = !(left & !right);
} else { } else {
data.bit(0) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, One); bool one = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, One);
data.bit(1) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Two); bool two = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Two);
data.bit(2) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Select); bool select = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Select);
data.bit(3) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Run); bool run = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Run);
data.bit(0) = !one;
data.bit(1) = !two;
data.bit(2) = !select;
data.bit(3) = !run;
} }
return data; return data;

View File

@@ -12,14 +12,7 @@ auto CPU::Enter() -> void {
} }
auto CPU::main() -> void { auto CPU::main() -> void {
#if 1 if(irq.pending()) return interrupt(irq.vector());
static uint counter = 0;
if(counter++ < 40) {
print(disassemble(r.pc), "\n");
}
#endif
if(irq.pending()) interrupt(irq.vector());
instruction(); instruction();
} }

View File

@@ -45,13 +45,13 @@ auto Interface::title() -> string {
} }
auto Interface::videoSize() -> VideoSize { auto Interface::videoSize() -> VideoSize {
return {512, 484}; return {256, 240};
} }
auto Interface::videoSize(uint width, uint height, bool arc) -> VideoSize { auto Interface::videoSize(uint width, uint height, bool arc) -> VideoSize {
auto a = arc ? 8.0 / 7.0 : 1.0; auto a = arc ? 8.0 / 7.0 : 1.0;
uint w = 256; uint w = 256;
uint h = 242; uint h = 240;
uint m = min(width / (w * a), height / h); uint m = min(width / (w * a), height / h);
return {uint(w * a * m), uint(h * m)}; return {uint(w * a * m), uint(h * m)};
} }
@@ -66,8 +66,8 @@ auto Interface::videoColors() -> uint32 {
auto Interface::videoColor(uint32 color) -> uint64 { auto Interface::videoColor(uint32 color) -> uint64 {
uint3 B = color.bits(0,2); uint3 B = color.bits(0,2);
uint3 G = color.bits(3,5); uint3 R = color.bits(3,5);
uint3 R = color.bits(6,8); uint3 G = color.bits(6,8);
uint64 r = image::normalize(R, 3, 16); uint64 r = image::normalize(R, 3, 16);
uint64 g = image::normalize(G, 3, 16); uint64 g = image::normalize(G, 3, 16);

View File

@@ -0,0 +1,29 @@
auto VDC::Background::scanline(uint y) -> void {
}
auto VDC::Background::run(uint x, uint y) -> void {
color = nothing;
//if(blank) return;
uint10 hoffset = x + hscroll;
uint9 voffset = y + vscroll;
uint16 batAddress = (voffset >> 3) * width + (hoffset >> 3);
uint16 tiledata = vdc.vramRead(batAddress);
uint16 patternAddress = tiledata.bits(0,11) << 4;
patternAddress += (voffset & 7);
uint4 palette = tiledata.bits(12,15);
uint16 d0 = vdc.vramRead(patternAddress + 0);
uint16 d1 = vdc.vramRead(patternAddress + 8);
uint3 index = 7 - (hoffset & 7);
uint4 output;
output.bit(0) = d0.bit(0 + index);
output.bit(1) = d0.bit(8 + index);
output.bit(2) = d1.bit(0 + index);
output.bit(3) = d1.bit(8 + index);
if(output == 0) return;
color = vdc.cram[palette << 4 | output];
}

View File

@@ -12,10 +12,11 @@ auto VDC::DMA::step(uint clocks) -> void {
} }
if(satbActive) { if(satbActive) {
uint16 data = vdc.vramRead(satbSource + satbTarget); uint16 data = vdc.vramRead(satbSource + satbOffset);
vdc.vramWrite(satbTarget++, data); vdc.satb[satbOffset] = data;
if(satbTarget == 256) { if(++satbOffset == 256) {
satbActive = false; satbActive = false;
satbOffset = 0;
satbPending = satbRepeat; satbPending = satbRepeat;
vdc.irq.raise(VDC::IRQ::Line::TransferSATB); vdc.irq.raise(VDC::IRQ::Line::TransferSATB);
} }
@@ -30,7 +31,7 @@ auto VDC::DMA::vramStart() -> void {
auto VDC::DMA::satbStart() -> void { auto VDC::DMA::satbStart() -> void {
if(!satbPending) return; if(!satbPending) return;
satbActive = true; satbActive = true;
satbTarget = 0; satbOffset = 0;
} }
auto VDC::DMA::satbQueue() -> void { auto VDC::DMA::satbQueue() -> void {

View File

@@ -99,8 +99,8 @@ auto VDC::write(uint11 addr, uint8 data) -> void {
irq.enableLineCoincidence = data.bit(2); irq.enableLineCoincidence = data.bit(2);
irq.enableVblank = data.bit(3); irq.enableVblank = data.bit(3);
io.externalSync = data.bits(4,5); io.externalSync = data.bits(4,5);
io.spriteBlank = data.bit(6); sprite.blank = data.bit(6);
io.backgroundBlank = data.bit(7); background.blank = data.bit(7);
} else { } else {
io.displayOutput = data.bits(0,1); io.displayOutput = data.bits(0,1);
io.dramRefresh = data.bit(2); io.dramRefresh = data.bit(2);
@@ -120,13 +120,13 @@ auto VDC::write(uint11 addr, uint8 data) -> void {
if(io.address == 0x07) { if(io.address == 0x07) {
//BXR //BXR
io.backgroundHscroll.byte(a0) = data; background.hscroll.byte(a0) = data;
return; return;
} }
if(io.address == 0x08) { if(io.address == 0x08) {
//BYR //BYR
io.backgroundVscroll.byte(a0) = data; background.vscroll.byte(a0) = data;
return; return;
} }
@@ -135,12 +135,12 @@ auto VDC::write(uint11 addr, uint8 data) -> void {
if(a0) return; if(a0) return;
io.vramAccess = data.bits(0,1); io.vramAccess = data.bits(0,1);
io.spriteAccess = data.bits(2,3); io.spriteAccess = data.bits(2,3);
if(data.bits(4,5) == 0) io.backgroundWidth = 32; if(data.bits(4,5) == 0) background.width = 32;
if(data.bits(4,5) == 1) io.backgroundWidth = 64; if(data.bits(4,5) == 1) background.width = 64;
if(data.bits(4,5) == 2) io.backgroundWidth = 128; if(data.bits(4,5) == 2) background.width = 128;
if(data.bits(4,5) == 3) io.backgroundWidth = 128; if(data.bits(4,5) == 3) background.width = 128;
if(data.bit(6) == 0) io.backgroundHeight = 32; if(data.bit(6) == 0) background.height = 32;
if(data.bit(6) == 1) io.backgroundHeight = 64; if(data.bit(6) == 1) background.height = 64;
io.cgMode = data.bit(7); io.cgMode = data.bit(7);
return; return;
} }

88
higan/pce/vdc/sprite.cpp Normal file
View File

@@ -0,0 +1,88 @@
auto VDC::Sprite::scanline(uint y) -> void {
y += 64;
objects.reset();
static const uint width[] = {15, 31};
static const uint height[] = {15, 31, 63, 63};
uint count = 0;
for(uint index : range(64)) {
uint16 d0 = vdc.satb[index << 2 | 0];
uint16 d1 = vdc.satb[index << 2 | 1];
uint16 d2 = vdc.satb[index << 2 | 2];
uint16 d3 = vdc.satb[index << 2 | 3];
Object object;
object.y = d0.bits(0,9);
object.height = height[d3.bits(12,13)];
if(y < object.y) continue;
if(y > object.y + object.height) continue;
object.x = d1.bits(0,9);
object.mode = d2.bit(0);
object.pattern = d2.bits(1,10);
object.palette = d3.bits(0,3);
object.priority = d3.bit(7);
object.width = width[d3.bit(8)];
object.hflip = d3.bit(11);
object.vflip = d3.bit(15);
objects.append(object);
count += 1 + d3.bit(8); //32-width sprites consume two slots
if(count >= 16) {
vdc.irq.raise(VDC::IRQ::Line::Overflow);
break;
}
}
}
auto VDC::Sprite::run(uint x, uint y) -> void {
x += 32;
y += 64;
color = nothing;
bool zero = 0;
uint index = 0;
for(auto& object : objects) {
uint id = index++;
if(x < object.x) continue;
if(x > object.x + object.width) continue;
uint10 hoffset = x - object.x;
uint10 voffset = y - object.y;
if(object.hflip) hoffset ^= object.width;
if(object.vflip) voffset ^= object.height;
uint10 pattern = object.pattern;
if(object.width == 31) pattern.bit(0) = 0;
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 d0 = vdc.vramRead(patternAddress + 0);
uint16 d1 = vdc.vramRead(patternAddress + 16);
uint16 d2 = vdc.vramRead(patternAddress + 32);
uint16 d3 = vdc.vramRead(patternAddress + 48);
uint4 index = 15 - (hoffset & 15);
uint4 output;
output.bit(0) = d0.bit(index);
output.bit(1) = d1.bit(index);
output.bit(2) = d2.bit(index);
output.bit(3) = d3.bit(index);
if(output == 0) continue;
if(color) {
if(zero) vdc.irq.raise(VDC::IRQ::Line::Collision);
break;
}
color = vdc.cram[1 << 8 | object.palette << 4 | output];
priority = object.priority;
if(id == 0) zero = 1;
}
}

View File

@@ -6,6 +6,8 @@ VDC vdc;
#include "io.cpp" #include "io.cpp"
#include "irq.cpp" #include "irq.cpp"
#include "dma.cpp" #include "dma.cpp"
#include "background.cpp"
#include "sprite.cpp"
auto VDC::Enter() -> void { auto VDC::Enter() -> void {
while(true) scheduler.synchronize(), vdc.main(); while(true) scheduler.synchronize(), vdc.main();
@@ -13,7 +15,25 @@ auto VDC::Enter() -> void {
auto VDC::main() -> void { auto VDC::main() -> void {
//1365 cycles/scanline //1365 cycles/scanline
uint y = state.y;
auto output = buffer + y * 512;
background.scanline(y);
sprite.scanline(y);
for(uint x : range(256)) { for(uint x : range(256)) {
if(y < 240) {
background.run(x, y);
sprite.run(x, y);
if(sprite.color && sprite.priority) {
*output++ = sprite.color();
} else if(background.color) {
*output++ = background.color();
} else if(sprite.color) {
*output++ = sprite.color();
} else {
*output++ = cram[0];
}
}
step(4); step(4);
} }
step(341); step(341);
@@ -41,7 +61,7 @@ auto VDC::step(uint clocks) -> void {
} }
auto VDC::refresh() -> void { auto VDC::refresh() -> void {
Emulator::video.refresh(buffer, 512 * sizeof(uint32), 512, 484); Emulator::video.refresh(buffer, 512 * sizeof(uint32), 256, 240);
} }
auto VDC::power() -> void { auto VDC::power() -> void {
@@ -55,6 +75,8 @@ auto VDC::power() -> void {
memory::fill(&irq, sizeof(IRQ)); memory::fill(&irq, sizeof(IRQ));
memory::fill(&dma, sizeof(DMA)); memory::fill(&dma, sizeof(DMA));
memory::fill(&io, sizeof(IO)); memory::fill(&io, sizeof(IO));
memory::fill(&background, sizeof(Background));
memory::fill(&sprite, sizeof(Sprite));
} }
} }

View File

@@ -77,9 +77,48 @@ private:
bool vramActive; bool vramActive;
bool satbActive; bool satbActive;
bool satbPending; bool satbPending;
uint16 satbTarget; uint16 satbOffset;
} dma; } dma;
struct Background {
//background.cpp
auto scanline(uint y) -> void;
auto run(uint x, uint y) -> void;
bool blank;
uint10 hscroll;
uint9 vscroll;
uint8 width;
uint8 height;
maybe<uint9> color;
} background;
struct Sprite {
//sprite.cpp
auto scanline(uint y) -> void;
auto run(uint x, uint y) -> void;
bool blank;
struct Object {
uint10 y;
uint10 x;
bool mode;
uint10 pattern;
uint4 palette;
bool priority;
uint width;
bool hflip;
uint height;
bool vflip;
};
array<Object, 64> objects;
maybe<uint9> color;
bool priority;
} sprite;
struct IO { struct IO {
uint5 address; uint5 address;
@@ -98,8 +137,6 @@ private:
//$05 CR (W) //$05 CR (W)
uint2 externalSync; uint2 externalSync;
bool spriteBlank;
bool backgroundBlank;
uint2 displayOutput; uint2 displayOutput;
bool dramRefresh; bool dramRefresh;
uint vramAddressIncrement; uint vramAddressIncrement;
@@ -107,17 +144,9 @@ private:
//$06 RCR //$06 RCR
uint10 lineCoincidence; uint10 lineCoincidence;
//$07 BXR
uint10 backgroundHscroll;
//$08 BYR
uint9 backgroundVscroll;
//$09 MWR //$09 MWR
uint2 vramAccess; uint2 vramAccess;
uint2 spriteAccess; uint2 spriteAccess;
uint backgroundWidth;
uint backgroundHeight;
bool cgMode; bool cgMode;
//$0a HSR //$0a HSR

View File

@@ -75,7 +75,7 @@ auto HuC6280::disassemble(uint16 pc_) -> string {
op(0x00, "brk") op(0x00, "brk")
op(0x01, "ora", indirectX()) op(0x01, "ora", indirectX())
op(0x02, "sxy") op(0x02, "sxy")
op(0x03, "st0") op(0x03, "st0", immediate())
op(0x04, "tsb", zeropage()) op(0x04, "tsb", zeropage())
op(0x05, "ora", zeropage()) op(0x05, "ora", zeropage())
op(0x06, "asl", zeropage()) op(0x06, "asl", zeropage())
@@ -91,7 +91,7 @@ U op(0x0b, "nop", "$0b")
op(0x10, "bpl", relative()) op(0x10, "bpl", relative())
op(0x11, "ora", indirectY()) op(0x11, "ora", indirectY())
op(0x12, "ora", indirect()) op(0x12, "ora", indirect())
op(0x13, "st1") op(0x13, "st1", immediate())
op(0x14, "trb", zeropage()) op(0x14, "trb", zeropage())
op(0x15, "ora", zeropageX()) op(0x15, "ora", zeropageX())
op(0x16, "asl", zeropageX()) op(0x16, "asl", zeropageX())
@@ -107,7 +107,7 @@ U op(0x1b, "nop", "$1b")
op(0x20, "jsr", absolute()) op(0x20, "jsr", absolute())
op(0x21, "and", indirectX()) op(0x21, "and", indirectX())
op(0x22, "sax") op(0x22, "sax")
op(0x23, "st2") op(0x23, "st2", immediate())
op(0x24, "bit", zeropage()) op(0x24, "bit", zeropage())
op(0x25, "and", zeropage()) op(0x25, "and", zeropage())
op(0x26, "rol", zeropage()) op(0x26, "rol", zeropage())

View File

@@ -7,10 +7,10 @@ auto HuC6280::interrupt(uint16 vector) -> void {
push(PC >> 8); push(PC >> 8);
push(PC >> 0); push(PC >> 0);
push(P); push(P);
PC.byte(0) = load(vector + 0);
PC.byte(1) = load(vector + 1);
D = 0; D = 0;
I = 1; I = 1;
PC.byte(0) = load(vector + 0);
L PC.byte(1) = load(vector + 1);
} }
auto HuC6280::instruction() -> void { auto HuC6280::instruction() -> void {

View File

@@ -23,34 +23,34 @@ auto HuC6280::ASL(uint8 i) -> uint8 {
} }
auto HuC6280::BIT(uint8 i) -> uint8 { auto HuC6280::BIT(uint8 i) -> uint8 {
Z = i == 0; Z = (A & i) == 0;
V = i.bit(6); V = i.bit(6);
N = i.bit(7); N = i.bit(7);
return i; return A;
} }
auto HuC6280::CMP(uint8 i) -> uint8 { auto HuC6280::CMP(uint8 i) -> uint8 {
uint9 o = A - i; uint9 o = A - i;
C = o.bit(8); C = !o.bit(8);
Z = uint8(o) == 0; Z = uint8(o) == 0;
N = o.bit(7); N = o.bit(7);
return i; return A;
} }
auto HuC6280::CPX(uint8 i) -> uint8 { auto HuC6280::CPX(uint8 i) -> uint8 {
uint9 o = X - i; uint9 o = X - i;
C = o.bit(8); C = !o.bit(8);
Z = uint8(o) == 0; Z = uint8(o) == 0;
N = o.bit(7); N = o.bit(7);
return i; return X;
} }
auto HuC6280::CPY(uint8 i) -> uint8 { auto HuC6280::CPY(uint8 i) -> uint8 {
uint9 o = Y - i; uint9 o = Y - i;
C = o.bit(8); C = !o.bit(8);
Z = uint8(o) == 0; Z = uint8(o) == 0;
N = o.bit(7); N = o.bit(7);
return i; return Y;
} }
auto HuC6280::DEC(uint8 i) -> uint8 { auto HuC6280::DEC(uint8 i) -> uint8 {
@@ -114,23 +114,26 @@ auto HuC6280::ROR(uint8 i) -> uint8 {
} }
auto HuC6280::SBC(uint8 i) -> uint8 { auto HuC6280::SBC(uint8 i) -> uint8 {
return ADC(~i); uint9 o = A - i - !C;
C = !o.bit(8);
Z = uint8(o) == 0;
V = (A ^ i) & (A ^ o) & 0x80;
N = o.bit(7);
return o;
} }
auto HuC6280::TRB(uint8 i) -> uint8 { auto HuC6280::TRB(uint8 i) -> uint8 {
uint8 o = i & A; Z = (A & i) == 0;
Z = o == 0; V = i.bit(6);
V = o.bit(6); N = i.bit(7);
N = o.bit(7); return ~A & i;
return i & ~A;
} }
auto HuC6280::TSB(uint8 i) -> uint8 { auto HuC6280::TSB(uint8 i) -> uint8 {
uint8 o = i & A; Z = (A & i) == 0;
Z = o == 0; V = i.bit(6);
V = o.bit(6); N = i.bit(7);
N = o.bit(7); return A | i;
return i | A;
} }
// //
@@ -187,15 +190,29 @@ L store(absolute + index, data);
auto HuC6280::instruction_blockmove(bp alu) -> void { auto HuC6280::instruction_blockmove(bp alu) -> void {
uint16 source = operand(); uint16 source = operand();
source |= operand() << 8; source |= operand() << 8;
io();
io();
io();
uint16 target = operand(); uint16 target = operand();
target |= operand() << 8; target |= operand() << 8;
io();
io();
io();
uint16 length = operand(); uint16 length = operand();
length |= operand() << 8; length |= operand() << 8;
io();
io();
io();
do { do {
auto data = load(source); auto data = load(source);
store(target, data); store(target, data);
ALU(source, target); ALU(source, target);
io();
io();
io();
io();
} while(--length); } while(--length);
io();
L io(); L io();
} }
@@ -211,23 +228,22 @@ auto HuC6280::instruction_branch(bool take) -> void {
} }
auto HuC6280::instruction_clear(uint8& data) -> void { auto HuC6280::instruction_clear(uint8& data) -> void {
data = 0;
L io(); L io();
data = 0;
} }
auto HuC6280::instruction_clear(bool& flag) -> void { auto HuC6280::instruction_clear(bool& flag) -> void {
flag = 0;
L io(); L io();
flag = 0;
} }
auto HuC6280::instruction_immediate(fp alu, uint8& data) -> void { auto HuC6280::instruction_immediate(fp alu, uint8& data) -> void {
data = ALU(operand()); L data = ALU(operand());
L io();
} }
auto HuC6280::instruction_implied(fp alu, uint8& data) -> void { auto HuC6280::instruction_implied(fp alu, uint8& data) -> void {
data = ALU(data);
L io(); L io();
data = ALU(data);
} }
auto HuC6280::instruction_indirectLoad(fp alu, uint8& data, uint8 index) -> void { auto HuC6280::instruction_indirectLoad(fp alu, uint8& data, uint8 index) -> void {
@@ -242,7 +258,7 @@ L data = ALU(load(absolute));
auto HuC6280::instruction_indirectStore(uint8 data, uint8 index) -> void { auto HuC6280::instruction_indirectStore(uint8 data, uint8 index) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
auto absolute = load(0x2000 + zeropage + index); uint16 absolute = load(0x2000 + zeropage + index);
absolute |= load(0x2001 + zeropage + index) << 8; absolute |= load(0x2001 + zeropage + index) << 8;
L store(absolute, data); L store(absolute, data);
} }
@@ -259,7 +275,7 @@ L data = ALU(load(absolute + Y));
auto HuC6280::instruction_indirectYStore(uint8 data) -> void { auto HuC6280::instruction_indirectYStore(uint8 data) -> void {
auto zeropage = operand(); auto zeropage = operand();
io(); io();
auto absolute = load(0x2000 + zeropage); uint16 absolute = load(0x2000 + zeropage);
absolute |= load(0x2001 + zeropage) << 8; absolute |= load(0x2001 + zeropage) << 8;
L store(absolute + Y, data); L store(absolute + Y, data);
} }
@@ -289,19 +305,19 @@ L push(data);
} }
auto HuC6280::instruction_set(bool& flag) -> void { auto HuC6280::instruction_set(bool& flag) -> void {
flag = 1;
L io(); L io();
flag = 1;
} }
auto HuC6280::instruction_swap(uint8& lhs, uint8& rhs) -> void { auto HuC6280::instruction_swap(uint8& lhs, uint8& rhs) -> void {
swap(lhs, rhs);
io(); io();
L io(); L io();
swap(lhs, rhs);
} }
auto HuC6280::instruction_transfer(uint8& source, uint8& target) -> void { auto HuC6280::instruction_transfer(uint8& source, uint8& target) -> void {
target = source;
L io(); L io();
target = source;
Z = target == 0; Z = target == 0;
N = target.bit(7); N = target.bit(7);
} }
@@ -333,8 +349,8 @@ auto HuC6280::instruction_BBR(uint3 index) -> void {
auto displacement = operand(); auto displacement = operand();
io(); io();
io(); io();
L io(); L auto data = load(0x2000 + zeropage);
if(zeropage.bit(index) == 0) { if(data.bit(index) == 0) {
PC += (int8)displacement; PC += (int8)displacement;
} }
} }
@@ -344,8 +360,8 @@ auto HuC6280::instruction_BBS(uint3 index) -> void {
auto displacement = operand(); auto displacement = operand();
io(); io();
io(); io();
L io(); L auto data = load(0x2000 + zeropage);
if(zeropage.bit(index) == 1) { if(data.bit(index) == 1) {
PC += (int8)displacement; PC += (int8)displacement;
} }
} }
@@ -357,8 +373,8 @@ auto HuC6280::instruction_BRK() -> void {
push(PC >> 0); push(PC >> 0);
uint8 p = P; uint8 p = P;
push(p | 0x10); //B flag set on push push(p | 0x10); //B flag set on push
I = 1;
D = 0; D = 0;
I = 1;
PC.byte(0) = load(0xfff6); PC.byte(0) = load(0xfff6);
L PC.byte(1) = load(0xfff7); L PC.byte(1) = load(0xfff7);
} }
@@ -375,13 +391,13 @@ L push((PC - 1) >> 0);
} }
auto HuC6280::instruction_CSL() -> void { auto HuC6280::instruction_CSL() -> void {
r.cs = 4;
L io(); L io();
r.cs = 4;
} }
auto HuC6280::instruction_CSH() -> void { auto HuC6280::instruction_CSH() -> void {
r.cs = 1;
L io(); L io();
r.cs = 1;
} }
auto HuC6280::instruction_JMP_absolute() -> void { auto HuC6280::instruction_JMP_absolute() -> void {
@@ -486,8 +502,8 @@ auto HuC6280::instruction_TST_absolute(uint8 index) -> void {
io(); io();
io(); io();
io(); io();
L uint8 data = load(absolute + index) & mask; L uint8 data = load(absolute + index);
Z = data == 0; Z = (data & mask) == 0;
V = data.bit(6); V = data.bit(6);
N = data.bit(7); N = data.bit(7);
} }
@@ -498,13 +514,13 @@ auto HuC6280::instruction_TST_zeropage(uint8 index) -> void {
io(); io();
io(); io();
io(); io();
L uint8 data = load(0x2000 + zeropage + index) & mask; L uint8 data = load(0x2000 + zeropage + index);
Z = data == 0; Z = (data & mask) == 0;
V = data.bit(6); V = data.bit(6);
N = data.bit(7); N = data.bit(7);
} }
auto HuC6280::instruction_TXS() -> void { auto HuC6280::instruction_TXS() -> void {
S = X;
L io(); L io();
S = X;
} }

View File

@@ -31,9 +31,9 @@ auto HuC6280::operand() -> uint8 {
// //
auto HuC6280::push(uint8 data) -> void { auto HuC6280::push(uint8 data) -> void {
store(0x2100 + ++S, data); store(0x2100 + (S--), data);
} }
auto HuC6280::pull() -> uint8 { auto HuC6280::pull() -> uint8 {
return load(0x2100 + S--); return load(0x2100 + (++S));
} }