More opcodes

This commit is contained in:
Tony Di Nucci 2019-03-27 23:29:11 +00:00
parent b2baba888f
commit ad1015759e
21 changed files with 660 additions and 72 deletions

View File

@ -25,9 +25,9 @@ add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
file(GLOB_RECURSE test_src "test/**.h" "test/**.cpp" "src/**.h" "src/**.cpp")
list(FILTER test_src EXCLUDE REGEX ".*/6502-emulator/src/main.cpp$")
add_executable(6502_emulator_test ${test_src} test/stack-opcode-handler-test.cpp test/ldx-opcode-handler-test.cpp)
add_executable(6502_emulator_test ${test_src})
target_link_libraries(6502_emulator_test gtest_main)
add_test(NAME run_tests COMMAND 6502_emulator_test)
file(GLOB_RECURSE emulator_src "src/**.h" "src/**.cpp")
add_executable(6502_emulator ${emulator_src} src/opcode/handler/stack-opcode-handler.cpp src/opcode/handler/stack-opcode-handler.h src/stack.cpp src/stack.h src/opcode/handler/lda-opcode-handler.cpp src/opcode/handler/lda-opcode-handler.h)
add_executable(6502_emulator ${emulator_src})

View File

@ -1,42 +1,10 @@
#include "register/register-manager.h"
#include <iostream>
#include <memory>
using namespace std;
void stack_test(string astring) {
astring.push_back('x');
}
void heap_test(shared_ptr<string> astring){
astring->push_back('y');
}
int main() {
auto reg = unique_ptr<Register<uint8_t>>(new Register<uint8_t>("PC"));
cout << "Register: " << reg->get_name() << " " << to_string(56) << endl;
string astr = "hello";
shared_ptr<string> bstr = make_shared<string>("there");
cout << astr << " - " << bstr->c_str() << endl;
stack_test(astr);
heap_test(bstr);
cout << astr << " - " << bstr->c_str() << endl;
auto reg_man = new RegisterManager();
auto accum = reg_man->get_accumulator();
cout << "****** " << accum->get_name() << " ******" << endl;
cout << "****** " << reg_man->get_x_index()->get_name() << " ******" << endl;
cout << "****** " << reg_man->get_y_index()->get_name() << " ******" << endl;
cout << "****** " << reg_man->get_stack_pointer()->get_name() << " ******" << endl;
cout << "****** " << reg_man->get_status_register()->get_name() << " ******" << endl;
cout << "****** " << reg_man->get_program_counter()->get_name() << " ******" << endl;
cout << "Only unit tests for now" << endl;
return 0;
}

View File

@ -1,8 +1,5 @@
#include "flag-opcode-handler.h"
#include <stdexcept>
#include <sstream>
const uint8_t FlagOpcodeHandler::CLC;
const uint8_t FlagOpcodeHandler::SEC;
const uint8_t FlagOpcodeHandler::CLI;
@ -39,9 +36,7 @@ void FlagOpcodeHandler::execute() {
statusReg->set_decimal(true);
break;
default:
stringstream stream;
stream << "Unexpected opcode 0x" << hex << opcode;
throw runtime_error(stream.str());
throw_unexpected_opcode(opcode);
}
move_program_counter(1);

View File

@ -1,5 +1,94 @@
//
// Created by tony on 27/03/19.
//
#include "lda-opcode-handler.h"
const uint8_t LdaOpcodeHandler::IMMEDIATE;
const uint8_t LdaOpcodeHandler::ZERO_PAGE;
const uint8_t LdaOpcodeHandler::ZERO_PAGE_X;
const uint8_t LdaOpcodeHandler::ABSOLUTE;
const uint8_t LdaOpcodeHandler::ABSOLUTE_X;
const uint8_t LdaOpcodeHandler::ABSOLUTE_Y;
const uint8_t LdaOpcodeHandler::INDIRECT_X;
const uint8_t LdaOpcodeHandler::INDIRECT_Y;
void LdaOpcodeHandler::execute() {
auto instructionIndex = reg_man->get_program_counter()->get_value();
auto opcode = program->get_byte_at(instructionIndex);
auto byte2 = program->get_byte_at(instructionIndex + 1);
auto accumulator = reg_man->get_accumulator();
switch (opcode) {
case IMMEDIATE:
accumulator->set_value(byte2);
move_program_counter(2);
break;
case ZERO_PAGE:
accumulator->set_value(memory->get_byte_at(byte2));
move_program_counter(2);
break;
case ZERO_PAGE_X: {
// expect wrap around
uint8_t address = byte2 + reg_man->get_x_index()->get_value();
accumulator->set_value(memory->get_byte_at(address));
move_program_counter(2);
break;
}
case ABSOLUTE: {
auto low = byte2;
auto high = program->get_byte_at(instructionIndex + 2);
uint16_t address = (high << 8) + low;
accumulator->set_value(memory->get_byte_at(address));
move_program_counter(3);
break;
}
case ABSOLUTE_X: {
auto low = byte2;
auto high = program->get_byte_at(instructionIndex + 2);
uint16_t address = (high << 8) + low + reg_man->get_x_index()->get_value();
accumulator->set_value(memory->get_byte_at(address));
move_program_counter(3);
break;
}
case ABSOLUTE_Y: {
auto low = byte2;
auto high = program->get_byte_at(instructionIndex + 2);
uint16_t address = (high << 8) + low + reg_man->get_y_index()->get_value();
accumulator->set_value(memory->get_byte_at(address));
move_program_counter(3);
break;
}
case INDIRECT_X: {
auto paddress = reg_man->get_x_index()->get_value() + byte2;
auto low = memory->get_byte_at(paddress);
auto high = memory->get_byte_at(paddress + 1);
uint16_t address = (high << 8) + low;
accumulator->set_value(memory->get_byte_at(address));
move_program_counter(2);
break;
}
case INDIRECT_Y : {
auto initial = byte2;
auto low = memory->get_byte_at(initial);
auto high = memory->get_byte_at(initial + 1);
auto y = reg_man->get_y_index()->get_value();
uint16_t address = (high << 8) + low + y;
accumulator->set_value(memory->get_byte_at(address));
move_program_counter(2);
break;
}
default:
throw_unexpected_opcode(opcode);
}
}

View File

