Update to v088r04 release.

byuu says:

This will hopefully be a short-lived WIP, I just want to save
a breakpoint before I attempt something else.
NES, GB, GBC and GBA all load via const stream& now.
NES CPU core moved to Processor::RP2A03.
This commit is contained in:
Tim Allen 2012-04-28 16:35:51 +10:00
parent 616372e96b
commit 67c13f749f
53 changed files with 726 additions and 689 deletions

View File

@ -1,7 +1,7 @@
#ifndef BASE_HPP
#define BASE_HPP
static const char Version[] = "088.03";
static const char Version[] = "088.04";
#include <nall/platform.hpp>
#include <nall/algorithm.hpp>

View File

@ -7,12 +7,14 @@ namespace GameBoyAdvance {
#include "serialization.cpp"
Cartridge cartridge;
bool Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
bool Cartridge::load(const string &markup, const stream &memory) {
information.markup = markup;
XML::Document document(markup);
for(unsigned addr = 0; addr < rom.size; addr++) {
rom.data[addr] = data[Bus::mirror(addr, size)];
unsigned size = memory.size();
memory.read(rom.data, min(rom.size, size));
for(unsigned addr = size; addr < rom.size; addr++) {
rom.data[addr] = rom.data[Bus::mirror(addr, size)];
}
has_sram = false;
@ -47,7 +49,7 @@ bool Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
}
}
sha256 = nall::sha256(rom.data, rom.size);
sha256 = nall::sha256(rom.data, size);
system.load();
return loaded = true;

View File

@ -12,7 +12,7 @@ struct Cartridge : property<Cartridge> {
string markup;
} information;
bool load(const string &markup, const uint8_t *data, unsigned size);
bool load(const string &markup, const stream &memory);
void unload();
void power();

View File

@ -44,7 +44,7 @@ struct stream {
return data;
}
void read(uint8_t *data, unsigned length) const {
virtual void read(uint8_t *data, unsigned length) const {
while(length--) *data++ = read();
}

View File

@ -111,7 +111,7 @@ void serialize(serializer &s) {
s.integer(irq_latch);
}
BandaiFCG(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
BandaiFCG(XML::Document &document, const stream &memory) : Board(document, memory) {
}
};

View File

@ -86,7 +86,7 @@ void Board::serialize(serializer &s) {
if(chrram.size) s.array(chrram.data, chrram.size);
}
Board::Board(XML::Document &document, const uint8_t *data, unsigned size) {
Board::Board(XML::Document &document, const stream &memory) {
auto &cartridge = document["cartridge"];
information.type = cartridge["board"]["type"].data;
@ -102,8 +102,8 @@ Board::Board(XML::Document &document, const uint8_t *data, unsigned size) {
if(chrrom.size) chrrom.data = new uint8[chrrom.size]();
if(chrram.size) chrram.data = new uint8[chrram.size]();
if(prgrom.size) memcpy(prgrom.data, data, prgrom.size);
if(chrrom.size) memcpy(chrrom.data, data + prgrom.size, chrrom.size);
if(prgrom.size) memory.read(prgrom.data, prgrom.size);
if(chrrom.size) memory.read(chrrom.data, chrrom.size);
prgram.writable = true;
chrram.writable = true;
@ -112,56 +112,56 @@ Board::Board(XML::Document &document, const uint8_t *data, unsigned size) {
Board::~Board() {
}
Board* Board::load(const string &markup, const uint8_t *data, unsigned size) {
Board* Board::load(const string &markup, const stream &memory) {
XML::Document document(markup);
string type = document["cartridge"]["board"]["type"].data;
if(type == "BANDAI-FCG") return new BandaiFCG(document, data, size);
if(type == "BANDAI-FCG") return new BandaiFCG(document, memory);
if(type == "KONAMI-VRC-1") return new KonamiVRC1(document, data, size);
if(type == "KONAMI-VRC-2") return new KonamiVRC2(document, data, size);
if(type == "KONAMI-VRC-3") return new KonamiVRC3(document, data, size);
if(type == "KONAMI-VRC-4") return new KonamiVRC4(document, data, size);
if(type == "KONAMI-VRC-6") return new KonamiVRC6(document, data, size);
if(type == "KONAMI-VRC-7") return new KonamiVRC7(document, data, size);
if(type == "KONAMI-VRC-1") return new KonamiVRC1(document, memory);
if(type == "KONAMI-VRC-2") return new KonamiVRC2(document, memory);
if(type == "KONAMI-VRC-3") return new KonamiVRC3(document, memory);
if(type == "KONAMI-VRC-4") return new KonamiVRC4(document, memory);
if(type == "KONAMI-VRC-6") return new KonamiVRC6(document, memory);
if(type == "KONAMI-VRC-7") return new KonamiVRC7(document, memory);
if(type == "NES-AMROM" ) return new NES_AxROM(document, data, size);
if(type == "NES-ANROM" ) return new NES_AxROM(document, data, size);
if(type == "NES-AN1ROM" ) return new NES_AxROM(document, data, size);
if(type == "NES-AOROM" ) return new NES_AxROM(document, data, size);
if(type == "NES-AMROM" ) return new NES_AxROM(document, memory);
if(type == "NES-ANROM" ) return new NES_AxROM(document, memory);
if(type == "NES-AN1ROM" ) return new NES_AxROM(document, memory);
if(type == "NES-AOROM" ) return new NES_AxROM(document, memory);
if(type == "NES-BNROM" ) return new NES_BNROM(document, data, size);
if(type == "NES-BNROM" ) return new NES_BNROM(document, memory);
if(type == "NES-CNROM" ) return new NES_CNROM(document, data, size);
if(type == "NES-CNROM" ) return new NES_CNROM(document, memory);
if(type == "NES-EKROM" ) return new NES_ExROM(document, data, size);
if(type == "NES-ELROM" ) return new NES_ExROM(document, data, size);
if(type == "NES-ETROM" ) return new NES_ExROM(document, data, size);
if(type == "NES-EWROM" ) return new NES_ExROM(document, data, size);
if(type == "NES-EKROM" ) return new NES_ExROM(document, memory);
if(type == "NES-ELROM" ) return new NES_ExROM(document, memory);
if(type == "NES-ETROM" ) return new NES_ExROM(document, memory);
if(type == "NES-EWROM" ) return new NES_ExROM(document, memory);
if(type == "NES-FJROM" ) return new NES_FxROM(document, data, size);
if(type == "NES-FKROM" ) return new NES_FxROM(document, data, size);
if(type == "NES-FJROM" ) return new NES_FxROM(document, memory);
if(type == "NES-FKROM" ) return new NES_FxROM(document, memory);
if(type == "NES-GNROM" ) return new NES_GxROM(document, data, size);
if(type == "NES-MHROM" ) return new NES_GxROM(document, data, size);
if(type == "NES-GNROM" ) return new NES_GxROM(document, memory);
if(type == "NES-MHROM" ) return new NES_GxROM(document, memory);
if(type == "NES-HKROM" ) return new NES_HKROM(document, data, size);
if(type == "NES-HKROM" ) return new NES_HKROM(document, memory);
if(type == "NES-NROM-128") return new NES_NROM(document, data, size);
if(type == "NES-NROM-256") return new NES_NROM(document, data, size);
if(type == "NES-NROM-128") return new NES_NROM(document, memory);
if(type == "NES-NROM-256") return new NES_NROM(document, memory);
if(type == "NES-PEEOROM" ) return new NES_PxROM(document, data, size);
if(type == "NES-PNROM" ) return new NES_PxROM(document, data, size);
if(type == "NES-PEEOROM" ) return new NES_PxROM(document, memory);
if(type == "NES-PNROM" ) return new NES_PxROM(document, memory);
if(type == "NES-SNROM" ) return new NES_SxROM(document, data, size);
if(type == "NES-SXROM" ) return new NES_SxROM(document, data, size);
if(type == "NES-SNROM" ) return new NES_SxROM(document, memory);
if(type == "NES-SXROM" ) return new NES_SxROM(document, memory);
if(type == "NES-TLROM" ) return new NES_TxROM(document, data, size);
if(type == "NES-TLROM" ) return new NES_TxROM(document, memory);
if(type == "NES-UNROM" ) return new NES_UxROM(document, data, size);
if(type == "NES-UOROM" ) return new NES_UxROM(document, data, size);
if(type == "NES-UNROM" ) return new NES_UxROM(document, memory);
if(type == "NES-UOROM" ) return new NES_UxROM(document, memory);
if(type == "SUNSOFT-5B" ) return new Sunsoft5B(document, data, size);
if(type == "SUNSOFT-5B" ) return new Sunsoft5B(document, memory);
return nullptr;
}

View File

@ -31,10 +31,10 @@ struct Board {
virtual void reset();
virtual void serialize(serializer&);
Board(XML::Document &document, const uint8_t *data, unsigned size);
Board(XML::Document &document, const stream &memory);
virtual ~Board();
static Board* load(const string &markup, const uint8_t *data, unsigned size);
static Board* load(const string &markup, const stream &memory);
struct Information {
string type;

View File

@ -34,7 +34,7 @@ void serialize(serializer &s) {
vrc1.serialize(s);
}
KonamiVRC1(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc1(*this) {
KonamiVRC1(XML::Document &document, const stream &memory) : Board(document, memory), vrc1(*this) {
}
};

View File

@ -49,7 +49,7 @@ void serialize(serializer &s) {
vrc2.serialize(s);
}
KonamiVRC2(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc2(*this) {
KonamiVRC2(XML::Document &document, const stream &memory) : Board(document, memory), vrc2(*this) {
settings.pinout.a0 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a0"].data);
settings.pinout.a1 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a1"].data);
}

View File

@ -50,7 +50,7 @@ void serialize(serializer &s) {
vrc3.serialize(s);
}
KonamiVRC3(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc3(*this) {
KonamiVRC3(XML::Document &document, const stream &memory) : Board(document, memory), vrc3(*this) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}

View File

@ -53,7 +53,7 @@ void serialize(serializer &s) {
vrc4.serialize(s);
}
KonamiVRC4(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc4(*this) {
KonamiVRC4(XML::Document &document, const stream &memory) : Board(document, memory), vrc4(*this) {
settings.pinout.a0 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a0"].data);
settings.pinout.a1 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a1"].data);
}

View File

@ -36,7 +36,7 @@ void main() { vrc6.main(); }
void power() { vrc6.power(); }
void reset() { vrc6.reset(); }
KonamiVRC6(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc6(*this) {
KonamiVRC6(XML::Document &document, const stream &memory) : Board(document, memory), vrc6(*this) {
}
};

View File

@ -41,7 +41,7 @@ void serialize(serializer &s) {
vrc7.serialize(s);
}
KonamiVRC7(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), vrc7(*this) {
KonamiVRC7(XML::Document &document, const stream &memory) : Board(document, memory), vrc7(*this) {
}
};

View File

@ -45,7 +45,7 @@ void serialize(serializer &s) {
s.integer(mirror_select);
}
NES_AxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
NES_AxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
}
};

View File

@ -45,7 +45,7 @@ void serialize(serializer &s) {
s.integer(prg_bank);
}
NES_BNROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
NES_BNROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}

View File

@ -47,7 +47,7 @@ void serialize(serializer &s) {
s.integer(chr_bank);
}
NES_CNROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
NES_CNROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}

View File

@ -46,7 +46,7 @@ void serialize(serializer &s) {
mmc5.serialize(s);
}
NES_ExROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), mmc5(*this) {
NES_ExROM(XML::Document &document, const stream &memory) : Board(document, memory), mmc5(*this) {
revision = Revision::ELROM;
}

View File

@ -84,7 +84,7 @@ void serialize(serializer &s) {
s.array(latch);
}
NES_FxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
NES_FxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
revision = Revision::FKROM;
}

View File

@ -54,7 +54,7 @@ void serialize(serializer &s) {
s.integer(chr_bank);
}
NES_GxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
NES_GxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}

View File

@ -42,7 +42,7 @@ void serialize(serializer &s) {
mmc6.serialize(s);
}
NES_HKROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), mmc6(*this) {
NES_HKROM(XML::Document &document, const stream &memory) : Board(document, memory), mmc6(*this) {
}
};

View File

@ -36,7 +36,7 @@ void serialize(serializer &s) {
Board::serialize(s);
}
NES_NROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
NES_NROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}

View File

@ -90,7 +90,7 @@ void serialize(serializer &s) {
s.array(latch);
}
NES_PxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
NES_PxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
revision = Revision::PNROM;
}

View File

@ -94,7 +94,7 @@ void serialize(serializer &s) {
mmc1.serialize(s);
}
NES_SxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), mmc1(*this) {
NES_SxROM(XML::Document &document, const stream &memory) : Board(document, memory), mmc1(*this) {
revision = Revision::SXROM;
}

View File

@ -60,7 +60,7 @@ void serialize(serializer &s) {
mmc3.serialize(s);
}
NES_TxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size), mmc3(*this) {
NES_TxROM(XML::Document &document, const stream &memory) : Board(document, memory), mmc3(*this) {
revision = Revision::TLROM;
}

View File

@ -48,7 +48,7 @@ void serialize(serializer &s) {
s.integer(prg_bank);
}
NES_UxROM(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
NES_UxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}

View File

@ -220,7 +220,7 @@ void serialize(serializer &s) {
pulse[2].serialize(s);
}
Sunsoft5B(XML::Document &document, const uint8_t *data, unsigned size) : Board(document, data, size) {
Sunsoft5B(XML::Document &document, const stream &memory) : Board(document, memory) {
}
};

View File

@ -14,18 +14,23 @@ void Cartridge::main() {
board->main();
}
void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
void Cartridge::load(const string &markup, const stream &memory) {
information.markup = markup;
if((size & 0xff) == 0) {
sha256 = nall::sha256(data, size);
board = Board::load(markup, data, size);
} else {
sha256 = nall::sha256(data + 16, size - 16);
board = Board::load(markup, data + 16, size - 16);
}
board = Board::load(markup, memory);
if(board == nullptr) return;
sha256_ctx sha;
uint8_t hash[32];
sha256_init(&sha);
sha256_chunk(&sha, board->prgrom.data, board->prgrom.size);
sha256_chunk(&sha, board->chrrom.data, board->chrrom.size);
sha256_final(&sha);
sha256_hash(&sha, hash);
string result;
for(auto &byte : hash) result.append(hex<2>(byte));
sha256 = result;
system.load();
loaded = true;
}

View File

@ -5,7 +5,7 @@ struct Cartridge : Thread, property<Cartridge> {
static void Main();
void main();
void load(const string &markup, const uint8_t *data, unsigned size);
void load(const string &markup, const stream &memory);
void unload();
unsigned ram_size();

View File

@ -1,10 +0,0 @@
#define call(op) (this->*op)()
#define L interrupt_test();
#include "interrupt.cpp"
#include "opcodes.cpp"
#include "exec.cpp"
#include "disassembler.cpp"
#undef L
#undef call

View File

@ -1,117 +0,0 @@
struct Flags {
bool n, v, d, i, z, c;
inline operator unsigned() {
return (n << 7) | (v << 6) | (d << 3) | (i << 2) | (z << 1) | (c << 0);
}
inline Flags& operator=(uint8 data) {
n = data & 0x80; v = data & 0x40;
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return *this;
}
};
struct Registers {
uint8 mdr;
uint16 pc;
uint8 a, x, y, s;
Flags p;
} regs;
struct Register16 {
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
};
} abs, iabs;
uint8 rd;
uint8 zp;
uint16 aa;
//interrupt.cpp
void interrupt();
void interrupt_test();
void set_nmi_line(bool);
void set_irq_line(bool);
void set_irq_apu_line(bool);
//opcodes.cpp
void opf_asl();
void opf_adc();
void opf_and();
void opf_bit();
void opf_cmp();
void opf_cpx();
void opf_cpy();
void opf_dec();
void opf_eor();
void opf_inc();
void opf_lda();
void opf_ldx();
void opf_ldy();
void opf_lsr();
void opf_ora();
void opf_rla();
void opf_rol();
void opf_ror();
void opf_rra();
void opf_sbc();
void opf_sla();
void opf_sra();
void opi_branch(bool condition);
void opi_clear_flag(bool &flag);
void opi_decrement(uint8 &r);
void opi_increment(uint8 &r);
void opi_pull(uint8 &r);
void opi_push(uint8 &r);
template<void (CPU::*op)()> void opi_read_absolute();
template<void (CPU::*op)()> void opi_read_absolute_x();
template<void (CPU::*op)()> void opi_read_absolute_y();
template<void (CPU::*op)()> void opi_read_immediate();
template<void (CPU::*op)()> void opi_read_indirect_zero_page_x();
template<void (CPU::*op)()> void opi_read_indirect_zero_page_y();
template<void (CPU::*op)()> void opi_read_zero_page();
template<void (CPU::*op)()> void opi_read_zero_page_x();
template<void (CPU::*op)()> void opi_read_zero_page_y();
template<void (CPU::*op)()> void opi_rmw_absolute();
template<void (CPU::*op)()> void opi_rmw_absolute_x();
template<void (CPU::*op)()> void opi_rmw_zero_page();
template<void (CPU::*op)()> void opi_rmw_zero_page_x();
void opi_set_flag(bool &flag);
template<void (CPU::*op)()> void opi_shift();
void opi_store_absolute(uint8 &r);
void opi_store_absolute_x(uint8 &r);
void opi_store_absolute_y(uint8 &r);
void opi_store_indirect_zero_page_x(uint8 &r);
void opi_store_indirect_zero_page_y(uint8 &r);
void opi_store_zero_page(uint8 &r);
void opi_store_zero_page_x(uint8 &r);
void opi_store_zero_page_y(uint8 &r);
void opi_transfer(uint8 &s, uint8 &d, bool flag);
void op_brk();
void op_jmp_absolute();
void op_jmp_indirect_absolute();
void op_jsr_absolute();
void op_nop();
void op_php();
void op_plp();
void op_rti();
void op_rts();
void opill_arr_immediate();
void opill_nop_absolute();
void opill_nop_absolute_x();
void opill_nop_immediate();
void opill_nop_implied();
void opill_nop_zero_page();
void opill_nop_zero_page_x();
//exec.cpp
void op_exec();
//disassembler.cpp
string disassemble();

View File

@ -1,196 +0,0 @@
//I = illegal instruction (only used as a visual indicator)
#define I
void CPU::op_exec() {
uint8 opcode = op_readpci();
switch(opcode) {
case 0x00: return op_brk();
case 0x01: return opi_read_indirect_zero_page_x<&CPU::opf_ora>();
I case 0x04: return opill_nop_zero_page();
case 0x05: return opi_read_zero_page<&CPU::opf_ora>();
case 0x06: return opi_rmw_zero_page<&CPU::opf_asl>();
case 0x08: return op_php();
case 0x09: return opi_read_immediate<&CPU::opf_ora>();
case 0x0a: return opi_shift<&CPU::opf_sla>();
I case 0x0c: return opill_nop_absolute();
case 0x0d: return opi_read_absolute<&CPU::opf_ora>();
case 0x0e: return opi_rmw_absolute<&CPU::opf_asl>();
case 0x10: return opi_branch(regs.p.n == 0);
case 0x11: return opi_read_indirect_zero_page_y<&CPU::opf_ora>();
I case 0x14: return opill_nop_zero_page_x();
case 0x15: return opi_read_zero_page_x<&CPU::opf_ora>();
case 0x16: return opi_rmw_zero_page_x<&CPU::opf_asl>();
case 0x18: return opi_clear_flag(regs.p.c);
case 0x19: return opi_read_absolute_y<&CPU::opf_ora>();
I case 0x1a: return opill_nop_implied();
I case 0x1c: return opill_nop_absolute_x();
case 0x1d: return opi_read_absolute_x<&CPU::opf_ora>();
case 0x1e: return opi_rmw_absolute_x<&CPU::opf_asl>();
case 0x20: return op_jsr_absolute();
case 0x21: return opi_read_indirect_zero_page_x<&CPU::opf_and>();
case 0x24: return opi_read_zero_page<&CPU::opf_bit>();
case 0x25: return opi_read_zero_page<&CPU::opf_and>();
case 0x26: return opi_rmw_zero_page<&CPU::opf_rol>();
case 0x28: return op_plp();
case 0x29: return opi_read_immediate<&CPU::opf_and>();
case 0x2a: return opi_shift<&CPU::opf_rla>();
case 0x2c: return opi_read_absolute<&CPU::opf_bit>();
case 0x2d: return opi_read_absolute<&CPU::opf_and>();
case 0x2e: return opi_rmw_absolute<&CPU::opf_rol>();
case 0x30: return opi_branch(regs.p.n == 1);
case 0x31: return opi_read_indirect_zero_page_y<&CPU::opf_and>();
I case 0x34: return opill_nop_zero_page_x();
case 0x35: return opi_read_zero_page_x<&CPU::opf_and>();
case 0x36: return opi_rmw_zero_page_x<&CPU::opf_rol>();
case 0x38: return opi_set_flag(regs.p.c);
case 0x39: return opi_read_absolute_y<&CPU::opf_and>();
I case 0x3a: return opill_nop_implied();
I case 0x3c: return opill_nop_absolute_x();
case 0x3d: return opi_read_absolute_x<&CPU::opf_and>();
case 0x3e: return opi_rmw_absolute_x<&CPU::opf_rol>();
case 0x40: return op_rti();
case 0x41: return opi_read_indirect_zero_page_x<&CPU::opf_eor>();
I case 0x44: return opill_nop_zero_page();
case 0x45: return opi_read_zero_page<&CPU::opf_eor>();
case 0x46: return opi_rmw_zero_page<&CPU::opf_lsr>();
case 0x48: return opi_push(regs.a);
case 0x49: return opi_read_immediate<&CPU::opf_eor>();
case 0x4a: return opi_shift<&CPU::opf_sra>();
case 0x4c: return op_jmp_absolute();
case 0x4d: return opi_read_absolute<&CPU::opf_eor>();
case 0x4e: return opi_rmw_absolute<&CPU::opf_lsr>();
case 0x50: return opi_branch(regs.p.v == 0);
case 0x51: return opi_read_indirect_zero_page_y<&CPU::opf_eor>();
I case 0x54: return opill_nop_zero_page_x();
case 0x55: return opi_read_zero_page_x<&CPU::opf_eor>();
case 0x56: return opi_rmw_zero_page_x<&CPU::opf_lsr>();
case 0x58: return opi_clear_flag(regs.p.i);
case 0x59: return opi_read_absolute_y<&CPU::opf_eor>();
I case 0x5a: return opill_nop_implied();
I case 0x5c: return opill_nop_absolute_x();
case 0x5d: return opi_read_absolute_x<&CPU::opf_eor>();
case 0x5e: return opi_rmw_absolute_x<&CPU::opf_lsr>();
case 0x60: return op_rts();
case 0x61: return opi_read_indirect_zero_page_x<&CPU::opf_adc>();
I case 0x64: return opill_nop_zero_page();
case 0x65: return opi_read_zero_page<&CPU::opf_adc>();
case 0x66: return opi_rmw_zero_page<&CPU::opf_ror>();
case 0x68: return opi_pull(regs.a);
case 0x69: return opi_read_immediate<&CPU::opf_adc>();
case 0x6a: return opi_shift<&CPU::opf_rra>();
I case 0x6b: return opill_arr_immediate();
case 0x6c: return op_jmp_indirect_absolute();
case 0x6d: return opi_read_absolute<&CPU::opf_adc>();
case 0x6e: return opi_rmw_absolute<&CPU::opf_ror>();
case 0x70: return opi_branch(regs.p.v == 1);
I case 0x74: return opill_nop_zero_page_x();
case 0x71: return opi_read_indirect_zero_page_y<&CPU::opf_adc>();
case 0x75: return opi_read_zero_page_x<&CPU::opf_adc>();
case 0x76: return opi_rmw_zero_page_x<&CPU::opf_ror>();
case 0x78: return opi_set_flag(regs.p.i);
case 0x79: return opi_read_absolute_y<&CPU::opf_adc>();
I case 0x7a: return opill_nop_implied();
I case 0x7c: return opill_nop_absolute_x();
case 0x7d: return opi_read_absolute_x<&CPU::opf_adc>();
case 0x7e: return opi_rmw_absolute_x<&CPU::opf_ror>();
I case 0x80: return opill_nop_absolute();
case 0x81: return opi_store_indirect_zero_page_x(regs.a);
I case 0x82: return opill_nop_immediate();
case 0x84: return opi_store_zero_page(regs.y);
case 0x85: return opi_store_zero_page(regs.a);
case 0x86: return opi_store_zero_page(regs.x);
case 0x88: return opi_decrement(regs.y);
I case 0x89: return opill_nop_immediate();
case 0x8a: return opi_transfer(regs.x, regs.a, 1);
case 0x8c: return opi_store_absolute(regs.y);
case 0x8d: return opi_store_absolute(regs.a);
case 0x8e: return opi_store_absolute(regs.x);
case 0x90: return opi_branch(regs.p.c == 0);
case 0x91: return opi_store_indirect_zero_page_y(regs.a);
case 0x94: return opi_store_zero_page_x(regs.y);
case 0x95: return opi_store_zero_page_x(regs.a);
case 0x96: return opi_store_zero_page_y(regs.x);
case 0x98: return opi_transfer(regs.y, regs.a, 1);
case 0x99: return opi_store_absolute_y(regs.a);
case 0x9a: return opi_transfer(regs.x, regs.s, 0);
case 0x9d: return opi_store_absolute_x(regs.a);
case 0xa0: return opi_read_immediate<&CPU::opf_ldy>();
case 0xa1: return opi_read_indirect_zero_page_x<&CPU::opf_lda>();
case 0xa2: return opi_read_immediate<&CPU::opf_ldx>();
case 0xa4: return opi_read_zero_page<&CPU::opf_ldy>();
case 0xa5: return opi_read_zero_page<&CPU::opf_lda>();
case 0xa6: return opi_read_zero_page<&CPU::opf_ldx>();
case 0xa8: return opi_transfer(regs.a, regs.y, 1);
case 0xa9: return opi_read_immediate<&CPU::opf_lda>();
case 0xaa: return opi_transfer(regs.a, regs.x, 1);
case 0xac: return opi_read_absolute<&CPU::opf_ldy>();
case 0xad: return opi_read_absolute<&CPU::opf_lda>();
case 0xae: return opi_read_absolute<&CPU::opf_ldx>();
case 0xb0: return opi_branch(regs.p.c == 1);
case 0xb1: return opi_read_indirect_zero_page_y<&CPU::opf_lda>();
case 0xb4: return opi_read_zero_page_x<&CPU::opf_ldy>();
case 0xb5: return opi_read_zero_page_x<&CPU::opf_lda>();
case 0xb6: return opi_read_zero_page_y<&CPU::opf_ldx>();
case 0xb8: return opi_clear_flag(regs.p.v);
case 0xb9: return opi_read_absolute_y<&CPU::opf_lda>();
case 0xba: return opi_transfer(regs.s, regs.x, 1);
case 0xbc: return opi_read_absolute_x<&CPU::opf_ldy>();
case 0xbd: return opi_read_absolute_x<&CPU::opf_lda>();
case 0xbe: return opi_read_absolute_y<&CPU::opf_ldx>();
case 0xc0: return opi_read_immediate<&CPU::opf_cpy>();
case 0xc1: return opi_read_indirect_zero_page_x<&CPU::opf_cmp>();
I case 0xc2: return opill_nop_immediate();
case 0xc4: return opi_read_zero_page<&CPU::opf_cpy>();
case 0xc5: return opi_read_zero_page<&CPU::opf_cmp>();
case 0xc6: return opi_rmw_zero_page<&CPU::opf_dec>();
case 0xc8: return opi_increment(regs.y);
case 0xc9: return opi_read_immediate<&CPU::opf_cmp>();
case 0xca: return opi_decrement(regs.x);
case 0xcc: return opi_read_absolute<&CPU::opf_cpy>();
case 0xcd: return opi_read_absolute<&CPU::opf_cmp>();
case 0xce: return opi_rmw_absolute<&CPU::opf_dec>();
case 0xd0: return opi_branch(regs.p.z == 0);
case 0xd1: return opi_read_indirect_zero_page_y<&CPU::opf_cmp>();
I case 0xd4: return opill_nop_zero_page_x();
case 0xd5: return opi_read_zero_page_x<&CPU::opf_cmp>();
case 0xd6: return opi_rmw_zero_page_x<&CPU::opf_dec>();
case 0xd8: return opi_clear_flag(regs.p.d);
case 0xd9: return opi_read_absolute_y<&CPU::opf_cmp>();
I case 0xda: return opill_nop_implied();
I case 0xdc: return opill_nop_absolute_x();
case 0xdd: return opi_read_absolute_x<&CPU::opf_cmp>();
case 0xde: return opi_rmw_absolute_x<&CPU::opf_dec>();
case 0xe0: return opi_read_immediate<&CPU::opf_cpx>();
case 0xe1: return opi_read_indirect_zero_page_x<&CPU::opf_sbc>();
I case 0xe2: return opill_nop_immediate();
case 0xe4: return opi_read_zero_page<&CPU::opf_cpx>();
case 0xe5: return opi_read_zero_page<&CPU::opf_sbc>();
case 0xe6: return opi_rmw_zero_page<&CPU::opf_inc>();
case 0xe8: return opi_increment(regs.x);
case 0xe9: return opi_read_immediate<&CPU::opf_sbc>();
case 0xea: return op_nop();
I case 0xeb: return opi_read_immediate<&CPU::opf_sbc>();
case 0xec: return opi_read_absolute<&CPU::opf_cpx>();
case 0xed: return opi_read_absolute<&CPU::opf_sbc>();
case 0xee: return opi_rmw_absolute<&CPU::opf_inc>();
case 0xf0: return opi_branch(regs.p.z == 1);
case 0xf1: return opi_read_indirect_zero_page_y<&CPU::opf_sbc>();
I case 0xf4: return opill_nop_zero_page_x();
case 0xf5: return opi_read_zero_page_x<&CPU::opf_sbc>();
case 0xf6: return opi_rmw_zero_page_x<&CPU::opf_inc>();
case 0xf8: return opi_set_flag(regs.p.d);
case 0xf9: return opi_read_absolute_y<&CPU::opf_sbc>();
I case 0xfa: return opill_nop_implied();
I case 0xfc: return opill_nop_absolute_x();
case 0xfd: return opi_read_absolute_x<&CPU::opf_sbc>();
case 0xfe: return opi_rmw_absolute_x<&CPU::opf_inc>();
}
//return op_nop();
regs.pc--;
print("Unimplemented opcode: ", hex<4>(regs.pc), " = ", hex<2>(bus.read(regs.pc)), "\n");
while(true) scheduler.exit(Scheduler::ExitReason::UnknownEvent);
}
#undef I

View File

@ -1,37 +0,0 @@
void CPU::interrupt() {
op_readpc();
op_readpc();
op_writesp(regs.pc >> 8);
op_writesp(regs.pc >> 0);
op_writesp(regs.p | 0x20);
uint16 vector = 0xfffe; //IRQ
if(status.nmi_pending) {
status.nmi_pending = false;
vector = 0xfffa;
}
abs.l = op_read(vector++);
regs.p.i = 1;
regs.p.d = 0;
L abs.h = op_read(vector++);
regs.pc = abs.w;
}
void CPU::interrupt_test() {
status.interrupt_pending = ((status.irq_line | status.irq_apu_line) & ~regs.p.i) | status.nmi_pending;
}
void CPU::set_nmi_line(bool line) {
//edge-sensitive (0->1)
if(!status.nmi_line && line) status.nmi_pending = true;
status.nmi_line = line;
}
void CPU::set_irq_line(bool line) {
//level-sensitive
status.irq_line = line;
}
void CPU::set_irq_apu_line(bool line) {
//level-sensitive
status.irq_apu_line = line;
}

View File

@ -2,39 +2,29 @@
namespace Famicom {
#include "core/core.cpp"
#include "memory/memory.cpp"
#include "timing.cpp"
#include "serialization.cpp"
CPU cpu;
void CPU::Main() {
cpu.main();
}
void CPU::main() {
//trace = true;
//FILE *fp = fopen("/home/byuu/Desktop/log.txt", "wb");
unsigned lpc = 0xffff;
void CPU::Enter() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
if(status.interrupt_pending) {
interrupt();
continue;
}
if(trace) {
if(lpc != regs.pc) { print(disassemble(), "\n"); } lpc = regs.pc;
//if(lpc != regs.pc) { fprintf(fp, "%s\n", (const char*)disassemble()); fflush(fp); } lpc = regs.pc;
}
op_exec();
cpu.main();
}
}
void CPU::main() {
if(status.interrupt_pending) {
interrupt();
return;
}
exec();
}
void CPU::add_clocks(unsigned clocks) {
apu.clock -= clocks;
if(apu.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(apu.thread);
@ -47,11 +37,7 @@ void CPU::add_clocks(unsigned clocks) {
}
void CPU::power() {
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
regs.s = 0x00;
regs.p = 0x04;
RP2A03::power();
for(unsigned addr = 0; addr < 0x0800; addr++) ram[addr] = 0xff;
ram[0x0008] = 0xf7;
@ -61,11 +47,8 @@ void CPU::power() {
}
void CPU::reset() {
create(CPU::Main, 21477272);
regs.mdr = 0x00;
regs.s -= 3;
regs.p.i = 1;
RP2A03::reset();
create(CPU::Enter, 21477272);
regs.pc = bus.read(0xfffc) << 0;
regs.pc |= bus.read(0xfffd) << 8;
@ -87,16 +70,8 @@ void CPU::reset() {
status.controller_port1 = 0;
}
uint8 CPU::mdr() const {
return regs.mdr;
}
void CPU::set_rdy_line(bool line) {
status.rdy_line = line;
}
void CPU::set_rdy_addr(optional<uint16> addr) {
status.rdy_addr = addr;
uint8 CPU::debugger_read(uint16 addr) {
return bus.read(addr);
}
uint8 CPU::ram_read(uint16 addr) {
@ -132,11 +107,4 @@ void CPU::write(uint16 addr, uint8 data) {
return apu.write(addr, data);
}
void CPU::oam_dma() {
for(unsigned n = 0; n < 256; n++) {
uint8 data = op_read((status.oam_dma_page << 8) + n);
op_write(0x2004, data);
}
}
}

View File

@ -1,6 +1,4 @@
struct CPU : Thread {
#include "core/core.hpp"
#include "memory/memory.hpp"
struct CPU : Processor::RP2A03, Thread {
uint8 ram[0x0800];
struct Status {
@ -21,16 +19,14 @@ struct CPU : Thread {
unsigned controller_port1;
} status;
static void Main();
static void Enter();
void main();
void add_clocks(unsigned clocks);
void power();
void reset();
uint8 mdr() const;
void set_rdy_line(bool);
void set_rdy_addr(optional<uint16>);
uint8 debugger_read(uint16 addr);
uint8 ram_read(uint16 addr);
void ram_write(uint16 addr, uint8 data);
@ -38,12 +34,22 @@ struct CPU : Thread {
uint8 read(uint16 addr);
void write(uint16 addr, uint8 data);
void oam_dma();
void serialize(serializer&);
//internal:
bool trace;
//timing.cpp
uint8 op_read(uint16 addr);
void op_write(uint16 addr, uint8 data);
void last_cycle();
void nmi(uint16 &vector);
void oam_dma();
void set_nmi_line(bool);
void set_irq_line(bool);
void set_irq_apu_line(bool);
void set_rdy_line(bool);
void set_rdy_addr(optional<uint16>);
};
extern CPU cpu;

View File

@ -1,59 +0,0 @@
uint8 CPU::op_read(uint16 addr) {
if(status.oam_dma_pending) {
status.oam_dma_pending = false;
op_read(addr);
oam_dma();
}
while(status.rdy_line == 0) {
regs.mdr = bus.read(status.rdy_addr ? status.rdy_addr() : addr);
add_clocks(12);
}
regs.mdr = bus.read(addr);
add_clocks(12);
return regs.mdr;
}
void CPU::op_write(uint16 addr, uint8 data) {
bus.write(addr, regs.mdr = data);
add_clocks(12);
}
//
uint8 CPU::op_readpc() {
return op_read(regs.pc);
}
uint8 CPU::op_readpci() {
return op_read(regs.pc++);
}
uint8 CPU::op_readsp() {
return op_read(0x0100 | ++regs.s);
}
uint8 CPU::op_readzp(uint8 addr) {
return op_read(addr);
}
//
void CPU::op_writesp(uint8 data) {
op_write(0x0100 | regs.s--, data);
}
void CPU::op_writezp(uint8 addr, uint8 data) {
op_write(addr, data);
}
//
void CPU::op_page(uint16 x, uint16 y) {
if((x & 0xff00) != (y & 0xff00)) op_read((x & 0xff00) | (y & 0x00ff));
}
void CPU::op_page_always(uint16 x, uint16 y) {
op_read((x & 0xff00) | (y & 0x00ff));
}

View File

@ -1,13 +0,0 @@
uint8 op_read(uint16 addr);
void op_write(uint16 addr, uint8 data);
uint8 op_readpc();
uint8 op_readpci();
uint8 op_readsp();
uint8 op_readzp(uint8 addr);
void op_writesp(uint8 data);
void op_writezp(uint8 addr, uint8 data);
void op_page(uint16 x, uint16 y);
void op_page_always(uint16 x, uint16 y);

View File

@ -1,27 +1,9 @@
void CPU::serialize(serializer &s) {
RP2A03::serialize(s);
Thread::serialize(s);
s.array(ram);
s.integer(regs.mdr);
s.integer(regs.pc);
s.integer(regs.a);
s.integer(regs.x);
s.integer(regs.y);
s.integer(regs.s);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.d);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(abs.w);
s.integer(iabs.w);
s.integer(rd);
s.integer(zp);
s.integer(aa);
s.integer(status.interrupt_pending);
s.integer(status.nmi_pending);
s.integer(status.nmi_line);

63
bsnes/nes/cpu/timing.cpp Executable file
View File

@ -0,0 +1,63 @@
uint8 CPU::op_read(uint16 addr) {
if(status.oam_dma_pending) {
status.oam_dma_pending = false;
op_read(addr);
oam_dma();
}
while(status.rdy_line == 0) {
regs.mdr = bus.read(status.rdy_addr ? status.rdy_addr() : addr);
add_clocks(12);
}
regs.mdr = bus.read(addr);
add_clocks(12);
return regs.mdr;
}
void CPU::op_write(uint16 addr, uint8 data) {
bus.write(addr, regs.mdr = data);
add_clocks(12);
}
void CPU::last_cycle() {
status.interrupt_pending = ((status.irq_line | status.irq_apu_line) & ~regs.p.i) | status.nmi_pending;
}
void CPU::nmi(uint16 &vector) {
if(status.nmi_pending) {
status.nmi_pending = false;
vector = 0xfffa;
}
}
void CPU::oam_dma() {
for(unsigned n = 0; n < 256; n++) {
uint8 data = op_read((status.oam_dma_page << 8) + n);
op_write(0x2004, data);
}
}
void CPU::set_nmi_line(bool line) {
//edge-sensitive (0->1)
if(!status.nmi_line && line) status.nmi_pending = true;
status.nmi_line = line;
}
void CPU::set_irq_line(bool line) {
//level-sensitive
status.irq_line = line;
}
void CPU::set_irq_apu_line(bool line) {
//level-sensitive
status.irq_apu_line = line;
}
void CPU::set_rdy_line(bool line) {
status.rdy_line = line;
}
void CPU::set_rdy_addr(optional<uint16> addr) {
status.rdy_addr = addr;
}

View File

@ -23,8 +23,4 @@ void Interface::message(const string &text) {
print(text, "\n");
}
void Interface::loadCartridge(const string &markup, const stream &memory) {
cartridge.load(markup, memory.data(), memory.size());
}
}

View File

@ -3,9 +3,8 @@ struct Interface {
virtual void videoRefresh(const uint32_t *data);
virtual void audioSample(int16_t sample);
virtual int16_t inputPoll(bool port, unsigned device, unsigned id);
virtual void message(const string &text);
void loadCartridge(const string &markup, const stream &memory);
virtual void message(const string &text);
};
extern Interface *interface;

View File

@ -2,6 +2,7 @@
#define NES_HPP
#include <base/base.hpp>
#include <processor/rp2a03/rp2a03.hpp>
namespace Famicom {
namespace Info {

View File

@ -2,6 +2,7 @@ processor_objects :=
processor_objects += $(if $(findstring arm,$(processors)),processor-arm)
processor_objects += $(if $(findstring hg51b,$(processors)),processor-hg51b)
processor_objects += $(if $(findstring lr35902,$(processors)),processor-lr35902)
processor_objects += $(if $(findstring rp2a03,$(processors)),processor-rp2a03)
processor_objects += $(if $(findstring upd96050,$(processors)),processor-upd96050)
objects += $(processor_objects)
@ -9,4 +10,5 @@ processor := processor
obj/processor-arm.o: $(processor)/arm/arm.cpp $(call rwildcard,$(processor)/arm)
obj/processor-hg51b.o: $(processor)/hg51b/hg51b.cpp $(call rwildcard,$(processor)/hg51b)
obj/processor-lr35902.o: $(processor)/lr35902/lr35902.cpp $(call rwildcard,$(processor)/lr35902)
obj/processor-rp2a03.o: $(processor)/rp2a03/rp2a03.cpp $(call rwildcard,$(processor)/rp2a03)
obj/processor-upd96050.o: $(processor)/upd96050/upd96050.cpp $(call rwildcard,$(processor)/upd96050)

View File

@ -1,24 +1,24 @@
string CPU::disassemble() {
string RP2A03::disassemble() {
string output = { hex<4>(regs.pc), " " };
auto abs = [&]() -> string { return { "$", hex<2>(bus.read(regs.pc + 2)), hex<2>(bus.read(regs.pc + 1)) }; };
auto abx = [&]() -> string { return { "$", hex<2>(bus.read(regs.pc + 2)), hex<2>(bus.read(regs.pc + 1)), ",x" }; };
auto aby = [&]() -> string { return { "$", hex<2>(bus.read(regs.pc + 2)), hex<2>(bus.read(regs.pc + 1)), ",y" }; };
auto iab = [&]() -> string { return { "($", hex<2>(bus.read(regs.pc + 2)), hex<2>(bus.read(regs.pc + 1)), ")" }; };
auto imm = [&]() -> string { return { "#$", hex<2>(bus.read(regs.pc + 1)) }; };
auto abs = [&]() -> string { return { "$", hex<2>(debugger_read(regs.pc + 2)), hex<2>(debugger_read(regs.pc + 1)) }; };
auto abx = [&]() -> string { return { "$", hex<2>(debugger_read(regs.pc + 2)), hex<2>(debugger_read(regs.pc + 1)), ",x" }; };
auto aby = [&]() -> string { return { "$", hex<2>(debugger_read(regs.pc + 2)), hex<2>(debugger_read(regs.pc + 1)), ",y" }; };
auto iab = [&]() -> string { return { "($", hex<2>(debugger_read(regs.pc + 2)), hex<2>(debugger_read(regs.pc + 1)), ")" }; };
auto imm = [&]() -> string { return { "#$", hex<2>(debugger_read(regs.pc + 1)) }; };
auto imp = [&]() -> string { return ""; };
auto izx = [&]() -> string { return { "($", hex<2>(bus.read(regs.pc + 1)), ",x)" }; };
auto izy = [&]() -> string { return { "($", hex<2>(bus.read(regs.pc + 1)), "),y" }; };
auto rel = [&]() -> string { return { "$", hex<4>((regs.pc + 2) + (int8)bus.read(regs.pc + 1)) }; };
auto zpg = [&]() -> string { return { "$", hex<2>(bus.read(regs.pc + 1)) }; };
auto zpx = [&]() -> string { return { "$", hex<2>(bus.read(regs.pc + 1)), ",x" }; };
auto zpy = [&]() -> string { return { "$", hex<2>(bus.read(regs.pc + 1)), ",y" }; };
auto izx = [&]() -> string { return { "($", hex<2>(debugger_read(regs.pc + 1)), ",x)" }; };
auto izy = [&]() -> string { return { "($", hex<2>(debugger_read(regs.pc + 1)), "),y" }; };
auto rel = [&]() -> string { return { "$", hex<4>((regs.pc + 2) + (int8)debugger_read(regs.pc + 1)) }; };
auto zpg = [&]() -> string { return { "$", hex<2>(debugger_read(regs.pc + 1)) }; };
auto zpx = [&]() -> string { return { "$", hex<2>(debugger_read(regs.pc + 1)), ",x" }; };
auto zpy = [&]() -> string { return { "$", hex<2>(debugger_read(regs.pc + 1)), ",y" }; };
#define op(byte, prefix, mode) \
case byte: output.append(#prefix, " ", mode()); \
break
uint8 opcode = bus.read(regs.pc);
uint8 opcode = debugger_read(regs.pc);
switch(opcode) {
op(0x00, brk, imm);
op(0x01, ora, izx);

View File

@ -1,7 +1,7 @@
//opcode functions
//================
void CPU::opf_adc() {
void RP2A03::opf_adc() {
signed result = regs.a + rd + regs.p.c;
regs.p.v = ~(regs.a ^ rd) & (regs.a ^ result) & 0x80;
regs.p.c = (result > 0xff);
@ -10,96 +10,96 @@ void CPU::opf_adc() {
regs.a = result;
}
void CPU::opf_and() {
void RP2A03::opf_and() {
regs.a &= rd;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void CPU::opf_asl() {
void RP2A03::opf_asl() {
regs.p.c = rd & 0x80;
rd <<= 1;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void CPU::opf_bit() {
void RP2A03::opf_bit() {
regs.p.n = (rd & 0x80);
regs.p.v = (rd & 0x40);
regs.p.z = ((rd & regs.a) == 0);
}
void CPU::opf_cmp() {
void RP2A03::opf_cmp() {
signed r = regs.a - rd;
regs.p.n = (r & 0x80);
regs.p.z = (uint8)(r == 0);
regs.p.c = (r >= 0);
}
void CPU::opf_cpx() {
void RP2A03::opf_cpx() {
signed r = regs.x - rd;
regs.p.n = (r & 0x80);
regs.p.z = (uint8)(r == 0);
regs.p.c = (r >= 0);
}
void CPU::opf_cpy() {
void RP2A03::opf_cpy() {
signed r = regs.y - rd;
regs.p.n = (r & 0x80);
regs.p.z = (uint8)(r == 0);
regs.p.c = (r >= 0);
}
void CPU::opf_dec() {
void RP2A03::opf_dec() {
rd--;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void CPU::opf_eor() {
void RP2A03::opf_eor() {
regs.a ^= rd;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void CPU::opf_inc() {
void RP2A03::opf_inc() {
rd++;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void CPU::opf_lda() {
void RP2A03::opf_lda() {
regs.a = rd;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void CPU::opf_ldx() {
void RP2A03::opf_ldx() {
regs.x = rd;
regs.p.n = (regs.x & 0x80);
regs.p.z = (regs.x == 0);
}
void CPU::opf_ldy() {
void RP2A03::opf_ldy() {
regs.y = rd;
regs.p.n = (regs.y & 0x80);
regs.p.z = (regs.y == 0);
}
void CPU::opf_lsr() {
void RP2A03::opf_lsr() {
regs.p.c = rd & 0x01;
rd >>= 1;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void CPU::opf_ora() {
void RP2A03::opf_ora() {
regs.a |= rd;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void CPU::opf_rla() {
void RP2A03::opf_rla() {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = regs.a & 0x80;
regs.a = (regs.a << 1) | carry;
@ -107,7 +107,7 @@ void CPU::opf_rla() {
regs.p.z = (regs.a == 0);
}
void CPU::opf_rol() {
void RP2A03::opf_rol() {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd & 0x80;
rd = (rd << 1) | carry;
@ -115,7 +115,7 @@ void CPU::opf_rol() {
regs.p.z = (rd == 0);
}
void CPU::opf_ror() {
void RP2A03::opf_ror() {
unsigned carry = (unsigned)regs.p.c << 7;
regs.p.c = rd & 0x01;
rd = carry | (rd >> 1);
@ -123,7 +123,7 @@ void CPU::opf_ror() {
regs.p.z = (rd == 0);
}
void CPU::opf_rra() {
void RP2A03::opf_rra() {
unsigned carry = (unsigned)regs.p.c << 7;
regs.p.c = regs.a & 0x01;
regs.a = carry | (regs.a >> 1);
@ -131,19 +131,19 @@ void CPU::opf_rra() {
regs.p.z = (regs.a == 0);
}
void CPU::opf_sbc() {
void RP2A03::opf_sbc() {
rd ^= 0xff;
return opf_adc();
}
void CPU::opf_sla() {
void RP2A03::opf_sla() {
regs.p.c = regs.a & 0x80;
regs.a <<= 1;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void CPU::opf_sra() {
void RP2A03::opf_sra() {
regs.p.c = regs.a & 0x01;
regs.a >>= 1;
regs.p.n = (regs.a & 0x80);
@ -153,7 +153,7 @@ void CPU::opf_sra() {
//opcode implementations
//======================
void CPU::opi_branch(bool condition) {
void RP2A03::opi_branch(bool condition) {
if(condition == false) {
L rd = op_readpci();
} else {
@ -165,26 +165,26 @@ L op_readpc();
}
}
void CPU::opi_clear_flag(bool &flag) {
void RP2A03::opi_clear_flag(bool &flag) {
L op_readpc();
flag = 0;
}
void CPU::opi_decrement(uint8 &r) {
void RP2A03::opi_decrement(uint8 &r) {
L op_readpc();
r--;
regs.p.n = (r & 0x80);
regs.p.z = (r == 0);
}
void CPU::opi_increment(uint8 &r) {
void RP2A03::opi_increment(uint8 &r) {
L op_readpc();
r++;
regs.p.n = (r & 0x80);
regs.p.z = (r == 0);
}
void CPU::opi_pull(uint8 &r) {
void RP2A03::opi_pull(uint8 &r) {
op_readpc();
op_readpc();
L r = op_readsp();
@ -192,21 +192,21 @@ L r = op_readsp();
regs.p.z = (r == 0);
}
void CPU::opi_push(uint8 &r) {
void RP2A03::opi_push(uint8 &r) {
op_readpc();
L op_writesp(r);
}
template<void (CPU::*op)()>
void CPU::opi_read_absolute() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
L rd = op_read(abs.w);
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_read_absolute_x() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_absolute_x() {
abs.l = op_readpci();
abs.h = op_readpci();
op_page(abs.w, abs.w + regs.x);
@ -214,8 +214,8 @@ L rd = op_read(abs.w + regs.x);
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_read_absolute_y() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_absolute_y() {
abs.l = op_readpci();
abs.h = op_readpci();
op_page(abs.w, abs.w + regs.y);
@ -223,14 +223,14 @@ L rd = op_read(abs.w + regs.y);
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_read_immediate() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_immediate() {
L rd = op_readpci();
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_read_indirect_zero_page_x() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_indirect_zero_page_x() {
zp = op_readpci();
op_readzp(zp);
abs.l = op_readzp(zp++ + regs.x);
@ -239,8 +239,8 @@ L rd = op_read(abs.w);
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_read_indirect_zero_page_y() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_indirect_zero_page_y() {
rd = op_readpci();
abs.l = op_readzp(rd++);
abs.h = op_readzp(rd++);
@ -249,31 +249,31 @@ L rd = op_read(abs.w + regs.y);
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_read_zero_page() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_zero_page() {
zp = op_readpci();
L rd = op_readzp(zp);
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_read_zero_page_x() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_zero_page_x() {
zp = op_readpci();
op_readzp(zp);
L rd = op_readzp(zp + regs.x);
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_read_zero_page_y() {
template<void (RP2A03::*op)()>
void RP2A03::opi_read_zero_page_y() {
zp = op_readpci();
op_readzp(zp);
L rd = op_readzp(zp + regs.y);
call(op);
}
template<void (CPU::*op)()>
void CPU::opi_rmw_absolute() {
template<void (RP2A03::*op)()>
void RP2A03::opi_rmw_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
rd = op_read(abs.w);
@ -282,8 +282,8 @@ void CPU::opi_rmw_absolute() {
L op_write(abs.w, rd);
}
template<void (CPU::*op)()>
void CPU::opi_rmw_absolute_x() {
template<void (RP2A03::*op)()>
void RP2A03::opi_rmw_absolute_x() {
abs.l = op_readpci();
abs.h = op_readpci();
op_page_always(abs.w, abs.w + regs.x);
@ -293,8 +293,8 @@ void CPU::opi_rmw_absolute_x() {
L op_write(abs.w + regs.x, rd);
}
template<void (CPU::*op)()>
void CPU::opi_rmw_zero_page() {
template<void (RP2A03::*op)()>
void RP2A03::opi_rmw_zero_page() {
zp = op_readpci();
rd = op_readzp(zp);
op_writezp(zp, rd);
@ -302,8 +302,8 @@ void CPU::opi_rmw_zero_page() {
L op_writezp(zp, rd);
}
template<void (CPU::*op)()>
void CPU::opi_rmw_zero_page_x() {
template<void (RP2A03::*op)()>
void RP2A03::opi_rmw_zero_page_x() {
zp = op_readpci();
op_readzp(zp);
rd = op_readzp(zp + regs.x);
@ -312,38 +312,38 @@ void CPU::opi_rmw_zero_page_x() {
L op_writezp(zp + regs.x, rd);
}
void CPU::opi_set_flag(bool &flag) {
void RP2A03::opi_set_flag(bool &flag) {
L op_readpc();
flag = 1;
}
template<void (CPU::*op)()>
void CPU::opi_shift() {
template<void (RP2A03::*op)()>
void RP2A03::opi_shift() {
L op_readpc();
call(op);
}
void CPU::opi_store_absolute(uint8 &r) {
void RP2A03::opi_store_absolute(uint8 &r) {
abs.l = op_readpci();
abs.h = op_readpci();
L op_write(abs.w, r);
}
void CPU::opi_store_absolute_x(uint8 &r) {
void RP2A03::opi_store_absolute_x(uint8 &r) {
abs.l = op_readpci();
abs.h = op_readpci();
op_page_always(abs.w, abs.w + regs.x);
L op_write(abs.w + regs.x, r);
}
void CPU::opi_store_absolute_y(uint8 &r) {
void RP2A03::opi_store_absolute_y(uint8 &r) {
abs.l = op_readpci();
abs.h = op_readpci();
op_page_always(abs.w, abs.w + regs.y);
L op_write(abs.w + regs.y, r);
}
void CPU::opi_store_indirect_zero_page_x(uint8 &r) {
void RP2A03::opi_store_indirect_zero_page_x(uint8 &r) {
zp = op_readpci();
op_readzp(zp);
abs.l = op_readzp(zp++ + regs.x);
@ -351,7 +351,7 @@ void CPU::opi_store_indirect_zero_page_x(uint8 &r) {
L op_write(abs.w, r);
}
void CPU::opi_store_indirect_zero_page_y(uint8 &r) {
void RP2A03::opi_store_indirect_zero_page_y(uint8 &r) {
rd = op_readpci();
abs.l = op_readzp(rd++);
abs.h = op_readzp(rd++);
@ -359,24 +359,24 @@ void CPU::opi_store_indirect_zero_page_y(uint8 &r) {
L op_write(abs.w + regs.y, r);
}
void CPU::opi_store_zero_page(uint8 &r) {
void RP2A03::opi_store_zero_page(uint8 &r) {
zp = op_readpci();
L op_writezp(zp, r);
}
void CPU::opi_store_zero_page_x(uint8 &r) {
void RP2A03::opi_store_zero_page_x(uint8 &r) {
zp = op_readpci();
op_readzp(zp);
L op_writezp(zp + regs.x, r);
}
void CPU::opi_store_zero_page_y(uint8 &r) {
void RP2A03::opi_store_zero_page_y(uint8 &r) {
zp = op_readpci();
op_readzp(zp);
L op_writezp(zp + regs.y, r);
}
void CPU::opi_transfer(uint8 &s, uint8 &d, bool flag) {
void RP2A03::opi_transfer(uint8 &s, uint8 &d, bool flag) {
L op_readpc();
d = s;
if(flag == false) return;
@ -387,7 +387,7 @@ L op_readpc();
//opcodes
//=======
void CPU::op_brk() {
void RP2A03::op_brk() {
op_readpci();
op_writesp(regs.pc >> 8);
op_writesp(regs.pc >> 0);
@ -399,13 +399,13 @@ L abs.h = op_read(0xffff);
regs.pc = abs.w;
}
void CPU::op_jmp_absolute() {
void RP2A03::op_jmp_absolute() {
abs.l = op_readpci();
L abs.h = op_readpci();
regs.pc = abs.w;
}
void CPU::op_jmp_indirect_absolute() {
void RP2A03::op_jmp_indirect_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
iabs.l = op_read(abs.w); abs.l++;
@ -413,7 +413,7 @@ L iabs.h = op_read(abs.w); abs.l++;
regs.pc = iabs.w;
}
void CPU::op_jsr_absolute() {
void RP2A03::op_jsr_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
op_readpc();
@ -423,22 +423,22 @@ L op_writesp(regs.pc >> 0);
regs.pc = abs.w;
}
void CPU::op_nop() {
void RP2A03::op_nop() {
L op_readpc();
}
void CPU::op_php() {
void RP2A03::op_php() {
op_readpc();
L op_writesp(regs.p | 0x30);
}
void CPU::op_plp() {
void RP2A03::op_plp() {
op_readpc();
op_readpc();
L regs.p = op_readsp();
}
void CPU::op_rti() {
void RP2A03::op_rti() {
op_readpc();
op_readpc();
regs.p = op_readsp();
@ -447,7 +447,7 @@ L abs.h = op_readsp();
regs.pc = abs.w;
}
void CPU::op_rts() {
void RP2A03::op_rts() {
op_readpc();
op_readpc();
abs.l = op_readsp();
@ -459,7 +459,7 @@ L op_readpc();
//illegal opcodes
//===============
void CPU::opill_arr_immediate() {
void RP2A03::opill_arr_immediate() {
L rd = op_readpci();
regs.a &= rd;
regs.a = (regs.p.c << 7) | (regs.a >> 1);
@ -469,33 +469,33 @@ L rd = op_readpci();
regs.p.v = regs.p.c ^ ((regs.a >> 5) & 1);
}
void CPU::opill_nop_absolute() {
void RP2A03::opill_nop_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
L op_readpc();
}
void CPU::opill_nop_absolute_x() {
void RP2A03::opill_nop_absolute_x() {
abs.l = op_readpci();
abs.h = op_readpci();
op_page(abs.w, abs.w + regs.x);
L op_readpc();
}
void CPU::opill_nop_immediate() {
void RP2A03::opill_nop_immediate() {
L rd = op_readpc();
}
void CPU::opill_nop_implied() {
void RP2A03::opill_nop_implied() {
L op_readpc();
}
void CPU::opill_nop_zero_page() {
void RP2A03::opill_nop_zero_page() {
zp = op_readpci();
L op_readzp(zp);
}
void CPU::opill_nop_zero_page_x() {
void RP2A03::opill_nop_zero_page_x() {
zp = op_readpci();
op_readzp(zp);
L op_readzp(zp + regs.x);

View File

@ -0,0 +1,35 @@
uint8 RP2A03::op_readpc() {
return op_read(regs.pc);
}
uint8 RP2A03::op_readpci() {
return op_read(regs.pc++);
}
uint8 RP2A03::op_readsp() {
return op_read(0x0100 | ++regs.s);
}
uint8 RP2A03::op_readzp(uint8 addr) {
return op_read(addr);
}
//
void RP2A03::op_writesp(uint8 data) {
op_write(0x0100 | regs.s--, data);
}
void RP2A03::op_writezp(uint8 addr, uint8 data) {
op_write(addr, data);
}
//
void RP2A03::op_page(uint16 x, uint16 y) {
if((x & 0xff00) != (y & 0xff00)) op_read((x & 0xff00) | (y & 0x00ff));
}
void RP2A03::op_page_always(uint16 x, uint16 y) {
op_read((x & 0xff00) | (y & 0x00ff));
}

View File

@ -0,0 +1,31 @@
struct Flags {
bool n, v, d, i, z, c;
inline operator unsigned() {
return (n << 7) | (v << 6) | (d << 3) | (i << 2) | (z << 1) | (c << 0);
}
inline Flags& operator=(uint8 data) {
n = data & 0x80; v = data & 0x40;
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return *this;
}
};
struct Registers {
uint8 mdr;
uint16 pc;
uint8 a, x, y, s;
Flags p;
} regs;
struct Register16 {
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
};
} abs, iabs;
uint8 rd;
uint8 zp;
uint16 aa;

241
bsnes/processor/rp2a03/rp2a03.cpp Executable file
View File

@ -0,0 +1,241 @@
#include <processor/processor.hpp>
#include "rp2a03.hpp"
namespace Processor {
#define I
#define L last_cycle();
#define call(op) (this->*op)()
#include "memory.cpp"
#include "instructions.cpp"
#include "disassembler.cpp"
#include "serialization.cpp"
uint8 RP2A03::mdr() const {
return regs.mdr;
}
void RP2A03::power() {
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
regs.s = 0x00;
regs.p = 0x04;
}
void RP2A03::reset() {
regs.mdr = 0x00;
regs.s -= 3;
regs.p.i = 1;
}
void RP2A03::interrupt() {
op_readpc();
op_readpc();
op_writesp(regs.pc >> 8);
op_writesp(regs.pc >> 0);
op_writesp(regs.p | 0x20);
uint16 vector = 0xfffe; //IRQ
nmi(vector);
abs.l = op_read(vector++);
regs.p.i = 1;
regs.p.d = 0;
L abs.h = op_read(vector++);
regs.pc = abs.w;
}
void RP2A03::exec() {
uint8 opcode = op_readpci();
switch(opcode) {
case 0x00: return op_brk();
case 0x01: return opi_read_indirect_zero_page_x<&RP2A03::opf_ora>();
I case 0x04: return opill_nop_zero_page();
case 0x05: return opi_read_zero_page<&RP2A03::opf_ora>();
case 0x06: return opi_rmw_zero_page<&RP2A03::opf_asl>();
case 0x08: return op_php();
case 0x09: return opi_read_immediate<&RP2A03::opf_ora>();
case 0x0a: return opi_shift<&RP2A03::opf_sla>();
I case 0x0c: return opill_nop_absolute();
case 0x0d: return opi_read_absolute<&RP2A03::opf_ora>();
case 0x0e: return opi_rmw_absolute<&RP2A03::opf_asl>();
case 0x10: return opi_branch(regs.p.n == 0);
case 0x11: return opi_read_indirect_zero_page_y<&RP2A03::opf_ora>();
I case 0x14: return opill_nop_zero_page_x();
case 0x15: return opi_read_zero_page_x<&RP2A03::opf_ora>();
case 0x16: return opi_rmw_zero_page_x<&RP2A03::opf_asl>();
case 0x18: return opi_clear_flag(regs.p.c);
case 0x19: return opi_read_absolute_y<&RP2A03::opf_ora>();
I case 0x1a: return opill_nop_implied();
I case 0x1c: return opill_nop_absolute_x();
case 0x1d: return opi_read_absolute_x<&RP2A03::opf_ora>();
case 0x1e: return opi_rmw_absolute_x<&RP2A03::opf_asl>();
case 0x20: return op_jsr_absolute();
case 0x21: return opi_read_indirect_zero_page_x<&RP2A03::opf_and>();
case 0x24: return opi_read_zero_page<&RP2A03::opf_bit>();
case 0x25: return opi_read_zero_page<&RP2A03::opf_and>();
case 0x26: return opi_rmw_zero_page<&RP2A03::opf_rol>();
case 0x28: return op_plp();
case 0x29: return opi_read_immediate<&RP2A03::opf_and>();
case 0x2a: return opi_shift<&RP2A03::opf_rla>();
case 0x2c: return opi_read_absolute<&RP2A03::opf_bit>();
case 0x2d: return opi_read_absolute<&RP2A03::opf_and>();
case 0x2e: return opi_rmw_absolute<&RP2A03::opf_rol>();
case 0x30: return opi_branch(regs.p.n == 1);
case 0x31: return opi_read_indirect_zero_page_y<&RP2A03::opf_and>();
I case 0x34: return opill_nop_zero_page_x();
case 0x35: return opi_read_zero_page_x<&RP2A03::opf_and>();
case 0x36: return opi_rmw_zero_page_x<&RP2A03::opf_rol>();
case 0x38: return opi_set_flag(regs.p.c);
case 0x39: return opi_read_absolute_y<&RP2A03::opf_and>();
I case 0x3a: return opill_nop_implied();
I case 0x3c: return opill_nop_absolute_x();
case 0x3d: return opi_read_absolute_x<&RP2A03::opf_and>();
case 0x3e: return opi_rmw_absolute_x<&RP2A03::opf_rol>();
case 0x40: return op_rti();
case 0x41: return opi_read_indirect_zero_page_x<&RP2A03::opf_eor>();
I case 0x44: return opill_nop_zero_page();
case 0x45: return opi_read_zero_page<&RP2A03::opf_eor>();
case 0x46: return opi_rmw_zero_page<&RP2A03::opf_lsr>();
case 0x48: return opi_push(regs.a);
case 0x49: return opi_read_immediate<&RP2A03::opf_eor>();
case 0x4a: return opi_shift<&RP2A03::opf_sra>();
case 0x4c: return op_jmp_absolute();
case 0x4d: return opi_read_absolute<&RP2A03::opf_eor>();
case 0x4e: return opi_rmw_absolute<&RP2A03::opf_lsr>();
case 0x50: return opi_branch(regs.p.v == 0);
case 0x51: return opi_read_indirect_zero_page_y<&RP2A03::opf_eor>();
I case 0x54: return opill_nop_zero_page_x();
case 0x55: return opi_read_zero_page_x<&RP2A03::opf_eor>();
case 0x56: return opi_rmw_zero_page_x<&RP2A03::opf_lsr>();
case 0x58: return opi_clear_flag(regs.p.i);
case 0x59: return opi_read_absolute_y<&RP2A03::opf_eor>();
I case 0x5a: return opill_nop_implied();
I case 0x5c: return opill_nop_absolute_x();
case 0x5d: return opi_read_absolute_x<&RP2A03::opf_eor>();
case 0x5e: return opi_rmw_absolute_x<&RP2A03::opf_lsr>();
case 0x60: return op_rts();
case 0x61: return opi_read_indirect_zero_page_x<&RP2A03::opf_adc>();
I case 0x64: return opill_nop_zero_page();
case 0x65: return opi_read_zero_page<&RP2A03::opf_adc>();
case 0x66: return opi_rmw_zero_page<&RP2A03::opf_ror>();
case 0x68: return opi_pull(regs.a);
case 0x69: return opi_read_immediate<&RP2A03::opf_adc>();
case 0x6a: return opi_shift<&RP2A03::opf_rra>();
I case 0x6b: return opill_arr_immediate();
case 0x6c: return op_jmp_indirect_absolute();
case 0x6d: return opi_read_absolute<&RP2A03::opf_adc>();
case 0x6e: return opi_rmw_absolute<&RP2A03::opf_ror>();
case 0x70: return opi_branch(regs.p.v == 1);
I case 0x74: return opill_nop_zero_page_x();
case 0x71: return opi_read_indirect_zero_page_y<&RP2A03::opf_adc>();
case 0x75: return opi_read_zero_page_x<&RP2A03::opf_adc>();
case 0x76: return opi_rmw_zero_page_x<&RP2A03::opf_ror>();
case 0x78: return opi_set_flag(regs.p.i);
case 0x79: return opi_read_absolute_y<&RP2A03::opf_adc>();
I case 0x7a: return opill_nop_implied();
I case 0x7c: return opill_nop_absolute_x();
case 0x7d: return opi_read_absolute_x<&RP2A03::opf_adc>();
case 0x7e: return opi_rmw_absolute_x<&RP2A03::opf_ror>();
I case 0x80: return opill_nop_absolute();
case 0x81: return opi_store_indirect_zero_page_x(regs.a);
I case 0x82: return opill_nop_immediate();
case 0x84: return opi_store_zero_page(regs.y);
case 0x85: return opi_store_zero_page(regs.a);
case 0x86: return opi_store_zero_page(regs.x);
case 0x88: return opi_decrement(regs.y);
I case 0x89: return opill_nop_immediate();
case 0x8a: return opi_transfer(regs.x, regs.a, 1);
case 0x8c: return opi_store_absolute(regs.y);
case 0x8d: return opi_store_absolute(regs.a);
case 0x8e: return opi_store_absolute(regs.x);
case 0x90: return opi_branch(regs.p.c == 0);
case 0x91: return opi_store_indirect_zero_page_y(regs.a);
case 0x94: return opi_store_zero_page_x(regs.y);
case 0x95: return opi_store_zero_page_x(regs.a);
case 0x96: return opi_store_zero_page_y(regs.x);
case 0x98: return opi_transfer(regs.y, regs.a, 1);
case 0x99: return opi_store_absolute_y(regs.a);
case 0x9a: return opi_transfer(regs.x, regs.s, 0);
case 0x9d: return opi_store_absolute_x(regs.a);
case 0xa0: return opi_read_immediate<&RP2A03::opf_ldy>();
case 0xa1: return opi_read_indirect_zero_page_x<&RP2A03::opf_lda>();
case 0xa2: return opi_read_immediate<&RP2A03::opf_ldx>();
case 0xa4: return opi_read_zero_page<&RP2A03::opf_ldy>();
case 0xa5: return opi_read_zero_page<&RP2A03::opf_lda>();
case 0xa6: return opi_read_zero_page<&RP2A03::opf_ldx>();
case 0xa8: return opi_transfer(regs.a, regs.y, 1);
case 0xa9: return opi_read_immediate<&RP2A03::opf_lda>();
case 0xaa: return opi_transfer(regs.a, regs.x, 1);
case 0xac: return opi_read_absolute<&RP2A03::opf_ldy>();
case 0xad: return opi_read_absolute<&RP2A03::opf_lda>();
case 0xae: return opi_read_absolute<&RP2A03::opf_ldx>();
case 0xb0: return opi_branch(regs.p.c == 1);
case 0xb1: return opi_read_indirect_zero_page_y<&RP2A03::opf_lda>();
case 0xb4: return opi_read_zero_page_x<&RP2A03::opf_ldy>();
case 0xb5: return opi_read_zero_page_x<&RP2A03::opf_lda>();
case 0xb6: return opi_read_zero_page_y<&RP2A03::opf_ldx>();
case 0xb8: return opi_clear_flag(regs.p.v);
case 0xb9: return opi_read_absolute_y<&RP2A03::opf_lda>();
case 0xba: return opi_transfer(regs.s, regs.x, 1);
case 0xbc: return opi_read_absolute_x<&RP2A03::opf_ldy>();
case 0xbd: return opi_read_absolute_x<&RP2A03::opf_lda>();
case 0xbe: return opi_read_absolute_y<&RP2A03::opf_ldx>();
case 0xc0: return opi_read_immediate<&RP2A03::opf_cpy>();
case 0xc1: return opi_read_indirect_zero_page_x<&RP2A03::opf_cmp>();
I case 0xc2: return opill_nop_immediate();
case 0xc4: return opi_read_zero_page<&RP2A03::opf_cpy>();
case 0xc5: return opi_read_zero_page<&RP2A03::opf_cmp>();
case 0xc6: return opi_rmw_zero_page<&RP2A03::opf_dec>();
case 0xc8: return opi_increment(regs.y);
case 0xc9: return opi_read_immediate<&RP2A03::opf_cmp>();
case 0xca: return opi_decrement(regs.x);
case 0xcc: return opi_read_absolute<&RP2A03::opf_cpy>();
case 0xcd: return opi_read_absolute<&RP2A03::opf_cmp>();
case 0xce: return opi_rmw_absolute<&RP2A03::opf_dec>();
case 0xd0: return opi_branch(regs.p.z == 0);
case 0xd1: return opi_read_indirect_zero_page_y<&RP2A03::opf_cmp>();
I case 0xd4: return opill_nop_zero_page_x();
case 0xd5: return opi_read_zero_page_x<&RP2A03::opf_cmp>();
case 0xd6: return opi_rmw_zero_page_x<&RP2A03::opf_dec>();
case 0xd8: return opi_clear_flag(regs.p.d);
case 0xd9: return opi_read_absolute_y<&RP2A03::opf_cmp>();
I case 0xda: return opill_nop_implied();
I case 0xdc: return opill_nop_absolute_x();
case 0xdd: return opi_read_absolute_x<&RP2A03::opf_cmp>();
case 0xde: return opi_rmw_absolute_x<&RP2A03::opf_dec>();
case 0xe0: return opi_read_immediate<&RP2A03::opf_cpx>();
case 0xe1: return opi_read_indirect_zero_page_x<&RP2A03::opf_sbc>();
I case 0xe2: return opill_nop_immediate();
case 0xe4: return opi_read_zero_page<&RP2A03::opf_cpx>();
case 0xe5: return opi_read_zero_page<&RP2A03::opf_sbc>();
case 0xe6: return opi_rmw_zero_page<&RP2A03::opf_inc>();
case 0xe8: return opi_increment(regs.x);
case 0xe9: return opi_read_immediate<&RP2A03::opf_sbc>();
case 0xea: return op_nop();
I case 0xeb: return opi_read_immediate<&RP2A03::opf_sbc>();
case 0xec: return opi_read_absolute<&RP2A03::opf_cpx>();
case 0xed: return opi_read_absolute<&RP2A03::opf_sbc>();
case 0xee: return opi_rmw_absolute<&RP2A03::opf_inc>();
case 0xf0: return opi_branch(regs.p.z == 1);
case 0xf1: return opi_read_indirect_zero_page_y<&RP2A03::opf_sbc>();
I case 0xf4: return opill_nop_zero_page_x();
case 0xf5: return opi_read_zero_page_x<&RP2A03::opf_sbc>();
case 0xf6: return opi_rmw_zero_page_x<&RP2A03::opf_inc>();
case 0xf8: return opi_set_flag(regs.p.d);
case 0xf9: return opi_read_absolute_y<&RP2A03::opf_sbc>();
I case 0xfa: return opill_nop_implied();
I case 0xfc: return opill_nop_absolute_x();
case 0xfd: return opi_read_absolute_x<&RP2A03::opf_sbc>();
case 0xfe: return opi_rmw_absolute_x<&RP2A03::opf_inc>();
}
//unimplemented opcode
return op_nop();
}
#undef I
#undef L
#undef call
}

117
bsnes/processor/rp2a03/rp2a03.hpp Executable file
View File

@ -0,0 +1,117 @@
#ifndef PROCESSOR_RP2A03_HPP
#define PROCESSOR_RP2A03_HPP
namespace Processor {
//Ricoh RP2A03
//Ricoh RP2A07
struct RP2A03 {
#include "registers.hpp"
virtual uint8 op_read(uint16 addr) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
virtual void last_cycle() = 0;
virtual void nmi(uint16 &vector) = 0;
virtual uint8 debugger_read(uint16 addr) { return 0u; }
uint8 mdr() const;
void power();
void reset();
void interrupt();
void exec();
void serialize(serializer&);
//memory.cpp
uint8 op_readpc();
uint8 op_readpci();
uint8 op_readsp();
uint8 op_readzp(uint8 addr);
void op_writesp(uint8 data);
void op_writezp(uint8 addr, uint8 data);
void op_page(uint16 x, uint16 y);
void op_page_always(uint16 x, uint16 y);
//instructions.cpp
void opf_asl();
void opf_adc();
void opf_and();
void opf_bit();
void opf_cmp();
void opf_cpx();
void opf_cpy();
void opf_dec();
void opf_eor();
void opf_inc();
void opf_lda();
void opf_ldx();
void opf_ldy();
void opf_lsr();
void opf_ora();
void opf_rla();
void opf_rol();
void opf_ror();
void opf_rra();
void opf_sbc();
void opf_sla();
void opf_sra();
void opi_branch(bool condition);
void opi_clear_flag(bool &flag);
void opi_decrement(uint8 &r);
void opi_increment(uint8 &r);
void opi_pull(uint8 &r);
void opi_push(uint8 &r);
template<void (RP2A03::*op)()> void opi_read_absolute();
template<void (RP2A03::*op)()> void opi_read_absolute_x();
template<void (RP2A03::*op)()> void opi_read_absolute_y();
template<void (RP2A03::*op)()> void opi_read_immediate();
template<void (RP2A03::*op)()> void opi_read_indirect_zero_page_x();
template<void (RP2A03::*op)()> void opi_read_indirect_zero_page_y();
template<void (RP2A03::*op)()> void opi_read_zero_page();
template<void (RP2A03::*op)()> void opi_read_zero_page_x();
template<void (RP2A03::*op)()> void opi_read_zero_page_y();
template<void (RP2A03::*op)()> void opi_rmw_absolute();
template<void (RP2A03::*op)()> void opi_rmw_absolute_x();
template<void (RP2A03::*op)()> void opi_rmw_zero_page();
template<void (RP2A03::*op)()> void opi_rmw_zero_page_x();
void opi_set_flag(bool &flag);
template<void (RP2A03::*op)()> void opi_shift();
void opi_store_absolute(uint8 &r);
void opi_store_absolute_x(uint8 &r);
void opi_store_absolute_y(uint8 &r);
void opi_store_indirect_zero_page_x(uint8 &r);
void opi_store_indirect_zero_page_y(uint8 &r);
void opi_store_zero_page(uint8 &r);
void opi_store_zero_page_x(uint8 &r);
void opi_store_zero_page_y(uint8 &r);
void opi_transfer(uint8 &s, uint8 &d, bool flag);
void op_brk();
void op_jmp_absolute();
void op_jmp_indirect_absolute();
void op_jsr_absolute();
void op_nop();
void op_php();
void op_plp();
void op_rti();
void op_rts();
void opill_arr_immediate();
void opill_nop_absolute();
void opill_nop_absolute_x();
void opill_nop_immediate();
void opill_nop_implied();
void opill_nop_zero_page();
void opill_nop_zero_page_x();
//disassembler.cpp
string disassemble();
};
}
#endif

View File

@ -0,0 +1,20 @@
void RP2A03::serialize(serializer &s) {
s.integer(regs.mdr);
s.integer(regs.pc);
s.integer(regs.a);
s.integer(regs.x);
s.integer(regs.y);
s.integer(regs.s);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.d);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(abs.w);
s.integer(iabs.w);
s.integer(rd);
s.integer(zp);
s.integer(aa);
}

View File

@ -1,4 +1,4 @@
processors := arm hg51b lr35902 upd96050
processors := arm hg51b lr35902 rp2a03 upd96050
include processor/Makefile
include $(nes)/Makefile

View File

@ -16,6 +16,7 @@ namespace GBA = GameBoyAdvance;
#include <nall/filemap.hpp>
#include <nall/input.hpp>
#include <nall/bps/patch.hpp>
#include <nall/stream/file.hpp>
#include <nall/stream/memory.hpp>
#include <nall/stream/vector.hpp>
#include <nall/nes/cartridge.hpp>

View File

@ -34,7 +34,7 @@ bool InterfaceGBA::loadCartridge(const string &filename) {
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
if(markup.empty()) markup = GameBoyAdvanceCartridge(memory.data(), memory.size()).markup;
GBA::cartridge.load(markup, memory.data(), memory.size());
GBA::cartridge.load(markup, vectorstream{memory});
GBA::system.power();
if(GBA::cartridge.ram_size()) {

View File

@ -47,7 +47,7 @@ bool InterfaceNES::loadCartridge(const string &filename) {
markup.readfile(interface->base.filename("manifest.xml", ".xml"));
if(markup.empty()) markup = FamicomCartridge(memory.data(), memory.size()).markup;
NES::cartridge.load(markup, memory.data(), memory.size());
NES::cartridge.load(markup, vectorstream{memory});
NES::system.power();
if(NES::cartridge.ram_size()) {