mirror of
https://github.com/zoriya/ComSquare.git
synced 2025-12-22 15:15:17 +00:00
Finishing the first opcode
This commit is contained in:
@@ -46,7 +46,10 @@ add_executable(unit_tests
|
||||
sources/Cartridge/InterruptVectors.hpp
|
||||
sources/Memory/RectangleShadow.cpp
|
||||
sources/Memory/RectangleShadow.hpp
|
||||
sources/CPU/CommonCpu.cpp sources/CPU/CommonCpu.hpp)
|
||||
sources/CPU/Instructions/CommonInstructions.cpp
|
||||
sources/CPU/Instructions/CommonInstructions.hpp
|
||||
sources/Exceptions/InvalidOpcode.hpp
|
||||
)
|
||||
|
||||
# include criterion & coverage
|
||||
target_link_libraries(unit_tests criterion -lgcov)
|
||||
@@ -95,7 +98,10 @@ add_executable(ComSquare
|
||||
sources/Cartridge/InterruptVectors.hpp
|
||||
sources/Memory/RectangleShadow.cpp
|
||||
sources/Memory/RectangleShadow.hpp
|
||||
sources/CPU/CommonCpu.cpp sources/CPU/CommonCpu.hpp)
|
||||
sources/CPU/Instructions/CommonInstructions.cpp
|
||||
sources/CPU/Instructions/CommonInstructions.hpp
|
||||
sources/Exceptions/InvalidOpcode.hpp
|
||||
)
|
||||
|
||||
target_link_libraries(ComSquare
|
||||
sfml-graphics
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
#include <utility>
|
||||
#include "../Exceptions/NotImplementedException.hpp"
|
||||
#include "../Exceptions/InvalidAddress.hpp"
|
||||
#include "../Exceptions/InvalidOpcode.hpp"
|
||||
|
||||
namespace ComSquare::CPU
|
||||
{
|
||||
CPU::CPU(std::shared_ptr<Memory::MemoryBus> bus)
|
||||
: _bus(std::move(bus))
|
||||
{ }
|
||||
CPU::CPU(std::shared_ptr<Memory::MemoryBus> bus, Cartridge::Header &cartridgeHeader)
|
||||
: _bus(std::move(bus)), _cartridgeHeader(cartridgeHeader)
|
||||
{
|
||||
this->_registers.pc = this->_cartridgeHeader.emulationInterrupts.reset;
|
||||
}
|
||||
|
||||
//! @bref The CPU's internal registers starts at $4200 and finish at $421F.
|
||||
uint8_t CPU::read(uint24_t addr)
|
||||
@@ -192,6 +195,24 @@ namespace ComSquare::CPU
|
||||
|
||||
int CPU::executeInstruction()
|
||||
{
|
||||
throw NotImplementedException();
|
||||
uint8_t opcode = this->_bus->read(this->_registers.pc++);
|
||||
|
||||
switch (opcode) {
|
||||
case 0x0: return this->BRK();
|
||||
default:
|
||||
throw InvalidOpcode("CPU", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CPU::BRK()
|
||||
{
|
||||
this->_registers.p.i = true;
|
||||
if (this->_isEmulationMode)
|
||||
this->_registers.pc = this->_cartridgeHeader.emulationInterrupts.brk;
|
||||
else
|
||||
this->_registers.pc = this->_cartridgeHeader.nativeInterrupts.brk;
|
||||
this->_registers.p.d = false;
|
||||
return 7 + !this->_isEmulationMode;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,8 @@
|
||||
#include "../Memory/IMemory.hpp"
|
||||
#include "../Memory/MemoryBus.hpp"
|
||||
#include "../Models/Ints.hpp"
|
||||
#include "CommonCpu.hpp"
|
||||
#include "Instructions/CommonInstructions.hpp"
|
||||
#include "../Cartridge/Cartridge.hpp"
|
||||
|
||||
namespace ComSquare::CPU
|
||||
{
|
||||
@@ -68,28 +69,27 @@ namespace ComSquare::CPU
|
||||
};
|
||||
|
||||
//! @brief The Processor status register;
|
||||
union p {
|
||||
union {
|
||||
struct {
|
||||
//! @brief The Negative flag
|
||||
bool n : 1;
|
||||
//! @brief The oVerflow flag
|
||||
bool v : 1;
|
||||
//! @brief The accumulator and Memory width flag (in native mode only)
|
||||
bool m : 1;
|
||||
union {
|
||||
//! @brief The indeX register width flag (in native mode only)
|
||||
bool x : 1;
|
||||
//! @brief The Break flag (in emulation mode only)
|
||||
bool b : 1;
|
||||
};
|
||||
//! @brief The indeX register width flag (in native mode only) OR the Break flag (in emulation mode only)
|
||||
bool x_b : 1;
|
||||
//! @brief The Decimal mode flag
|
||||
bool d : 1;
|
||||
//! @brief The Interrupt disable flag
|
||||
//! @brief The Interrupt request disable flag
|
||||
bool i : 1;
|
||||
//! @brief The Zero flag
|
||||
bool z : 1;
|
||||
//! @brief The Carry flag
|
||||
bool c : 1;
|
||||
};
|
||||
uint8_t flags;
|
||||
} p;
|
||||
};
|
||||
|
||||
//! @brief Struct containing internal registers of the CPU.
|
||||
@@ -175,7 +175,7 @@ namespace ComSquare::CPU
|
||||
};
|
||||
|
||||
//! @brief The main CPU
|
||||
class CPU : public CommonCPU, public Memory::IMemory {
|
||||
class CPU : public CommonInstructions, public Memory::IMemory {
|
||||
private:
|
||||
//! @brief All the registers of the CPU
|
||||
Registers _registers{};
|
||||
@@ -185,12 +185,14 @@ namespace ComSquare::CPU
|
||||
InternalRegisters _internalRegisters{};
|
||||
//! @brief The memory bus to use for read/write.
|
||||
std::shared_ptr<Memory::MemoryBus> _bus;
|
||||
//! @brief The cartridge header (stored for interrupt vectors..
|
||||
Cartridge::Header &_cartridgeHeader;
|
||||
|
||||
//! @brief Execute a single instruction.
|
||||
//! @return The number of CPU cycles that the instruction took.
|
||||
int executeInstruction();
|
||||
public:
|
||||
explicit CPU(std::shared_ptr<Memory::MemoryBus> bus);
|
||||
explicit CPU(std::shared_ptr<Memory::MemoryBus> bus, Cartridge::Header &cartridgeHeader);
|
||||
//! @brief This function continue to execute the Cartridge code.
|
||||
//! @return The number of CPU cycles that elapsed
|
||||
int update();
|
||||
@@ -204,6 +206,10 @@ namespace ComSquare::CPU
|
||||
//! @param data The new value of the register.
|
||||
//! @throw InvalidAddress will be thrown if the address is more than $1F (the number of register).
|
||||
void write(uint24_t addr, uint8_t data) override;
|
||||
|
||||
private:
|
||||
//! @brief Break instruction (0x00) - Causes a software break. The PC is loaded from a vector table.
|
||||
int BRK();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Created by anonymus-raccoon on 2/5/20.
|
||||
//
|
||||
|
||||
#include "CommonCpu.hpp"
|
||||
#include "CommonInstructions.hpp"
|
||||
|
||||
namespace ComSquare::CPU
|
||||
{
|
||||
@@ -2,15 +2,15 @@
|
||||
// Created by anonymus-raccoon on 2/5/20.
|
||||
//
|
||||
|
||||
#ifndef COMSQUARE_COMMONCPU_HPP
|
||||
#define COMSQUARE_COMMONCPU_HPP
|
||||
#ifndef COMSQUARE_COMMONINSTRUCTIONS_HPP
|
||||
#define COMSQUARE_COMMONINSTRUCTIONS_HPP
|
||||
|
||||
namespace ComSquare::CPU
|
||||
{
|
||||
//! @brief The shared states of the Main's CPU and the APU's CPU.
|
||||
class CommonCPU {
|
||||
class CommonInstructions {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif //COMSQUARE_COMMONCPU_HPP
|
||||
#endif //COMSQUARE_COMMONINSTRUCTIONS_HPP
|
||||
28
sources/Exceptions/InvalidOpcode.hpp
Normal file
28
sources/Exceptions/InvalidOpcode.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Created by anonymus-raccoon on 1/30/20.
|
||||
//
|
||||
|
||||
#ifndef COMSQUARE_INVALIDACTION_HPP
|
||||
#define COMSQUARE_INVALIDACTION_HPP
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <ios>
|
||||
|
||||
namespace ComSquare
|
||||
{
|
||||
//! @brief Exception thrown when someone tries to load an invalid rom.
|
||||
class InvalidOpcode : std::exception {
|
||||
private:
|
||||
std::string _msg;
|
||||
public:
|
||||
explicit InvalidOpcode(const std::string &pu, unsigned opcode)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "The " + pu + ": 0x" << std::hex << opcode;
|
||||
this->_msg = stream.str();
|
||||
}
|
||||
const char *what() const noexcept override { return this->_msg.c_str(); }
|
||||
};
|
||||
}
|
||||
#endif //COMSQUARE_INVALIDACTION_HPP
|
||||
@@ -7,10 +7,10 @@
|
||||
namespace ComSquare
|
||||
{
|
||||
SNES::SNES(const std::shared_ptr<Memory::MemoryBus> &bus, const std::string &romPath, Renderer::IRenderer &renderer) :
|
||||
cpu(new CPU::CPU(bus)),
|
||||
cartridge(new Cartridge::Cartridge(romPath)),
|
||||
cpu(new CPU::CPU(bus, cartridge->header)),
|
||||
ppu(new PPU::PPU()),
|
||||
apu(new APU::APU()),
|
||||
cartridge(new Cartridge::Cartridge(romPath)),
|
||||
wram(new Ram::Ram(16384)),
|
||||
sram(new Ram::Ram(this->cartridge->header.sramSize))
|
||||
{
|
||||
|
||||
@@ -18,14 +18,14 @@ namespace ComSquare
|
||||
//! @brief Container of all the components of the SNES.
|
||||
struct SNES {
|
||||
public:
|
||||
//! @brief Cartridge containing instructions (ROM).
|
||||
std::shared_ptr<Cartridge::Cartridge> cartridge;
|
||||
//! @brief Central Processing Unit of the SNES.
|
||||
std::shared_ptr<CPU::CPU> cpu;
|
||||
//! @brief Picture Processing Unit of the SNES
|
||||
std::shared_ptr<PPU::PPU> ppu;
|
||||
//! @brief Audio Processing Unit if the SNES
|
||||
std::shared_ptr<APU::APU> apu;
|
||||
//! @brief Cartridge containing instructions (ROM).
|
||||
std::shared_ptr<Cartridge::Cartridge> cartridge;
|
||||
//! @brief Work Ram shared by all the components.
|
||||
std::shared_ptr<Ram::Ram> wram;
|
||||
//! @brief Save Ram residing inside the Cartridge in a real SNES.
|
||||
|
||||
@@ -2,3 +2,36 @@
|
||||
// Created by anonymus-raccoon on 1/24/20.
|
||||
//
|
||||
|
||||
#include <criterion/criterion.h>
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
#include "communism.hpp"
|
||||
#include "../sources/SNES.hpp"
|
||||
#include "../sources/Memory/MemoryBus.hpp"
|
||||
using namespace ComSquare;
|
||||
|
||||
std::pair<Memory::MemoryBus, SNES> Init();
|
||||
|
||||
Test(CPU_emulated, BRK)
|
||||
{
|
||||
auto pair = Init();
|
||||
pair.second.cartridge->header.emulationInterrupts.brk = 0x123u;
|
||||
pair.second.cpu->_registers.p.d = true;
|
||||
pair.second.cpu->_registers.pc = 0x156u;
|
||||
cr_assert_eq(pair.second.cpu->BRK(), 7);
|
||||
cr_assert_eq(pair.second.cpu->_registers.pc, 0x123u);
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.i, 1, "pair.second.cpu->_registers.p.i mmust be equal to 1 but it was %d", pair.second.cpu->_registers.p.i);
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.d, false);
|
||||
}
|
||||
|
||||
Test(CPU_native, BRK)
|
||||
{
|
||||
auto pair = Init();
|
||||
pair.second.cpu->_isEmulationMode = false;
|
||||
pair.second.cartridge->header.nativeInterrupts.brk = 0x123u;
|
||||
pair.second.cpu->_registers.pc = 0x156u;
|
||||
cr_assert_eq(pair.second.cpu->BRK(), 8);
|
||||
cr_assert_eq(pair.second.cpu->_registers.pc, 0x123u);
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.i, true);
|
||||
cr_assert_eq(pair.second.cpu->_registers.p.d, false);
|
||||
}
|
||||
Reference in New Issue
Block a user