1
0
Fork 0
2019-nes-emulator/Source/CPU/CPU.hpp

247 lines
5.1 KiB
C++

#pragma once
#include <cstdint>
#include <fstream>
const unsigned int INSTRUCTION_COUNT = 256;
const unsigned int RAM_SIZE = 2048;
const unsigned int SRAM_SIZE = 8192;
const unsigned int IRQ_VECTOR_MSB = 0xFFFF;
const unsigned int IRQ_VECTOR_LSB = 0xFFFE;
class NES;
class Status
{
friend class NES;
public:
void SetByte(uint8_t byte)
{
negative = (byte & 0x80u) >> 7u;
overflow = (byte & 0x40u) >> 6u;
b1 = (byte & 0x20u) >> 5u;
b0 = (byte & 0x10u) >> 4u;
decimal = (byte & 0x08u) >> 3u;
interruptDisable = (byte & 0x04u) >> 2u;
zero = (byte & 0x02u) >> 1u;
carry = (byte & 0x01u);
}
uint8_t GetByte()
{
return negative << 7u | overflow << 6u | b1 << 5u | b0 << 4u
| decimal << 3u | interruptDisable << 2u | zero << 1u | carry;
}
uint8_t carry;
uint8_t zero;
uint8_t interruptDisable;
uint8_t decimal;
uint8_t b0;
uint8_t b1;
uint8_t overflow;
uint8_t negative;
};
class CPU;
class Instruction
{
public:
char const* name;
uint8_t cycles;
using CpuFunc = void (CPU::*)();
CpuFunc fetch;
CpuFunc execute;
};
class CPU
{
public:
CPU();
uint64_t Cycle();
void Log();
void Reset();
void NMI();
void WriteMemory(uint16_t address, uint8_t value);
uint8_t ReadMemory(uint16_t address);
friend class NES;
void StackPush(uint8_t val);
uint8_t StackPop();
// --------------- HELPERS --------------- //
static bool TestBits(uint8_t value, uint8_t bits);
static bool IsNegative(uint8_t value);
static bool IsPageBoundaryCrossed(uint16_t before, uint16_t after);
static uint16_t ComposeAddress(uint8_t msb, uint8_t lsb);
// --------------- ADDRESS MODES --------------- //
// Operand is implied by the instruction
void Implicit();
// Operand is the byte/STA
void Immediate();
// Operand contains a zero-page address (0x00 to 0xFF)
// Byte is retrieved from that address in memory
void ZeroPage();
// Operand is added to X to get effective address, with wrap around back to 0x00
void ZeroPageX();
// Operand is added to X to get effective address, with wrap around back to 0x00
void ZeroPageY();
// Operand is the memory location
void Absolute();
// Operand contains an absolute address which can be added to X to get a new address
// If the address after adding X crosses a page-boundary, an additional cycle occurs
void AbsoluteX();
// Operand contains an absolute address which can be added to Y to get a new address
// If the address after adding Y crosses a page-boundary, an additional cycle occurs
void AbsoluteY();
// Operand contains address of LSB of effective address - MSB is in address + 1
void Indirect();
// Operand contains a zero-page address (0x00 to 0xFF)
// Value in X is added to operand to retrieve two bytes of address in memory (addition will wrap around back to 0x00)
// Effective address is used to retrieve the byte
void IndirectX();
// Operand contains a zero-page address (0x00 to 0xFF)
// Two bytes of address are retrieved from that address in memory
// Y is added to that address and the new address is used to retrieve the byte
// If the addition of Y causes a page-boundary crossing, an additional cycle occurs
void IndirectY();
// Operand is an offset from current instruction used for branching
void Relative();
// --------------- LOGICAL --------------- //
void AND();
void EOR();
void ORA();
void BIT();
// --------------- ARITHMETIC --------------- //
void ADC();
void SBC();
void CMP();
void CPX();
void CPY();
// --------------- LOAD/STORE --------------- //
void STA();
void STX();
void STY();
void LDA();
void LDX();
void LDY();
// --------------- TRANSFERS --------------- //
void TXA();
void TYA();
void TXS();
void TAX();
void TAY();
void TSX();
// --------------- STACK --------------- //
void PHP();
void PLP();
void PHA();
void PLA();
// --------------- INCREMENTS & DECREMENTS --------------- //
void INC();
void INX();
void INY();
void DEC();
void DEX();
void DEY();
// --------------- SHIFTS --------------- //
void ASL();
void LSR();
void ROL();
void ROR();
// --------------- JUMPS & CALLS --------------- //
void JMP();
void JSR();
void RTS();
// --------------- STATUS FLAG CHANGES --------------- //
void CLC();
void SEC();
void CLI();
void SEI();
void CLV();
void CLD();
void SED();
// --------------- BRANCHES --------------- //
void BPL();
void BMI();
void BVC();
void BVS();
void BCC();
void BCS();
void BNE();
void BEQ();
// --------------- SYSTEM --------------- //
void BRK();
void NOP();
void RTI();
// --------------- UNOFFICIAL --------------- //
void LAX();
void SAX();
void DCP();
void ISC();
void SLO();
void RLA();
void SRE();
void RRA();
void ANC();
void ALR();
void ARR();
void AXS();
// Machine features
uint8_t ram[RAM_SIZE]{};
uint8_t sram[SRAM_SIZE]{};
uint16_t pc{};
uint8_t sp{};
uint8_t acc{};
uint8_t x{};
uint8_t y{};
Status status{};
uint64_t prevCycles{};
uint64_t cycles{};
bool irq{};
// Emulator variables
bool pageBoundaryCrossed{};
uint8_t opcode{};
uint16_t fetchedAddress{};
uint8_t fetchedByte{};
Instruction instructions[INSTRUCTION_COUNT]{};
NES* nes;
};