@ -1,13 +1,33 @@
//
// Created by tony on 27/03/19.
//
#ifndef INC_6502_EMULATOR_LDA_OPCODE_HANDLER_H
#define INC_6502_EMULATOR_LDA_OPCODE_HANDLER_H
#include "../opcode-handler.h"
class LdaOpcodeHandler {
class LdaOpcodeHandler : public OpcodeHandler {
public:
static const uint8_t IMMEDIATE = 0xA9;
static const uint8_t ZERO_PAGE = 0xA5;
static const uint8_t ZERO_PAGE_X = 0xB5;
static const uint8_t ABSOLUTE = 0xAD;
static const uint8_t ABSOLUTE_X = 0xBD;
static const uint8_t ABSOLUTE_Y = 0xB9;
static const uint8_t INDIRECT_X = 0xA1;
static const uint8_t INDIRECT_Y = 0xB1;
explicit LdaOpcodeHandler(shared_ptr<Program> program, shared_ptr<RegisterManager> reg_man,
shared_ptr<Memory> memory) :
OpcodeHandler(program, reg_man, memory) {
handled_opcodes->push_back(IMMEDIATE);
handled_opcodes->push_back(ZERO_PAGE);
handled_opcodes->push_back(ZERO_PAGE_X);
handled_opcodes->push_back(ABSOLUTE);
handled_opcodes->push_back(ABSOLUTE_X);
handled_opcodes->push_back(ABSOLUTE_Y);
handled_opcodes->push_back(INDIRECT_X);
handled_opcodes->push_back(INDIRECT_Y);
}
virtual void execute() override;
};

View File

@ -1,5 +1,4 @@
#include "ldx-opcode-handler.h"
#include <sstream>
const uint8_t LdxOpcodeHandler::IMMEDIATE;
const uint8_t LdxOpcodeHandler::ZERO_PAGE;
@ -25,7 +24,8 @@ void LdxOpcodeHandler::execute() {
break;
case ZERO_PAGE_Y: {
uint16_t address = byte2 + reg_man->get_y_index()->get_value();
// expect wrap around
uint8_t address = byte2 + reg_man->get_y_index()->get_value();
x_reg->set_value(memory->get_byte_at(address));
move_program_counter(2);
@ -53,8 +53,6 @@ void LdxOpcodeHandler::execute() {
}
default:
stringstream stream;
stream << "Unexpected opcode 0x" << hex << opcode;
throw runtime_error(stream.str());
throw_unexpected_opcode(opcode);
}
}

View File

@ -0,0 +1,17 @@
#include "nop-opcode-handler.h"
const uint8_t NopOpcodeHandler::IMPLIED;
void NopOpcodeHandler::execute() {
auto instructionIndex = reg_man->get_program_counter()->get_value();
auto opcode = program->get_byte_at(instructionIndex);
switch (opcode) {
case IMPLIED:
move_program_counter(1);
break;
default:
throw_unexpected_opcode(opcode);
}
}

View File

@ -0,0 +1,20 @@
#ifndef INC_6502_EMULATOR_NOP_OPCODE_HANDLER_H
#define INC_6502_EMULATOR_NOP_OPCODE_HANDLER_H
#include "../opcode-handler.h"
class NopOpcodeHandler : public OpcodeHandler {
public:
static const uint8_t IMPLIED = 0xEA;
explicit NopOpcodeHandler(shared_ptr<Program> program, shared_ptr<RegisterManager> reg_man,
shared_ptr<Memory> memory) :
OpcodeHandler(program, reg_man, memory) {
handled_opcodes->push_back(IMPLIED);
}
virtual void execute() override;
};
#endif //INC_6502_EMULATOR_NOP_OPCODE_HANDLER_H

View File

@ -1,8 +1,5 @@
#include "register-opcode-handler.h"
#include <stdexcept>
#include <sstream>
const uint8_t RegisterOpcodeHandler::TAX;
const uint8_t RegisterOpcodeHandler::TXA;
const uint8_t RegisterOpcodeHandler::DEX;
@ -23,31 +20,37 @@ void RegisterOpcodeHandler::execute() {
case TAX:
x_index->set_value(accumulator->get_value());
break;
case TXA:
accumulator->set_value(x_index->get_value());
break;
case DEX:
x_index->set_value(x_index->get_value() - 1);
break;
case INX:
x_index->set_value(x_index->get_value() + 1);
break;
case TAY:
y_index->set_value(accumulator->get_value());
break;
case TYA:
accumulator->set_value(y_index->get_value());
break;
case DEY:
y_index->set_value(y_index->get_value() - 1);
break;
case INY:
y_index->set_value(y_index->get_value() + 1);
break;
default:
stringstream stream;
stream << "Unexpected opcode 0x" << hex << opcode;
throw runtime_error(stream.str());
throw_unexpected_opcode(opcode);
}
move_program_counter(1);

View File

@ -1,6 +1,4 @@
#include "stack-opcode-handler.h"
#include <sstream>
#include <climits>
const uint8_t StackOpcodeHandler::PHA;
const uint8_t StackOpcodeHandler::PLA;
@ -34,9 +32,7 @@ void StackOpcodeHandler::execute() {
}
default:
stringstream stream;
stream << "Unexpected opcode 0x" << hex << opcode;
throw runtime_error(stream.str());
throw_unexpected_opcode(opcode);
}
move_program_counter(1);

View File

