DirectPage and DirectPageIndirect

This commit is contained in:
scawful
2023-08-19 20:12:56 -04:00
parent 7dcbc7f83c
commit 536136d8c9
5 changed files with 49 additions and 67 deletions

View File

@@ -54,8 +54,10 @@ int16_t CPU::FetchSignedWord() {
} }
uint8_t CPU::FetchByteDirectPage(uint8_t operand) { uint8_t CPU::FetchByteDirectPage(uint8_t operand) {
uint16_t distance = D * 0x100;
// Calculate the effective address in the Direct Page // Calculate the effective address in the Direct Page
uint16_t effectiveAddress = D + operand; uint16_t effectiveAddress = operand + distance;
// Fetch the byte from memory // Fetch the byte from memory
uint8_t fetchedByte = memory.ReadByte(effectiveAddress); uint8_t fetchedByte = memory.ReadByte(effectiveAddress);
@@ -81,8 +83,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
ADC(operand); ADC(operand);
break; break;
case 0x65: // ADC Direct Page case 0x65: // ADC Direct Page
operand = FetchByteDirectPage(PC); ADC(FetchByteDirectPage(PC));
ADC(operand);
break; break;
case 0x67: // ADC DP Indirect Long case 0x67: // ADC DP Indirect Long
operand = memory.ReadByte(DirectPageIndirectLong()); operand = memory.ReadByte(DirectPageIndirectLong());

View File

@@ -75,7 +75,7 @@ class CPU : public Memory {
// JMP (addr, X) // JMP (addr, X)
uint16_t AbsoluteIndexedIndirect() { uint16_t AbsoluteIndexedIndirect() {
uint16_t address = FetchWord() + X; uint16_t address = FetchWord() + X;
return memory.ReadWord(address); return memory.ReadWord(address & 0xFFFF); // Consider PBR if needed
} }
// Effective Address: // Effective Address:
@@ -136,7 +136,10 @@ class CPU : public Memory {
// High/low: Direct Page Register plus operand byte // High/low: Direct Page Register plus operand byte
// //
// LDA dp // LDA dp
uint16_t DirectPage() { return FetchByte(); } uint16_t DirectPage() {
uint8_t dp = FetchByte();
return D + dp;
}
// Effective Address: // Effective Address:
// Bank: Zero // Bank: Zero
@@ -168,7 +171,9 @@ class CPU : public Memory {
// LDA (dp, X) // LDA (dp, X)
uint16_t DirectPageIndexedIndirectX() { uint16_t DirectPageIndexedIndirectX() {
uint8_t dp = FetchByte(); uint8_t dp = FetchByte();
return memory.ReadWord((dp + X) & 0xFF); uint16_t effective_address = D + dp + X;
uint16_t indirect_address = memory.ReadWord(effective_address & 0xFFFF);
return indirect_address;
} }
// Effective Address: // Effective Address:
@@ -180,7 +185,9 @@ class CPU : public Memory {
// LDA (dp) // LDA (dp)
uint16_t DirectPageIndirect() { uint16_t DirectPageIndirect() {
uint8_t dp = FetchByte(); uint8_t dp = FetchByte();
return memory.ReadWord(dp); // Add the Direct Page register to the fetched operand
uint16_t effective_address = D + dp;
return memory.ReadWord(effective_address);
} }
// Effective Address: // Effective Address:
@@ -191,7 +198,8 @@ class CPU : public Memory {
// LDA [dp] // LDA [dp]
uint16_t DirectPageIndirectLong() { uint16_t DirectPageIndirectLong() {
uint8_t dp = FetchByte(); uint8_t dp = FetchByte();
return memory.ReadWordLong(dp); uint16_t effective_address = D + dp;
return memory.ReadWordLong(effective_address);
} }
// Effective Address: // Effective Address:
@@ -204,7 +212,8 @@ class CPU : public Memory {
// LDA (dp), Y // LDA (dp), Y
uint16_t DirectPageIndirectIndexedY() { uint16_t DirectPageIndirectIndexedY() {
uint8_t dp = FetchByte(); uint8_t dp = FetchByte();
return memory.ReadWord(dp) + Y; uint16_t effective_address = D + dp;
return memory.ReadWord(effective_address) + Y;
} }
// Effective Address: // Effective Address:
@@ -218,7 +227,8 @@ class CPU : public Memory {
// LDA (dp), Y // LDA (dp), Y
uint16_t DirectPageIndirectLongIndexedY() { uint16_t DirectPageIndirectLongIndexedY() {
uint8_t dp = FetchByte(); uint8_t dp = FetchByte();
return memory.ReadWordLong(dp) + Y; uint16_t effective_address = D + dp;
return memory.ReadWordLong(effective_address) + Y;
} }
// 8-bit data: Data Operand Byte // 8-bit data: Data Operand Byte

View File

@@ -9,20 +9,6 @@ namespace yaze {
namespace app { namespace app {
namespace emu { namespace emu {
class DirectPageMemory {
public:
explicit DirectPageMemory(size_t size = 256) : memory_(size, 0) {}
uint8_t ReadByte(uint8_t address) const { return memory_[address]; }
void WriteByte(uint8_t address, uint8_t value) { memory_[address] = value; }
auto size() const { return memory_.size(); }
private:
std::vector<uint8_t> memory_;
};
// memory.h // memory.h
class Memory { class Memory {
public: public:
@@ -55,16 +41,10 @@ class Memory {
class MemoryImpl : public Memory { class MemoryImpl : public Memory {
public: public:
uint8_t ReadByte(uint16_t address) const override { uint8_t ReadByte(uint16_t address) const override {
if (address < dp_memory_.size()) {
return dp_memory_.ReadByte(static_cast<uint8_t>(address));
}
uint32_t mapped_address = GetMappedAddress(address); uint32_t mapped_address = GetMappedAddress(address);
return memory_.at(mapped_address); return memory_.at(mapped_address);
} }
uint16_t ReadWord(uint16_t address) const override { uint16_t ReadWord(uint16_t address) const override {
if (address < dp_memory_.size()) {
return dp_memory_.ReadByte(static_cast<uint8_t>(address));
}
uint32_t mapped_address = GetMappedAddress(address); uint32_t mapped_address = GetMappedAddress(address);
return static_cast<uint16_t>(memory_.at(mapped_address)) | return static_cast<uint16_t>(memory_.at(mapped_address)) |
(static_cast<uint16_t>(memory_.at(mapped_address + 1)) << 8); (static_cast<uint16_t>(memory_.at(mapped_address + 1)) << 8);
@@ -172,9 +152,6 @@ class MemoryImpl : public Memory {
} }
} }
// Direct Page Memory
DirectPageMemory dp_memory_;
// Define memory regions // Define memory regions
std::vector<uint8_t> rom_; std::vector<uint8_t> rom_;
std::vector<uint8_t> ram_; std::vector<uint8_t> ram_;

View File

@@ -13,8 +13,8 @@ namespace emu {
class SNES { class SNES {
public: public:
SNES()=default; SNES() = default;
~SNES()=default; ~SNES() = default;
// Initialization // Initialization
void Init(ROM& rom); void Init(ROM& rom);

View File

@@ -110,7 +110,6 @@ class MockMemory : public Memory {
}); });
} }
private:
std::vector<uint8_t> memory_; std::vector<uint8_t> memory_;
uint16_t SP_ = 0x01FF; uint16_t SP_ = 0x01FF;
}; };
@@ -209,58 +208,53 @@ TEST_F(CPUTest, ADC_AbsoluteLong) {
EXPECT_EQ(cpu.A, 0x06); EXPECT_EQ(cpu.A, 0x06);
} }
/**
* Direct Page Unimplemented
*
TEST_F(CPUTest, ADC_DirectPage) { TEST_F(CPUTest, ADC_DirectPage) {
cpu.A = 0x01; cpu.A = 0x01;
cpu.D = 0x0001; cpu.D = 0x0001;
std::vector<uint8_t> data = {0x65, 0x01, 0x05}; std::vector<uint8_t> data = {0x65, 0x01, 0x00};
mock_memory.SetMemoryContents(data); mock_memory.SetMemoryContents(data);
mock_memory.InsertMemory(0x100, {0x05, 0x05, 0x05});
EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x01)); EXPECT_CALL(mock_memory, ReadByte(0x100)).WillOnce(Return(0x05));
cpu.ExecuteInstruction(0x65); // ADC Direct Page cpu.ExecuteInstruction(0x65); // ADC Direct Page
EXPECT_EQ(cpu.A, 0x06); EXPECT_EQ(cpu.A, 0x06);
} }
// ADC Direct Page Indirect
TEST_F(CPUTest, ADC_DirectPageIndirect) { TEST_F(CPUTest, ADC_DirectPageIndirect) {
cpu.A = 0x02;
cpu.D = 0x2000; // Setting Direct Page register to 0x2000
cpu.A = 0x01; // A register std::vector<uint8_t> data = {0x72, 0x10}; // ADC (dp)
cpu.X = 0x02; // X register
cpu.PC = 0; // PC register
cpu.status = 0x00; // 16-bit mode
std::vector<uint8_t> data = {0x72, 0x04, 0x00, 0x00, 0x20, 0x05, 0xFF};
mock_memory.SetMemoryContents(data); mock_memory.SetMemoryContents(data);
mock_memory.InsertMemory(0x2010, {0x00, 0x30}); // [0x2010] = 0x3000
mock_memory.InsertMemory(0x3000, {0x05}); // [0x3000] = 0x05
// Get the absolute address EXPECT_CALL(mock_memory, ReadByte(0x0000)).WillOnce(Return(0x10));
EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0004)); EXPECT_CALL(mock_memory, ReadWord(0x2010)).WillOnce(Return(0x3000));
EXPECT_CALL(mock_memory, ReadByte(0x3000)).WillOnce(Return(0x05));
cpu.ExecuteInstruction(0x72); // ADC Indirect Indexed with X cpu.ExecuteInstruction(0x72); // ADC (dp)
EXPECT_EQ(cpu.A, 0x06); EXPECT_EQ(cpu.A, 0x07); // 0x02 + 0x05 = 0x07
} }
// ADC Direct Page Indexed Indirect, X
TEST_F(CPUTest, ADC_DirectPageIndexedIndirectX) { TEST_F(CPUTest, ADC_DirectPageIndexedIndirectX) {
cpu.A = 0x03;
cpu.D = 0x2000; // Setting Direct Page register to 0x2000
cpu.A = 0x01; std::vector<uint8_t> data = {0x61, 0x10}; // ADC (dp, X)
cpu.X = 0x02;
cpu.PC = 1;
cpu.status = 0x00; // 16-bit mode
std::vector<uint8_t> data = {0x61, 0x01, 0x18, 0x00, 0x05};
mock_memory.SetMemoryContents(data); mock_memory.SetMemoryContents(data);
mock_memory.InsertMemory(0x2012, {0x00, 0x30}); // [0x2012] = 0x3000
mock_memory.InsertMemory(0x3000, {0x06}); // [0x3000] = 0x06
EXPECT_CALL(mock_memory, ReadByte(0x0001)).WillOnce(Return(0x0001)); cpu.X = 0x02; // X register
EXPECT_CALL(mock_memory, ReadByte(0x0000)).WillOnce(Return(0x10));
EXPECT_CALL(mock_memory, ReadWord(0x2012)).WillOnce(Return(0x3000));
EXPECT_CALL(mock_memory, ReadByte(0x3000)).WillOnce(Return(0x06));
EXPECT_CALL(mock_memory, ReadWord(0x0003)).WillOnce(Return(0x0005)); cpu.ExecuteInstruction(0x61); // ADC (dp, X)
EXPECT_EQ(cpu.A, 0x09); // 0x03 + 0x06 = 0x09
cpu.ExecuteInstruction(0x61); // ADC Indexed Indirect
EXPECT_EQ(cpu.A, 0x06);
} }
**/
TEST_F(CPUTest, ADC_CheckCarryFlag) { TEST_F(CPUTest, ADC_CheckCarryFlag) {
cpu.A = 0xFF; cpu.A = 0xFF;