139 lines
2.9 KiB
C++
139 lines
2.9 KiB
C++
#include "CPU.hpp"
|
|
#include "NES.hpp"
|
|
|
|
|
|
void CPU::Implicit()
|
|
{
|
|
pc += 1;
|
|
}
|
|
|
|
void CPU::Immediate()
|
|
{
|
|
pc += 2;
|
|
|
|
fetchedAddress = pc - 1;
|
|
}
|
|
|
|
void CPU::ZeroPage()
|
|
{
|
|
pc += 2;
|
|
|
|
fetchedAddress = nes->Read(BusSource::CPU, pc - 1);
|
|
}
|
|
|
|
void CPU::ZeroPageX()
|
|
{
|
|
pc += 2;
|
|
|
|
uint8_t operand = nes->Read(BusSource::CPU, pc - 1);
|
|
fetchedAddress = (operand + x) & 0xFFu;
|
|
}
|
|
|
|
void CPU::ZeroPageY()
|
|
{
|
|
pc += 2;
|
|
|
|
uint8_t operand = nes->Read(BusSource::CPU, pc - 1);
|
|
fetchedAddress = (operand + y) & 0xFFu;
|
|
}
|
|
|
|
void CPU::Absolute()
|
|
{
|
|
pc += 3;
|
|
|
|
uint8_t addressLsb = nes->Read(BusSource::CPU, pc - 2);
|
|
uint8_t addressMsb = nes->Read(BusSource::CPU, pc - 1);
|
|
|
|
fetchedAddress = ComposeAddress(addressMsb, addressLsb);
|
|
}
|
|
|
|
void CPU::AbsoluteX()
|
|
{
|
|
pc += 3;
|
|
|
|
uint8_t addressLsb = nes->Read(BusSource::CPU, pc - 2);
|
|
uint8_t addressMsb = nes->Read(BusSource::CPU, pc - 1);
|
|
|
|
uint16_t preAddress = ComposeAddress(addressMsb, addressLsb);
|
|
fetchedAddress = preAddress + x;
|
|
|
|
pageBoundaryCrossed = IsPageBoundaryCrossed(preAddress, fetchedAddress);
|
|
}
|
|
|
|
void CPU::AbsoluteY()
|
|
{
|
|
pc += 3;
|
|
|
|
uint8_t addressLsb = nes->Read(BusSource::CPU, pc - 2);
|
|
uint8_t addressMsb = nes->Read(BusSource::CPU, pc - 1);
|
|
|
|
uint16_t preAddress = ComposeAddress(addressMsb, addressLsb);
|
|
fetchedAddress = preAddress + y;
|
|
|
|
pageBoundaryCrossed = IsPageBoundaryCrossed(preAddress, fetchedAddress);
|
|
}
|
|
|
|
void CPU::Indirect()
|
|
{
|
|
pc += 3;
|
|
|
|
uint8_t indirectLsb = nes->Read(BusSource::CPU, pc - 2);
|
|
uint8_t indirectMsb = nes->Read(BusSource::CPU, pc - 1);
|
|
|
|
// NOTE: 6502 BUG - indirect address wraps
|
|
// $02FF + 1 = $0200
|
|
|
|
uint16_t addressIndirect = ComposeAddress(indirectMsb, indirectLsb);
|
|
uint8_t addressLsb = nes->Read(BusSource::CPU, addressIndirect);
|
|
|
|
// Increment LSB to read second byte - it will wrap
|
|
++indirectLsb;
|
|
|
|
addressIndirect = ComposeAddress(indirectMsb, indirectLsb);
|
|
uint8_t addressMsb = nes->Read(BusSource::CPU, addressIndirect);
|
|
|
|
fetchedAddress = ComposeAddress(addressMsb, addressLsb);
|
|
}
|
|
|
|
void CPU::IndirectX()
|
|
{
|
|
pc += 2;
|
|
|
|
uint8_t addressIndirect = nes->Read(BusSource::CPU, pc - 1) + x;
|
|
|
|
// Modulo to keep within zero-page
|
|
uint16_t addressLsb = nes->Read(BusSource::CPU, (addressIndirect % 0x100));
|
|
uint16_t addressMsb = nes->Read(BusSource::CPU, (addressIndirect + 1) % 0x100);
|
|
|
|
fetchedAddress = ComposeAddress(addressMsb, addressLsb);
|
|
}
|
|
|
|
void CPU::IndirectY()
|
|
{
|
|
pc += 2;
|
|
|
|
uint8_t addressIndirect = nes->Read(BusSource::CPU, pc - 1);
|
|
|
|
// Modulo to keep within zero-page
|
|
uint8_t addressLsb = nes->Read(BusSource::CPU, addressIndirect % 0x100);
|
|
uint8_t addressMsb = nes->Read(BusSource::CPU, (addressIndirect + 1) % 0x100);
|
|
|
|
uint16_t preAddress = ComposeAddress(addressMsb, addressLsb);
|
|
fetchedAddress = preAddress + y;
|
|
|
|
pageBoundaryCrossed = IsPageBoundaryCrossed(preAddress, fetchedAddress);
|
|
}
|
|
|
|
void CPU::Relative()
|
|
{
|
|
pc += 2;
|
|
|
|
int8_t operand = nes->Read(BusSource::CPU, pc - 1);
|
|
|
|
uint16_t oldPc = pc;
|
|
|
|
fetchedAddress = pc + operand;
|
|
|
|
pageBoundaryCrossed = IsPageBoundaryCrossed(oldPc, fetchedAddress);
|
|
}
|