@ -0,0 +1,39 @@
#include "stx-opcode-handler.h"
const uint8_t StxOpcodeHandler::ZERO_PAGE;
const uint8_t StxOpcodeHandler::ZERO_PAGE_Y;
const uint8_t StxOpcodeHandler::ABSOLUTE;
void StxOpcodeHandler::execute() {
auto instructionIndex = reg_man->get_program_counter()->get_value();
auto opcode = program->get_byte_at(instructionIndex);
auto byte2 = program->get_byte_at(instructionIndex + 1);
auto x_reg = reg_man->get_x_index();
switch (opcode) {
case ZERO_PAGE:
memory->set_byte_at(byte2, x_reg->get_value());
move_program_counter(2);
break;
case ZERO_PAGE_Y: {
// expect wrap around
uint8_t address = reg_man->get_y_index()->get_value() + byte2;
memory->set_byte_at(address, x_reg->get_value());
move_program_counter(2);
break;
}
case ABSOLUTE: {
auto low = byte2;
auto high = program->get_byte_at(instructionIndex + 2);
uint16_t address = (high << 8) + low;
memory->set_byte_at(address, x_reg->get_value());
move_program_counter(3);
break;
}
default:
throw_unexpected_opcode(opcode);
}
}

View File

@ -0,0 +1,24 @@
#ifndef INC_6502_EMULATOR_STX_OPCODE_HANDLER_H
#define INC_6502_EMULATOR_STX_OPCODE_HANDLER_H
#include "../opcode-handler.h"
class StxOpcodeHandler : public OpcodeHandler {
public:
static const uint8_t ZERO_PAGE = 0x86;
static const uint8_t ZERO_PAGE_Y = 0x96;
static const uint8_t ABSOLUTE = 0x8E;
explicit StxOpcodeHandler(shared_ptr<Program> program, shared_ptr<RegisterManager> reg_man,
shared_ptr<Memory> memory) :
OpcodeHandler(program, reg_man, memory) {
handled_opcodes->push_back(ZERO_PAGE);
handled_opcodes->push_back(ZERO_PAGE_Y);
handled_opcodes->push_back(ABSOLUTE);
}
virtual void execute() override;
};
#endif //INC_6502_EMULATOR_STX_OPCODE_HANDLER_H

View File

@ -0,0 +1,39 @@
#include "sty-opcode-handler.h"
const uint8_t StyOpcodeHandler::ZERO_PAGE;
const uint8_t StyOpcodeHandler::ZERO_PAGE_X;
const uint8_t StyOpcodeHandler::ABSOLUTE;
void StyOpcodeHandler::execute() {
auto instructionIndex = reg_man->get_program_counter()->get_value();
auto opcode = program->get_byte_at(instructionIndex);
auto byte2 = program->get_byte_at(instructionIndex + 1);
auto y_reg = reg_man->get_y_index();
switch (opcode) {
case ZERO_PAGE:
memory->set_byte_at(byte2, y_reg->get_value());
move_program_counter(2);
break;
case ZERO_PAGE_X: {
// expect wrap around
uint8_t address = reg_man->get_x_index()->get_value() + byte2;
memory->set_byte_at(address, y_reg->get_value());
move_program_counter(2);
break;
}
case ABSOLUTE: {
auto low = byte2;
auto high = program->get_byte_at(instructionIndex + 2);
uint16_t address = (high << 8) + low;
memory->set_byte_at(address, y_reg->get_value());
move_program_counter(3);
break;
}
default:
throw_unexpected_opcode(opcode);
}
}

View File

@ -0,0 +1,24 @@
#ifndef INC_6502_EMULATOR_STY_OPCODE_HANDLER_H
#define INC_6502_EMULATOR_STY_OPCODE_HANDLER_H
#include "../opcode-handler.h"
class StyOpcodeHandler : public OpcodeHandler {
public:
static const uint8_t ZERO_PAGE = 0x84;
static const uint8_t ZERO_PAGE_X = 0x94;
static const uint8_t ABSOLUTE = 0x8C;
explicit StyOpcodeHandler(shared_ptr<Program> program, shared_ptr<RegisterManager> reg_man,
shared_ptr<Memory> memory) :
OpcodeHandler(program, reg_man, memory) {
handled_opcodes->push_back(ZERO_PAGE);
handled_opcodes->push_back(ZERO_PAGE_X);
handled_opcodes->push_back(ABSOLUTE);
}
virtual void execute() override;
};
#endif //INC_6502_EMULATOR_STY_OPCODE_HANDLER_H

View File

@ -1,7 +1,10 @@
#include "opcode-handler-directory.h"
#include "handler/flag-opcode-handler.h"
#include "handler/register-opcode-handler.h"
#include "handler/lda-opcode-handler.h"
#include "handler/ldx-opcode-handler.h"
#include "handler/stx-opcode-handler.h"
#include "handler/sty-opcode-handler.h"
#include "handler/stack-opcode-handler.h"
#include <sstream>
@ -12,7 +15,10 @@ OpcodeHandlerDirectory::OpcodeHandlerDirectory(shared_ptr<Program> program, shar
register_handler(make_shared<FlagOpcodeHandler>(FlagOpcodeHandler(program, reg_man, memory)));
register_handler(make_shared<RegisterOpcodeHandler>(RegisterOpcodeHandler(program, reg_man, memory)));
register_handler(make_shared<LdaOpcodeHandler>(LdaOpcodeHandler(program, reg_man, memory)));
register_handler(make_shared<LdxOpcodeHandler>(LdxOpcodeHandler(program, reg_man, memory)));
register_handler(make_shared<StxOpcodeHandler>(StxOpcodeHandler(program, reg_man, memory)));
register_handler(make_shared<StyOpcodeHandler>(StyOpcodeHandler(program, reg_man, memory)));
register_handler(make_shared<StackOpcodeHandler>(StackOpcodeHandler(program, reg_man, memory)));
}

View File

@ -1,4 +1,6 @@
#include "opcode-handler.h"
#include <sstream>
#include <stdexcept>
OpcodeHandler::OpcodeHandler(shared_ptr<Program> program, shared_ptr<RegisterManager> reg_man,
shared_ptr<Memory> memory) {
@ -10,4 +12,10 @@ OpcodeHandler::OpcodeHandler(shared_ptr<Program> program, shared_ptr<RegisterMan
void OpcodeHandler::move_program_counter(uint8_t forward_by) {
auto pc = reg_man->get_program_counter();
pc->set_value(pc->get_value() + forward_by);
}
void OpcodeHandler::throw_unexpected_opcode(uint8_t opcode) {
stringstream stream;
stream << "Unexpected opcode 0x" << hex << opcode;
throw runtime_error(stream.str());
}

View File

@ -13,10 +13,11 @@ class OpcodeHandler {
public:
OpcodeHandler(shared_ptr<Program> program, shared_ptr<RegisterManager> reg_man, shared_ptr<Memory> memory);
shared_ptr<vector<uint8_t>> get_handled_opcodes() { return handled_opcodes; }
virtual void execute() = 0;
shared_ptr<vector<uint8_t>> get_handled_opcodes() { return handled_opcodes; }
void throw_unexpected_opcode(uint8_t opcode);
protected:
shared_ptr<vector<uint8_t>> handled_opcodes = make_shared<vector<uint8_t>>();
shared_ptr<Program> program;

View File

@ -0,0 +1,199 @@
#include "gtest/gtest.h"
#include "../src/machine.h"
#include "../src/program.h"
#include "../src/opcode/handler/lda-opcode-handler.h"
#include <memory>
#include <vector>
using namespace std;
const uint8_t IMMEDIATE = 0xA9;
const uint8_t ZERO_PAGE = 0xA5;
const uint8_t ZERO_PAGE_X = 0xB5;
const uint8_t ABSOLUTE = 0xAD;
const uint8_t ABSOLUTE_X = 0xBD;
const uint8_t ABSOLUTE_Y = 0xB9;
const uint8_t INDIRECT_X = 0xA1;
const uint8_t INDIRECT_Y = 0xB1;
unique_ptr<Machine> ldat_get_machine(shared_ptr<vector<uint8_t>> code) {
auto program = make_shared<Program>(Program(code));
auto machine = make_unique<Machine>(Machine(program));
return machine;
}
TEST(LdaOpcodeHandler, Immediate) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{IMMEDIATE, 36});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
ASSERT_EQ(0, accumulator->get_value());
machine->execute();
ASSERT_EQ(36, accumulator->get_value());
}
TEST(LdaOpcodeHandler, ZeroPage) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE, 123});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
ASSERT_EQ(0, accumulator->get_value());
machine->get_memory()->set_byte_at(123, 78);
machine->execute();
ASSERT_EQ(78, accumulator->get_value());
}
TEST(LdaOpcodeHandler, ZeroPageX) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE_X, 0x50});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
auto x_reg = reg_man->get_x_index();
ASSERT_EQ(0, accumulator->get_value());
ASSERT_EQ(0, x_reg->get_value());
machine->get_memory()->set_byte_at(0x50, 0xff);
machine->execute();
ASSERT_EQ(0xff, accumulator->get_value());
x_reg->set_value(0x15);
reg_man->get_program_counter()->set_value(0);
machine->execute();
ASSERT_EQ(0, accumulator->get_value());
machine->get_memory()->set_byte_at(0x65, 233);
reg_man->get_program_counter()->set_value(0);
machine->execute();
ASSERT_EQ(233, accumulator->get_value());
}
TEST(LdaOpcodeHandler, ZeroPageXWrap) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE_X, 0x80});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
auto x_reg = reg_man->get_x_index();
ASSERT_EQ(0, accumulator->get_value());
ASSERT_EQ(0, x_reg->get_value());
x_reg->set_value(0xff);
machine->get_memory()->set_byte_at(0x7f, 0x12);
machine->execute();
ASSERT_EQ(0x12, accumulator->get_value());
}
TEST(LdaOpcodeHandler, Absolute) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ABSOLUTE, 0xe5, 0xff});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
ASSERT_EQ(0, accumulator->get_value());
machine->get_memory()->set_byte_at(0xffe5, 0xde);
machine->execute();
ASSERT_EQ(0xde, accumulator->get_value());
}
TEST(LdaOpcodeHandler, AbsoluteX) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ABSOLUTE_X, 0x33, 0xc2});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
auto x_reg = reg_man->get_x_index();
ASSERT_EQ(0, accumulator->get_value());
ASSERT_EQ(0, x_reg->get_value());
machine->get_memory()->set_byte_at(0xc233, 0xc8);
machine->execute();
ASSERT_EQ(0xc8, accumulator->get_value());
x_reg->set_value(0x55);
machine->get_memory()->set_byte_at(0xc233 + 0x55, 0xab);
reg_man->get_program_counter()->set_value(0);
machine->execute();
ASSERT_EQ(0xab, accumulator->get_value());
}
TEST(LdaOpcodeHandler, AbsoluteY) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ABSOLUTE_Y, 0x33, 0xc2});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
auto y_reg = reg_man->get_y_index();
ASSERT_EQ(0, accumulator->get_value());
ASSERT_EQ(0, y_reg->get_value());
machine->get_memory()->set_byte_at(0xc233, 0xc8);
machine->execute();
ASSERT_EQ(0xc8, accumulator->get_value());
y_reg->set_value(0x55);
machine->get_memory()->set_byte_at(0xc233 + 0x55, 0xab);
reg_man->get_program_counter()->set_value(0);
machine->execute();
ASSERT_EQ(0xab, accumulator->get_value());
}
TEST(LdaOpcodeHandler, IndirectX) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{INDIRECT_X, 0x00});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
auto x_reg = reg_man->get_x_index();
ASSERT_EQ(0, accumulator->get_value());
x_reg->set_value(0x01);
machine->get_memory()->set_byte_at(0x01, 0x05);
machine->get_memory()->set_byte_at(0x02, 0x07);
machine->get_memory()->set_byte_at(0x0705, 0xc6);
machine->execute();
ASSERT_EQ(0xc6, accumulator->get_value());
code->at(1) = 0x15;
reg_man->get_program_counter()->set_value(0);
x_reg->set_value(0x20);
machine->get_memory()->set_byte_at(0x35, 0xef);
machine->get_memory()->set_byte_at(0x36, 0xa8);
machine->get_memory()->set_byte_at(0xa8ef, 0x9d);
machine->execute();
ASSERT_EQ(0x9d, accumulator->get_value());
}
TEST(LdaOpcodeHandler, IndirectY) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{INDIRECT_Y, 0x00});
auto machine = ldat_get_machine(code);
auto reg_man = machine->get_reg_man();
auto accumulator = reg_man->get_accumulator();
auto y_reg = reg_man->get_y_index();
ASSERT_EQ(0, accumulator->get_value());
y_reg->set_value(0x00);
machine->get_memory()->set_byte_at(0x00, 0x25);
machine->get_memory()->set_byte_at(0x01, 0x3e);
machine->get_memory()->set_byte_at(0x3e25, 0xf0);
machine->execute();
ASSERT_EQ(0xf0, accumulator->get_value());
code->at(1) = 0x15;
reg_man->get_program_counter()->set_value(0);
y_reg->set_value(0x25);
machine->get_memory()->set_byte_at(0x15, 0x20);
machine->get_memory()->set_byte_at(0x16, 0x07);
machine->get_memory()->set_byte_at(0x0745, 0x89);
machine->execute();
ASSERT_EQ(0x89, accumulator->get_value());
}

