mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
f500426158
commit
b03563426f
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
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 License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -54,6 +54,12 @@ auto Cartridge::write(uint20 addr, uint8 data) -> void {
|
|||
}
|
||||
|
||||
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 mask = 1 << 20;
|
||||
while(addr >= size) {
|
||||
|
|
|
@ -7,17 +7,23 @@ auto Gamepad::readData() -> uint4 {
|
|||
uint4 data;
|
||||
|
||||
if(sel) {
|
||||
data.bit(0) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Up);
|
||||
data.bit(1) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Down);
|
||||
data.bit(2) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Right);
|
||||
data.bit(3) = !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
|
||||
if(data.bits(2,3) == 0) data.bits(2,3) = 3; //disallow left+right at the same time
|
||||
bool up = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Up);
|
||||
bool right = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Right);
|
||||
bool down = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Down);
|
||||
bool left = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Left);
|
||||
data.bit(0) = !(up & !down);
|
||||
data.bit(1) = !(right & !left);
|
||||
data.bit(2) = !(down & !up);
|
||||
data.bit(3) = !(left & !right);
|
||||
} else {
|
||||
data.bit(0) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, One);
|
||||
data.bit(1) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Two);
|
||||
data.bit(2) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Select);
|
||||
data.bit(3) = !platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Run);
|
||||
bool one = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, One);
|
||||
bool two = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Two);
|
||||
bool select = platform->inputPoll(ID::Port::Controller, ID::Device::Gamepad, Select);
|
||||
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;
|
||||
|
|
|
@ -12,14 +12,7 @@ auto CPU::Enter() -> void {
|
|||
}
|
||||
|
||||
auto CPU::main() -> void {
|
||||
#if 1
|
||||
static uint counter = 0;
|
||||
if(counter++ < 40) {
|
||||
print(disassemble(r.pc), "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if(irq.pending()) interrupt(irq.vector());
|
||||
if(irq.pending()) return interrupt(irq.vector());
|
||||
instruction();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,13 +45,13 @@ auto Interface::title() -> string {
|
|||
}
|
||||
|
||||
auto Interface::videoSize() -> VideoSize {
|
||||
return {512, 484};
|
||||
return {256, 240};
|
||||
}
|
||||
|
||||
auto Interface::videoSize(uint width, uint height, bool arc) -> VideoSize {
|
||||
auto a = arc ? 8.0 / 7.0 : 1.0;
|
||||
uint w = 256;
|
||||
uint h = 242;
|
||||
uint h = 240;
|
||||
uint m = min(width / (w * a), height / h);
|
||||
return {uint(w * a * m), uint(h * m)};
|
||||
}
|
||||
|
@ -66,8 +66,8 @@ auto Interface::videoColors() -> uint32 {
|
|||
|
||||
auto Interface::videoColor(uint32 color) -> uint64 {
|
||||
uint3 B = color.bits(0,2);
|
||||
uint3 G = color.bits(3,5);
|
||||
uint3 R = color.bits(6,8);
|
||||
uint3 R = color.bits(3,5);
|
||||
uint3 G = color.bits(6,8);
|
||||
|
||||
uint64 r = image::normalize(R, 3, 16);
|
||||
uint64 g = image::normalize(G, 3, 16);
|
||||
|
|
|
@ -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];
|
||||
}
|
|
@ -12,10 +12,11 @@ auto VDC::DMA::step(uint clocks) -> void {
|
|||
}
|
||||
|
||||
if(satbActive) {
|
||||
uint16 data = vdc.vramRead(satbSource + satbTarget);
|
||||
vdc.vramWrite(satbTarget++, data);
|
||||
if(satbTarget == 256) {
|
||||
uint16 data = vdc.vramRead(satbSource + satbOffset);
|
||||
vdc.satb[satbOffset] = data;
|
||||
if(++satbOffset == 256) {
|
||||
satbActive = false;
|
||||
satbOffset = 0;
|
||||
satbPending = satbRepeat;
|
||||
vdc.irq.raise(VDC::IRQ::Line::TransferSATB);
|
||||
}
|
||||
|
@ -30,7 +31,7 @@ auto VDC::DMA::vramStart() -> void {
|
|||
auto VDC::DMA::satbStart() -> void {
|
||||
if(!satbPending) return;
|
||||
satbActive = true;
|
||||
satbTarget = 0;
|
||||
satbOffset = 0;
|
||||
}
|
||||
|
||||
auto VDC::DMA::satbQueue() -> void {
|
||||
|
|
|
@ -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);
|
||||
io.spriteBlank = data.bit(6);
|
||||
io.backgroundBlank = data.bit(7);
|
||||
sprite.blank = data.bit(6);
|
||||
background.blank = data.bit(7);
|
||||
} else {
|
||||
io.displayOutput = data.bits(0,1);
|
||||
io.dramRefresh = data.bit(2);
|
||||
|
@ -120,13 +120,13 @@ auto VDC::write(uint11 addr, uint8 data) -> void {
|
|||
|
||||
if(io.address == 0x07) {
|
||||
//BXR
|
||||
io.backgroundHscroll.byte(a0) = data;
|
||||
background.hscroll.byte(a0) = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(io.address == 0x08) {
|
||||
//BYR
|
||||
io.backgroundVscroll.byte(a0) = data;
|
||||
background.vscroll.byte(a0) = data;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -135,12 +135,12 @@ auto VDC::write(uint11 addr, uint8 data) -> void {
|
|||
if(a0) return;
|
||||
io.vramAccess = data.bits(0,1);
|
||||
io.spriteAccess = data.bits(2,3);
|
||||
if(data.bits(4,5) == 0) io.backgroundWidth = 32;
|
||||
if(data.bits(4,5) == 1) io.backgroundWidth = 64;
|
||||
if(data.bits(4,5) == 2) io.backgroundWidth = 128;
|
||||
if(data.bits(4,5) == 3) io.backgroundWidth = 128;
|
||||
if(data.bit(6) == 0) io.backgroundHeight = 32;
|
||||
if(data.bit(6) == 1) io.backgroundHeight = 64;
|
||||
if(data.bits(4,5) == 0) background.width = 32;
|
||||
if(data.bits(4,5) == 1) background.width = 64;
|
||||
if(data.bits(4,5) == 2) background.width = 128;
|
||||
if(data.bits(4,5) == 3) background.width = 128;
|
||||
if(data.bit(6) == 0) background.height = 32;
|
||||
if(data.bit(6) == 1) background.height = 64;
|
||||
io.cgMode = data.bit(7);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -6,6 +6,8 @@ VDC vdc;
|
|||
#include "io.cpp"
|
||||
#include "irq.cpp"
|
||||
#include "dma.cpp"
|
||||
#include "background.cpp"
|
||||
#include "sprite.cpp"
|
||||
|
||||
auto VDC::Enter() -> void {
|
||||
while(true) scheduler.synchronize(), vdc.main();
|
||||
|
@ -13,7 +15,25 @@ auto VDC::Enter() -> void {
|
|||
|
||||
auto VDC::main() -> void {
|
||||
//1365 cycles/scanline
|
||||
uint y = state.y;
|
||||
auto output = buffer + y * 512;
|
||||
background.scanline(y);
|
||||
sprite.scanline(y);
|
||||
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(341);
|
||||
|
@ -41,7 +61,7 @@ auto VDC::step(uint clocks) -> 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 {
|
||||
|
@ -55,6 +75,8 @@ auto VDC::power() -> void {
|
|||
memory::fill(&irq, sizeof(IRQ));
|
||||
memory::fill(&dma, sizeof(DMA));
|
||||
memory::fill(&io, sizeof(IO));
|
||||
memory::fill(&background, sizeof(Background));
|
||||
memory::fill(&sprite, sizeof(Sprite));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -77,9 +77,48 @@ private:
|
|||
bool vramActive;
|
||||
bool satbActive;
|
||||
bool satbPending;
|
||||
uint16 satbTarget;
|
||||
uint16 satbOffset;
|
||||
} 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 {
|
||||
uint5 address;
|
||||
|
||||
|
@ -98,8 +137,6 @@ private:
|
|||
|
||||
//$05 CR (W)
|
||||
uint2 externalSync;
|
||||
bool spriteBlank;
|
||||
bool backgroundBlank;
|
||||
uint2 displayOutput;
|
||||
bool dramRefresh;
|
||||
uint vramAddressIncrement;
|
||||
|
@ -107,17 +144,9 @@ private:
|
|||
//$06 RCR
|
||||
uint10 lineCoincidence;
|
||||
|
||||
//$07 BXR
|
||||
uint10 backgroundHscroll;
|
||||
|
||||
//$08 BYR
|
||||
uint9 backgroundVscroll;
|
||||
|
||||
//$09 MWR
|
||||
uint2 vramAccess;
|
||||
uint2 spriteAccess;
|
||||
uint backgroundWidth;
|
||||
uint backgroundHeight;
|
||||
bool cgMode;
|
||||
|
||||
//$0a HSR
|
||||
|
|
|
@ -75,7 +75,7 @@ auto HuC6280::disassemble(uint16 pc_) -> string {
|
|||
op(0x00, "brk")
|
||||
op(0x01, "ora", indirectX())
|
||||
op(0x02, "sxy")
|
||||
op(0x03, "st0")
|
||||
op(0x03, "st0", immediate())
|
||||
op(0x04, "tsb", zeropage())
|
||||
op(0x05, "ora", zeropage())
|
||||
op(0x06, "asl", zeropage())
|
||||
|
@ -91,7 +91,7 @@ U op(0x0b, "nop", "$0b")
|
|||
op(0x10, "bpl", relative())
|
||||
op(0x11, "ora", indirectY())
|
||||
op(0x12, "ora", indirect())
|
||||
op(0x13, "st1")
|
||||
op(0x13, "st1", immediate())
|
||||
op(0x14, "trb", zeropage())
|
||||
op(0x15, "ora", zeropageX())
|
||||
op(0x16, "asl", zeropageX())
|
||||
|
@ -107,7 +107,7 @@ U op(0x1b, "nop", "$1b")
|
|||
op(0x20, "jsr", absolute())
|
||||
op(0x21, "and", indirectX())
|
||||
op(0x22, "sax")
|
||||
op(0x23, "st2")
|
||||
op(0x23, "st2", immediate())
|
||||
op(0x24, "bit", zeropage())
|
||||
op(0x25, "and", zeropage())
|
||||
op(0x26, "rol", zeropage())
|
||||
|
|
|
@ -7,10 +7,10 @@ auto HuC6280::interrupt(uint16 vector) -> void {
|
|||
push(PC >> 8);
|
||||
push(PC >> 0);
|
||||
push(P);
|
||||
PC.byte(0) = load(vector + 0);
|
||||
PC.byte(1) = load(vector + 1);
|
||||
D = 0;
|
||||
I = 1;
|
||||
PC.byte(0) = load(vector + 0);
|
||||
L PC.byte(1) = load(vector + 1);
|
||||
}
|
||||
|
||||
auto HuC6280::instruction() -> void {
|
||||
|
|
|
@ -23,34 +23,34 @@ auto HuC6280::ASL(uint8 i) -> uint8 {
|
|||
}
|
||||
|
||||
auto HuC6280::BIT(uint8 i) -> uint8 {
|
||||
Z = i == 0;
|
||||
Z = (A & i) == 0;
|
||||
V = i.bit(6);
|
||||
N = i.bit(7);
|
||||
return i;
|
||||
return A;
|
||||
}
|
||||
|
||||
auto HuC6280::CMP(uint8 i) -> uint8 {
|
||||
uint9 o = A - i;
|
||||
C = o.bit(8);
|
||||
C = !o.bit(8);
|
||||
Z = uint8(o) == 0;
|
||||
N = o.bit(7);
|
||||
return i;
|
||||
return A;
|
||||
}
|
||||
|
||||
auto HuC6280::CPX(uint8 i) -> uint8 {
|
||||
uint9 o = X - i;
|
||||
C = o.bit(8);
|
||||
C = !o.bit(8);
|
||||
Z = uint8(o) == 0;
|
||||
N = o.bit(7);
|
||||
return i;
|
||||
return X;
|
||||
}
|
||||
|
||||
auto HuC6280::CPY(uint8 i) -> uint8 {
|
||||
uint9 o = Y - i;
|
||||
C = o.bit(8);
|
||||
C = !o.bit(8);
|
||||
Z = uint8(o) == 0;
|
||||
N = o.bit(7);
|
||||
return i;
|
||||
return Y;
|
||||
}
|
||||
|
||||
auto HuC6280::DEC(uint8 i) -> uint8 {
|
||||
|
@ -114,23 +114,26 @@ auto HuC6280::ROR(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 {
|
||||
uint8 o = i & A;
|
||||
Z = o == 0;
|
||||
V = o.bit(6);
|
||||
N = o.bit(7);
|
||||
return i & ~A;
|
||||
Z = (A & i) == 0;
|
||||
V = i.bit(6);
|
||||
N = i.bit(7);
|
||||
return ~A & i;
|
||||
}
|
||||
|
||||
auto HuC6280::TSB(uint8 i) -> uint8 {
|
||||
uint8 o = i & A;
|
||||
Z = o == 0;
|
||||
V = o.bit(6);
|
||||
N = o.bit(7);
|
||||
return i | A;
|
||||
Z = (A & i) == 0;
|
||||
V = i.bit(6);
|
||||
N = i.bit(7);
|
||||
return A | i;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -187,15 +190,29 @@ L store(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;
|
||||
io();
|
||||
io();
|
||||
io();
|
||||
do {
|
||||
auto data = load(source);
|
||||
store(target, data);
|
||||
ALU(source, target);
|
||||
io();
|
||||
io();
|
||||
io();
|
||||
io();
|
||||
} while(--length);
|
||||
io();
|
||||
L io();
|
||||
}
|
||||
|
||||
|
@ -211,23 +228,22 @@ auto HuC6280::instruction_branch(bool take) -> void {
|
|||
}
|
||||
|
||||
auto HuC6280::instruction_clear(uint8& data) -> void {
|
||||
data = 0;
|
||||
L io();
|
||||
data = 0;
|
||||
}
|
||||
|
||||
auto HuC6280::instruction_clear(bool& flag) -> void {
|
||||
flag = 0;
|
||||
L io();
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
auto HuC6280::instruction_immediate(fp alu, uint8& data) -> void {
|
||||
data = ALU(operand());
|
||||
L io();
|
||||
L data = ALU(operand());
|
||||
}
|
||||
|
||||
auto HuC6280::instruction_implied(fp alu, uint8& data) -> void {
|
||||
data = ALU(data);
|
||||
L io();
|
||||
data = ALU(data);
|
||||
}
|
||||
|
||||
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 zeropage = operand();
|
||||
io();
|
||||
auto absolute = load(0x2000 + zeropage + index);
|
||||
uint16 absolute = load(0x2000 + zeropage + index);
|
||||
absolute |= load(0x2001 + zeropage + index) << 8;
|
||||
L store(absolute, data);
|
||||
}
|
||||
|
@ -259,7 +275,7 @@ L data = ALU(load(absolute + Y));
|
|||
auto HuC6280::instruction_indirectYStore(uint8 data) -> void {
|
||||
auto zeropage = operand();
|
||||
io();
|
||||
auto absolute = load(0x2000 + zeropage);
|
||||
uint16 absolute = load(0x2000 + zeropage);
|
||||
absolute |= load(0x2001 + zeropage) << 8;
|
||||
L store(absolute + Y, data);
|
||||
}
|
||||
|
@ -289,19 +305,19 @@ L push(data);
|
|||
}
|
||||
|
||||
auto HuC6280::instruction_set(bool& flag) -> void {
|
||||
flag = 1;
|
||||
L io();
|
||||
flag = 1;
|
||||
}
|
||||
|
||||
auto HuC6280::instruction_swap(uint8& lhs, uint8& rhs) -> void {
|
||||
swap(lhs, rhs);
|
||||
io();
|
||||
L io();
|
||||
swap(lhs, rhs);
|
||||
}
|
||||
|
||||
auto HuC6280::instruction_transfer(uint8& source, uint8& target) -> void {
|
||||
target = source;
|
||||
L io();
|
||||
target = source;
|
||||
Z = target == 0;
|
||||
N = target.bit(7);
|
||||
}
|
||||
|
@ -333,8 +349,8 @@ auto HuC6280::instruction_BBR(uint3 index) -> void {
|
|||
auto displacement = operand();
|
||||
io();
|
||||
io();
|
||||
L io();
|
||||
if(zeropage.bit(index) == 0) {
|
||||
L auto data = load(0x2000 + zeropage);
|
||||
if(data.bit(index) == 0) {
|
||||
PC += (int8)displacement;
|
||||
}
|
||||
}
|
||||
|
@ -344,8 +360,8 @@ auto HuC6280::instruction_BBS(uint3 index) -> void {
|
|||
auto displacement = operand();
|
||||
io();
|
||||
io();
|
||||
L io();
|
||||
if(zeropage.bit(index) == 1) {
|
||||
L auto data = load(0x2000 + zeropage);
|
||||
if(data.bit(index) == 1) {
|
||||
PC += (int8)displacement;
|
||||
}
|
||||
}
|
||||
|
@ -357,8 +373,8 @@ auto HuC6280::instruction_BRK() -> void {
|
|||
push(PC >> 0);
|
||||
uint8 p = P;
|
||||
push(p | 0x10); //B flag set on push
|
||||
I = 1;
|
||||
D = 0;
|
||||
I = 1;
|
||||
PC.byte(0) = load(0xfff6);
|
||||
L PC.byte(1) = load(0xfff7);
|
||||
}
|
||||
|
@ -375,13 +391,13 @@ L push((PC - 1) >> 0);
|
|||
}
|
||||
|
||||
auto HuC6280::instruction_CSL() -> void {
|
||||
r.cs = 4;
|
||||
L io();
|
||||
r.cs = 4;
|
||||
}
|
||||
|
||||
auto HuC6280::instruction_CSH() -> void {
|
||||
r.cs = 1;
|
||||
L io();
|
||||
r.cs = 1;
|
||||
}
|
||||
|
||||
auto HuC6280::instruction_JMP_absolute() -> void {
|
||||
|
@ -486,8 +502,8 @@ auto HuC6280::instruction_TST_absolute(uint8 index) -> void {
|
|||
io();
|
||||
io();
|
||||
io();
|
||||
L uint8 data = load(absolute + index) & mask;
|
||||
Z = data == 0;
|
||||
L uint8 data = load(absolute + index);
|
||||
Z = (data & mask) == 0;
|
||||
V = data.bit(6);
|
||||
N = data.bit(7);
|
||||
}
|
||||
|
@ -498,13 +514,13 @@ auto HuC6280::instruction_TST_zeropage(uint8 index) -> void {
|
|||
io();
|
||||
io();
|
||||
io();
|
||||
L uint8 data = load(0x2000 + zeropage + index) & mask;
|
||||
Z = data == 0;
|
||||
L uint8 data = load(0x2000 + zeropage + index);
|
||||
Z = (data & mask) == 0;
|
||||
V = data.bit(6);
|
||||
N = data.bit(7);
|
||||
}
|
||||
|
||||
auto HuC6280::instruction_TXS() -> void {
|
||||
S = X;
|
||||
L io();
|
||||
S = X;
|
||||
}
|
||||
|
|
|
@ -31,9 +31,9 @@ auto HuC6280::operand() -> uint8 {
|
|||
//
|
||||
|
||||
auto HuC6280::push(uint8 data) -> void {
|
||||
store(0x2100 + ++S, data);
|
||||
store(0x2100 + (S--), data);
|
||||
}
|
||||
|
||||
auto HuC6280::pull() -> uint8 {
|
||||
return load(0x2100 + S--);
|
||||
return load(0x2100 + (++S));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue