mirror of https://github.com/bsnes-emu/bsnes.git
Update to v102 release.
byuu says (in the public announcement): This release adds very preliminary emulation of the Sega Master System (Mark III), Sega Game Gear, Sega Mega Drive (Genesis), and NEC PC Engine (Turbografx-16). These cores do not yet offer sound emulation, save states or cheat codes. I'm always very hesitant to release a new emulation core in its alpha stages, as in the past this has resulted in lasting bad impressions of cores that have since improved greatly. For instance, the Game Boy Advance emulation offered today is easily the second most accurate around, yet it is still widely judged by its much older alpha implementation. However, it's always been tradition with higan to not hold onto code in secret. Rather than delay future releases for another year or two, I'll put my faith in you all to understand that the emulation of these systems will improve over time. I hope that by releasing things as they are now, I might be able to receive some much needed assistance in improving these cores, as the documentation for these new systems is very much less than ideal. byuu says (in the WIP forum): Changelog: - PCE: latch background scroll registers (fixes Neutopia scrolling) - PCE: clip background attribute table scrolling (fixes Blazing Lazers scrolling) - PCE: support background/sprite enable/disable bits - PCE: fix large sprite indexing (fixes Blazing Lazers title screen sprites) - HuC6280: wrap zeropage accesses to never go beyond $20xx - HuC6280: fix alternating addresses for block move instructions (fixes Neutopia II) - HuC6280: block move instructions save and restore A,X,Y registers - HuC6280: emulate BCD mode (may not be 100% correct, based on SNES BCD) (fixes Blazing Lazers scoring)
This commit is contained in:
parent
b03563426f
commit
ae5968cfeb
|
@ -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.35";
|
static const string Version = "102";
|
||||||
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/";
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
auto VDC::Background::scanline(uint y) -> void {
|
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 {
|
auto VDC::Background::run(uint x, uint y) -> void {
|
||||||
color = nothing;
|
color = nothing;
|
||||||
//if(blank) return;
|
|
||||||
|
|
||||||
uint10 hoffset = x + hscroll;
|
uint16 batAddress;
|
||||||
uint9 voffset = y + vscroll;
|
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 tiledata = vdc.vramRead(batAddress);
|
||||||
uint16 patternAddress = tiledata.bits(0,11) << 4;
|
uint16 patternAddress = tiledata.bits(0,11) << 4;
|
||||||
patternAddress += (voffset & 7);
|
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(2) = d1.bit(0 + index);
|
||||||
output.bit(3) = d1.bit(8 + index);
|
output.bit(3) = d1.bit(8 + index);
|
||||||
|
|
||||||
if(output == 0) return;
|
if(enable && output) color = vdc.cram[palette << 4 | output];
|
||||||
color = vdc.cram[palette << 4 | output];
|
hoffset++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
sprite.blank = data.bit(6);
|
sprite.enable = data.bit(6);
|
||||||
background.blank = data.bit(7);
|
background.enable = 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);
|
||||||
|
@ -127,6 +127,7 @@ auto VDC::write(uint11 addr, uint8 data) -> void {
|
||||||
if(io.address == 0x08) {
|
if(io.address == 0x08) {
|
||||||
//BYR
|
//BYR
|
||||||
background.vscroll.byte(a0) = data;
|
background.vscroll.byte(a0) = data;
|
||||||
|
background.voffset = background.vscroll;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,9 @@ auto VDC::Sprite::scanline(uint y) -> void {
|
||||||
auto VDC::Sprite::run(uint x, uint y) -> void {
|
auto VDC::Sprite::run(uint x, uint y) -> void {
|
||||||
x += 32;
|
x += 32;
|
||||||
y += 64;
|
y += 64;
|
||||||
|
|
||||||
color = nothing;
|
color = nothing;
|
||||||
|
if(!enable) return;
|
||||||
|
|
||||||
bool zero = 0;
|
bool zero = 0;
|
||||||
uint index = 0;
|
uint index = 0;
|
||||||
|
@ -58,9 +60,10 @@ auto VDC::Sprite::run(uint x, uint y) -> void {
|
||||||
if(object.height == 31) pattern.bit(1) = 0;
|
if(object.height == 31) pattern.bit(1) = 0;
|
||||||
if(object.height == 63) pattern.bits(1,2) = 0;
|
if(object.height == 63) pattern.bits(1,2) = 0;
|
||||||
|
|
||||||
uint16 patternAddress = pattern << 6;
|
uint16 patternAddress = pattern;
|
||||||
patternAddress += (voffset >> 4) << (6 + (object.height == 31));
|
patternAddress += (voffset >> 4) << 1;
|
||||||
patternAddress += (hoffset >> 4) << 6;
|
patternAddress += (hoffset >> 4);
|
||||||
|
patternAddress <<= 6;
|
||||||
patternAddress += (voffset & 15);
|
patternAddress += (voffset & 15);
|
||||||
|
|
||||||
uint16 d0 = vdc.vramRead(patternAddress + 0);
|
uint16 d0 = vdc.vramRead(patternAddress + 0);
|
||||||
|
|
|
@ -15,6 +15,7 @@ auto VDC::Enter() -> void {
|
||||||
|
|
||||||
auto VDC::main() -> void {
|
auto VDC::main() -> void {
|
||||||
//1365 cycles/scanline
|
//1365 cycles/scanline
|
||||||
|
state.x = 0;
|
||||||
uint y = state.y;
|
uint y = state.y;
|
||||||
auto output = buffer + y * 512;
|
auto output = buffer + y * 512;
|
||||||
background.scanline(y);
|
background.scanline(y);
|
||||||
|
@ -37,11 +38,7 @@ auto VDC::main() -> void {
|
||||||
step(4);
|
step(4);
|
||||||
}
|
}
|
||||||
step(341);
|
step(341);
|
||||||
scanline();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto VDC::scanline() -> void {
|
|
||||||
state.x = 0;
|
|
||||||
if(++state.y == 262) {
|
if(++state.y == 262) {
|
||||||
state.y = 0;
|
state.y = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
struct VDC : Thread {
|
struct VDC : Thread {
|
||||||
static auto Enter() -> void;
|
static auto Enter() -> void;
|
||||||
auto main() -> void;
|
auto main() -> void;
|
||||||
auto scanline() -> void;
|
|
||||||
auto step(uint clocks) -> void;
|
auto step(uint clocks) -> void;
|
||||||
auto refresh() -> void;
|
auto refresh() -> void;
|
||||||
|
|
||||||
|
@ -85,12 +84,15 @@ private:
|
||||||
auto scanline(uint y) -> void;
|
auto scanline(uint y) -> void;
|
||||||
auto run(uint x, uint y) -> void;
|
auto run(uint x, uint y) -> void;
|
||||||
|
|
||||||
bool blank;
|
bool enable;
|
||||||
uint10 hscroll;
|
uint10 hscroll;
|
||||||
uint9 vscroll;
|
uint9 vscroll;
|
||||||
uint8 width;
|
uint8 width;
|
||||||
uint8 height;
|
uint8 height;
|
||||||
|
|
||||||
|
uint10 hoffset;
|
||||||
|
uint9 voffset;
|
||||||
|
|
||||||
maybe<uint9> color;
|
maybe<uint9> color;
|
||||||
} background;
|
} background;
|
||||||
|
|
||||||
|
@ -99,7 +101,7 @@ private:
|
||||||
auto scanline(uint y) -> void;
|
auto scanline(uint y) -> void;
|
||||||
auto run(uint x, uint y) -> void;
|
auto run(uint x, uint y) -> void;
|
||||||
|
|
||||||
bool blank;
|
bool enable;
|
||||||
|
|
||||||
struct Object {
|
struct Object {
|
||||||
uint10 y;
|
uint10 y;
|
||||||
|
|
|
@ -14,8 +14,11 @@ struct HuC6280 {
|
||||||
|
|
||||||
//memory.cpp
|
//memory.cpp
|
||||||
inline auto mmu(uint16) const -> uint21;
|
inline auto mmu(uint16) const -> uint21;
|
||||||
inline auto load(uint16) -> uint8;
|
inline auto load8(uint8) -> uint8;
|
||||||
inline auto store(uint16, uint8) -> void;
|
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 io() -> uint8;
|
||||||
auto opcode() -> uint8;
|
auto opcode() -> uint8;
|
||||||
|
@ -49,12 +52,12 @@ struct HuC6280 {
|
||||||
auto TRB(uint8) -> uint8;
|
auto TRB(uint8) -> uint8;
|
||||||
auto TSB(uint8) -> uint8;
|
auto TSB(uint8) -> uint8;
|
||||||
|
|
||||||
using bp = auto (HuC6280::*)(uint16&, uint16&) -> void;
|
using bp = auto (HuC6280::*)(uint16&, uint16&, bool) -> void;
|
||||||
auto TAI(uint16&, uint16&) -> void;
|
auto TAI(uint16&, uint16&, bool) -> void;
|
||||||
auto TDD(uint16&, uint16&) -> void;
|
auto TDD(uint16&, uint16&, bool) -> void;
|
||||||
auto TIA(uint16&, uint16&) -> void;
|
auto TIA(uint16&, uint16&, bool) -> void;
|
||||||
auto TII(uint16&, uint16&) -> void;
|
auto TII(uint16&, uint16&, bool) -> void;
|
||||||
auto TIN(uint16&, uint16&) -> void;
|
auto TIN(uint16&, uint16&, bool) -> void;
|
||||||
|
|
||||||
auto instruction_absoluteLoad(fp, uint8&, uint8 = 0) -> void;
|
auto instruction_absoluteLoad(fp, uint8&, uint8 = 0) -> void;
|
||||||
auto instruction_absoluteModify(fp, uint8 = 0) -> void;
|
auto instruction_absoluteModify(fp, uint8 = 0) -> void;
|
||||||
|
|
|
@ -9,8 +9,8 @@ auto HuC6280::interrupt(uint16 vector) -> void {
|
||||||
push(P);
|
push(P);
|
||||||
D = 0;
|
D = 0;
|
||||||
I = 1;
|
I = 1;
|
||||||
PC.byte(0) = load(vector + 0);
|
PC.byte(0) = load16(vector + 0);
|
||||||
L PC.byte(1) = load(vector + 1);
|
L PC.byte(1) = load16(vector + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction() -> void {
|
auto HuC6280::instruction() -> void {
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
auto HuC6280::ADC(uint8 i) -> uint8 {
|
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);
|
C = o.bit(8);
|
||||||
Z = uint8(o) == 0;
|
Z = uint8(o) == 0;
|
||||||
V = ~(A ^ i) & (A ^ o) & 0x80;
|
|
||||||
N = o.bit(7);
|
N = o.bit(7);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -114,10 +124,21 @@ auto HuC6280::ROR(uint8 i) -> uint8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::SBC(uint8 i) -> uint8 {
|
auto HuC6280::SBC(uint8 i) -> uint8 {
|
||||||
uint9 o = A - i - !C;
|
i ^= 0xff;
|
||||||
C = !o.bit(8);
|
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;
|
Z = uint8(o) == 0;
|
||||||
V = (A ^ i) & (A ^ o) & 0x80;
|
|
||||||
N = o.bit(7);
|
N = o.bit(7);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -138,27 +159,27 @@ auto HuC6280::TSB(uint8 i) -> uint8 {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
auto HuC6280::TAI(uint16& source, uint16& target) -> void {
|
auto HuC6280::TAI(uint16& source, uint16& target, bool alternate) -> void {
|
||||||
source ^= 1;
|
!alternate ? source++ : source--;
|
||||||
target++;
|
target++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::TDD(uint16& source, uint16& target) -> void {
|
auto HuC6280::TDD(uint16& source, uint16& target, bool) -> void {
|
||||||
source--;
|
source--;
|
||||||
target--;
|
target--;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::TIA(uint16& source, uint16& target) -> void {
|
auto HuC6280::TIA(uint16& source, uint16& target, bool alternate) -> void {
|
||||||
source++;
|
source++;
|
||||||
target ^= 1;
|
!alternate ? target++ : target--;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::TII(uint16& source, uint16& target) -> void {
|
auto HuC6280::TII(uint16& source, uint16& target, bool) -> void {
|
||||||
source++;
|
source++;
|
||||||
target++;
|
target++;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::TIN(uint16& source, uint16& target) -> void {
|
auto HuC6280::TIN(uint16& source, uint16& target, bool) -> void {
|
||||||
source++;
|
source++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +189,7 @@ auto HuC6280::instruction_absoluteLoad(fp alu, uint8& data, uint8 index) -> void
|
||||||
uint16 absolute = operand();
|
uint16 absolute = operand();
|
||||||
absolute |= operand() << 8;
|
absolute |= operand() << 8;
|
||||||
io();
|
io();
|
||||||
L data = ALU(load(absolute + index));
|
L data = ALU(load16(absolute + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_absoluteModify(fp alu, uint8 index) -> void {
|
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;
|
absolute |= operand() << 8;
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
auto data = ALU(load(absolute + index));
|
auto data = ALU(load16(absolute + index));
|
||||||
L store(absolute + index, data);
|
L store16(absolute + index, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_absoluteStore(uint8 data, uint8 index) -> void {
|
auto HuC6280::instruction_absoluteStore(uint8 data, uint8 index) -> void {
|
||||||
uint16 absolute = operand();
|
uint16 absolute = operand();
|
||||||
absolute |= operand() << 8;
|
absolute |= operand() << 8;
|
||||||
io();
|
io();
|
||||||
L store(absolute + index, data);
|
L store16(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;
|
||||||
|
push(Y);
|
||||||
|
push(A);
|
||||||
|
push(X);
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
|
io();
|
||||||
|
io();
|
||||||
|
bool alternate = 0;
|
||||||
do {
|
do {
|
||||||
auto data = load(source);
|
auto data = load16(source);
|
||||||
store(target, data);
|
store16(target, data);
|
||||||
ALU(source, target);
|
ALU(source, target, alternate);
|
||||||
|
alternate ^= 1;
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
} while(--length);
|
} while(--length);
|
||||||
io();
|
X = pull();
|
||||||
L io();
|
A = pull();
|
||||||
|
L Y = pull();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_branch(bool take) -> void {
|
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 HuC6280::instruction_indirectLoad(fp alu, uint8& data, uint8 index) -> void {
|
||||||
auto zeropage = operand();
|
auto zeropage = operand();
|
||||||
io();
|
io();
|
||||||
uint16 absolute = load(0x2000 + zeropage + index);
|
uint16 absolute = load8(zeropage + index + 0);
|
||||||
absolute |= load(0x2001 + zeropage + index) << 8;
|
absolute |= load8(zeropage + index + 1) << 8;
|
||||||
io();
|
io();
|
||||||
L data = ALU(load(absolute));
|
L data = ALU(load16(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();
|
||||||
uint16 absolute = load(0x2000 + zeropage + index);
|
uint16 absolute = load8(zeropage + index + 0);
|
||||||
absolute |= load(0x2001 + zeropage + index) << 8;
|
absolute |= load8(zeropage + index + 1) << 8;
|
||||||
L store(absolute, data);
|
L store16(absolute, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_indirectYLoad(fp alu, uint8& data) -> void {
|
auto HuC6280::instruction_indirectYLoad(fp alu, uint8& data) -> void {
|
||||||
auto zeropage = operand();
|
auto zeropage = operand();
|
||||||
io();
|
io();
|
||||||
uint16 absolute = load(0x2000 + zeropage);
|
uint16 absolute = load8(zeropage + 0);
|
||||||
absolute |= load(0x2001 + zeropage) << 8;
|
absolute |= load8(zeropage + 1) << 8;
|
||||||
io();
|
io();
|
||||||
L data = ALU(load(absolute + Y));
|
L data = ALU(load16(absolute + Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_indirectYStore(uint8 data) -> void {
|
auto HuC6280::instruction_indirectYStore(uint8 data) -> void {
|
||||||
auto zeropage = operand();
|
auto zeropage = operand();
|
||||||
io();
|
io();
|
||||||
uint16 absolute = load(0x2000 + zeropage);
|
uint16 absolute = load8(zeropage + 0);
|
||||||
absolute |= load(0x2001 + zeropage) << 8;
|
absolute |= load8(zeropage + 1) << 8;
|
||||||
L store(absolute + Y, data);
|
L store16(absolute + Y, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_memory(fp alu) -> void {
|
auto HuC6280::instruction_memory(fp alu) -> void {
|
||||||
auto a = A;
|
auto a = A;
|
||||||
A = ALU(load(0x2000 + X));
|
A = ALU(load8(X));
|
||||||
L store(0x2000 + X, A);
|
L store8(X, A);
|
||||||
A = a;
|
A = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,21 +348,21 @@ L io();
|
||||||
auto HuC6280::instruction_zeropageLoad(fp alu, uint8& data, uint8 index) -> void {
|
auto HuC6280::instruction_zeropageLoad(fp alu, uint8& data, uint8 index) -> void {
|
||||||
auto zeropage = operand();
|
auto zeropage = operand();
|
||||||
io();
|
io();
|
||||||
L data = ALU(load(0x2000 + zeropage + index));
|
L data = ALU(load8(zeropage + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_zeropageModify(fp alu, uint8 index) -> void {
|
auto HuC6280::instruction_zeropageModify(fp alu, uint8 index) -> void {
|
||||||
auto zeropage = operand();
|
auto zeropage = operand();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
auto data = ALU(load(0x2000 + zeropage + index));
|
auto data = ALU(load8(zeropage + index));
|
||||||
L store(0x2000 + zeropage + index, data);
|
L store8(zeropage + index, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_zeropageStore(uint8 data, uint8 index) -> void {
|
auto HuC6280::instruction_zeropageStore(uint8 data, uint8 index) -> void {
|
||||||
auto zeropage = operand();
|
auto zeropage = operand();
|
||||||
io();
|
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();
|
auto displacement = operand();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
L auto data = load(0x2000 + zeropage);
|
L auto data = load8(zeropage);
|
||||||
if(data.bit(index) == 0) {
|
if(data.bit(index) == 0) {
|
||||||
PC += (int8)displacement;
|
PC += (int8)displacement;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +383,7 @@ auto HuC6280::instruction_BBS(uint3 index) -> void {
|
||||||
auto displacement = operand();
|
auto displacement = operand();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
L auto data = load(0x2000 + zeropage);
|
L auto data = load8(zeropage);
|
||||||
if(data.bit(index) == 1) {
|
if(data.bit(index) == 1) {
|
||||||
PC += (int8)displacement;
|
PC += (int8)displacement;
|
||||||
}
|
}
|
||||||
|
@ -375,8 +398,8 @@ auto HuC6280::instruction_BRK() -> void {
|
||||||
push(p | 0x10); //B flag set on push
|
push(p | 0x10); //B flag set on push
|
||||||
D = 0;
|
D = 0;
|
||||||
I = 1;
|
I = 1;
|
||||||
PC.byte(0) = load(0xfff6);
|
PC.byte(0) = load16(0xfff6);
|
||||||
L PC.byte(1) = load(0xfff7);
|
L PC.byte(1) = load16(0xfff7);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_BSR() -> void {
|
auto HuC6280::instruction_BSR() -> void {
|
||||||
|
@ -412,8 +435,8 @@ auto HuC6280::instruction_JMP_indirect(uint8 index) -> void {
|
||||||
address |= operand() << 8;
|
address |= operand() << 8;
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
PC.byte(0) = load(address + index + 0);
|
PC.byte(0) = load16(address + index + 0);
|
||||||
L PC.byte(1) = load(address + index + 1);
|
L PC.byte(1) = load16(address + index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_JSR() -> void {
|
auto HuC6280::instruction_JSR() -> void {
|
||||||
|
@ -435,9 +458,9 @@ auto HuC6280::instruction_RMB(uint3 index) -> void {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
auto data = load(0x2000 + zeropage);
|
auto data = load8(zeropage);
|
||||||
data.bit(index) = 0;
|
data.bit(index) = 0;
|
||||||
L store(0x2000 + zeropage, data);
|
L store8(zeropage, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_RTI() -> void {
|
auto HuC6280::instruction_RTI() -> void {
|
||||||
|
@ -464,16 +487,15 @@ auto HuC6280::instruction_SMB(uint3 index) -> void {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
auto data = load(0x2000 + zeropage);
|
auto data = load8(zeropage);
|
||||||
data.bit(index) = 1;
|
data.bit(index) = 1;
|
||||||
L store(0x2000 + zeropage, data);
|
L store8(zeropage, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_ST(uint2 index) -> void {
|
auto HuC6280::instruction_ST(uint2 index) -> void {
|
||||||
auto data = operand();
|
auto data = operand();
|
||||||
io();
|
io();
|
||||||
L io();
|
L store21(0x1fe000 + index, data);
|
||||||
write(0x1fe000 + index, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_TAM() -> void {
|
auto HuC6280::instruction_TAM() -> void {
|
||||||
|
@ -502,7 +524,7 @@ auto HuC6280::instruction_TST_absolute(uint8 index) -> void {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
L uint8 data = load(absolute + index);
|
L uint8 data = load16(absolute + index);
|
||||||
Z = (data & mask) == 0;
|
Z = (data & mask) == 0;
|
||||||
V = data.bit(6);
|
V = data.bit(6);
|
||||||
N = data.bit(7);
|
N = data.bit(7);
|
||||||
|
@ -514,7 +536,7 @@ auto HuC6280::instruction_TST_zeropage(uint8 index) -> void {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
L uint8 data = load(0x2000 + zeropage + index);
|
L uint8 data = load8(zeropage + index);
|
||||||
Z = (data & mask) == 0;
|
Z = (data & mask) == 0;
|
||||||
V = data.bit(6);
|
V = data.bit(6);
|
||||||
N = data.bit(7);
|
N = data.bit(7);
|
||||||
|
|
|
@ -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);
|
step(r.cs);
|
||||||
return read(mmu(addr));
|
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);
|
step(r.cs);
|
||||||
return write(mmu(addr), data);
|
return write(mmu(addr), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto HuC6280::store21(uint21 addr, uint8 data) -> void {
|
||||||
|
step(r.cs);
|
||||||
|
return write(addr, data);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
auto HuC6280::io() -> uint8 {
|
auto HuC6280::io() -> uint8 {
|
||||||
return load(r.pc);
|
step(r.cs);
|
||||||
|
return read(mmu(PC));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::opcode() -> uint8 {
|
auto HuC6280::opcode() -> uint8 {
|
||||||
return load(r.pc++);
|
step(r.cs);
|
||||||
|
return read(mmu(PC++));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::operand() -> uint8 {
|
auto HuC6280::operand() -> uint8 {
|
||||||
return load(r.pc++);
|
step(r.cs);
|
||||||
|
return read(mmu(PC++));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
auto HuC6280::push(uint8 data) -> void {
|
auto HuC6280::push(uint8 data) -> void {
|
||||||
store(0x2100 + (S--), data);
|
step(r.cs);
|
||||||
|
write(mmu(0x2100 + S), data);
|
||||||
|
S--;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::pull() -> uint8 {
|
auto HuC6280::pull() -> uint8 {
|
||||||
return load(0x2100 + (++S));
|
step(r.cs);
|
||||||
|
S++;
|
||||||
|
return read(mmu(0x2100 + S));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue