diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index c459992..50b8750 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -2,3 +2,97 @@ // Created by Melefo on 27/01/2020. // +#include "APU.hpp" +#include "../Exceptions/NotImplementedException.hpp" +#include "../Exceptions/InvalidAddress.hpp" + +namespace ComSquare::APU +{ + APU::APU(std::shared_ptr dsp) + : _dsp(std::move(dsp)) + { } + + uint8_t APU::read(uint24_t addr) + { + switch (addr) { + case 0xF0: + return this->_internalRegisters.unknown; + case 0xF2: + return this->_internalRegisters.dspregAddr; + case 0xF3: + return this->_internalRegisters.dspregData; + case 0xF4: + return this->_internalRegisters.port0; + case 0xF5: + return this->_internalRegisters.port1; + case 0xF6: + return this->_internalRegisters.port2; + case 0xF7: + return this->_internalRegisters.port3; + case 0xF8: + return this->_internalRegisters.regmem1; + case 0xF9: + return this->_internalRegisters.regmem2; + case 0xFD: + return this->_internalRegisters.counter0; + case 0xFE: + return this->_internalRegisters.counter1; + case 0xFF: + return this->_internalRegisters.counter2; + default: + throw InvalidAddress("APU Internal Registers read", addr); + } + } + + void APU::write(uint24_t addr, uint8_t data) + { + switch (addr) { + case 0xF0: + this->_internalRegisters.unknown = data; + break; + case 0xF1: + this->_internalRegisters.ctrlreg = data; + break; + case 0xF2: + this->_internalRegisters.dspregAddr = data; + break; + case 0xF3: + this->_internalRegisters.dspregData = data; + break; + case 0xF4: + this->_internalRegisters.port0 = data; + break; + case 0xF5: + this->_internalRegisters.port1 = data; + break; + case 0xF6: + this->_internalRegisters.port2 = data; + break; + case 0xF7: + this->_internalRegisters.port3 = data; + break; + case 0xF8: + this->_internalRegisters.regmem1 = data; + break; + case 0xF9: + this->_internalRegisters.regmem2 = data; + break; + case 0xFA: + this->_internalRegisters.timer0 = data; + break; + case 0xFB: + this->_internalRegisters.timer1 = data; + break; + case 0xFC: + this->_internalRegisters.timer2 = data; + break; + default: + throw InvalidAddress("APU Internal Registers write", addr); + } + } + + bool APU::update() + { + throw NotImplementedException(); + } +} diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index a882ce1..af75bf3 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -5,30 +5,37 @@ #ifndef COMSQUARE_APU_HPP #define COMSQUARE_APU_HPP +#include #include "../Memory/IMemory.hpp" namespace ComSquare::APU { struct Registers { - //! @brief The Accumulator register - unsigned char a; //! @brief The X index register - unsigned char x; + uint8_t x; - //! @brief The Y index register - unsigned char y; + //! @brief The YA register + union { + struct { + //! @brief The Accumulator register + uint8_t a; + //! @brief The Y Index register + uint8_t y; + }; + uint16_t ya; + }; //! @brief The Stack pointer register - unsigned char sp; + uint8_t sp; //! @brief The Program counter register union { struct { - unsigned char pch; - unsigned char pcl; + uint8_t pcl; + uint8_t pch; }; - unsigned short pc; + uint16_t pc; }; //! @brief Program Status Word register @@ -52,9 +59,66 @@ namespace ComSquare::APU }; }; + struct InternalRegisters + { + //! @brief An undocumented register + uint8_t unknown; + + //! @brief Control Register register + uint8_t ctrlreg; + + //! @brief DSP Register Address register + uint8_t dspregAddr; + //! @brief DSP Register data register + uint8_t dspregData; + + //! @brief Port 0 register + uint8_t port0; + //! @brief Port 1 register + uint8_t port1; + //! @brief Port 2 register + uint8_t port2; + //! @brief Port 3 register + uint8_t port3; + + //! @brief Regular Memory register + uint8_t regmem1; + //! @brief Another Regular Memory register + uint8_t regmem2; + + //! @brief Timer-0 register + uint8_t timer0; + //! @brief Timer-1 register + uint8_t timer1; + //! @brief Timer-2 register + uint8_t timer2; + + //! @brief Counter-0 register + uint8_t counter0; + //! @brief Counter-1 register + uint8_t counter1; + //! @brief Counter-2 register + uint8_t counter2; + + }; + + class APU : IMemory { private: Registers _registers; + InternalRegisters _internalRegisters{}; + public: + //! @brief Read from the internal APU register. + //! @param addr The address to read from. The address 0xF0 should refer to the first byte of the register. + //! @throw InvalidAddress will be thrown if the address is more than $FF (the number of register). + //! @return Return the value of the register. + uint8_t read(uint24_t addr) override; + //! @brief Write data to the internal APY register. + //! @param addr The address to write to. The address 0xF0 should refer to the first byte of register. + //! @param data The new value of the register. + //! @throw InvalidAddress will be thrown if the address is more than $FF (the number of register). + void write(uint24_t addr, uint8_t data) override; + bool update(); }; }