View File

@ -48,7 +48,7 @@ TEST(LdxOpcodeHandler, ZeroPage) {
}
TEST(LdxOpcodeHandler, ZeroPageY) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE_Y, 250});
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE_Y, 0x50});
auto machine = ldxt_get_machine(code);
auto reg_man = machine->get_reg_man();
auto x_reg = reg_man->get_x_index();
@ -56,16 +56,16 @@ TEST(LdxOpcodeHandler, ZeroPageY) {
ASSERT_EQ(0, x_reg->get_value());
ASSERT_EQ(0, y_reg->get_value());
machine->get_memory()->set_byte_at(250, 255);
machine->get_memory()->set_byte_at(0x50, 255);
machine->execute();
ASSERT_EQ(255, x_reg->get_value());
reg_man->get_y_index()->set_value(100);
reg_man->get_y_index()->set_value(0x17);
reg_man->get_program_counter()->set_value(0);
machine->execute();
ASSERT_EQ(0, x_reg->get_value());
machine->get_memory()->set_byte_at(350, 233);
machine->get_memory()->set_byte_at(0x67, 233);
reg_man->get_program_counter()->set_value(0);
machine->execute();
ASSERT_EQ(233, x_reg->get_value());

View File

@ -0,0 +1,71 @@
#include "gtest/gtest.h"
#include "../src/machine.h"
#include "../src/program.h"
#include <memory>
#include <vector>
using namespace std;
const uint8_t ZERO_PAGE = 0x86;
const uint8_t ZERO_PAGE_Y = 0x96;
const uint8_t ABSOLUTE = 0x8E;
unique_ptr<Machine> stxt_get_machine(shared_ptr<vector<uint8_t>> code) {
auto program = make_shared<Program>(Program(code));
auto machine = make_unique<Machine>(Machine(program));
return machine;
}
TEST(StxOpcodeHandler, ZeroPage) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE, 50});
auto machine = stxt_get_machine(code);
auto memory = machine->get_memory();
auto reg_man = machine->get_reg_man();
auto x_reg = reg_man->get_x_index();
ASSERT_EQ(0, x_reg->get_value());
ASSERT_EQ(0, memory->get_byte_at(50));
x_reg->set_value(0x8a);
machine->execute();
ASSERT_EQ(0x8a, memory->get_byte_at(50));
}
TEST(StxOpcodeHandler, ZeroPageY) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE_Y, 0x45});
auto machine = stxt_get_machine(code);
auto memory = machine->get_memory();
auto reg_man = machine->get_reg_man();
auto x_reg = reg_man->get_x_index();
auto y_reg = reg_man->get_y_index();
ASSERT_EQ(0, x_reg->get_value());
ASSERT_EQ(0, y_reg->get_value());
ASSERT_EQ(0, memory->get_byte_at(0x4a));
x_reg->set_value(0x8b);
y_reg->set_value(0x5);
machine->execute();
ASSERT_EQ(0x8b, memory->get_byte_at(0x4a));
}
TEST(StxOpcodeHandler, Absolute) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ABSOLUTE, 0x33, 0x44});
auto machine = stxt_get_machine(code);
auto memory = machine->get_memory();
auto reg_man = machine->get_reg_man();
auto x_reg = reg_man->get_x_index();
auto y_reg = reg_man->get_y_index();
ASSERT_EQ(0, x_reg->get_value());
ASSERT_EQ(0, y_reg->get_value());
ASSERT_EQ(0, memory->get_byte_at(0x4433));
x_reg->set_value(0x9f);
machine->execute();
ASSERT_EQ(0x9f, memory->get_byte_at(0x4433));
}

