Browse Source

implementing renderer, debugging readPalette function to a working state

constantinfuerst 3 years ago
  1. 144
  2. 27
  3. 16
  4. 8
  5. 513
  6. 4
  7. 24
  8. BIN
  9. 65
  10. 12
  11. 45
  12. 7
  13. 37
  14. 2362


@ -1,45 +1,125 @@
#include "pch.h"
#include "../olcPGE/olcPixelGameEngine.h"
#include "bus/bus.h"
#include "memory/debugmem/dbgmem.h"
#include "microprocessor/microprocessor.h"
#include "microprocessor/cpu/cpu.h"
#include "microprocessor/ppu/ppu.h"
#include "microprocessor/sdh/sdh.h"
int main() {
bool* quit = new bool(false);
auto* code = new std::array<uint8_t, 2048> {0x00};
(*code)[0] = 0x25; //set register 1 to val
(*code)[1] = 0x02; //val = 2
(*code)[2] = 0x26; //set register 2 to val
(*code)[3] = 0x01; //val = 1
(*code)[4] = 0x52; //jump by relative address if register 1 == 2
(*code)[5] = 0x05; //relative address (skip the next five lines)
(*code)[6] = 0x27; //set register 3 to val
(*code)[7] = 0x05; //val = 5
(*code)[8] = 0x1a; //move reg 3 to temp reg
(*code)[9] = 0xf0; //debug instruction, output register[val]
(*code)[10] = 0x07; //val = 7 (output temp reg)
(*code)[11] = 0xf1; //debug instruction end program
bus main_bus;
bus graphics_bus;
bool* quit = new bool(false);
class CPU : public olc::PixelGameEngine {
CPU() {
sAppName = "CPU";
const auto p_cpu = new cpu(&main_bus, quit);
const auto p_ram = new dbgmem_RAM<247>(0x0009);
const auto p_rom = new dbgmem_ROM(code);
const auto p_ppu = new ppu(&main_bus, &graphics_bus);
const auto p_sdh = new sdh(&graphics_bus);
const auto p_vram = new dbgmem_RAM<635>(0x0009);
std::array<uint8_t, 2048>* code;
bus main_bus;
bus graphics_bus;
cpu* p_cpu;
dbgmem_RAM* p_ram;
dbgmem_ROM* p_rom;
ppu* p_ppu;
sdh* p_sdh;
dbgmem_VRAM* p_vram;
std::array<buselement*, 6> busMembers;
std::array<microprocessor*, 3> mChips;
main_bus.attachElement(p_cpu); main_bus.attachElement(p_ram); main_bus.attachElement(p_rom); main_bus.attachElement(p_ppu);
graphics_bus.attachElement(p_ppu); graphics_bus.attachElement(p_sdh); graphics_bus.attachElement(p_vram);
void initMembers();
while(*quit == false) {
bool OnUserCreate() override {
// Called once at the start, so create things here
SetScreenSize(184, 64);
return true;
bool OnUserUpdate(float fElapsedTime) override {
if (*quit == false)
for (auto& chip : mChips)
else {
std::cout << "QUIT" << std::endl;
return true;
bool OnUserDestroy() override {
for (auto& e : busMembers)
delete e;
return true;
int main() {
std::cout << "STARTING" << std::endl;
CPU cpuEngine;
if (cpuEngine.Construct(184, 64, 4, 4))
return 0;
delete quit; delete code; delete p_cpu; delete p_ram; delete p_rom; delete p_ppu; delete p_sdh; delete p_vram;
void CPU::initMembers() {
code = new std::array<uint8_t, 2048> { 0x00 };
p_cpu = new cpu(&main_bus, quit); p_ram = new dbgmem_RAM(); p_rom = new dbgmem_ROM(code);
p_ppu = new ppu(&main_bus, &graphics_bus); p_sdh = new sdh(&main_bus, &graphics_bus, this); p_vram = new dbgmem_VRAM();
busMembers = { p_cpu, p_ram, p_rom, p_ppu, p_sdh, p_vram };
mChips = { p_cpu, p_ppu, p_sdh };
main_bus.attachElement(p_cpu); main_bus.attachElement(p_ram); main_bus.attachElement(p_rom); main_bus.attachElement(p_ppu);
graphics_bus.attachElement(p_ppu); graphics_bus.attachElement(p_sdh); graphics_bus.attachElement(p_vram);
(*code)[0] = 0x41; //256 jumpreturn
(*code)[1] = 0x28; //address lo
(*code)[2] = 0x01; //address hi
(*code)[3] = 0x00;
(*code)[4] = 0x00;
(*code)[5] = 0x00;
(*code)[6] = 0x00;
(*code)[7] = 0x70; //call to PPU
(*code)[8] = 0x12; //ppu-op = 0x2 (LTS), color palette = 0x0
(*code)[9] = 0x1a; //accessing screen sector 0x1b (26), the visible top left
(*code)[10] = 0x00; //displaying segment 0x00 (number 1 defined below)
(*code)[11] = 0xf1; //debug op: end of program
//segment displaying a number 1 | 0 = 00 00 00, 1 = ff ff ff, 2 = a5 a5 a5, 3 = 5a 5a 5a
(*code)[12] = 0x00; (*code)[13] = 0x00;
(*code)[14] = 0x01; (*code)[15] = 0x60;
(*code)[16] = 0x06; (*code)[17] = 0x60;
(*code)[18] = 0x18; (*code)[19] = 0x60;
(*code)[20] = 0x00; (*code)[21] = 0x60;
(*code)[22] = 0x18; (*code)[23] = 0x60;
(*code)[24] = 0x18; (*code)[25] = 0x60;
(*code)[26] = 0x00; (*code)[27] = 0x00;
//color palette using 4 color greyscale | 0 = 00 00 00, 1 = ff ff ff, 2 = a5 a5 a5, 3 = 5a 5a 5a
(*code)[28] = 0x00; (*code)[29] = 0x00; (*code)[30] = 0x00;
(*code)[31] = 0xff; (*code)[32] = 0xff; (*code)[33] = 0xff;
(*code)[34] = 0xa5; (*code)[35] = 0xa5; (*code)[36] = 0xa5;
(*code)[37] = 0x5a; (*code)[38] = 0x5a; (*code)[39] = 0x5a;
//program jumpdest setting locations for ppu
(*code)[40] = 0x1f; //set offset page 0 to val
(*code)[41] = 0x02; //offset = 2
(*code)[42] = 0x0c; //val
(*code)[43] = 0x1f; //set offset page 0 to val
(*code)[44] = 0x03; //offset = 3
(*code)[45] = 0x01; //val
(*code)[46] = 0x1f; //set offset page 0 to val
(*code)[47] = 0x04; //offset = 4
(*code)[48] = 0x1c; //val
(*code)[49] = 0x1f; //set offset page 0 to val
(*code)[50] = 0x05; //offset = 5
(*code)[51] = 0x01; //val
(*code)[52] = 0x08; //return to retReg stored pointer


@ -1,19 +1,16 @@
#include "pch.h"
#include "dbgmem.h"
template <uint16_t T>
dbgmem_RAM<T>::dbgmem_RAM(uint16_t starting_address) {
m_range = addressRange(starting_address, T + starting_address);
dbgmem_RAM::dbgmem_RAM() {
m_range = addressRange(0x0009, 0x00FF);
template <uint16_t T>
uint8_t dbgmem_RAM<T>::read(const uint16_t& address) {
return ram[address];
uint8_t dbgmem_RAM::read(const uint16_t& address) {
return zeropage[address];
template <uint16_t T>
void dbgmem_RAM<T>::write(const uint16_t& address, const uint8_t& value) {
ram[address] = value;
void dbgmem_RAM::write(const uint16_t& address, const uint8_t& value) {
zeropage[address] = value;
dbgmem_ROM::dbgmem_ROM(std::array<uint8_t, 2048>* code) {
@ -28,4 +25,16 @@ uint8_t dbgmem_ROM::read(const uint16_t& address) {
void dbgmem_ROM::write(const uint16_t& address, const uint8_t& value) {
std::cout << "Illegal write operation on ROM" << std::endl;
dbgmem_VRAM::dbgmem_VRAM() {
m_range = addressRange(0x0009, 0x027b);
uint8_t dbgmem_VRAM::read(const uint16_t& address) {
return vram[address];
void dbgmem_VRAM::write(const uint16_t& address, const uint8_t& value) {
vram[address] = value;


@ -2,13 +2,12 @@
#include "pch.h"
#include "../../bus/bus.h"
template <uint16_t T>
class dbgmem_RAM final : public buselement {
std::array<uint8_t, T> ram = { 0x00 };
std::array<uint8_t, 247> zeropage = {0x00 };
dbgmem_RAM(uint16_t starting_address);
uint8_t read(const uint16_t& address) override;
void write(const uint16_t& address, const uint8_t& value) override;
@ -21,4 +20,15 @@ public:
dbgmem_ROM(std::array<uint8_t, 2048>* code);
uint8_t read(const uint16_t& address) override;
void write(const uint16_t& address, const uint8_t& value) override;
//I have not figured out how to create polymorphic member classes with template arguments
class dbgmem_VRAM final : public buselement {
std::array<uint8_t, 625> vram = { 0x00 };
uint8_t read(const uint16_t& address) override;
void write(const uint16_t& address, const uint8_t& value) override;


@ -54,3 +54,11 @@ void cpu::RTA() {
m_addrAbs = m_regGP[0];
m_addrAbs = m_regGP[1] << 8;
void cpu::DZV() {
m_addrAbs = read(m_pc);
m_addrAbs &= 0x00FF;
m_regTemp = read(m_pc);


@ -5,6 +5,7 @@ void cpu::onCycle() {
opcode = read(m_pc);
auto& instr = lookupTable[opcode];
std::cout << "cpu opcode: " << instr.ostr << " at: " << m_pc << std::endl;
opcode = 0x00;
@ -34,276 +35,276 @@ cpu::cpu(bus* parent, bool* running_flag) {
m_range = addressRange(false);
lookupTable = {
instruction(0x00,"0x00", &cpu::IMP, &cpu::NOP),
instruction(0x01,"0x01", &cpu::IMP, &cpu::NOP),
instruction(0x02,"0x02", &cpu::IMP, &cpu::CLC),
instruction(0x03,"0x03", &cpu::IMP, &cpu::CLO),
instruction(0x04,"0x04", &cpu::IMP, &cpu::CLD),
instruction(0x05,"0x05", &cpu::IMP, &cpu::CLI),
instruction(0x06,"0x06", &cpu::IMP, &cpu::NOP),
instruction(0x07,"0x07", &cpu::ABS, &cpu::BRK),
instruction(0x08,"0x08", &cpu::IMP, &cpu::BRT),
instruction(0x09,"0x09", &cpu::IMP, &cpu::NOP),
instruction(0x0a,"0x0a", &cpu::IMP, &cpu::NOP),
instruction(0x0b,"0x0b", &cpu::IMP, &cpu::NOP),
instruction(0x0c,"0x0c", &cpu::IMP, &cpu::NOP),
instruction(0x0d,"0x0d", &cpu::IMP, &cpu::NOP),
instruction(0x0e,"0x0e", &cpu::IMP, &cpu::NOP),
instruction(0x0f,"0x0f", &cpu::IMP, &cpu::NOP),
instruction(0x00,"0x00 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x01,"0x01 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x02,"0x02 CLC", &cpu::IMP, &cpu::CLC),
instruction(0x03,"0x03 CLO", &cpu::IMP, &cpu::CLO),
instruction(0x04,"0x04 CLD", &cpu::IMP, &cpu::CLD),
instruction(0x05,"0x05 CLI", &cpu::IMP, &cpu::CLI),
instruction(0x06,"0x06 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x07,"0x07 BRK", &cpu::ABS, &cpu::BRK),
instruction(0x08,"0x08 BRT", &cpu::IMP, &cpu::BRT),
instruction(0x09,"0x09 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x0a,"0x0a NOP", &cpu::IMP, &cpu::NOP),
instruction(0x0b,"0x0b NOP", &cpu::IMP, &cpu::NOP),
instruction(0x0c,"0x0c NOP", &cpu::IMP, &cpu::NOP),
instruction(0x0d,"0x0d NOP", &cpu::IMP, &cpu::NOP),
instruction(0x0e,"0x0e NOP", &cpu::IMP, &cpu::NOP),
instruction(0x0f,"0x0f NOP", &cpu::IMP, &cpu::NOP),
instruction(0x10,"0x10", &cpu::DAV, &cpu::MOV),
instruction(0x11,"0x11", &cpu::ABS, &cpu::MOV),
instruction(0x12,"0x12", &cpu::ZP0, &cpu::MOV),
instruction(0x13,"0x13", &cpu::IMP, &cpu::MR1),
instruction(0x14,"0x14", &cpu::IMP, &cpu::MR2),
instruction(0x15,"0x15", &cpu::IMP, &cpu::MR3),
instruction(0x16,"0x16", &cpu::IMP, &cpu::MR4),
instruction(0x17,"0x17", &cpu::ABS, &cpu::MSR),
instruction(0x18,"0x18", &cpu::IMP, &cpu::M1T),
instruction(0x19,"0x19", &cpu::IMP, &cpu::M2T),
instruction(0x1a,"0x1a", &cpu::IMP, &cpu::M3T),
instruction(0x1b,"0x1b", &cpu::IMP, &cpu::M4T),
instruction(0x1c,"0x1c", &cpu::IMP, &cpu::JJR),
instruction(0x1d,"0x1d", &cpu::IMP, &cpu::MJL),
instruction(0x1e,"0x1e", &cpu::IMP, &cpu::MJH),
instruction(0x1f,"0x1f", &cpu::IMP, &cpu::NOP),
instruction(0x10,"0x10 MOV", &cpu::DAV, &cpu::MOV),
instruction(0x11,"0x11 MOV", &cpu::ABS, &cpu::MOV),
instruction(0x12,"0x12 MOV", &cpu::ZP0, &cpu::MOV),
instruction(0x13,"0x13 MR1", &cpu::IMP, &cpu::MR1),
instruction(0x14,"0x14 MR2", &cpu::IMP, &cpu::MR2),
instruction(0x15,"0x15 MR3", &cpu::IMP, &cpu::MR3),
instruction(0x16,"0x16 MR4", &cpu::IMP, &cpu::MR4),
instruction(0x17,"0x17 MSR", &cpu::ABS, &cpu::MSR),
instruction(0x18,"0x18 M1T", &cpu::IMP, &cpu::M1T),
instruction(0x19,"0x19 M2T", &cpu::IMP, &cpu::M2T),
instruction(0x1a,"0x1a M3T", &cpu::IMP, &cpu::M3T),
instruction(0x1b,"0x1b M4$", &cpu::IMP, &cpu::M4T),
instruction(0x1c,"0x1c JJR", &cpu::IMP, &cpu::JJR),
instruction(0x1d,"0x1d MJL", &cpu::IMP, &cpu::MJL),
instruction(0x1e,"0x1e MJH", &cpu::IMP, &cpu::MJH),
instruction(0x1f,"0x1f MOV", &cpu::DZV, &cpu::MOV),
instruction(0x20,"0x20", &cpu::IMP, &cpu::LOD),
instruction(0x21,"0x21", &cpu::IMP, &cpu::LOD),
instruction(0x22,"0x22", &cpu::IMP, &cpu::LDA),
instruction(0x23,"0x23", &cpu::IMP, &cpu::LD1),
instruction(0x24,"0x24", &cpu::IMP, &cpu::NOP),
instruction(0x25,"0x25", &cpu::VAL, &cpu::LV1),
instruction(0x26,"0x26", &cpu::VAL, &cpu::LV2),
instruction(0x27,"0x27", &cpu::VAL, &cpu::LV3),
instruction(0x28,"0x28", &cpu::VAL, &cpu::LV4),
instruction(0x29,"0x29", &cpu::ABS, &cpu::MUL),
instruction(0x2a,"0x2a", &cpu::IMP, &cpu::NOP),
instruction(0x2b,"0x2b", &cpu::RTA, &cpu::MUL),
instruction(0x2c,"0x2c", &cpu::IMP, &cpu::NOP),
instruction(0x2d,"0x2d", &cpu::IMP, &cpu::NOP),
instruction(0x2e,"0x2e", &cpu::IMP, &cpu::NOP),
instruction(0x2f,"0x2f", &cpu::IMP, &cpu::NOP),
instruction(0x20,"0x20 LOD", &cpu::ABS, &cpu::LOD),
instruction(0x21,"0x21 LOD", &cpu::ZP0, &cpu::LOD),
instruction(0x22,"0x22 LDA", &cpu::IMP, &cpu::LDA),
instruction(0x23,"0x23 LD1", &cpu::IMP, &cpu::LD1),
instruction(0x24,"0x24 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x25,"0x25 LV1", &cpu::VAL, &cpu::LV1),
instruction(0x26,"0x26 LV2", &cpu::VAL, &cpu::LV2),
instruction(0x27,"0x27 LV3", &cpu::VAL, &cpu::LV3),
instruction(0x28,"0x28 LV4", &cpu::VAL, &cpu::LV4),
instruction(0x29,"0x29 MUL", &cpu::ABS, &cpu::MUL),
instruction(0x2a,"0x2a NOP", &cpu::IMP, &cpu::NOP),
instruction(0x2b,"0x2b MUL", &cpu::RTA, &cpu::MUL),
instruction(0x2c,"0x2c NOP", &cpu::IMP, &cpu::NOP),
instruction(0x2d,"0x2d NOP", &cpu::IMP, &cpu::NOP),
instruction(0x2e,"0x2e NOP", &cpu::IMP, &cpu::NOP),
instruction(0x2f,"0x2f NOP", &cpu::IMP, &cpu::NOP),
instruction(0x30,"0x30", &cpu::VAL, &cpu::ADC),
instruction(0x31,"0x31", &cpu::ABS, &cpu::ADC),
instruction(0x32,"0x32", &cpu::IMP, &cpu::AC1),
instruction(0x33,"0x33", &cpu::ZP0, &cpu::ADC),
instruction(0x34,"0x34", &cpu::VAL, &cpu::SBC),
instruction(0x35,"0x35", &cpu::ABS, &cpu::SBC),
instruction(0x36,"0x36", &cpu::IMP, &cpu::SC1),
instruction(0x37,"0x37", &cpu::ZP0, &cpu::SBC),
instruction(0x38,"0x38", &cpu::VAL, &cpu::INT),
instruction(0x39,"0x39", &cpu::VAL, &cpu::DET),
instruction(0x3a,"0x3a", &cpu::IMP, &cpu::IN1),
instruction(0x3b,"0x3b", &cpu::IMP, &cpu::NOP),
instruction(0x3c,"0x3c", &cpu::IMP, &cpu::DE1),
instruction(0x3d,"0x3d", &cpu::IMP, &cpu::NOP),
instruction(0x3e,"0x3e", &cpu::VAL, &cpu::INR),
instruction(0x3f,"0x3f", &cpu::VAL, &cpu::DER),
instruction(0x30,"0x30 ADC", &cpu::VAL, &cpu::ADC),
instruction(0x31,"0x31 ADC", &cpu::ABS, &cpu::ADC),
instruction(0x32,"0x32 AC1", &cpu::IMP, &cpu::AC1),
instruction(0x33,"0x33 ADC", &cpu::ZP0, &cpu::ADC),
instruction(0x34,"0x34 SBC", &cpu::VAL, &cpu::SBC),
instruction(0x35,"0x35 SBC", &cpu::ABS, &cpu::SBC),
instruction(0x36,"0x36 SC1", &cpu::IMP, &cpu::SC1),
instruction(0x37,"0x37 SBC", &cpu::ZP0, &cpu::SBC),
instruction(0x38,"0x38 INT", &cpu::VAL, &cpu::INT),
instruction(0x39,"0x39 DET", &cpu::VAL, &cpu::DET),
instruction(0x3a,"0x3a IN1", &cpu::IMP, &cpu::IN1),
instruction(0x3b,"0x3b NOP", &cpu::IMP, &cpu::NOP),
instruction(0x3c,"0x3c DE1", &cpu::IMP, &cpu::DE1),
instruction(0x3d,"0x3d NOP", &cpu::IMP, &cpu::NOP),
instruction(0x3e,"0x3e INR", &cpu::VAL, &cpu::INR),
instruction(0x3f,"0x3f DER", &cpu::VAL, &cpu::DER),
instruction(0x40,"0x40", &cpu::ABS, &cpu::JMP),
instruction(0x41,"0x41", &cpu::ABS, &cpu::JPR),
instruction(0x42,"0x42", &cpu::DAV, &cpu::BOE),
instruction(0x43,"0x43", &cpu::IMP, &cpu::NOP),
instruction(0x44,"0x44", &cpu::IMP, &cpu::NOP),
instruction(0x45,"0x45", &cpu::DAV, &cpu::BNE),
instruction(0x46,"0x46", &cpu::IMP, &cpu::NOP),
instruction(0x47,"0x47", &cpu::IMP, &cpu::NOP),
instruction(0x48,"0x48", &cpu::IMP, &cpu::RET),
instruction(0x49,"0x49", &cpu::IMP, &cpu::NOP),
instruction(0x4a,"0x4a", &cpu::IMP, &cpu::NOP),
instruction(0x4b,"0x4b", &cpu::IMP, &cpu::NOP),
instruction(0x4c,"0x4c", &cpu::IMP, &cpu::NOP),
instruction(0x4d,"0x4d", &cpu::IMP, &cpu::NOP),
instruction(0x4e,"0x4e", &cpu::IMP, &cpu::NOP),
instruction(0x4f,"0x4f", &cpu::IMP, &cpu::NOP),
instruction(0x40,"0x40 JMP", &cpu::ABS, &cpu::JMP),
instruction(0x41,"0x41 JPR", &cpu::ABS, &cpu::JPR),
instruction(0x42,"0x42 BOE", &cpu::DAV, &cpu::BOE),
instruction(0x43,"0x43 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x44,"0x44 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x45,"0x45 BNE", &cpu::DAV, &cpu::BNE),
instruction(0x46,"0x46 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x47,"0x47 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x48,"0x48 RET", &cpu::IMP, &cpu::RET),
instruction(0x49,"0x49 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x4a,"0x4a NOP", &cpu::IMP, &cpu::NOP),
instruction(0x4b,"0x4b NOP", &cpu::IMP, &cpu::NOP),
instruction(0x4c,"0x4c NOP", &cpu::IMP, &cpu::NOP),
instruction(0x4d,"0x4d NOP", &cpu::IMP, &cpu::NOP),
instruction(0x4e,"0x4e NOP", &cpu::IMP, &cpu::NOP),
instruction(0x4f,"0x4f NOP", &cpu::IMP, &cpu::NOP),
instruction(0x50,"0x50", &cpu::DRV, &cpu::BOE),
instruction(0x51,"0x51", &cpu::DRV, &cpu::BNE),
instruction(0x52,"0x52", &cpu::REL, &cpu::BRE),
instruction(0x53,"0x53", &cpu::REL, &cpu::BRN),
instruction(0x54,"0x54", &cpu::IMP, &cpu::NOP),
instruction(0x55,"0x55", &cpu::IMP, &cpu::NOP),
instruction(0x56,"0x56", &cpu::IMP, &cpu::NOP),
instruction(0x57,"0x57", &cpu::IMP, &cpu::NOP),
instruction(0x58,"0x58", &cpu::IMP, &cpu::NOP),
instruction(0x59,"0x59", &cpu::IMP, &cpu::NOP),
instruction(0x5a,"0x5a", &cpu::IMP, &cpu::NOP),
instruction(0x5b,"0x5b", &cpu::IMP, &cpu::NOP),
instruction(0x5c,"0x5c", &cpu::ABS, &cpu::BLM),
instruction(0x5d,"0x5d", &cpu::ABS, &cpu::BRM),
instruction(0x5e,"0x5e", &cpu::VAL, &cpu::BSL),
instruction(0x5f,"0x5f", &cpu::VAL, &cpu::BSR),
instruction(0x50,"0x50 BOE", &cpu::DRV, &cpu::BOE),
instruction(0x51,"0x51 BNE", &cpu::DRV, &cpu::BNE),
instruction(0x52,"0x52 BRE", &cpu::REL, &cpu::BRE),
instruction(0x53,"0x53 BRN", &cpu::REL, &cpu::BRN),
instruction(0x54,"0x54 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x55,"0x55 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x56,"0x56 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x57,"0x57 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x58,"0x58 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x59,"0x59 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x5a,"0x5a NOP", &cpu::IMP, &cpu::NOP),
instruction(0x5b,"0x5b NOP", &cpu::IMP, &cpu::NOP),
instruction(0x5c,"0x5c BLM", &cpu::ABS, &cpu::BLM),
instruction(0x5d,"0x5d BRM", &cpu::ABS, &cpu::BRM),
instruction(0x5e,"0x5e BSL", &cpu::VAL, &cpu::BSL),
instruction(0x5f,"0x5f BSR", &cpu::VAL, &cpu::BSR),
instruction(0x60,"0x60", &cpu::VAL, &cpu::CMP),
instruction(0x61,"0x61", &cpu::VAL, &cpu::CP1),
instruction(0x62,"0x62", &cpu::VAL, &cpu::CP2),
instruction(0x63,"0x63", &cpu::IMP, &cpu::NOP),
instruction(0x64,"0x64", &cpu::IMP, &cpu::NOP),
instruction(0x65,"0x65", &cpu::IMP, &cpu::NOP),
instruction(0x66,"0x66", &cpu::IMP, &cpu::NOP),
instruction(0x67,"0x67", &cpu::IMP, &cpu::NOP),
instruction(0x68,"0x68", &cpu::IMP, &cpu::NOP),
instruction(0x69,"0x69", &cpu::VAL, &cpu::RSR),
instruction(0x6a,"0x6a", &cpu::IMP, &cpu::NOP),
instruction(0x6b,"0x6b", &cpu::IMP, &cpu::NOP),
instruction(0x6c,"0x6c", &cpu::IMP, &cpu::NOP),
instruction(0x6d,"0x6d", &cpu::IMP, &cpu::NOP),
instruction(0x6e,"0x6e", &cpu::IMP, &cpu::NOP),
instruction(0x6f,"0x6f", &cpu::IMP, &cpu::NOP),
instruction(0x60,"0x60 CMP", &cpu::VAL, &cpu::CMP),
instruction(0x61,"0x61 CP1", &cpu::VAL, &cpu::CP1),
instruction(0x62,"0x62 CP2", &cpu::VAL, &cpu::CP2),
instruction(0x63,"0x63 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x64,"0x64 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x65,"0x65 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x66,"0x66 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x67,"0x67 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x68,"0x68 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x69,"0x69 RSR", &cpu::VAL, &cpu::RSR),
instruction(0x6a,"0x6a NOP", &cpu::IMP, &cpu::NOP),
instruction(0x6b,"0x6b NOP", &cpu::IMP, &cpu::NOP),
instruction(0x6c,"0x6c NOP", &cpu::IMP, &cpu::NOP),
instruction(0x6d,"0x6d NOP", &cpu::IMP, &cpu::NOP),
instruction(0x6e,"0x6e NOP", &cpu::IMP, &cpu::NOP),
instruction(0x6f,"0x6f NOP", &cpu::IMP, &cpu::NOP),
instruction(0x70,"0x70", &cpu::IMP, &cpu::NOP),
instruction(0x71,"0x71", &cpu::IMP, &cpu::NOP),
instruction(0x72,"0x72", &cpu::IMP, &cpu::NOP),
instruction(0x73,"0x73", &cpu::IMP, &cpu::NOP),
instruction(0x74,"0x74", &cpu::IMP, &cpu::NOP),
instruction(0x75,"0x75", &cpu::IMP, &cpu::NOP),
instruction(0x76,"0x76", &cpu::IMP, &cpu::NOP),
instruction(0x77,"0x77", &cpu::IMP, &cpu::NOP),
instruction(0x78,"0x78", &cpu::IMP, &cpu::NOP),
instruction(0x79,"0x79", &cpu::IMP, &cpu::NOP),
instruction(0x7a,"0x7a", &cpu::IMP, &cpu::NOP),
instruction(0x7b,"0x7b", &cpu::IMP, &cpu::NOP),
instruction(0x7c,"0x7c", &cpu::IMP, &cpu::NOP),
instruction(0x7d,"0x7d", &cpu::IMP, &cpu::NOP),
instruction(0x7e,"0x7e", &cpu::IMP, &cpu::NOP),
instruction(0x7f,"0x7f", &cpu::IMP, &cpu::NOP),
instruction(0x70,"0x70 PPU", &cpu::DAV, &cpu::PPU),
instruction(0x71,"0x71 POX", &cpu::VAL, &cpu::POX),
instruction(0x72,"0x72 POY", &cpu::VAL, &cpu::POY),
instruction(0x73,"0x73 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x74,"0x74 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x75,"0x75 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x76,"0x76 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x77,"0x77 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x78,"0x78 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x79,"0x79 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x7a,"0x7a NOP", &cpu::IMP, &cpu::NOP),
instruction(0x7b,"0x7b NOP", &cpu::IMP, &cpu::NOP),
instruction(0x7c,"0x7c NOP", &cpu::IMP, &cpu::NOP),
instruction(0x7d,"0x7d NOP", &cpu::IMP, &cpu::NOP),
instruction(0x7e,"0x7e NOP", &cpu::IMP, &cpu::NOP),
instruction(0x7f,"0x7f NOP", &cpu::IMP, &cpu::NOP),
instruction(0x80,"0x80", &cpu::IMP, &cpu::NOP),
instruction(0x81,"0x81", &cpu::IMP, &cpu::NOP),
instruction(0x82,"0x82", &cpu::IMP, &cpu::NOP),
instruction(0x83,"0x83", &cpu::IMP, &cpu::NOP),
instruction(0x84,"0x84", &cpu::IMP, &cpu::NOP),
instruction(0x85,"0x85", &cpu::IMP, &cpu::NOP),
instruction(0x86,"0x86", &cpu::IMP, &cpu::NOP),
instruction(0x87,"0x87", &cpu::IMP, &cpu::NOP),
instruction(0x88,"0x88", &cpu::IMP, &cpu::NOP),
instruction(0x89,"0x89", &cpu::IMP, &cpu::NOP),
instruction(0x8a,"0x8a", &cpu::IMP, &cpu::NOP),
instruction(0x8b,"0x8b", &cpu::IMP, &cpu::NOP),
instruction(0x8c,"0x8c", &cpu::IMP, &cpu::NOP),
instruction(0x8d,"0x8d", &cpu::IMP, &cpu::NOP),
instruction(0x8e,"0x8e", &cpu::IMP, &cpu::NOP),
instruction(0x8f,"0x8f", &cpu::IMP, &cpu::NOP),
instruction(0x80,"0x80 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x81,"0x81 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x82,"0x82 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x83,"0x83 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x84,"0x84 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x85,"0x85 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x86,"0x86 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x87,"0x87 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x88,"0x88 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x89,"0x89 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x8a,"0x8a NOP", &cpu::IMP, &cpu::NOP),
instruction(0x8b,"0x8b NOP", &cpu::IMP, &cpu::NOP),
instruction(0x8c,"0x8c NOP", &cpu::IMP, &cpu::NOP),
instruction(0x8d,"0x8d NOP", &cpu::IMP, &cpu::NOP),
instruction(0x8e,"0x8e NOP", &cpu::IMP, &cpu::NOP),
instruction(0x8f,"0x8f NOP", &cpu::IMP, &cpu::NOP),
instruction(0x90,"0x90", &cpu::IMP, &cpu::NOP),
instruction(0x91,"0x91", &cpu::IMP, &cpu::NOP),
instruction(0x92,"0x92", &cpu::IMP, &cpu::NOP),
instruction(0x93,"0x93", &cpu::IMP, &cpu::NOP),
instruction(0x94,"0x94", &cpu::IMP, &cpu::NOP),
instruction(0x95,"0x95", &cpu::IMP, &cpu::NOP),
instruction(0x96,"0x96", &cpu::IMP, &cpu::NOP),
instruction(0x97,"0x97", &cpu::IMP, &cpu::NOP),
instruction(0x98,"0x98", &cpu::IMP, &cpu::NOP),
instruction(0x99,"0x99", &cpu::IMP, &cpu::NOP),
instruction(0x9a,"0x9a", &cpu::IMP, &cpu::NOP),
instruction(0x9b,"0x9b", &cpu::IMP, &cpu::NOP),
instruction(0x9c,"0x9c", &cpu::IMP, &cpu::NOP),
instruction(0x9d,"0x9d", &cpu::IMP, &cpu::NOP),
instruction(0x9e,"0x9e", &cpu::IMP, &cpu::NOP),
instruction(0x9f,"0x9f", &cpu::IMP, &cpu::NOP),
instruction(0x90,"0x90 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x91,"0x91 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x92,"0x92 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x93,"0x93 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x94,"0x94 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x95,"0x95 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x96,"0x96 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x97,"0x97 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x98,"0x98 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x99,"0x99 NOP", &cpu::IMP, &cpu::NOP),
instruction(0x9a,"0x9a NOP", &cpu::IMP, &cpu::NOP),
instruction(0x9b,"0x9b NOP", &cpu::IMP, &cpu::NOP),
instruction(0x9c,"0x9c NOP", &cpu::IMP, &cpu::NOP),
instruction(0x9d,"0x9d NOP", &cpu::IMP, &cpu::NOP),
instruction(0x9e,"0x9e NOP", &cpu::IMP, &cpu::NOP),
instruction(0x9f,"0x9f NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa0,"0xa0", &cpu::IMP, &cpu::NOP),
instruction(0xa1,"0xa1", &cpu::IMP, &cpu::NOP),
instruction(0xa2,"0xa2", &cpu::IMP, &cpu::NOP),
instruction(0xa3,"0xa3", &cpu::IMP, &cpu::NOP),
instruction(0xa4,"0xa4", &cpu::IMP, &cpu::NOP),
instruction(0xa5,"0xa5", &cpu::IMP, &cpu::NOP),
instruction(0xa6,"0xa6", &cpu::IMP, &cpu::NOP),
instruction(0xa7,"0xa7", &cpu::IMP, &cpu::NOP),
instruction(0xa8,"0xa8", &cpu::IMP, &cpu::NOP),
instruction(0xa9,"0xa9", &cpu::IMP, &cpu::NOP),
instruction(0xaa,"0xaa", &cpu::IMP, &cpu::NOP),
instruction(0xab,"0xab", &cpu::IMP, &cpu::NOP),
instruction(0xac,"0xac", &cpu::IMP, &cpu::NOP),
instruction(0xad,"0xad", &cpu::IMP, &cpu::NOP),
instruction(0xae,"0xae", &cpu::IMP, &cpu::NOP),
instruction(0xaf,"0xaf", &cpu::IMP, &cpu::NOP),
instruction(0xa0,"0xa0 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa1,"0xa1 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa2,"0xa2 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa3,"0xa3 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa4,"0xa4 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa5,"0xa5 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa6,"0xa6 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa7,"0xa7 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa8,"0xa8 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xa9,"0xa9 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xaa,"0xaa NOP", &cpu::IMP, &cpu::NOP),
instruction(0xab,"0xab NOP", &cpu::IMP, &cpu::NOP),
instruction(0xac,"0xac NOP", &cpu::IMP, &cpu::NOP),
instruction(0xad,"0xad NOP", &cpu::IMP, &cpu::NOP),
instruction(0xae,"0xae NOP", &cpu::IMP, &cpu::NOP),
instruction(0xaf,"0xaf NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb0,"0xb0", &cpu::IMP, &cpu::NOP),
instruction(0xb1,"0xb1", &cpu::IMP, &cpu::NOP),
instruction(0xb2,"0xb2", &cpu::IMP, &cpu::NOP),
instruction(0xb3,"0xb3", &cpu::IMP, &cpu::NOP),
instruction(0xb4,"0xb4", &cpu::IMP, &cpu::NOP),
instruction(0xb5,"0xb5", &cpu::IMP, &cpu::NOP),
instruction(0xb6,"0xb6", &cpu::IMP, &cpu::NOP),
instruction(0xb7,"0xb7", &cpu::IMP, &cpu::NOP),
instruction(0xb8,"0xb8", &cpu::IMP, &cpu::NOP),
instruction(0xb9,"0xb9", &cpu::IMP, &cpu::NOP),
instruction(0xba,"0xba", &cpu::IMP, &cpu::NOP),
instruction(0xbb,"0xbb", &cpu::IMP, &cpu::NOP),
instruction(0xbc,"0xbc", &cpu::IMP, &cpu::NOP),
instruction(0xbd,"0xbd", &cpu::IMP, &cpu::NOP),
instruction(0xbe,"0xbe", &cpu::IMP, &cpu::NOP),
instruction(0xbf,"0xbf", &cpu::IMP, &cpu::NOP),
instruction(0xb0,"0xb0 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb1,"0xb1 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb2,"0xb2 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb3,"0xb3 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb4,"0xb4 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb5,"0xb5 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb6,"0xb6 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb7,"0xb7 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb8,"0xb8 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xb9,"0xb9 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xba,"0xba NOP", &cpu::IMP, &cpu::NOP),
instruction(0xbb,"0xbb NOP", &cpu::IMP, &cpu::NOP),
instruction(0xbc,"0xbc NOP", &cpu::IMP, &cpu::NOP),
instruction(0xbd,"0xbd NOP", &cpu::IMP, &cpu::NOP),
instruction(0xbe,"0xbe NOP", &cpu::IMP, &cpu::NOP),
instruction(0xbf,"0xbf NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc0,"0xc0", &cpu::IMP, &cpu::NOP),
instruction(0xc1,"0xc1", &cpu::IMP, &cpu::NOP),
instruction(0xc2,"0xc2", &cpu::IMP, &cpu::NOP),
instruction(0xc3,"0xc3", &cpu::IMP, &cpu::NOP),
instruction(0xc4,"0xc4", &cpu::IMP, &cpu::NOP),
instruction(0xc5,"0xc5", &cpu::IMP, &cpu::NOP),
instruction(0xc6,"0xc6", &cpu::IMP, &cpu::NOP),
instruction(0xc7,"0xc7", &cpu::IMP, &cpu::NOP),
instruction(0xc8,"0xc8", &cpu::IMP, &cpu::NOP),
instruction(0xc9,"0xc9", &cpu::IMP, &cpu::NOP),
instruction(0xca,"0xca", &cpu::IMP, &cpu::NOP),
instruction(0xcb,"0xcb", &cpu::IMP, &cpu::NOP),
instruction(0xcc,"0xcc", &cpu::IMP, &cpu::NOP),
instruction(0xcd,"0xcd", &cpu::IMP, &cpu::NOP),
instruction(0xce,"0xce", &cpu::IMP, &cpu::NOP),
instruction(0xcf,"0xcf", &cpu::IMP, &cpu::NOP),
instruction(0xc0,"0xc0 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc1,"0xc1 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc2,"0xc2 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc3,"0xc3 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc4,"0xc4 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc5,"0xc5 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc6,"0xc6 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc7,"0xc7 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc8,"0xc8 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xc9,"0xc9 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xca,"0xca NOP", &cpu::IMP, &cpu::NOP),
instruction(0xcb,"0xcb NOP", &cpu::IMP, &cpu::NOP),
instruction(0xcc,"0xcc NOP", &cpu::IMP, &cpu::NOP),
instruction(0xcd,"0xcd NOP", &cpu::IMP, &cpu::NOP),
instruction(0xce,"0xce NOP", &cpu::IMP, &cpu::NOP),
instruction(0xcf,"0xcf NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd0,"0xd0", &cpu::IMP, &cpu::NOP),
instruction(0xd1,"0xd1", &cpu::IMP, &cpu::NOP),
instruction(0xd2,"0xd2", &cpu::IMP, &cpu::NOP),
instruction(0xd3,"0xd3", &cpu::IMP, &cpu::NOP),
instruction(0xd4,"0xd4", &cpu::IMP, &cpu::NOP),
instruction(0xd5,"0xd5", &cpu::IMP, &cpu::NOP),
instruction(0xd6,"0xd6", &cpu::IMP, &cpu::NOP),
instruction(0xd7,"0xd7", &cpu::IMP, &cpu::NOP),
instruction(0xd8,"0xd8", &cpu::IMP, &cpu::NOP),
instruction(0xd9,"0xd9", &cpu::IMP, &cpu::NOP),
instruction(0xda,"0xda", &cpu::IMP, &cpu::NOP),
instruction(0xdb,"0xdb", &cpu::IMP, &cpu::NOP),
instruction(0xdc,"0xdc", &cpu::IMP, &cpu::NOP),
instruction(0xdd,"0xdd", &cpu::IMP, &cpu::NOP),
instruction(0xde,"0xde", &cpu::IMP, &cpu::NOP),
instruction(0xdf,"0xdf", &cpu::IMP, &cpu::NOP),
instruction(0xd0,"0xd0 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd1,"0xd1 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd2,"0xd2 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd3,"0xd3 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd4,"0xd4 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd5,"0xd5 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd6,"0xd6 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd7,"0xd7 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd8,"0xd8 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xd9,"0xd9 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xda,"0xda NOP", &cpu::IMP, &cpu::NOP),
instruction(0xdb,"0xdb NOP", &cpu::IMP, &cpu::NOP),
instruction(0xdc,"0xdc NOP", &cpu::IMP, &cpu::NOP),
instruction(0xdd,"0xdd NOP", &cpu::IMP, &cpu::NOP),
instruction(0xde,"0xde NOP", &cpu::IMP, &cpu::NOP),
instruction(0xdf,"0xdf NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe0,"0xe0", &cpu::IMP, &cpu::NOP),
instruction(0xe1,"0xe1", &cpu::IMP, &cpu::NOP),
instruction(0xe2,"0xe2", &cpu::IMP, &cpu::NOP),
instruction(0xe3,"0xe3", &cpu::IMP, &cpu::NOP),
instruction(0xe4,"0xe4", &cpu::IMP, &cpu::NOP),
instruction(0xe5,"0xe5", &cpu::IMP, &cpu::NOP),
instruction(0xe6,"0xe6", &cpu::IMP, &cpu::NOP),
instruction(0xe7,"0xe7", &cpu::IMP, &cpu::NOP),
instruction(0xe8,"0xe8", &cpu::IMP, &cpu::NOP),
instruction(0xe9,"0xe9", &cpu::IMP, &cpu::NOP),
instruction(0xea,"0xea", &cpu::IMP, &cpu::NOP),
instruction(0xeb,"0xeb", &cpu::IMP, &cpu::NOP),
instruction(0xec,"0xec", &cpu::IMP, &cpu::NOP),
instruction(0xed,"0xed", &cpu::IMP, &cpu::NOP),
instruction(0xee,"0xee", &cpu::IMP, &cpu::NOP),
instruction(0xef,"0xef", &cpu::IMP, &cpu::NOP),
instruction(0xe0,"0xe0 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe1,"0xe1 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe2,"0xe2 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe3,"0xe3 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe4,"0xe4 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe5,"0xe5 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe6,"0xe6 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe7,"0xe7 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe8,"0xe8 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xe9,"0xe9 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xea,"0xea NOP", &cpu::IMP, &cpu::NOP),
instruction(0xeb,"0xeb NOP", &cpu::IMP, &cpu::NOP),
instruction(0xec,"0xec NOP", &cpu::IMP, &cpu::NOP),
instruction(0xed,"0xed NOP", &cpu::IMP, &cpu::NOP),
instruction(0xee,"0xee NOP", &cpu::IMP, &cpu::NOP),
instruction(0xef,"0xef NOP", &cpu::IMP, &cpu::NOP),
//internally reserved instructions for emulator debugging
instruction(0xf0,"0xf0", &cpu::VAL, &cpu::OUT),
instruction(0xf1,"0xf1", &cpu::IMP, &cpu::END),
instruction(0xf2,"0xf2", &cpu::IMP, &cpu::NOP),
instruction(0xf3,"0xf3", &cpu::IMP, &cpu::NOP),
instruction(0xf4,"0xf4", &cpu::IMP, &cpu::NOP),
instruction(0xf5,"0xf5", &cpu::IMP, &cpu::NOP),
instruction(0xf6,"0xf6", &cpu::IMP, &cpu::NOP),
instruction(0xf7,"0xf7", &cpu::IMP, &cpu::NOP),
instruction(0xf8,"0xf8", &cpu::IMP, &cpu::NOP),
instruction(0xf9,"0xf9", &cpu::IMP, &cpu::NOP),
instruction(0xfa,"0xfa", &cpu::IMP, &cpu::NOP),
instruction(0xfb,"0xfb", &cpu::IMP, &cpu::NOP),
instruction(0xfc,"0xfc", &cpu::IMP, &cpu::NOP),
instruction(0xfd,"0xfd", &cpu::IMP, &cpu::NOP),
instruction(0xfe,"0xfe", &cpu::IMP, &cpu::NOP),
instruction(0xff,"0xff", &cpu::IMP, &cpu::NOP),
instruction(0xf0,"0xf0 OUT", &cpu::VAL, &cpu::OTP),
instruction(0xf1,"0xf1 END", &cpu::IMP, &cpu::END),
instruction(0xf2,"0xf2 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xf3,"0xf3 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xf4,"0xf4 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xf5,"0xf5 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xf6,"0xf6 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xf7,"0xf7 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xf8,"0xf8 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xf9,"0xf9 NOP", &cpu::IMP, &cpu::NOP),
instruction(0xfa,"0xfa NOP", &cpu::IMP, &cpu::NOP),
instruction(0xfb,"0xfb NOP", &cpu::IMP, &cpu::NOP),
instruction(0xfc,"0xfc NOP", &cpu::IMP, &cpu::NOP),
instruction(0xfd,"0xfd NOP", &cpu::IMP, &cpu::NOP),
instruction(0xfe,"0xfe NOP", &cpu::IMP, &cpu::NOP),
instruction(0xff,"0xff NOP", &cpu::IMP, &cpu::NOP),


@ -43,6 +43,7 @@ private:
void ABS(); void VAL();
void REL(); void DAV();
void DRV(); void RTA();
void DZV();
//cpu instructions
void NOP(); void CLC(); void CLO(); void CLD(); void CLI(); void BRK(); void BRT();
@ -52,9 +53,10 @@ private:
void JMP(); void JPR(); void BOE(); void BNE(); void RET();
void BRN(); void BRE(); void BCS(); void BCC(); void BLM(); void BRM(); void BSL(); void BSR();
void CMP(); void CP1(); void CP2(); void RSR();
void PPU(); void POX(); void POY();
//emulator specific debugging instructions
void OUT(); void END();
void OTP(); void END();
bool* flagQUIT;
struct instruction {


@ -188,14 +188,15 @@ void cpu::DE1() {
void cpu::JMP() {
m_pc = read(m_addrAbs);
m_pc = m_addrAbs;
void cpu::JPR() {
if (getStatus(Interrupt) == 0x1)
m_regRet = m_pc;
m_pc = read(m_addrAbs);
auto x = m_addrAbs;
m_pc = x;
void cpu::BOE() {
@ -281,9 +282,26 @@ void cpu::LV4() {
m_regGP[3] = read(m_addrAbs);
void cpu::PPU() {
uint8_t b1 = m_addrAbs & 0x00ff;
uint8_t b2 = uint16_t(m_addrAbs & 0xff00) >> 8;
uint8_t b3 = m_regTemp;
write(0x0006, b1);
write(0x0007, b2);
write(0x0008, b3);
void cpu::POX() {
write(0x0000, read(m_addrAbs));
void cpu::POY() {
write(0x0001, read(m_addrAbs));
void cpu::OUT() {
void cpu::OTP() {
const uint16_t pc_temp = m_pc - 1;
const uint8_t val = read(m_addrAbs);
uint16_t out = 0x0000;



@ -2,23 +2,24 @@
#include "ppu.h"
void ppu::onCycle() {
opcode = public_register[0] & 0x0f;
current = lookupTable[opcode];
opcode = public_register[6] & 0x0f;
instr = lookupTable[opcode];
std::cout << "ppu opcode: " << instr.ostr << std::endl;
public_register[5] = public_register[6] = public_register[7] = 0x00;
void ppu::ppuCall(std::array<uint8_t, 3>& data) {
public_register[5] = data[0]; public_register[6] = data[1]; public_register[7] = data[2];
public_register[6] = public_register[7] = public_register[8] = 0x00;
void ppu::write(const uint16_t& address, const uint8_t& value) {
public_register[address] = value;
uint8_t ppu::read(const uint16_t& address) {
return public_register[address];
//addressing modes
void ppu::IMP() {
@ -26,7 +27,10 @@ void ppu::IMP() {
void ppu::FUL() {
opcode = public_register[6] & 0x0f;
palette = (public_register[6] & 0xf0) > 1;
sector = public_register[7];
segment = public_register[8];
//ppu ops
@ -36,15 +40,50 @@ void ppu::NOP() {
void ppu::CLS() {
std::cout << "[x] MSG: PPU.INSTR.CLS not implemented\n";
void ppu::LTS() {
const uint16_t segment_addr = (public_register[3] << 8) + public_register[2] + segment;
const uint16_t gmemaddr = 0x0009 + sector * 2;
const uint8_t seg_addr_lo = segment_addr;
const uint8_t seg_addr_hi = segment_addr >> 8;
graphics_bus->write(gmemaddr + 0, seg_addr_lo);
graphics_bus->write(gmemaddr + 1, seg_addr_hi);
const uint16_t p_addr = floor(sector / 2) + 0x01ff;
uint8_t p_current = graphics_bus->read(p_addr);
uint8_t s_palette = palette << ((sector % 2) * 4);
uint8_t p_ret = p_current | s_palette;
graphics_bus->write(p_addr, p_ret);
ppu::instruction::instruction(uint8_t c, std::string s, void (ppu::* a)(), void (ppu::* i)()) {
ostr = s;
ocode = c;
addr = a;
instr = i;
ppu::ppu(bus* parent, bus* gbus) {
graphics_bus = gbus;
m_parentBus = parent;
m_range = addressRange(0x0000, 0x0006, false, true);
m_range = addressRange(0x0000, 0x0008, false, false);
lookupTable = {
instruction(0x00,"0x00", &ppu::IMP, &ppu::NOP),
instruction(0x01,"0x01", &ppu::IMP, &ppu::CLS),
instruction(0x02,"0x02", &ppu::FUL, &ppu::LTS),
instruction(0x03,"0x03", &ppu::IMP, &ppu::NOP),
instruction(0x04,"0x04", &ppu::IMP, &ppu::NOP),
instruction(0x05,"0x05", &ppu::IMP, &ppu::NOP),
instruction(0x06,"0x06", &ppu::IMP, &ppu::NOP),
instruction(0x07,"0x07", &ppu::IMP, &ppu::NOP),
instruction(0x08,"0x08", &ppu::IMP, &ppu::NOP),
instruction(0x09,"0x09", &ppu::IMP, &ppu::NOP),
instruction(0x0a,"0x0a", &ppu::IMP, &ppu::NOP),
instruction(0x0b,"0x0b", &ppu::IMP, &ppu::NOP),
instruction(0x0c,"0x0c", &ppu::IMP, &ppu::NOP),
instruction(0x0d,"0x0d", &ppu::IMP, &ppu::NOP),
instruction(0x0e,"0x0e", &ppu::IMP, &ppu::NOP),
instruction(0x0f,"0x0f", &ppu::IMP, &ppu::NOP)


@ -4,20 +4,24 @@
class ppu final : public microprocessor {
std::array<uint8_t, 7> public_register = { 0x00 }; // 0 = palette start lo | 1 = palette start hi | 3 = segment start lo |4 = segment start hi | 5,6,7 = ppu call reg
std::array<uint8_t, 9> public_register = { 0x00 }; // 0 = palette start lo | 1 = palette start hi | 3 = segment start lo |4 = segment start hi | 5,6,7 = ppu call reg
uint8_t opcode = 0x00;
uint8_t palette = 0x00;
uint8_t sector = 0x00;
uint8_t segment = 0x00;
struct instruction {
uint8_t opcode = 0x00;
std::string ostr;
uint8_t ocode = 0x00;
void (ppu::* addr)(void) = nullptr;
void (ppu::* instr)(void) = nullptr;
instruction(uint8_t c, std::string s, void (ppu::* a)(void), void (ppu::* i)(void));
instruction() = default;
std::array<instruction, 16> lookupTable;
instruction current;
instruction instr;
//instructionset opcodes for the PPU
void NOP(); void CLS(); void LTS();
@ -29,7 +33,7 @@ private:
ppu(bus* parent, bus* gbus);
void ppuCall(std::array<uint8_t, 3>& data);
void onCycle() override;
void write(const uint16_t& address, const uint8_t& value) override;
uint8_t read(const uint16_t& address) override;


@ -1,7 +1,9 @@
#include "pch.h"
#include "sdh.h"
sdh::sdh(bus* ppu_bus) {
sdh::sdh(bus* main_bus, bus* ppu_bus, olc::PixelGameEngine* engine) {
rom = main_bus;
drawenv = engine;
m_parentBus = ppu_bus;
m_range = addressRange(false);
@ -9,22 +11,25 @@ sdh::sdh(bus* ppu_bus) {
void sdh::readPalette(const int8_t& segment) {
const bool LO = false; const bool HI = true;
const uint8_t palette_byte = read(floor(segment / 2) + 0x1ff);
bool bit = segment % 2;
uint8_t p_requested = 0x00;
if (bit == LO) p_requested = palette_byte & 0x00ff;
else p_requested = palette_byte >> 4;
const uint16_t ppos = floor(segment / 2) + 0x1ff;
const uint8_t palette_byte = read(ppos);
uint8_t p_requested = (palette_byte >> (segment % 2) * 4);
if (p_requested <= 0)
if (!cache_valid && cp_cached != p_requested) {
uint16_t sel = (read(0x0005) << 8) + (read(0x0004)) + (p_requested * 12);
color tempcol;
uint16_t addr_lo_base = read(0x0004);
uint16_t addr_hi_base = read(0x0005) << 8;
uint16_t sel = (addr_lo_base | addr_hi_base) + p_requested * 12;
for (int i = 0; i < 4; i++) {
tempcol.c_red = read(sel);
tempcol.c_green = read(sel++);
tempcol.c_blue = read(sel++);
c_palette[i].c_red = rom->read(sel);
c_palette[i].c_green = rom->read(sel++);
c_palette[i].c_blue = rom->read(sel++);
c_palette[i] = tempcol;
cache_valid = true;
@ -34,12 +39,16 @@ void sdh::readPalette(const int8_t& segment) {
void sdh::calcPos(const int8_t& segment) {
c_pos.x = segment % 24;
c_pos.y = segment - 24 * c_pos.x;
c_pos.y = floor(segment / 10);
void sdh::readSegmentPtr(const int8_t& segment) {
c_segAddr = read((segment * 2) + 10);
c_segAddr |= read((segment * 2 + 1) + 10) << 8;
const uint8_t seg_offset = (segment * 2) + 9;
c_segAddr = read(seg_offset + 0);
c_segAddr |= read(seg_offset + 1) << 8;
for (uint8_t seg_part = 0; seg_part < 16; seg_part++) {
const uint8_t current_segval = read(c_segAddr + seg_part);
void sdh::onCycle() {
@ -48,7 +57,7 @@ void sdh::onCycle() {
for (uint8_t seg_part = 0; seg_part < 16; seg_part++) {
const uint8_t current_segval = read(c_segAddr + seg_part);
const uint8_t current_segval = rom->read(c_segAddr + seg_part);
const std::array<uint8_t, 4> twoBit {
current_segval & 0x03,
current_segval & 0x0c,
@ -64,7 +73,9 @@ void sdh::onCycle() {
c_pos.x * 8 + segmentOffset.x,
c_pos.y * 8 + segmentOffset.y
//void setPixel(pixelOffset, c_palette[twoBit[byte_part]]);
auto drawcol = &c_palette[twoBit[byte_part]];
drawenv->Draw(pixelOffset.x, pixelOffset.y, olc::Pixel(drawcol->c_red, drawcol->c_green, drawcol->c_blue));


@ -1,6 +1,8 @@
#pragma once
#include "pch.h"
#include "../microprocessor.h"
#include "../../bus/bus.h"
#include "../../../olcPGE/olcPixelGameEngine.h"
class sdh final : public microprocessor {
@ -24,8 +26,11 @@ private:
void readSegmentPtr(const int8_t& segment);
void readPalette(const int8_t& segment);
void calcPos(const int8_t& segment);
olc::PixelGameEngine* drawenv;
bus* rom;
sdh(bus* ppu_bus);
sdh(bus* main_bus, bus* ppu_bus, olc::PixelGameEngine* engine);
void onCycle() override;


@ -0,0 +1,37 @@
#include "olcPixelGameEngine.h"
class Example : public olc::PixelGameEngine
sAppName = "Example";
bool OnUserCreate() override
// Called once at the start, so create things here
return true;
bool OnUserUpdate(float fElapsedTime) override
// called once per frame