ADC, AND with tests for various addressing modes

This commit is contained in:
scawful
2023-08-19 14:14:24 -04:00
parent 28ac82d68b
commit e76aa69254
5 changed files with 240 additions and 124 deletions

View File

@@ -2,7 +2,10 @@ add_executable(
yaze
app/yaze.cc
app/rom.cc
app/emu/apu.cc
app/emu/cpu.cc
app/emu/ppu.cc
app/emu/snes.cc
${YAZE_APP_CORE_SRC}
${YAZE_APP_EDITOR_SRC}
${YAZE_APP_GFX_SRC}

View File

@@ -8,25 +8,28 @@ namespace yaze {
namespace app {
namespace emu {
uint8_t CPU::ReadByte(uint16_t addr) const {
return memory.at(addr); // Read a byte from memory at the specified address
uint8_t CPU::ReadByte(uint16_t address) const {
return memory.ReadByte(address);
}
uint16_t CPU::ReadWord(uint16_t address) const {
uint8_t low = ReadByte(address);
uint8_t high = ReadByte(address + 1);
return (high << 8) | low;
return memory.ReadWord(address);
}
uint32_t CPU::ReadWordLong(uint16_t address) const {
uint8_t low = ReadByte(address);
uint8_t mid = ReadByte(address + 1);
uint8_t high = ReadByte(address + 2);
return (high << 16) | (mid << 8) | low;
return memory.ReadWordLong(address);
}
void CPU::WriteByte(uint32_t address, uint8_t value) {
memory.WriteByte(address, value);
}
void CPU::WriteWord(uint32_t address, uint16_t value) {
memory.WriteWord(address, value);
}
uint8_t CPU::FetchByte() {
uint8_t byte = memory.ReadWord(PC); // Read a byte from memory at PC
uint8_t byte = memory.ReadByte(PC); // Read a byte from memory at PC
PC++; // Increment the Program Counter
return byte;
}
@@ -64,7 +67,7 @@ uint8_t CPU::FetchByteDirectPage(uint8_t operand) {
uint16_t CPU::DirectPageIndexedIndirectX() {
uint8_t dp = FetchByte();
return ReadWord((dp + X) & 0xFF);
return memory.ReadWord((dp + X) & 0xFF);
}
uint16_t CPU::StackRelative() {
@@ -76,7 +79,7 @@ uint16_t CPU::DirectPage() { return FetchByte(); }
uint16_t CPU::DirectPageIndirectLong() {
uint8_t dp = FetchByte();
return ReadWordLong(dp);
return memory.ReadWordLong(dp);
}
uint16_t CPU::Immediate() { return PC++; }
@@ -87,17 +90,17 @@ uint16_t CPU::AbsoluteLong() { return FetchLong(); }
uint16_t CPU::DirectPageIndirectIndexedY() {
uint8_t dp = FetchByte();
return ReadWord(dp) + Y;
return memory.ReadWord(dp) + Y;
}
uint16_t CPU::DirectPageIndirect() {
uint8_t dp = FetchByte();
return ReadWord(dp);
return memory.ReadWord(dp);
}
uint16_t CPU::StackRelativeIndirectIndexedY() {
uint8_t sr = FetchByte();
return ReadWord(SP + sr) + Y;
return memory.ReadWord(SP + sr) + Y;
}
uint16_t CPU::DirectPageIndexedX() {
@@ -107,7 +110,7 @@ uint16_t CPU::DirectPageIndexedX() {
uint16_t CPU::DirectPageIndirectLongIndexedY() {
uint8_t dp = FetchByte();
return ReadWordLong(dp) + Y;
return memory.ReadWordLong(dp) + Y;
}
uint16_t CPU::AbsoluteIndexedY() { return FetchWord() + Y; }
@@ -141,7 +144,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
ADC(operand);
break;
case 0x6D: // ADC Absolute
operand = memory.ReadByte(Absolute());
operand = memory.ReadWord(Absolute());
ADC(operand);
break;
case 0x6F: // ADC Absolute Long
@@ -182,49 +185,62 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
break;
case 0x21: // AND DP Indexed Indirect, X
// AND();
operand = memory.ReadByte(DirectPageIndexedIndirectX());
AND(operand);
break;
case 0x23: // AND Stack Relative
// AND();
operand = memory.ReadByte(StackRelative());
AND(operand);
break;
case 0x25: // AND Direct Page
// AND();
operand = FetchByteDirectPage(PC);
AND(operand);
break;
case 0x27: // AND DP Indirect Long
// AND();
operand = memory.ReadByte(DirectPageIndirectLong());
AND(operand);
break;
case 0x29: // AND Immediate
// AND();
AND(Immediate());
break;
case 0x2D: // AND Absolute
// AND();
AND(Absolute());
break;
case 0x2F: // AND Absolute Long
// AND();
operand = memory.ReadByte(AbsoluteLong());
AND(operand);
break;
case 0x31: // AND DP Indirect Indexed, Y
// AND();
operand = memory.ReadByte(DirectPageIndirectIndexedY());
AND(operand);
break;
case 0x32: // AND DP Indirect
// AND();
operand = memory.ReadByte(DirectPageIndirect());
AND(operand);
break;
case 0x33: // AND SR Indirect Indexed, Y
// AND();
operand = memory.ReadByte(StackRelativeIndirectIndexedY());
AND(operand);
break;
case 0x35: // AND DP Indexed, X
// AND();
operand = memory.ReadByte(DirectPageIndexedX());
AND(operand);
break;
case 0x37: // AND DP Indirect Long Indexed, Y
// AND();
operand = memory.ReadByte(DirectPageIndirectLongIndexedY());
AND(operand);
break;
case 0x39: // AND Absolute Indexed, Y
// AND();
operand = memory.ReadByte(AbsoluteIndexedY());
AND(operand);
break;
case 0x3D: // AND Absolute Indexed, X
// AND();
operand = memory.ReadByte(AbsoluteIndexedX());
AND(operand);
break;
case 0x3F: // AND Absolute Long Indexed, X
// AND();
operand = memory.ReadByte(AbsoluteLongIndexedX());
AND(operand);
break;
case 0x06: // ASL Direct Page
@@ -999,7 +1015,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
}
void CPU::ADC(uint8_t operand) {
auto C = (bool)GetCarryFlag();
auto C = GetCarryFlag();
if (GetAccumulatorSize()) { // 8-bit mode
uint16_t result = (A & 0xFF) + (operand & 0xFF); // + (C ? 1 : 0);
SetCarryFlag(!(result > 0xFF)); // Update the carry flag
@@ -1033,6 +1049,21 @@ void CPU::ADC(uint8_t operand) {
}
}
void CPU::AND(uint16_t address) {
uint8_t operand;
if (GetAccumulatorSize() == 0) { // 16-bit mode
uint16_t operand16 = memory.ReadWord(address);
A &= operand16;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x8000);
} else { // 8-bit mode
operand = memory.ReadByte(address);
A &= operand;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
}
} // namespace emu
} // namespace app
} // namespace yaze

View File

@@ -1,8 +1,11 @@
#ifndef YAZE_APP_EMU_CPU_H_
#define YAZE_APP_EMU_CPU_H_
#include <cstdint>
#include <iostream>
#include <vector>
#include "mem.h"
#include "app/emu/mem.h"
namespace yaze {
namespace app {
@@ -91,9 +94,15 @@ class CPU : public Memory {
public:
explicit CPU(Memory& mem) : memory(mem) {}
void Init() {}
uint8_t ReadByte(uint16_t address) const override;
uint16_t ReadWord(uint16_t address) const override;
uint32_t ReadWordLong(uint16_t address) const override;
void WriteByte(uint32_t address, uint8_t value) override;
void WriteWord(uint32_t address, uint16_t value) override;
void SetMemory(const std::vector<uint8_t>& data) override {
memory.SetMemory(data);
}
@@ -156,48 +165,30 @@ class CPU : public Memory {
// B #$10 00010000 Break (emulation mode only)
// Setting flags in the status register
void SetZeroFlag(bool condition) {
if (condition) {
status |= 0x02;
} else {
status &= ~0x02;
}
}
void SetNegativeFlag(bool condition) {
if (condition) {
status |= 0x80;
} else {
status &= ~0x80;
}
}
void SetOverflowFlag(bool condition) {
if (condition) {
status |= 0x40;
} else {
status &= ~0x40;
}
}
void SetCarryFlag(bool condition) {
if (condition) {
status |= 0x01;
} else {
status &= ~0x01;
}
}
int GetCarryFlag() { return status & 0x01; }
int GetZeroFlag() { return status & 0x02; }
int GetAccumulatorSize() { return status & 0x20; }
int GetIndexSize() { return status & 0x10; }
int GetEmulationMode() { return status & 0x04; }
// Set individual flags
void SetNegativeFlag(bool set) { SetFlag(0x80, set); }
void SetOverflowFlag(bool set) { SetFlag(0x40, set); }
void SetBreakFlag(bool set) { SetFlag(0x10, set); }
void SetDecimalFlag(bool set) { SetFlag(0x08, set); }
void SetInterruptFlag(bool set) { SetFlag(0x04, set); }
void SetZeroFlag(bool set) { SetFlag(0x02, set); }
void SetCarryFlag(bool set) { SetFlag(0x01, set); }
// Get individual flags
bool GetNegativeFlag() const { return GetFlag(0x80); }
bool GetOverflowFlag() const { return GetFlag(0x40); }
bool GetBreakFlag() const { return GetFlag(0x10); }
bool GetDecimalFlag() const { return GetFlag(0x08); }
bool GetInterruptFlag() const { return GetFlag(0x04); }
bool GetZeroFlag() const { return GetFlag(0x02); }
bool GetCarryFlag() const { return GetFlag(0x01); }
// Instructions
void ADC(uint8_t operand);
void AND(uint16_t address);
void BEQ(int8_t offset) {
if (GetZeroFlag()) { // If the zero flag is set
@@ -324,6 +315,19 @@ class CPU : public Memory {
SetNegativeFlag(Y & 0x80);
}
private:
// Helper function to set or clear a specific flag bit
void SetFlag(uint8_t mask, bool set) {
if (set) {
status |= mask; // Set the bit
} else {
status &= ~mask; // Clear the bit
}
}
// Helper function to get the value of a specific flag bit
bool GetFlag(uint8_t mask) const { return (status & mask) != 0; }
// Appease the C++ Gods...
uint8_t operator[](int i) const override { return 0; }
uint8_t at(int i) const override { return 0; }
@@ -331,4 +335,6 @@ class CPU : public Memory {
} // namespace emu
} // namespace app
} // namespace yaze
} // namespace yaze
#endif // YAZE_APP_EMU_CPU_H_