View File

@ -0,0 +1,71 @@
#include "gtest/gtest.h"
#include "../src/machine.h"
#include "../src/program.h"
#include <memory>
#include <vector>
using namespace std;
const uint8_t ZERO_PAGE = 0x84;
const uint8_t ZERO_PAGE_X = 0x94;
const uint8_t ABSOLUTE = 0x8C;
unique_ptr<Machine> styt_get_machine(shared_ptr<vector<uint8_t>> code) {
auto program = make_shared<Program>(Program(code));
auto machine = make_unique<Machine>(Machine(program));
return machine;
}
TEST(StyOpcodeHandler, ZeroPage) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE, 50});
auto machine = styt_get_machine(code);
auto memory = machine->get_memory();
auto reg_man = machine->get_reg_man();
auto y_reg = reg_man->get_y_index();
ASSERT_EQ(0, y_reg->get_value());
ASSERT_EQ(0, memory->get_byte_at(50));
y_reg->set_value(0x8a);
machine->execute();
ASSERT_EQ(0x8a, memory->get_byte_at(50));
}
TEST(StyOpcodeHandler, ZeroPageX) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ZERO_PAGE_X, 0x45});
auto machine = styt_get_machine(code);
auto memory = machine->get_memory();
auto reg_man = machine->get_reg_man();
auto x_reg = reg_man->get_x_index();
auto y_reg = reg_man->get_y_index();
ASSERT_EQ(0, x_reg->get_value());
ASSERT_EQ(0, y_reg->get_value());
ASSERT_EQ(0, memory->get_byte_at(0x5b));
x_reg->set_value(0x16);
y_reg->set_value(0xe1);
machine->execute();
ASSERT_EQ(0xe1, memory->get_byte_at(0x5b));
}
TEST(StyOpcodeHandler, Absolute) {
auto code = make_shared<vector<uint8_t>>(vector<uint8_t>{ABSOLUTE, 0x33, 0x44});
auto machine = styt_get_machine(code);
auto memory = machine->get_memory();
auto reg_man = machine->get_reg_man();
auto x_reg = reg_man->get_x_index();
auto y_reg = reg_man->get_y_index();
ASSERT_EQ(0, x_reg->get_value());
ASSERT_EQ(0, y_reg->get_value());
ASSERT_EQ(0, memory->get_byte_at(0x4433));
y_reg->set_value(0x9f);
machine->execute();
ASSERT_EQ(0x9f, memory->get_byte_at(0x4433));
}