diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..ac5eb82 --- /dev/null +++ b/.clang-format @@ -0,0 +1,66 @@ +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: None +AlignOperands: DontAlign +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterReturnType: None +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterStruct: true + AfterControlStatement: Never + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterUnion: true + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: true +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +ColumnLimit: 0 +CompactNamespaces: false +ContinuationIndentWidth: 4 +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PointerAlignment: Right +ReflowComments: false +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 0 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: ForIndentation diff --git a/CMakeLists.txt b/CMakeLists.txt index cba781e..d29a4c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 3.12) set(CMAKE_CXX_STANDARD 20) - -# set the project name project(ComSquare) -# show compilation warnings -add_compile_options(-W -Wall -Wextra -Wshadow) +if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Wextra -Wshadow -Wno-unused-parameter -W -g") +endif () +set(CMAKE_CXX_FLAGS_RELEASE "-O3") include_directories(sources) @@ -95,14 +95,15 @@ set(SOURCES sources/PPU/Tile.hpp sources/PPU/TileRenderer.cpp sources/PPU/TileRenderer.hpp -) + sources/PPU/Tile.hpp + sources/CPU/Registers.hpp) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC_SEARCH_PATHS ./) -add_executable(ComSquare +add_executable(comsquare sources/main.cpp ${SOURCES} sources/Renderer/SFRenderer.hpp @@ -113,30 +114,34 @@ add_executable(ComSquare sources/Renderer/QtRenderer/QtWidgetSFML.hpp sources/Renderer/QtRenderer/QtSfmlTileRenderer.cpp sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp - sources/Debugger/CPU/CPUDebug.cpp - sources/Debugger/CPU/CPUDebug.hpp - sources/Debugger/MemoryViewer.cpp - sources/Debugger/MemoryViewer.hpp - sources/Debugger/HeaderViewer.cpp - sources/Debugger/HeaderViewer.hpp - sources/Debugger/HeaderViewer.cpp - sources/Debugger/HeaderViewer.hpp - sources/Debugger/APUDebug.hpp - sources/Debugger/APUDebug.cpp - sources/Debugger/MemoryBusDebug.cpp - sources/Debugger/MemoryBusDebug.hpp - sources/Debugger/ClosableWindow.hpp - sources/Debugger/CPU/Disassembly.cpp - sources/Debugger/CGramDebug.cpp - sources/Debugger/CGramDebug.hpp - sources/Debugger/RegisterViewer.cpp - sources/Debugger/RegisterViewer.hpp - sources/Debugger/CPU/SymbolLoaders/WlaDx.cpp - sources/Debugger/CPU/SymbolLoaders/WlaDx.hpp - sources/Debugger/TileViewer/TileViewer.cpp - sources/Debugger/TileViewer/TileViewer.hpp - sources/Debugger/TileViewer/RAMTileRenderer.cpp - sources/Debugger/TileViewer/RAMTileRenderer.hpp + sources/Renderer/QtRenderer/QtSfmlTileRenderer.cpp + sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp + # sources/PPU/PpuDebug.cpp + # sources/PPU/PpuDebug.hpp + # sources/Debugger/CPU/CPUDebug.cpp + # sources/Debugger/CPU/CPUDebug.hpp + # sources/Debugger/MemoryViewer.cpp + # sources/Debugger/MemoryViewer.hpp + # sources/Debugger/HeaderViewer.cpp + # sources/Debugger/HeaderViewer.hpp + # sources/Debugger/HeaderViewer.cpp + # sources/Debugger/HeaderViewer.hpp + # sources/Debugger/APUDebug.hpp + # sources/Debugger/APUDebug.cpp + # sources/Debugger/MemoryBusDebug.cpp + # sources/Debugger/MemoryBusDebug.hpp + # sources/Debugger/ClosableWindow.hpp + # sources/Debugger/CPU/Disassembly.cpp + # sources/Debugger/CGramDebug.cpp + # sources/Debugger/CGramDebug.hpp + # sources/Debugger/RegisterViewer.cpp + # sources/Debugger/RegisterViewer.hpp + # sources/Debugger/CPU/SymbolLoaders/WlaDx.cpp + # sources/Debugger/CPU/SymbolLoaders/WlaDx.hpp + # sources/Debugger/TileViewer/TileViewer.cpp + # sources/Debugger/TileViewer/TileViewer.hpp + # sources/Debugger/TileViewer/RAMTileRenderer.cpp + # sources/Debugger/TileViewer/RAMTileRenderer.hpp ui/tileView.ui ui/registersView.ui ui/cpuView.ui @@ -145,48 +150,48 @@ add_executable(ComSquare ui/apuView.ui ui/busView.ui resources/appResources.qrc -) -target_include_directories(ComSquare PRIVATE ./) -target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) + ) +target_include_directories(comsquare PRIVATE ./) +#target_compile_definitions(comsquare PUBLIC DEBUGGER_ENABLED) find_package(Qt5 COMPONENTS Widgets REQUIRED) -target_link_libraries(ComSquare +target_link_libraries(comsquare sfml-graphics sfml-window sfml-system sfml-audio sfml-network Qt5::Widgets -) + ) add_executable(unit_tests EXCLUDE_FROM_ALL ${SOURCES} tests/MainTest.cpp tests/tests.hpp tests/CPU/testInterupts.cpp -# tests/APU/testAPUInstructions.cpp -# tests/APU/testAPU.cpp -# tests/PPU/testPpuWrite.cpp -# tests/PPU/testPpuWriteFromVmain.cpp -# tests/CPU/Math/testADC.cpp -# tests/CPU/testStore.cpp -# tests/CPU/testInternal.cpp -# tests/CPU/testBits.cpp -# tests/APU/testOperand.cpp -# tests/CPU/Math/testSBC.cpp -# tests/CPU/testTransfers.cpp -# tests/CPU/Math/testOthersMath.cpp -# tests/testRectangleMemory.cpp -# tests/CPU/Math/testCMP.cpp -# tests/CPU/testDMA.cpp -# tests/CPU/testAddressingMode.cpp -# tests/testMemoryBus.cpp -) + tests/APU/testAPUInstructions.cpp + tests/APU/testAPU.cpp + tests/PPU/testPpuWrite.cpp + tests/PPU/testPpuWriteFromVmain.cpp + tests/CPU/Math/testADC.cpp + tests/CPU/testStore.cpp + tests/CPU/testInternal.cpp + tests/CPU/testBits.cpp + tests/APU/testOperand.cpp + tests/CPU/Math/testSBC.cpp + tests/CPU/testTransfers.cpp + tests/CPU/Math/testOthersMath.cpp + tests/testRectangleMemory.cpp + tests/CPU/Math/testCMP.cpp + tests/CPU/testDMA.cpp + tests/CPU/testAddressingMode.cpp + tests/testMemoryBus.cpp + ) if (CMAKE_COMPILER_IS_GNUCXX) -# target_link_libraries(unit_tests PRIVATE -lgcov) -# target_compile_options(unit_tests PUBLIC -fprofile-arcs -ftest-coverage) -endif() + # target_link_libraries(unit_tests PRIVATE -lgcov) + # target_compile_options(unit_tests PUBLIC -fprofile-arcs -ftest-coverage) +endif () find_package(Catch2 QUIET) if (NOT Catch2_FOUND) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index 6179c4e..c9dfbf8 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -2,20 +2,19 @@ // Created by Melefo on 27/01/2020. // -#include -#include #include "APU.hpp" -#include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" #include "../Exceptions/InvalidOpcode.hpp" +#include "../Exceptions/NotImplementedException.hpp" +#include +#include namespace ComSquare::APU { - APU::APU(Renderer::IRenderer &renderer) : - _renderer(renderer), - _map(new MemoryMap()), - _soundBuffer(), - _dsp(this->_soundBuffer, this->_soundBuffer.size() / 2, _map) + APU::APU(Renderer::IRenderer &renderer) : _renderer(renderer), + _map(new MemoryMap()), + _soundBuffer(), + _dsp(this->_soundBuffer, this->_soundBuffer.size() / 2, _map) { this->reset(); } @@ -278,7 +277,7 @@ namespace ComSquare::APU return this->SET1(this->_getDirectAddr(), 1); case 0x23: { auto ope1 = this->_getDirectAddr(); - auto ope2 = this->_getImmediateData(); + auto ope2 = this->_getImmediateData(); return this->BBS(ope1, ope2, 1); } case 0x24: @@ -751,11 +750,11 @@ namespace ComSquare::APU case 0xE8: return this->MOV(this->_internalRegisters.a, this->_getImmediateData(), 2); case 0xE9: - return this->MOV(this->_internalRegisters.x, this->_getAbsoluteAddr(),4); + return this->MOV(this->_internalRegisters.x, this->_getAbsoluteAddr(), 4); case 0xEA: return this->NOT1(this->_getAbsoluteBit()); case 0xEB: - return this->MOV(this->_internalRegisters.y, this->_getDirectAddr(),3); + return this->MOV(this->_internalRegisters.y, this->_getDirectAddr(), 3); case 0xEC: return this->MOV(this->_internalRegisters.y, this->_getAbsoluteAddr(), 4); case 0xED: @@ -822,13 +821,13 @@ namespace ComSquare::APU this->_dsp.update(); samples = this->_dsp.getSamplesCount(); if (samples > 0) - this->_renderer.playAudio(std::span{this->_soundBuffer}, samples / 2); + this->_renderer.playAudio(std::span {this->_soundBuffer}, samples / 2); } - void APU::loadFromSPC(const std::shared_ptr& cartridge) + void APU::loadFromSPC(Cartridge::Cartridge &cartridge) { - const uint8_t *data = cartridge->getData(); - uint24_t size = cartridge->getSize(); + const uint8_t *data = cartridge.getData(); + uint24_t size = cartridge.getSize(); if (size < 0x101C0) throw InvalidAddress("Cartridge is not the right size", size); @@ -839,61 +838,61 @@ namespace ComSquare::APU std::string date = std::string(reinterpret_cast(data + 0x9E), 0x0B); std::string artist = std::string(reinterpret_cast(data + 0xB1), 0x20); - this->_internalRegisters.pcl = cartridge->read(0x25); - this->_internalRegisters.pch = cartridge->read(0x26); - this->_internalRegisters.a = cartridge->read(0x27); - this->_internalRegisters.x = cartridge->read(0x28); - this->_internalRegisters.y = cartridge->read(0x29); - this->_internalRegisters.psw = cartridge->read(0x2A); - this->_internalRegisters.sp = cartridge->read(0x2B); + this->_internalRegisters.pcl = cartridge.read(0x25); + this->_internalRegisters.pch = cartridge.read(0x26); + this->_internalRegisters.a = cartridge.read(0x27); + this->_internalRegisters.x = cartridge.read(0x28); + this->_internalRegisters.y = cartridge.read(0x29); + this->_internalRegisters.psw = cartridge.read(0x2A); + this->_internalRegisters.sp = cartridge.read(0x2B); std::memcpy(this->_map->Page0.getData(), data + 0x100, this->_map->Page0.getSize()); std::memcpy(this->_map->Page1.getData(), data + 0x200, this->_map->Page1.getSize()); std::memcpy(this->_map->Memory.getData(), data + 0x300, this->_map->Memory.getSize()); - this->_registers.unknown = cartridge->read(0x100 + 0xF0); - this->_registers.ctrlreg = cartridge->read(0x100 + 0xF1); - this->_registers.dspregAddr = cartridge->read(0x100 + 0xF2); - this->_dsp.write(this->_registers.dspregAddr, cartridge->read(0x100 + 0xF3)); - this->_registers.port0 = cartridge->read(0x100 + 0xF4); - this->_registers.port1 = cartridge->read(0x100 + 0xF5); - this->_registers.port2 = cartridge->read(0x100 + 0xF6); - this->_registers.port3 = cartridge->read(0x100 + 0xF7); - this->_registers.regmem1 = cartridge->read(0x100 + 0xF8); - this->_registers.regmem2 = cartridge->read(0x100 + 0xF9); - this->_registers.timer0 = cartridge->read(0x100 + 0xFA); - this->_registers.timer1 = cartridge->read(0x100 + 0xFB); - this->_registers.timer2 = cartridge->read(0x100 + 0xFC); - this->_registers.counter0 = cartridge->read(0x100 + 0xFD); - this->_registers.counter1 = cartridge->read(0x100 + 0xFE); - this->_registers.counter2 = cartridge->read(0x100 + 0xFF); + this->_registers.unknown = cartridge.read(0x100 + 0xF0); + this->_registers.ctrlreg = cartridge.read(0x100 + 0xF1); + this->_registers.dspregAddr = cartridge.read(0x100 + 0xF2); + this->_dsp.write(this->_registers.dspregAddr, cartridge.read(0x100 + 0xF3)); + this->_registers.port0 = cartridge.read(0x100 + 0xF4); + this->_registers.port1 = cartridge.read(0x100 + 0xF5); + this->_registers.port2 = cartridge.read(0x100 + 0xF6); + this->_registers.port3 = cartridge.read(0x100 + 0xF7); + this->_registers.regmem1 = cartridge.read(0x100 + 0xF8); + this->_registers.regmem2 = cartridge.read(0x100 + 0xF9); + this->_registers.timer0 = cartridge.read(0x100 + 0xFA); + this->_registers.timer1 = cartridge.read(0x100 + 0xFB); + this->_registers.timer2 = cartridge.read(0x100 + 0xFC); + this->_registers.counter0 = cartridge.read(0x100 + 0xFD); + this->_registers.counter1 = cartridge.read(0x100 + 0xFE); + this->_registers.counter2 = cartridge.read(0x100 + 0xFF); for (int i = 0x00; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x01; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x02; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x03; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x04; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x05; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x06; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x07; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x08; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x09; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x0C; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x0D; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); for (int i = 0x0F; i < 0x80; i += 0x10) - this->_dsp.write(i, cartridge->read(0x10100 + i)); + this->_dsp.write(i, cartridge.read(0x10100 + i)); } void APU::_setNZflags(uint8_t value) @@ -902,10 +901,9 @@ namespace ComSquare::APU this->_internalRegisters.z = !value; } - MemoryMap::MemoryMap() : - Page0(0x00F0, Apu, "APU's Page 0"), - Page1(0x0100, Apu, "APU's Page 1"), - Memory(0xFDC0, Apu, "APU's Ram"), - IPL(Apu, "IPL Rom") - { } -} \ No newline at end of file + MemoryMap::MemoryMap() : Page0(0x00F0, Apu, "APU's Page 0"), + Page1(0x0100, Apu, "APU's Page 1"), + Memory(0xFDC0, Apu, "APU's Ram"), + IPL(Apu, "IPL Rom") + {} +}// namespace ComSquare::APU \ No newline at end of file diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index d8bdc03..d65257b 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -390,12 +390,16 @@ namespace ComSquare::APU //! @brief Get the component of this accessor (used for debug purpose) Component getComponent() const override; + //! @brief Get the name of the data at the address + //! @param addr The address (in local space) + [[nodiscard]] std::string getValueName(uint24_t addr) const override; + //! @brief Get the size of the data. This size can be lower than the mapped data. //! @return The number of bytes inside this memory. uint24_t getSize() const override; //! @brief Parses rom data to uploads directly into RAM and corresponding registers - void loadFromSPC(const std::shared_ptr& cartridge); + void loadFromSPC(Cartridge::Cartridge &cartridge); //! @brief This function execute the instructions received until the maximum number of cycles is reached. //! @return The number of cycles that elapsed. diff --git a/sources/APU/IPL/IPL.cpp b/sources/APU/IPL/IPL.cpp index d87acd7..0a50862 100644 --- a/sources/APU/IPL/IPL.cpp +++ b/sources/APU/IPL/IPL.cpp @@ -4,18 +4,15 @@ #include "IPL.hpp" -#include #include "../../Exceptions/InvalidAddress.hpp" +#include namespace ComSquare::APU::IPL { IPL::IPL(Component type, std::string iplName) - : _iplType(type), - _iplName(std::move(iplName)) - { } - - IPL::~IPL() - { } + : _iplType(type), + _iplName(std::move(iplName)) + {} uint8_t IPL::read(uint24_t addr) { @@ -45,4 +42,10 @@ namespace ComSquare::APU::IPL { return this->_iplType; } -} \ No newline at end of file + + std::string IPL::getValueName(uint24_t) const + { + // TODO implement this + return "???"; + } +}// namespace ComSquare::APU::IPL \ No newline at end of file diff --git a/sources/APU/IPL/IPL.hpp b/sources/APU/IPL/IPL.hpp index 94d6f42..333f29f 100644 --- a/sources/APU/IPL/IPL.hpp +++ b/sources/APU/IPL/IPL.hpp @@ -2,10 +2,9 @@ // Created by Melefo on 27/02/2020. // -#ifndef COMSQUARE_IPL_HPP -#define COMSQUARE_IPL_HPP +#pragma once -#include "../../Memory/AMemory.hpp" +#include "Memory/AMemory.hpp" namespace ComSquare::APU::IPL { @@ -31,15 +30,12 @@ namespace ComSquare::APU::IPL public: //! @brief Create the rom with its value. explicit IPL(Component, std::string iplName); - //! @brief The rom can't be copied. IPL(const IPL &) = delete; - //! @brief The rom can't be assigned. IPL &operator=(IPL &) = delete; - - //! @brief Destructor that free the rom. - ~IPL(); + //! @brief A default destructor + ~IPL() override = default; //! @brief Read data from the component using the same method as the basic IMemory. //! @param addr The global 24 bits address. This method is responsible of mapping to the component's read. @@ -55,14 +51,16 @@ namespace ComSquare::APU::IPL //! @brief Get the size of the data. This size can be lower than the mapped data. //! @return The number of bytes inside this memory. - uint24_t getSize() const override; + [[nodiscard]] uint24_t getSize() const override; //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() const override; + [[nodiscard]] std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() const override; - }; -} + [[nodiscard]] Component getComponent() const override; -#endif //COMSQUARE_IPL_HPP \ No newline at end of file + //! @brief Get the name of the data at the address + //! @param addr The address (in local space) + [[nodiscard]] std::string getValueName(uint24_t addr) const override; + }; +} \ No newline at end of file diff --git a/sources/APU/Instructions/DecimalCompensation.cpp b/sources/APU/Instructions/DecimalCompensation.cpp index d93e562..c8bc81b 100644 --- a/sources/APU/Instructions/DecimalCompensation.cpp +++ b/sources/APU/Instructions/DecimalCompensation.cpp @@ -2,7 +2,7 @@ // Created by Melefo on 25/02/2020. // -#include "../APU.hpp" +#include "APU/APU.hpp" namespace ComSquare::APU { @@ -31,4 +31,9 @@ namespace ComSquare::APU this->_setNZflags(this->_internalRegisters.a); return 3; } + std::string APU::getValueName(uint24_t) const + { + // TODO implement this + return "???"; + } } \ No newline at end of file diff --git a/sources/CPU/AddressingModes.cpp b/sources/CPU/AddressingModes.cpp index 3f649c2..7cdd538 100644 --- a/sources/CPU/AddressingModes.cpp +++ b/sources/CPU/AddressingModes.cpp @@ -64,8 +64,8 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectIndexedYAddr() { uint16_t dp = this->readPC() + this->_registers.d; - uint24_t base = this->_bus->read(dp); - base += this->_bus->read(dp + 1) << 8u; + uint24_t base = this->_bus.read(dp); + base += this->_bus.read(dp + 1) << 8u; base += this->_registers.dbr << 16u; if ((base & 0x80000000u) == (((base + this->_registers.y) & 0x80000000u))) this->_hasIndexCrossedPageBoundary = true; @@ -75,9 +75,9 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectIndexedYLongAddr() { uint16_t dp = this->readPC() + this->_registers.d; - uint24_t base = this->_bus->read(dp); - base += this->_bus->read(dp + 1) << 8u; - base += this->_bus->read(dp + 2) << 16u; + uint24_t base = this->_bus.read(dp); + base += this->_bus.read(dp + 1) << 8u; + base += this->_bus.read(dp + 2) << 16u; return base; } @@ -85,8 +85,8 @@ namespace ComSquare::CPU { uint16_t dp = this->readPC() + this->_registers.d; dp += this->_registers.x; - uint24_t base = this->_bus->read(dp); - base += this->_bus->read(dp + 1) << 8u; + uint24_t base = this->_bus.read(dp); + base += this->_bus.read(dp + 1) << 8u; base += this->_registers.dbr << 16u; return base; } @@ -137,8 +137,8 @@ namespace ComSquare::CPU { uint16_t abs = this->readPC(); abs += this->readPC() << 8u; - uint24_t effective = this->_bus->read(abs); - effective += this->_bus->read(abs + 1) << 8u; + uint24_t effective = this->_bus.read(abs); + effective += this->_bus.read(abs + 1) << 8u; return effective; } @@ -146,9 +146,9 @@ namespace ComSquare::CPU { uint16_t abs = this->readPC(); abs += this->readPC() << 8u; - uint24_t effective = this->_bus->read(abs); - effective += this->_bus->read(abs + 1) << 8u; - effective += this->_bus->read(abs + 2) << 16u; + uint24_t effective = this->_bus.read(abs); + effective += this->_bus.read(abs + 1) << 8u; + effective += this->_bus.read(abs + 2) << 16u; return effective; } @@ -157,16 +157,16 @@ namespace ComSquare::CPU uint24_t abs = this->readPC(); abs += this->readPC() << 8u; abs += this->_registers.x; - uint24_t effective = this->_bus->read(abs); - effective += this->_bus->read(abs + 1) << 8u; + uint24_t effective = this->_bus.read(abs); + effective += this->_bus.read(abs + 1) << 8u; return effective; } uint24_t CPU::_getDirectIndirectAddr() { uint16_t dp = this->readPC() + this->_registers.d; - uint24_t effective = this->_bus->read(dp); - effective += this->_bus->read(dp + 1) << 8u; + uint24_t effective = this->_bus.read(dp); + effective += this->_bus.read(dp + 1) << 8u; effective += this->_registers.dbr << 16u; return effective; } @@ -174,9 +174,9 @@ namespace ComSquare::CPU uint24_t CPU::_getDirectIndirectLongAddr() { uint16_t dp = this->readPC() + this->_registers.d; - uint24_t effective = this->_bus->read(dp); - effective += this->_bus->read(++dp) << 8u; - effective += this->_bus->read(++dp) << 16u; + uint24_t effective = this->_bus.read(dp); + effective += this->_bus.read(++dp) << 8u; + effective += this->_bus.read(++dp) << 16u; return effective; } diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 310ba6d..71c7967 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -3,32 +3,21 @@ // #include "CPU.hpp" - -#include +#include "Exceptions/InvalidAddress.hpp" +#include "Exceptions/InvalidOpcode.hpp" +#include "Utility/Utility.hpp" #include -#include "../Exceptions/InvalidAddress.hpp" -#include "../Exceptions/InvalidOpcode.hpp" namespace ComSquare::CPU { - CPU::CPU(std::shared_ptr bus, Cartridge::Header &cartridgeHeader) - : _bus(std::move(bus)), - _cartridgeHeader(cartridgeHeader) + CPU::CPU(Memory::MemoryBus &bus, Cartridge::Header &cartridgeHeader) + : _bus(bus), + _cartridgeHeader(cartridgeHeader), + _dmaChannels({DMA(bus), DMA(bus), DMA(bus), DMA(bus), DMA(bus), DMA(bus), DMA(bus), DMA(bus)}) { this->RESB(); - for (DMA &channel : this->_dmaChannels) - channel.setBus(_bus); } - bool CPU::isDebugger() const - { - return false; - } - - void CPU::setMemoryBus(std::shared_ptr bus) - { - this->_bus = std::move(bus); - } //! @bref The CPU's internal registers starts at $4200 and finish at $421F. uint8_t CPU::read(uint24_t addr) @@ -214,7 +203,7 @@ namespace ComSquare::CPU uint8_t CPU::readPC() { - uint8_t ret = this->_bus->read(this->_registers.pac); + uint8_t ret = this->_bus.read(this->_registers.pac); this->_registers.pc++; return ret; } @@ -251,14 +240,14 @@ namespace ComSquare::CPU if (this->IsNMIRequested) { this->_runInterrupt( - this->_cartridgeHeader.nativeInterrupts.nmi, - this->_cartridgeHeader.emulationInterrupts.nmi); + this->_cartridgeHeader.nativeInterrupts.nmi, + this->_cartridgeHeader.emulationInterrupts.nmi); return; } if (this->IsIRQRequested && !this->_registers.p.i) { this->_runInterrupt( - this->_cartridgeHeader.nativeInterrupts.irq, - this->_cartridgeHeader.emulationInterrupts.irq); + this->_cartridgeHeader.nativeInterrupts.irq, + this->_cartridgeHeader.emulationInterrupts.irq); return; } } @@ -333,24 +322,24 @@ namespace ComSquare::CPU void CPU::_push(uint8_t data) { - this->_bus->write(this->_registers.s--, data); + this->_bus.write(this->_registers.s--, data); } void CPU::_push(uint16_t data) { - this->_bus->write(this->_registers.s--, data >> 8u); - this->_bus->write(this->_registers.s--, data); + this->_bus.write(this->_registers.s--, data >> 8u); + this->_bus.write(this->_registers.s--, data); } uint8_t CPU::_pop() { - return this->_bus->read(++this->_registers.s); + return this->_bus.read(++this->_registers.s); } uint16_t CPU::_pop16() { - uint16_t value = this->_bus->read(++this->_registers.s); - value +=this->_bus->read(++this->_registers.s) << 8u; + uint16_t value = this->_bus.read(++this->_registers.s); + value += this->_bus.read(++this->_registers.s) << 8u; return value; } @@ -363,4 +352,4 @@ namespace ComSquare::CPU { return Cpu; } -} \ No newline at end of file +}// namespace ComSquare::CPU \ No newline at end of file diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 023f407..9ff9827 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -2,8 +2,7 @@ // Created by anonymus-raccoon on 1/24/20. // -#ifndef COMSQUARE_CPU_HPP -#define COMSQUARE_CPU_HPP +#pragma once #include "Memory/AMemory.hpp" #include "Memory/MemoryBus.hpp" @@ -12,180 +11,21 @@ #include "Memory/AMemory.hpp" #include "Instruction.hpp" #include "DMA/DMA.hpp" +#include "CPU/Registers.hpp" +#ifdef DEBUGGER_ENABLED +#include "Debugger/RegisterViewer.hpp" +#endif namespace ComSquare::CPU { - //! @brief Struct containing registers for the main CPU. - struct Registers { - //! @brief The Accumulator - union { - struct { - uint8_t al; - uint8_t ah; - }; - uint16_t a; - }; - //! @brief The Data Bank Register; - uint8_t dbr; - //! @brief The Direct Page register; - union { - struct { - uint8_t dl; - uint8_t dh; - }; - uint16_t d; - }; - union { - struct { - //! @brief The Program Counter; - union { - struct { - uint8_t pcl; - uint8_t pch; - }; - uint16_t pc; - }; - //! @brief The Program Bank Register; - uint8_t pbr; - }; - //! @brief The current Program Address Counter (does not exist in a snes but is useful here). - uint24_t pac; - }; - //! @brief The Stack pointer - union { - struct { - uint8_t sl; - uint8_t sh; - }; - uint16_t s; - }; - //! @brief The X index register - union { - struct { - uint8_t xl; - uint8_t xh; - }; - uint16_t x; - }; - //! @brief The Y index register - union { - struct { - uint8_t yl; - uint8_t yh; - }; - uint16_t y; - }; - - //! @brief The Processor status register; - union { - struct { - //! @brief The Carry flag - bool c : 1; - //! @brief The Zero flag - bool z : 1; - //! @brief The Interrupt request disable flag - bool i : 1; - //! @brief The Decimal mode flag - bool d : 1; - //! @brief The indeX register width flag (in native mode only) - 0 = 16 bits mode, 1 = 8 bits mode OR the Break flag (in emulation mode only) - bool x_b : 1; - //! @brief The accumulator and Memory width flag (in native mode only) - 0 = 16 bits mode, 1 = 8 bits mode. - bool m : 1; - //! @brief The oVerflow flag - bool v : 1; - //! @brief The Negative flag - bool n : 1; - }; - uint8_t flags; - } p; - }; - - //! @brief Struct containing internal registers of the CPU. - struct InternalRegisters - { - //! @brief Interrupt Enable Register - uint8_t nmitimen; - - //! @brief IO Port Write Register - uint8_t wrio; - - //! @brief Multiplicand Register A - uint8_t wrmpya; - //! @brief Multiplicand Register B - uint8_t wrmpyb; - - //! @brief Divisor & Dividend Registers (A - Low) - uint8_t wrdivl; - //! @brief Divisor & Dividend Registers (A - High) - uint8_t wrdivh; - //! @brief Divisor & Dividend Registers (B) - uint8_t wrdivb; - - //! @brief IRQ Timer Registers (Horizontal - Low) - uint8_t htimel; - //! @brief IRQ Timer Registers (Horizontal - High) - uint8_t htimeh; - - //! @brief IRQ Timer Registers (Vertical - Low) - uint8_t vtimel; - //! @brief IRQ Timer Registers (Vertical - High) - uint8_t vtimeh; - - //! @brief HDMA Enable Register - uint8_t hdmaen; - - //! @brief ROM Speed Register - uint8_t memsel; - - //! @brief Interrupt Flag Registers - uint8_t rdnmi; - //! @brief Interrupt Flag Registers - TimeUp - uint8_t timeup; - - //! @brief PPU Status Register - uint8_t hvbjoy; - - //! @brief IO Port Read Register - uint8_t rdio; - - //! @brief Divide Result Registers (can sometimes be used as multiplication result register) - LOW - uint8_t rddivl; - //! @brief Divide Result Registers (can sometimes be used as multiplication result register) - HIGH - uint8_t rddivh; - - //! @brief Multiplication Result Registers (can sometimes be used as divide result register) - LOW - uint8_t rdmpyl; - //! @brief Multiplication Result Registers (can sometimes be used as divide result register) - HIGH - uint8_t rdmpyh; - - //! @brief Controller Port Data Registers (Pad 1 - Low) - uint8_t joy1l; - //! @brief Controller Port Data Registers (Pad 1 - High) - uint8_t joy1h; - - //! @brief Controller Port Data Registers (Pad 2 - Low) - uint8_t joy2l; - //! @brief Controller Port Data Registers (Pad 2 - High) - uint8_t joy2h; - - //! @brief Controller Port Data Registers (Pad 3 - Low) - uint8_t joy3l; - //! @brief Controller Port Data Registers (Pad 3 - High) - uint8_t joy3h; - - //! @brief Controller Port Data Registers (Pad 4 - Low) - uint8_t joy4l; - //! @brief Controller Port Data Registers (Pad 4 - High) - uint8_t joy4h; - }; - //! @brief The main CPU - class CPU : public Memory::AMemory { + class CPU : public Memory::AMemory + { protected: //! @brief All the registers of the CPU - Registers _registers{}; + Registers _registers {}; //! @brief Internal registers of the CPU (accessible from the bus via addr $4200 to $421F). - InternalRegisters _internalRegisters{}; + InternalRegisters _internalRegisters {}; //! @brief Is the CPU running in emulation mode (in 8bits) bool _isEmulationMode = true; @@ -195,8 +35,8 @@ namespace ComSquare::CPU bool _isWaitingForInterrupt = false; //! @brief The memory bus to use for read/write. - std::shared_ptr _bus; - //! @brief The cartridge header (stored for interrupt vectors.. + Memory::MemoryBus &_bus; + //! @brief The cartridge header (stored for interrupt vectors..) Cartridge::Header &_cartridgeHeader; //! @brief DMA channels witch are mapped to the bus. @@ -250,7 +90,6 @@ namespace ComSquare::CPU //! @brief The <8-bit exp> is added to S and combined with DBR to form the base address. Y is added to the base address to form the effective address. uint24_t _getStackRelativeIndirectIndexedYAddr(); - //! @brief Push 8 bits of data to the stack. void _push(uint8_t data); //! @brief Push 16 bits of data to the stack. @@ -470,273 +309,279 @@ namespace ComSquare::CPU //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode - Instruction _instructions[0x100] = { - {&CPU::BRK, 7, "brk", AddressingMode::Immediate8bits, 2}, // 00 - {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 01 - {&CPU::COP, 7, "cop", AddressingMode::Immediate8bits, 2}, // 02 - {&CPU::ORA, 4, "ora", AddressingMode::StackRelative, 2}, // 03 - {&CPU::TSB, 5, "tsb", AddressingMode::DirectPage, 2}, // 04 - {&CPU::ORA, 3, "ora", AddressingMode::DirectPage, 2}, // 05 - {&CPU::ASL, 5, "asl", AddressingMode::DirectPage, 2}, // 06 - {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectLong, 2}, // 07 - {&CPU::PHP, 3, "php", AddressingMode::Implied, 1}, // 08 - {&CPU::ORA, 2, "ora", AddressingMode::ImmediateForA, 2}, // 09 - {&CPU::ASL, 2, "asl", AddressingMode::Implied, 1}, // 0A - {&CPU::PHD, 4, "phd", AddressingMode::Implied, 1}, // 0B - {&CPU::TSB, 6, "tsb", AddressingMode::Absolute, 3}, // 0C - {&CPU::ORA, 3, "ora", AddressingMode::Absolute, 4}, // 0D - {&CPU::ASL, 6, "asl", AddressingMode::Absolute, 3}, // 0E - {&CPU::ORA, 5, "ora", AddressingMode::AbsoluteLong, 5}, // 0F - {&CPU::BPL, 7, "bpl", AddressingMode::Immediate8bits, 2}, // 10 - {&CPU::ORA, 5, "ora", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 11 - {&CPU::ORA, 5, "ora", AddressingMode::DirectPageIndirect, 2}, // 12 - {&CPU::ORA, 7, "ora", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 13 - {&CPU::TRB, 5, "trb", AddressingMode::DirectPage, 2}, // 14 - {&CPU::ORA, 4, "ora", AddressingMode::DirectPageIndexedByX, 2}, // 15 - {&CPU::ASL, 6, "asl", AddressingMode::DirectPageIndexedByX, 2}, // 16 + const Instruction _instructions[0x100] = { + {&CPU::BRK, 7, "brk", AddressingMode::Immediate8bits, 2}, // 00 + {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 01 + {&CPU::COP, 7, "cop", AddressingMode::Immediate8bits, 2}, // 02 + {&CPU::ORA, 4, "ora", AddressingMode::StackRelative, 2}, // 03 + {&CPU::TSB, 5, "tsb", AddressingMode::DirectPage, 2}, // 04 + {&CPU::ORA, 3, "ora", AddressingMode::DirectPage, 2}, // 05 + {&CPU::ASL, 5, "asl", AddressingMode::DirectPage, 2}, // 06 + {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectLong, 2}, // 07 + {&CPU::PHP, 3, "php", AddressingMode::Implied, 1}, // 08 + {&CPU::ORA, 2, "ora", AddressingMode::ImmediateForA, 2}, // 09 + {&CPU::ASL, 2, "asl", AddressingMode::Implied, 1}, // 0A + {&CPU::PHD, 4, "phd", AddressingMode::Implied, 1}, // 0B + {&CPU::TSB, 6, "tsb", AddressingMode::Absolute, 3}, // 0C + {&CPU::ORA, 3, "ora", AddressingMode::Absolute, 4}, // 0D + {&CPU::ASL, 6, "asl", AddressingMode::Absolute, 3}, // 0E + {&CPU::ORA, 5, "ora", AddressingMode::AbsoluteLong, 5}, // 0F + {&CPU::BPL, 7, "bpl", AddressingMode::Immediate8bits, 2}, // 10 + {&CPU::ORA, 5, "ora", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 11 + {&CPU::ORA, 5, "ora", AddressingMode::DirectPageIndirect, 2}, // 12 + {&CPU::ORA, 7, "ora", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 13 + {&CPU::TRB, 5, "trb", AddressingMode::DirectPage, 2}, // 14 + {&CPU::ORA, 4, "ora", AddressingMode::DirectPageIndexedByX, 2}, // 15 + {&CPU::ASL, 6, "asl", AddressingMode::DirectPageIndexedByX, 2}, // 16 {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 17 - {&CPU::CLC, 2, "clc", AddressingMode::Implied, 1}, // 18 - {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByY, 3}, // 19 - {&CPU::INC, 2, "inc", AddressingMode::Implied, 1}, // 1A - {&CPU::TCS, 2, "tcs", AddressingMode::Implied, 1}, // 1B - {&CPU::TRB, 6, "trb", AddressingMode::Absolute, 3}, // 1C - {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByX, 3}, // 1D - {&CPU::ASL, 7, "asl", AddressingMode::AbsoluteIndexedByX, 3}, // 1E - {&CPU::ORA, 5, "ora", AddressingMode::AbsoluteIndexedByXLong, 4}, // 1F - {&CPU::JSR, 6, "jsr", AddressingMode::Absolute, 3}, // 20 - {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 21 - {&CPU::JSL, 8, "jsl", AddressingMode::AbsoluteLong, 4}, // 22 - {&CPU::AND, 4, "and", AddressingMode::StackRelative, 2}, // 23 - {&CPU::BIT, 3, "bit", AddressingMode::DirectPage, 2}, // 24 - {&CPU::AND, 3, "and", AddressingMode::DirectPage, 2}, // 25 - {&CPU::ROL, 5, "rol", AddressingMode::DirectPage, 2}, // 26 - {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectLong, 2}, // 27 - {&CPU::PLP, 4, "plp", AddressingMode::Implied, 1}, // 28 - {&CPU::AND, 2, "and", AddressingMode::ImmediateForA, 2}, // 29 - {&CPU::ROL, 2, "rol", AddressingMode::Implied, 1}, // 2A - {&CPU::PLD, 5, "pld", AddressingMode::Implied, 1}, // 2B - {&CPU::BIT, 4, "bit", AddressingMode::Absolute, 3}, // 2C - {&CPU::AND, 4, "and", AddressingMode::Absolute, 3}, // 2D - {&CPU::ROL, 6, "rol", AddressingMode::Absolute, 3}, // 2E - {&CPU::AND, 5, "and", AddressingMode::AbsoluteLong, 4}, // 2F - {&CPU::BMI, 2, "bmi", AddressingMode::Immediate8bits, 2}, // 30 - {&CPU::AND, 5, "and", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 31 - {&CPU::AND, 5, "and", AddressingMode::DirectPageIndirect, 2}, // 32 - {&CPU::AND, 7, "and", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 33 - {&CPU::BIT, 4, "bit", AddressingMode::DirectPageIndexedByX, 2}, // 34 - {&CPU::AND, 4, "and", AddressingMode::DirectPageIndexedByX, 2}, // 35 - {&CPU::ROL, 6, "rol", AddressingMode::DirectPageIndexedByX, 2}, // 36 + {&CPU::CLC, 2, "clc", AddressingMode::Implied, 1}, // 18 + {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByY, 3}, // 19 + {&CPU::INC, 2, "inc", AddressingMode::Implied, 1}, // 1A + {&CPU::TCS, 2, "tcs", AddressingMode::Implied, 1}, // 1B + {&CPU::TRB, 6, "trb", AddressingMode::Absolute, 3}, // 1C + {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByX, 3}, // 1D + {&CPU::ASL, 7, "asl", AddressingMode::AbsoluteIndexedByX, 3}, // 1E + {&CPU::ORA, 5, "ora", AddressingMode::AbsoluteIndexedByXLong, 4}, // 1F + {&CPU::JSR, 6, "jsr", AddressingMode::Absolute, 3}, // 20 + {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 21 + {&CPU::JSL, 8, "jsl", AddressingMode::AbsoluteLong, 4}, // 22 + {&CPU::AND, 4, "and", AddressingMode::StackRelative, 2}, // 23 + {&CPU::BIT, 3, "bit", AddressingMode::DirectPage, 2}, // 24 + {&CPU::AND, 3, "and", AddressingMode::DirectPage, 2}, // 25 + {&CPU::ROL, 5, "rol", AddressingMode::DirectPage, 2}, // 26 + {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectLong, 2}, // 27 + {&CPU::PLP, 4, "plp", AddressingMode::Implied, 1}, // 28 + {&CPU::AND, 2, "and", AddressingMode::ImmediateForA, 2}, // 29 + {&CPU::ROL, 2, "rol", AddressingMode::Implied, 1}, // 2A + {&CPU::PLD, 5, "pld", AddressingMode::Implied, 1}, // 2B + {&CPU::BIT, 4, "bit", AddressingMode::Absolute, 3}, // 2C + {&CPU::AND, 4, "and", AddressingMode::Absolute, 3}, // 2D + {&CPU::ROL, 6, "rol", AddressingMode::Absolute, 3}, // 2E + {&CPU::AND, 5, "and", AddressingMode::AbsoluteLong, 4}, // 2F + {&CPU::BMI, 2, "bmi", AddressingMode::Immediate8bits, 2}, // 30 + {&CPU::AND, 5, "and", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 31 + {&CPU::AND, 5, "and", AddressingMode::DirectPageIndirect, 2}, // 32 + {&CPU::AND, 7, "and", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 33 + {&CPU::BIT, 4, "bit", AddressingMode::DirectPageIndexedByX, 2}, // 34 + {&CPU::AND, 4, "and", AddressingMode::DirectPageIndexedByX, 2}, // 35 + {&CPU::ROL, 6, "rol", AddressingMode::DirectPageIndexedByX, 2}, // 36 {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 37 - {&CPU::SEC, 2, "sec", AddressingMode::Implied, 1}, // 38 - {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByY, 3}, // 39 - {&CPU::DEC, 2, "dec", AddressingMode::Implied, 1}, // 3A - {&CPU::TSC, 2, "tsc", AddressingMode::Implied, 1}, // 3B - {&CPU::BIT, 4, "bit", AddressingMode::AbsoluteIndexedByX, 3}, // 3C - {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByX, 3}, // 3D - {&CPU::ROL, 7, "rol", AddressingMode::AbsoluteIndexedByX, 3}, // 3E - {&CPU::AND, 5, "and", AddressingMode::AbsoluteIndexedByXLong, 4}, // 3F - {&CPU::RTI, 6, "rti", AddressingMode::Implied, 1}, // 40 - {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41 - {&CPU::WDM, 2, "wdm", AddressingMode::Immediate8bits, 2}, // 42 - {&CPU::EOR, 4, "eor", AddressingMode::StackRelative, 2}, // 43 - {&CPU::MVP, 0, "mvp", AddressingMode::Immediate16bits, 3}, // 44 - {&CPU::EOR, 3, "eor", AddressingMode::DirectPage, 2}, // 45 - {&CPU::LSR, 5, "lsr", AddressingMode::DirectPage, 2}, // 46 - {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectLong, 2}, // 47 - {&CPU::PHA, 3, "pha", AddressingMode::Implied, 1}, // 48 - {&CPU::EOR, 2, "eor", AddressingMode::ImmediateForA, 2}, // 49 - {&CPU::LSR, 2, "lsr", AddressingMode::Implied, 1}, // 4A - {&CPU::PHK, 3, "phk", AddressingMode::Implied, 1}, // 4B - {&CPU::JMP, 3, "jmp", AddressingMode::Absolute, 3}, // 4C - {&CPU::EOR, 4, "eor", AddressingMode::Absolute, 3}, // 4D - {&CPU::LSR, 6, "lsr", AddressingMode::Absolute, 3}, // 4E - {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteLong, 4}, // 4F - {&CPU::BVC, 2, "bvc", AddressingMode::Immediate8bits, 2}, // 50 - {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 51 - {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirect, 2}, // 52 - {&CPU::EOR, 4, "eor", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 53 - {&CPU::MVN, 0, "mvn", AddressingMode::Immediate16bits, 2}, // 54 - {&CPU::EOR, 4, "eor", AddressingMode::DirectPageIndexedByX, 2}, // 55 - {&CPU::LSR, 6, "lsr", AddressingMode::DirectPageIndexedByX, 2}, // 56 + {&CPU::SEC, 2, "sec", AddressingMode::Implied, 1}, // 38 + {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByY, 3}, // 39 + {&CPU::DEC, 2, "dec", AddressingMode::Implied, 1}, // 3A + {&CPU::TSC, 2, "tsc", AddressingMode::Implied, 1}, // 3B + {&CPU::BIT, 4, "bit", AddressingMode::AbsoluteIndexedByX, 3}, // 3C + {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByX, 3}, // 3D + {&CPU::ROL, 7, "rol", AddressingMode::AbsoluteIndexedByX, 3}, // 3E + {&CPU::AND, 5, "and", AddressingMode::AbsoluteIndexedByXLong, 4}, // 3F + {&CPU::RTI, 6, "rti", AddressingMode::Implied, 1}, // 40 + {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41 + {&CPU::WDM, 2, "wdm", AddressingMode::Immediate8bits, 2}, // 42 + {&CPU::EOR, 4, "eor", AddressingMode::StackRelative, 2}, // 43 + {&CPU::MVP, 0, "mvp", AddressingMode::Immediate16bits, 3}, // 44 + {&CPU::EOR, 3, "eor", AddressingMode::DirectPage, 2}, // 45 + {&CPU::LSR, 5, "lsr", AddressingMode::DirectPage, 2}, // 46 + {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectLong, 2}, // 47 + {&CPU::PHA, 3, "pha", AddressingMode::Implied, 1}, // 48 + {&CPU::EOR, 2, "eor", AddressingMode::ImmediateForA, 2}, // 49 + {&CPU::LSR, 2, "lsr", AddressingMode::Implied, 1}, // 4A + {&CPU::PHK, 3, "phk", AddressingMode::Implied, 1}, // 4B + {&CPU::JMP, 3, "jmp", AddressingMode::Absolute, 3}, // 4C + {&CPU::EOR, 4, "eor", AddressingMode::Absolute, 3}, // 4D + {&CPU::LSR, 6, "lsr", AddressingMode::Absolute, 3}, // 4E + {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteLong, 4}, // 4F + {&CPU::BVC, 2, "bvc", AddressingMode::Immediate8bits, 2}, // 50 + {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 51 + {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirect, 2}, // 52 + {&CPU::EOR, 4, "eor", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 53 + {&CPU::MVN, 0, "mvn", AddressingMode::Immediate16bits, 2}, // 54 + {&CPU::EOR, 4, "eor", AddressingMode::DirectPageIndexedByX, 2}, // 55 + {&CPU::LSR, 6, "lsr", AddressingMode::DirectPageIndexedByX, 2}, // 56 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 57 - {&CPU::CLI, 2, "cli", AddressingMode::Implied, 1}, // 58 - {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByY, 3}, // 59 - {&CPU::PHY, 3, "phy", AddressingMode::Implied, 1}, // 5A - {&CPU::TCD, 2, "tcd", AddressingMode::Implied, 1}, // 5B - {&CPU::JML, 4, "jml", AddressingMode::Implied, 4}, // 5C - {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByX, 3}, // 5D - {&CPU::LSR, 7, "lsr", AddressingMode::AbsoluteIndexedByX, 3}, // 5E - {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteIndexedByXLong, 4}, // 5F - {&CPU::RTS, 6, "rts", AddressingMode::Implied, 1}, // 60 - {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 61 - {&CPU::PER, 6, "per", AddressingMode::Immediate16bits, 3}, // 62 - {&CPU::ADC, 4, "adc", AddressingMode::StackRelative, 2}, // 63 - {&CPU::STZ, 3, "stz", AddressingMode::DirectPage, 2}, // 64 - {&CPU::ADC, 3, "adc", AddressingMode::DirectPage, 2}, // 65 - {&CPU::ROR, 5, "ror", AddressingMode::DirectPage, 2}, // 66 - {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectLong, 2}, // 67 - {&CPU::PLA, 4, "pla", AddressingMode::Implied, 1}, // 68 - {&CPU::ADC, 2, "adc", AddressingMode::ImmediateForA, 2}, // 69 - {&CPU::ROR, 2, "ror", AddressingMode::Implied, 1}, // 6A - {&CPU::RTL, 6, "rtl", AddressingMode::Implied, 1}, // 6B - {&CPU::JMP, 5, "jmp", AddressingMode::AbsoluteIndirect, 3}, // 6C - {&CPU::ADC, 4, "adc", AddressingMode::Absolute, 3}, // 6D - {&CPU::ROR, 6, "ror", AddressingMode::Absolute, 3}, // 6E - {&CPU::ADC, 5, "adc", AddressingMode::AbsoluteLong, 4}, // 6F - {&CPU::BVS, 2, "bvs", AddressingMode::Immediate8bits, 2}, // 70 - {&CPU::ADC, 5, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 71 - {&CPU::ADC, 5, "adc", AddressingMode::DirectPageIndirect, 2}, // 72 - {&CPU::ADC, 7, "adc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 73 - {&CPU::STZ, 4, "stz", AddressingMode::DirectPageIndexedByX, 2}, // 74 - {&CPU::ADC, 4, "adc", AddressingMode::DirectPageIndexedByX, 2}, // 75 - {&CPU::ROR, 6, "ror", AddressingMode::DirectPageIndexedByX, 2}, // 76 - {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 77 - {&CPU::SEI, 2, "sei", AddressingMode::Implied, 1}, // 78 - {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByY, 2}, // 79 - {&CPU::PLY, 4, "ply", AddressingMode::Implied, 1}, // 7A - {&CPU::TDC, 2, "tdc", AddressingMode::Implied, 1}, // 7B - {&CPU::JMP, 6, "jmp", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // 7C - {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByX, 3}, // 7D - {&CPU::ROR, 7, "ror", AddressingMode::AbsoluteIndexedByX, 3}, // 7E - {&CPU::ADC, 5, "adc", AddressingMode::AbsoluteIndexedByXLong, 4}, // 7F - {&CPU::BRA, 3, "bra", AddressingMode::Immediate8bits, 2}, // 80 - {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 81 - {&CPU::BRL, 4, "brl", AddressingMode::Absolute, 3}, // 82 - {&CPU::STA, 4, "sta", AddressingMode::StackRelative, 2}, // 83 - {&CPU::STY, 3, "sty", AddressingMode::DirectPage, 2}, // 84 - {&CPU::STA, 3, "sta", AddressingMode::DirectPage, 2}, // 85 - {&CPU::STX, 3, "stx", AddressingMode::DirectPage, 2}, // 86 - {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectLong, 2}, // 87 - {&CPU::DEY, 2, "dey", AddressingMode::Implied, 1}, // 88 - {&CPU::BIT, 2, "bit", AddressingMode::ImmediateForA, 2}, // 89 - {&CPU::TXA, 2, "txa", AddressingMode::Implied, 2}, // 8A - {&CPU::PHB, 3, "phb", AddressingMode::Implied, 1}, // 8B - {&CPU::STY, 4, "sty", AddressingMode::Absolute, 3}, // 8C - {&CPU::STA, 4, "sta", AddressingMode::Absolute, 3}, // 8D - {&CPU::STX, 4, "stx", AddressingMode::Absolute, 3}, // 8E - {&CPU::STA, 5, "sta", AddressingMode::AbsoluteLong, 4}, // 8F - {&CPU::BCC, 2, "bcc", AddressingMode::Immediate8bits, 2}, // 90 - {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 91 - {&CPU::STA, 5, "sta", AddressingMode::DirectPageIndirect, 2}, // 92 - {&CPU::STA, 7, "sta", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 93 - {&CPU::STY, 4, "sty", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 94 - {&CPU::STA, 4, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 95 - {&CPU::STX, 4, "stx", AddressingMode::DirectPageIndexedByY, 2}, // 96 + {&CPU::CLI, 2, "cli", AddressingMode::Implied, 1}, // 58 + {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByY, 3}, // 59 + {&CPU::PHY, 3, "phy", AddressingMode::Implied, 1}, // 5A + {&CPU::TCD, 2, "tcd", AddressingMode::Implied, 1}, // 5B + {&CPU::JML, 4, "jml", AddressingMode::Implied, 4}, // 5C + {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByX, 3}, // 5D + {&CPU::LSR, 7, "lsr", AddressingMode::AbsoluteIndexedByX, 3}, // 5E + {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteIndexedByXLong, 4}, // 5F + {&CPU::RTS, 6, "rts", AddressingMode::Implied, 1}, // 60 + {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 61 + {&CPU::PER, 6, "per", AddressingMode::Immediate16bits, 3}, // 62 + {&CPU::ADC, 4, "adc", AddressingMode::StackRelative, 2}, // 63 + {&CPU::STZ, 3, "stz", AddressingMode::DirectPage, 2}, // 64 + {&CPU::ADC, 3, "adc", AddressingMode::DirectPage, 2}, // 65 + {&CPU::ROR, 5, "ror", AddressingMode::DirectPage, 2}, // 66 + {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectLong, 2}, // 67 + {&CPU::PLA, 4, "pla", AddressingMode::Implied, 1}, // 68 + {&CPU::ADC, 2, "adc", AddressingMode::ImmediateForA, 2}, // 69 + {&CPU::ROR, 2, "ror", AddressingMode::Implied, 1}, // 6A + {&CPU::RTL, 6, "rtl", AddressingMode::Implied, 1}, // 6B + {&CPU::JMP, 5, "jmp", AddressingMode::AbsoluteIndirect, 3}, // 6C + {&CPU::ADC, 4, "adc", AddressingMode::Absolute, 3}, // 6D + {&CPU::ROR, 6, "ror", AddressingMode::Absolute, 3}, // 6E + {&CPU::ADC, 5, "adc", AddressingMode::AbsoluteLong, 4}, // 6F + {&CPU::BVS, 2, "bvs", AddressingMode::Immediate8bits, 2}, // 70 + {&CPU::ADC, 5, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 71 + {&CPU::ADC, 5, "adc", AddressingMode::DirectPageIndirect, 2}, // 72 + {&CPU::ADC, 7, "adc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 73 + {&CPU::STZ, 4, "stz", AddressingMode::DirectPageIndexedByX, 2}, // 74 + {&CPU::ADC, 4, "adc", AddressingMode::DirectPageIndexedByX, 2}, // 75 + {&CPU::ROR, 6, "ror", AddressingMode::DirectPageIndexedByX, 2}, // 76 + {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 77 + {&CPU::SEI, 2, "sei", AddressingMode::Implied, 1}, // 78 + {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByY, 2}, // 79 + {&CPU::PLY, 4, "ply", AddressingMode::Implied, 1}, // 7A + {&CPU::TDC, 2, "tdc", AddressingMode::Implied, 1}, // 7B + {&CPU::JMP, 6, "jmp", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // 7C + {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByX, 3}, // 7D + {&CPU::ROR, 7, "ror", AddressingMode::AbsoluteIndexedByX, 3}, // 7E + {&CPU::ADC, 5, "adc", AddressingMode::AbsoluteIndexedByXLong, 4}, // 7F + {&CPU::BRA, 3, "bra", AddressingMode::Immediate8bits, 2}, // 80 + {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 81 + {&CPU::BRL, 4, "brl", AddressingMode::Absolute, 3}, // 82 + {&CPU::STA, 4, "sta", AddressingMode::StackRelative, 2}, // 83 + {&CPU::STY, 3, "sty", AddressingMode::DirectPage, 2}, // 84 + {&CPU::STA, 3, "sta", AddressingMode::DirectPage, 2}, // 85 + {&CPU::STX, 3, "stx", AddressingMode::DirectPage, 2}, // 86 + {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectLong, 2}, // 87 + {&CPU::DEY, 2, "dey", AddressingMode::Implied, 1}, // 88 + {&CPU::BIT, 2, "bit", AddressingMode::ImmediateForA, 2}, // 89 + {&CPU::TXA, 2, "txa", AddressingMode::Implied, 2}, // 8A + {&CPU::PHB, 3, "phb", AddressingMode::Implied, 1}, // 8B + {&CPU::STY, 4, "sty", AddressingMode::Absolute, 3}, // 8C + {&CPU::STA, 4, "sta", AddressingMode::Absolute, 3}, // 8D + {&CPU::STX, 4, "stx", AddressingMode::Absolute, 3}, // 8E + {&CPU::STA, 5, "sta", AddressingMode::AbsoluteLong, 4}, // 8F + {&CPU::BCC, 2, "bcc", AddressingMode::Immediate8bits, 2}, // 90 + {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 91 + {&CPU::STA, 5, "sta", AddressingMode::DirectPageIndirect, 2}, // 92 + {&CPU::STA, 7, "sta", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 93 + {&CPU::STY, 4, "sty", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 94 + {&CPU::STA, 4, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 95 + {&CPU::STX, 4, "stx", AddressingMode::DirectPageIndexedByY, 2}, // 96 {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 97 - {&CPU::TYA, 2, "tya", AddressingMode::Implied, 1}, // 98 - {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByY, 3}, // 99 - {&CPU::TXS, 2, "txs", AddressingMode::Implied, 1}, // 9A - {&CPU::TXY, 2, "txy", AddressingMode::Implied, 1}, // 9B - {&CPU::STZ, 4, "stz", AddressingMode::Absolute, 3}, // 9C - {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByX, 3}, // 9D - {&CPU::STZ, 5, "stz", AddressingMode::AbsoluteIndexedByX, 3}, // 9E - {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByXLong, 4}, // 9F - {&CPU::LDY, 2, "ldy", AddressingMode::ImmediateForX, 2}, // A0 - {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectIndexedByX, 2}, // A1 - {&CPU::LDX, 2, "ldx", AddressingMode::ImmediateForX, 2}, // A2 - {&CPU::LDA, 4, "lda", AddressingMode::StackRelative, 2}, // A3 - {&CPU::LDY, 3, "ldy", AddressingMode::DirectPage, 2}, // A4 - {&CPU::LDA, 3, "lda", AddressingMode::DirectPage, 2}, // A5 - {&CPU::LDX, 3, "ldx", AddressingMode::DirectPage, 2}, // A6 - {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectLong, 2}, // A7 - {&CPU::TAY, 2, "tay", AddressingMode::Implied, 1}, // A8 - {&CPU::LDA, 2, "lda", AddressingMode::ImmediateForA, 2}, // A9 - {&CPU::TAX, 2, "tax", AddressingMode::Implied, 1}, // AA - {&CPU::PLB, 4, "plb", AddressingMode::Implied, 1}, // AB - {&CPU::LDY, 4, "ldy", AddressingMode::Absolute, 4}, // AC - {&CPU::LDA, 4, "lda", AddressingMode::Absolute, 3}, // AD - {&CPU::LDX, 4, "ldx", AddressingMode::Absolute, 3}, // AE - {&CPU::LDA, 5, "lda", AddressingMode::AbsoluteLong, 4}, // AF - {&CPU::BCS, 2, "bcs", AddressingMode::Immediate8bits, 2}, // B0 - {&CPU::LDA, 5, "lda", AddressingMode::DirectPageIndirectIndexedByY, 2}, // B1 - {&CPU::LDA, 5, "lda", AddressingMode::DirectPageIndirect, 2}, // B2 - {&CPU::LDA, 7, "lda", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // B3 - {&CPU::LDY, 4, "ldy", AddressingMode::DirectPageIndexedByX, 2}, // B4 - {&CPU::LDA, 4, "lda", AddressingMode::DirectPageIndexedByX, 2}, // B5 - {&CPU::LDX, 4, "ldx", AddressingMode::DirectPageIndexedByY, 2}, // B6 + {&CPU::TYA, 2, "tya", AddressingMode::Implied, 1}, // 98 + {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByY, 3}, // 99 + {&CPU::TXS, 2, "txs", AddressingMode::Implied, 1}, // 9A + {&CPU::TXY, 2, "txy", AddressingMode::Implied, 1}, // 9B + {&CPU::STZ, 4, "stz", AddressingMode::Absolute, 3}, // 9C + {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByX, 3}, // 9D + {&CPU::STZ, 5, "stz", AddressingMode::AbsoluteIndexedByX, 3}, // 9E + {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByXLong, 4}, // 9F + {&CPU::LDY, 2, "ldy", AddressingMode::ImmediateForX, 2}, // A0 + {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectIndexedByX, 2}, // A1 + {&CPU::LDX, 2, "ldx", AddressingMode::ImmediateForX, 2}, // A2 + {&CPU::LDA, 4, "lda", AddressingMode::StackRelative, 2}, // A3 + {&CPU::LDY, 3, "ldy", AddressingMode::DirectPage, 2}, // A4 + {&CPU::LDA, 3, "lda", AddressingMode::DirectPage, 2}, // A5 + {&CPU::LDX, 3, "ldx", AddressingMode::DirectPage, 2}, // A6 + {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectLong, 2}, // A7 + {&CPU::TAY, 2, "tay", AddressingMode::Implied, 1}, // A8 + {&CPU::LDA, 2, "lda", AddressingMode::ImmediateForA, 2}, // A9 + {&CPU::TAX, 2, "tax", AddressingMode::Implied, 1}, // AA + {&CPU::PLB, 4, "plb", AddressingMode::Implied, 1}, // AB + {&CPU::LDY, 4, "ldy", AddressingMode::Absolute, 4}, // AC + {&CPU::LDA, 4, "lda", AddressingMode::Absolute, 3}, // AD + {&CPU::LDX, 4, "ldx", AddressingMode::Absolute, 3}, // AE + {&CPU::LDA, 5, "lda", AddressingMode::AbsoluteLong, 4}, // AF + {&CPU::BCS, 2, "bcs", AddressingMode::Immediate8bits, 2}, // B0 + {&CPU::LDA, 5, "lda", AddressingMode::DirectPageIndirectIndexedByY, 2}, // B1 + {&CPU::LDA, 5, "lda", AddressingMode::DirectPageIndirect, 2}, // B2 + {&CPU::LDA, 7, "lda", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // B3 + {&CPU::LDY, 4, "ldy", AddressingMode::DirectPageIndexedByX, 2}, // B4 + {&CPU::LDA, 4, "lda", AddressingMode::DirectPageIndexedByX, 2}, // B5 + {&CPU::LDX, 4, "ldx", AddressingMode::DirectPageIndexedByY, 2}, // B6 {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // B7 - {&CPU::CLV, 7, "clv", AddressingMode::Implied, 1}, // B8 - {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByY, 3}, // B9 - {&CPU::TSX, 2, "tsx", AddressingMode::Implied, 1}, // BA - {&CPU::TYX, 2, "tyx", AddressingMode::Implied, 1}, // BB - {&CPU::LDY, 4, "ldy", AddressingMode::AbsoluteIndexedByX, 3}, // BC - {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByX, 3}, // BD - {&CPU::LDX, 4, "ldx", AddressingMode::AbsoluteIndexedByY, 3}, // BE - {&CPU::LDA, 5, "lda", AddressingMode::AbsoluteIndexedByXLong, 4}, // BF - {&CPU::CPY, 2, "cpy", AddressingMode::ImmediateForX, 2}, // C0 - {&CPU::CMP, 6, "cmp", AddressingMode::DirectPageIndirectIndexedByX, 2}, // C1 - {&CPU::REP, 3, "rep", AddressingMode::Immediate8bits, 2}, // C2 - {&CPU::CMP, 4, "cmp", AddressingMode::StackRelative, 2}, // C3 - {&CPU::CPY, 3, "cpy", AddressingMode::DirectPage, 2}, // C4 - {&CPU::CMP, 3, "cmp", AddressingMode::DirectPage, 2}, // C5 - {&CPU::DEC, 5, "dec", AddressingMode::DirectPage, 2}, // C6 - {&CPU::CMP, 6, "cmp", AddressingMode::DirectPageIndirectLong, 2}, // C7 - {&CPU::INY, 2, "iny", AddressingMode::Implied, 1}, // C8 - {&CPU::CMP, 2, "cmp", AddressingMode::ImmediateForA, 2}, // C9 - {&CPU::DEX, 2, "dex", AddressingMode::Implied, 1}, // CA - {&CPU::WAI, 3, "wai", AddressingMode::Implied, 1}, // CB - {&CPU::CPY, 4, "cpy", AddressingMode::Absolute, 3}, // CC - {&CPU::CMP, 4, "cmp", AddressingMode::Absolute, 3}, // CD - {&CPU::DEC, 6, "dec", AddressingMode::Absolute, 3}, // CE - {&CPU::CMP, 6, "cmp", AddressingMode::AbsoluteLong, 4}, // CF - {&CPU::BNE, 2, "bne", AddressingMode::Immediate8bits, 2}, // D0 - {&CPU::CMP, 5, "cmp", AddressingMode::DirectPageIndirectIndexedByY, 2}, // D1 - {&CPU::CMP, 5, "cmp", AddressingMode::DirectPageIndirect, 2}, // D2 - {&CPU::CMP, 7, "cmp", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // D3 - {&CPU::PEI, 6, "pei", AddressingMode::DirectPage, 2}, // D4 - {&CPU::CMP, 4, "cmp", AddressingMode::DirectPageIndexedByX, 2}, // D5 - {&CPU::DEC, 6, "dec", AddressingMode::DirectPageIndexedByX, 2}, // D6 + {&CPU::CLV, 7, "clv", AddressingMode::Implied, 1}, // B8 + {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByY, 3}, // B9 + {&CPU::TSX, 2, "tsx", AddressingMode::Implied, 1}, // BA + {&CPU::TYX, 2, "tyx", AddressingMode::Implied, 1}, // BB + {&CPU::LDY, 4, "ldy", AddressingMode::AbsoluteIndexedByX, 3}, // BC + {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByX, 3}, // BD + {&CPU::LDX, 4, "ldx", AddressingMode::AbsoluteIndexedByY, 3}, // BE + {&CPU::LDA, 5, "lda", AddressingMode::AbsoluteIndexedByXLong, 4}, // BF + {&CPU::CPY, 2, "cpy", AddressingMode::ImmediateForX, 2}, // C0 + {&CPU::CMP, 6, "cmp", AddressingMode::DirectPageIndirectIndexedByX, 2}, // C1 + {&CPU::REP, 3, "rep", AddressingMode::Immediate8bits, 2}, // C2 + {&CPU::CMP, 4, "cmp", AddressingMode::StackRelative, 2}, // C3 + {&CPU::CPY, 3, "cpy", AddressingMode::DirectPage, 2}, // C4 + {&CPU::CMP, 3, "cmp", AddressingMode::DirectPage, 2}, // C5 + {&CPU::DEC, 5, "dec", AddressingMode::DirectPage, 2}, // C6 + {&CPU::CMP, 6, "cmp", AddressingMode::DirectPageIndirectLong, 2}, // C7 + {&CPU::INY, 2, "iny", AddressingMode::Implied, 1}, // C8 + {&CPU::CMP, 2, "cmp", AddressingMode::ImmediateForA, 2}, // C9 + {&CPU::DEX, 2, "dex", AddressingMode::Implied, 1}, // CA + {&CPU::WAI, 3, "wai", AddressingMode::Implied, 1}, // CB + {&CPU::CPY, 4, "cpy", AddressingMode::Absolute, 3}, // CC + {&CPU::CMP, 4, "cmp", AddressingMode::Absolute, 3}, // CD + {&CPU::DEC, 6, "dec", AddressingMode::Absolute, 3}, // CE + {&CPU::CMP, 6, "cmp", AddressingMode::AbsoluteLong, 4}, // CF + {&CPU::BNE, 2, "bne", AddressingMode::Immediate8bits, 2}, // D0 + {&CPU::CMP, 5, "cmp", AddressingMode::DirectPageIndirectIndexedByY, 2}, // D1 + {&CPU::CMP, 5, "cmp", AddressingMode::DirectPageIndirect, 2}, // D2 + {&CPU::CMP, 7, "cmp", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // D3 + {&CPU::PEI, 6, "pei", AddressingMode::DirectPage, 2}, // D4 + {&CPU::CMP, 4, "cmp", AddressingMode::DirectPageIndexedByX, 2}, // D5 + {&CPU::DEC, 6, "dec", AddressingMode::DirectPageIndexedByX, 2}, // D6 {&CPU::CMP, 6, "cmp", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // D7 - {&CPU::CLD, 2, "cld", AddressingMode::Implied, 2}, // D8 - {&CPU::CMP, 4, "cmp", AddressingMode::AbsoluteIndexedByY, 3}, // D9 - {&CPU::PHX, 3, "phx", AddressingMode::Implied, 1}, // DA - {&CPU::STP, 3, "stp", AddressingMode::Implied, 1}, // DB - {&CPU::JML, 7, "jml", AddressingMode::AbsoluteIndirectLong, 2}, // DC - {&CPU::CMP, 4, "cmp", AddressingMode::AbsoluteIndexedByX, 3}, // DD - {&CPU::DEC, 7, "dec", AddressingMode::AbsoluteIndexedByX, 3}, // DE - {&CPU::CMP, 5, "cmp", AddressingMode::AbsoluteIndexedByXLong, 4}, // DF - {&CPU::CPX, 2, "cpx", AddressingMode::ImmediateForX, 2}, // E0 - {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // E1 - {&CPU::SEP, 3, "sep", AddressingMode::Immediate8bits, 2}, // E2 - {&CPU::SBC, 4, "sbc", AddressingMode::StackRelative, 2}, // E3 - {&CPU::CPX, 3, "cpx", AddressingMode::DirectPage, 2}, // E4 - {&CPU::SBC, 3, "sbc", AddressingMode::DirectPage, 2}, // E5 - {&CPU::INC, 5, "inc", AddressingMode::DirectPage, 2}, // E6 - {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectLong, 2}, // E7 - {&CPU::INX, 2, "inx", AddressingMode::Implied, 1}, // E8 - {&CPU::SBC, 2, "sbc", AddressingMode::ImmediateForA, 2}, // E9 - {&CPU::NOP, 2, "nop", AddressingMode::Implied, 1}, // EA - {&CPU::XBA, 3, "xba", AddressingMode::Implied, 1}, // EB - {&CPU::CPX, 4, "cpx", AddressingMode::Absolute, 3}, // EC - {&CPU::SBC, 4, "sbc", AddressingMode::Absolute, 3}, // ED - {&CPU::INC, 6, "inc", AddressingMode::Absolute, 3}, // EE - {&CPU::SBC, 5, "sbc", AddressingMode::AbsoluteLong, 4}, // EF - {&CPU::BEQ, 2, "beq", AddressingMode::Immediate8bits, 2}, // F0 - {&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // F1 - {&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirect, 2}, // F2 - {&CPU::SBC, 7, "sbc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // F3 - {&CPU::PEA, 5, "pea", AddressingMode::Immediate16bits, 3}, // F4 - {&CPU::SBC, 4, "sbc", AddressingMode::DirectPageIndexedByX, 2}, // F5 - {&CPU::INC, 6, "inc", AddressingMode::DirectPageIndexedByX, 2}, // F6 + {&CPU::CLD, 2, "cld", AddressingMode::Implied, 2}, // D8 + {&CPU::CMP, 4, "cmp", AddressingMode::AbsoluteIndexedByY, 3}, // D9 + {&CPU::PHX, 3, "phx", AddressingMode::Implied, 1}, // DA + {&CPU::STP, 3, "stp", AddressingMode::Implied, 1}, // DB + {&CPU::JML, 7, "jml", AddressingMode::AbsoluteIndirectLong, 2}, // DC + {&CPU::CMP, 4, "cmp", AddressingMode::AbsoluteIndexedByX, 3}, // DD + {&CPU::DEC, 7, "dec", AddressingMode::AbsoluteIndexedByX, 3}, // DE + {&CPU::CMP, 5, "cmp", AddressingMode::AbsoluteIndexedByXLong, 4}, // DF + {&CPU::CPX, 2, "cpx", AddressingMode::ImmediateForX, 2}, // E0 + {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // E1 + {&CPU::SEP, 3, "sep", AddressingMode::Immediate8bits, 2}, // E2 + {&CPU::SBC, 4, "sbc", AddressingMode::StackRelative, 2}, // E3 + {&CPU::CPX, 3, "cpx", AddressingMode::DirectPage, 2}, // E4 + {&CPU::SBC, 3, "sbc", AddressingMode::DirectPage, 2}, // E5 + {&CPU::INC, 5, "inc", AddressingMode::DirectPage, 2}, // E6 + {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectLong, 2}, // E7 + {&CPU::INX, 2, "inx", AddressingMode::Implied, 1}, // E8 + {&CPU::SBC, 2, "sbc", AddressingMode::ImmediateForA, 2}, // E9 + {&CPU::NOP, 2, "nop", AddressingMode::Implied, 1}, // EA + {&CPU::XBA, 3, "xba", AddressingMode::Implied, 1}, // EB + {&CPU::CPX, 4, "cpx", AddressingMode::Absolute, 3}, // EC + {&CPU::SBC, 4, "sbc", AddressingMode::Absolute, 3}, // ED + {&CPU::INC, 6, "inc", AddressingMode::Absolute, 3}, // EE + {&CPU::SBC, 5, "sbc", AddressingMode::AbsoluteLong, 4}, // EF + {&CPU::BEQ, 2, "beq", AddressingMode::Immediate8bits, 2}, // F0 + {&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // F1 + {&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirect, 2}, // F2 + {&CPU::SBC, 7, "sbc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // F3 + {&CPU::PEA, 5, "pea", AddressingMode::Immediate16bits, 3}, // F4 + {&CPU::SBC, 4, "sbc", AddressingMode::DirectPageIndexedByX, 2}, // F5 + {&CPU::INC, 6, "inc", AddressingMode::DirectPageIndexedByX, 2}, // F6 {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // F7 - {&CPU::SED, 2, "sed", AddressingMode::Implied, 1}, // F8 - {&CPU::SBC, 4, "sbc", AddressingMode::AbsoluteIndexedByY, 3}, // F9 - {&CPU::PLX, 4, "plx", AddressingMode::Implied, 1}, // FA - {&CPU::XCE, 2, "xce", AddressingMode::Implied, 1}, // FB - {&CPU::JSR, 8, "jsr", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // FC - {&CPU::SBC, 4, "sbc", AddressingMode::AbsoluteIndexedByX, 3}, // FD - {&CPU::INC, 7, "inc", AddressingMode::AbsoluteIndexedByX, 3}, // FE - {&CPU::SBC, 5, "sbc", AddressingMode::AbsoluteIndexedByXLong, 4}, // FF + {&CPU::SED, 2, "sed", AddressingMode::Implied, 1}, // F8 + {&CPU::SBC, 4, "sbc", AddressingMode::AbsoluteIndexedByY, 3}, // F9 + {&CPU::PLX, 4, "plx", AddressingMode::Implied, 1}, // FA + {&CPU::XCE, 2, "xce", AddressingMode::Implied, 1}, // FB + {&CPU::JSR, 8, "jsr", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // FC + {&CPU::SBC, 4, "sbc", AddressingMode::AbsoluteIndexedByX, 3}, // FD + {&CPU::INC, 7, "inc", AddressingMode::AbsoluteIndexedByX, 3}, // FE + {&CPU::SBC, 5, "sbc", AddressingMode::AbsoluteIndexedByXLong, 4}, // FF }; public: - explicit CPU(std::shared_ptr bus, Cartridge::Header &cartridgeHeader); + //! @brief Construct a new generic CPU. + //! @param bus The memory bus to use to transfer data. + //! @param cartridgeHeader The header used to know interrupts, main entry point etc... + CPU(Memory::MemoryBus &bus, Cartridge::Header &cartridgeHeader); + //! @brief A default copy constructor CPU(const CPU &) = default; + //! @brief A CPU is not assignable CPU &operator=(const CPU &) = delete; + //! @brief A default destructor ~CPU() override = default; //! @brief This function continue to execute the Cartridge code. //! @return The number of CPU cycles that elapsed - virtual unsigned update(); + unsigned update(); //! @brief Read from the internal CPU register. //! @param addr The address to read from. The address 0x0 should refer to the first byte of the register. //! @throw InvalidAddress will be thrown if the address is more than $1F (the number of register). @@ -748,18 +593,22 @@ namespace ComSquare::CPU //! @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; + //! @brief Get the name of the data at the address + //! @param addr The address (in local space) + [[nodiscard]] std::string getValueName(uint24_t addr) const override; + //! @brief Get the size of the data. This size can be lower than the mapped data. //! @return The number of bytes inside this memory. - uint24_t getSize() const override; + [[nodiscard]] uint24_t getSize() const override; //! @brief Get the name of this accessor (used for debug purpose) - std::string getName() const override; + [[nodiscard]] std::string getName() const override; //! @brief Get the component of this accessor (used for debug purpose) - Component getComponent() const override; + [[nodiscard]] Component getComponent() const override; - //! @brief Reset interrupt - Called on boot and when the reset button is pressed. - virtual int RESB(); + //! @copydoc + int RESB(); //! @brief Is an NMI (non-maskable interrupt) requested. bool IsNMIRequested = false; @@ -768,16 +617,8 @@ namespace ComSquare::CPU //! @brief Is an abort requested bool IsAbortRequested = false; - //! @brief Return true if the CPU is overloaded with debugging features. - virtual bool isDebugger() const; - - //! @brief Change the memory bus used by the CPU. - virtual void setMemoryBus(std::shared_ptr bus); - - #ifdef DEBUGGER_ENABLED +#ifdef DEBUGGER_ENABLED friend Debugger::RegisterViewer; - #endif +#endif }; -} - -#endif //COMSQUARE_CPU_HPP +} \ No newline at end of file diff --git a/sources/CPU/DMA/DMA.cpp b/sources/CPU/DMA/DMA.cpp index 9c049ca..cfd52df 100644 --- a/sources/CPU/DMA/DMA.cpp +++ b/sources/CPU/DMA/DMA.cpp @@ -2,18 +2,15 @@ // Created by anonymus-raccoon on 5/26/20. // -#include #include "DMA.hpp" -#include "../../Exceptions/InvalidAddress.hpp" +#include "Exceptions/InvalidAddress.hpp" namespace ComSquare::CPU { - DMA::DMA(std::shared_ptr bus) : _bus(std::move(bus)) {} - - void DMA::setBus(std::shared_ptr bus) - { - this->_bus = std::move(bus); - } + DMA::DMA(Memory::MemoryBus &bus) + : _bus(bus), + enabled(false) + {} uint8_t DMA::read(uint8_t addr) const { @@ -68,24 +65,25 @@ namespace ComSquare::CPU unsigned DMA::_writeOneByte(uint24_t aAddress, uint24_t bAddress) { - // Address $2180 refers to the WRam data register. Write to/Read from this port when the a address is on the vram cause different behaviors. + // Address $2180 refers to the WRam data register. + // Write to/Read from this port when the a address is on the vram cause different behaviors. if (this->_port == 0x80) { - auto accessor = this->_bus->getAccessor(aAddress); + auto accessor = this->_bus.getAccessor(aAddress); if (accessor && accessor->getComponent() == WRam) { // WRAM->$2180 The write is not performed but the time is consumed anyway. if (this->_controlRegister.direction == AtoB) return 8; // $2180->WRAM No read is performed (so only 4 master cycles are needed) but the value written is invalid. - this->_bus->write(aAddress, 0xFF); + this->_bus.write(aAddress, 0xFF); return 4; } } if (this->_controlRegister.direction == AtoB) { - uint8_t data = this->_bus->read(aAddress); - this->_bus->write(bAddress, data); + uint8_t data = this->_bus.read(aAddress); + this->_bus.write(bAddress, data); } else { - uint8_t data = this->_bus->read(bAddress); - this->_bus->write(aAddress, data); + uint8_t data = this->_bus.read(bAddress); + this->_bus.write(aAddress, data); } return 8; } @@ -106,7 +104,7 @@ namespace ComSquare::CPU return cycles; } - int DMA::_getModeOffset(int index) + int DMA::_getModeOffset(int index) const { switch (this->_controlRegister.mode) { case OneToOne: @@ -127,4 +125,4 @@ namespace ComSquare::CPU } return 0; } -} \ No newline at end of file +}// namespace ComSquare::CPU \ No newline at end of file diff --git a/sources/CPU/DMA/DMA.hpp b/sources/CPU/DMA/DMA.hpp index eef46dc..26a8d3a 100644 --- a/sources/CPU/DMA/DMA.hpp +++ b/sources/CPU/DMA/DMA.hpp @@ -2,25 +2,26 @@ // Created by anonymus-raccoon on 5/26/20. // -#ifndef COMSQUARE_DMA_HPP -#define COMSQUARE_DMA_HPP +#pragma once +#include "Memory/MemoryBus.hpp" +#include "Models/Int24.hpp" #include #include -#include "../../Models/Int24.hpp" -#include "../../Memory/MemoryBus.hpp" #ifdef DEBUGGER_ENABLED - #include "../../Debugger/RegisterViewer.hpp" +#include "Debugger/RegisterViewer.hpp" #endif namespace ComSquare::CPU { //! @brief Class handling all DMA/HDMA transfers (Direct Memory Access or H-Blank Direct Memory Access) - class DMA { + class DMA + { public: //! @brief The first three bytes of the DMA's control register. Used to tell how many bytes/registers there is. - enum DMAMode { + enum DMAMode + { //! @brief 1 byte is transferred to 1 register (write once) OneToOne = 0b000, //! @brief 2 byte is transferred to 2 register (write once) @@ -39,63 +40,73 @@ namespace ComSquare::CPU FourToTwoBis = 0b111 }; - enum Direction { + enum Direction + { AtoB, BtoA }; + private: //! @brief Write one byte using the A address, the port and the _direction. Handle special cases where no write occurs. //! @return The number of cycles used. unsigned _writeOneByte(uint24_t aAddress, uint24_t bAddress); //! @brief Get an offset corresponding to the current DMAMode and the index of the currently transferred byte. - int _getModeOffset(int index); + [[nodiscard]] int _getModeOffset(int index) const; //! @brief DMA Control register (various information about the transfer) - union { + union + { struct { //! @brief DMA's mode: how many bytes/registers there is, how many writes... - DMAMode mode: 3; + DMAMode mode : 3; //! @brief If this flag is set, no increment/decrement will be done. - bool fixed: 1; + bool fixed : 1; //! @brief if this flag is 0: increment. Else: decrement. (The A address) - bool increment: 1; + bool increment : 1; //! @brief Two unused bites. - bool _: 2; + bool _ : 2; //! @brief The direction of the transfer. - Direction direction: 1; + Direction direction : 1; }; uint8_t raw; - } _controlRegister; + } _controlRegister {}; + //! @brief If this is 'xx', the register accessed will be $21xx. - uint8_t _port; + uint8_t _port {}; + //! @brief The absolute long address of the data from the A bus. - union { + union + { uint8_t bytes[3]; struct { uint16_t page; uint8_t bank; }; - uint24_t raw: 24; - } _aAddress; + uint24_t raw : 24; + } _aAddress {}; + //! @brief The number of bytes to be transferred. - union { + union + { uint8_t bytes[2]; uint16_t raw; - } _count; + } _count {}; //! @brief The memory bus to use for read/write. - std::shared_ptr _bus; + Memory::MemoryBus &_bus; public: //! @brief Is this channel set to run? bool enabled; - //! @brief Set the memory bus used by this dma channel. - void setBus(std::shared_ptr bus); - //! @brief Bus helper to read from this channel. - uint8_t read(uint8_t addr) const; + //! @param addr The address to read from + //! @return The value at the given address. + [[nodiscard]] uint8_t read(uint8_t addr) const; + //! @brief Bus helper to write to this channel. + //! @param addr The address to write to + //! @param data The data to write. void write(uint8_t addr, uint8_t data); //! @brief Run the DMA for x cycles @@ -103,16 +114,18 @@ namespace ComSquare::CPU //! @return the number of cycles taken unsigned run(unsigned cycles); - DMA() = default; - DMA(std::shared_ptr bus); + //! @brief Create a DMA channel with a given bus + //! @param bus The memory bus to use. + explicit DMA(Memory::MemoryBus &bus); + //! @brief A DMA is copy constructable. DMA(const DMA &) = default; - DMA &operator=(const DMA &) = default; + //! @brief A DMA is not assignable + DMA &operator=(const DMA &) = delete; + //! @brief A default destructor. ~DMA() = default; - #ifdef DEBUGGER_ENABLED +#ifdef DEBUGGER_ENABLED friend Debugger::RegisterViewer; - #endif +#endif }; -} - -#endif //COMSQUARE_DMA_HPP +}// namespace ComSquare::CPU diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp index 2332114..82ce7be 100644 --- a/sources/CPU/Instructions/BitsInstructions.cpp +++ b/sources/CPU/Instructions/BitsInstructions.cpp @@ -10,13 +10,13 @@ namespace ComSquare::CPU { int CPU::TSB(uint24_t valueAddr, AddressingMode mode) { - uint16_t value = this->_bus->read(valueAddr); + uint16_t value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; value |= this->_registers.a; - this->_bus->write(valueAddr, value); + this->_bus.write(valueAddr, value); if (!this->_registers.p.m) - this->_bus->write(valueAddr + 1, value >> 8u); + this->_bus.write(valueAddr + 1, value >> 8u); this->_registers.p.z = value == 0; @@ -30,14 +30,14 @@ namespace ComSquare::CPU int CPU::TRB(uint24_t valueAddr, AddressingMode mode) { - uint16_t value = this->_bus->read(valueAddr); + uint16_t value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; uint16_t newValue = value & ~this->_registers.a; - this->_bus->write(valueAddr, newValue); + this->_bus.write(valueAddr, newValue); if (!this->_registers.p.m) - this->_bus->write(valueAddr + 1, newValue >> 8u); + this->_bus.write(valueAddr + 1, newValue >> 8u); this->_registers.p.z = (value & this->_registers.a) == 0; @@ -52,9 +52,9 @@ namespace ComSquare::CPU int CPU::BIT(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus->read(valueAddr); + unsigned value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; if (mode != ImmediateForA) { this->_registers.p.n = value & negativeMask; @@ -89,18 +89,18 @@ namespace ComSquare::CPU return 0; } - uint16_t value = this->_bus->read(valueAddr); + uint16_t value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; this->_registers.p.c = value & highByte; value <<= 1u; this->_registers.p.n = value & highByte; this->_registers.p.z = value == 0; - this->_bus->write(valueAddr, value); + this->_bus.write(valueAddr, value); if (!this->_registers.p.m) - this->_bus->write(valueAddr + 1, value >> 8u); + this->_bus.write(valueAddr + 1, value >> 8u); int cycles = 2 * !this->_registers.p.m; switch (mode) { @@ -128,17 +128,17 @@ namespace ComSquare::CPU return 0; } - uint16_t value = this->_bus->read(valueAddr); + uint16_t value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; this->_registers.p.c = value & 1u; value >>= 1u; this->_registers.p.z = value == 0; - this->_bus->write(valueAddr, value); + this->_bus.write(valueAddr, value); if (!this->_registers.p.m) - this->_bus->write(valueAddr + 1, value >> 8u); + this->_bus.write(valueAddr + 1, value >> 8u); int cycles = 2 * !this->_registers.p.m; switch (mode) { @@ -169,9 +169,9 @@ namespace ComSquare::CPU return 0; } - uint16_t value = this->_bus->read(valueAddr); + uint16_t value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; this->_registers.p.c = value & highByte; value <<= 1u; @@ -179,9 +179,9 @@ namespace ComSquare::CPU this->_registers.p.n = value & highByte; this->_registers.p.z = value == 0; - this->_bus->write(valueAddr, value); + this->_bus.write(valueAddr, value); if (!this->_registers.p.m) - this->_bus->write(valueAddr + 1, value >> 8u); + this->_bus.write(valueAddr + 1, value >> 8u); int cycles = 2 * !this->_registers.p.m; switch (mode) { @@ -212,18 +212,18 @@ namespace ComSquare::CPU return 0; } - uint16_t value = this->_bus->read(valueAddr); + uint16_t value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; this->_registers.p.c = value & 1u; value >>= 1u; value |= oldCarry << highByteIndex; this->_registers.p.z = value == 0; - this->_bus->write(valueAddr, value); + this->_bus.write(valueAddr, value); if (!this->_registers.p.m) - this->_bus->write(valueAddr + 1, value >> 8u); + this->_bus.write(valueAddr + 1, value >> 8u); int cycles = 2 * !this->_registers.p.m; switch (mode) { diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index 03fb101..c03e21b 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -50,13 +50,13 @@ namespace ComSquare::CPU int CPU::SEP(uint24_t valueAddr, AddressingMode) { - this->_registers.p.flags |= this->_bus->read(valueAddr); + this->_registers.p.flags |= this->_bus.read(valueAddr); return 0; } int CPU::REP(uint24_t valueAddr, AddressingMode) { - this->_registers.p.flags &= ~this->_bus->read(valueAddr); + this->_registers.p.flags &= ~this->_bus.read(valueAddr); if (this->_isEmulationMode) { this->_registers.p.x_b = true; this->_registers.p.m = true; @@ -189,8 +189,8 @@ namespace ComSquare::CPU int CPU::PER(uint24_t valueAddr, AddressingMode) { - uint16_t value = this->_bus->read(valueAddr); - value += this->_bus->read(valueAddr + 1) << 8u; + uint16_t value = this->_bus.read(valueAddr); + value += this->_bus.read(valueAddr + 1) << 8u; value += this->_registers.pc; this->_push(value); return 0; @@ -226,55 +226,55 @@ namespace ComSquare::CPU int CPU::BCC(uint24_t valueAddr, AddressingMode) { if (!this->_registers.p.c) - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return !this->_registers.p.c + this->_isEmulationMode; } int CPU::BCS(uint24_t valueAddr, AddressingMode) { if (this->_registers.p.c) - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return this->_registers.p.c + this->_isEmulationMode; } int CPU::BEQ(uint24_t valueAddr, AddressingMode) { if (this->_registers.p.z) - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return this->_registers.p.z + this->_isEmulationMode; } int CPU::BNE(uint24_t valueAddr, AddressingMode) { if (!this->_registers.p.z) - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return !this->_registers.p.z + this->_isEmulationMode; } int CPU::BMI(uint24_t valueAddr, AddressingMode) { if (this->_registers.p.n) - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return this->_registers.p.n + this->_isEmulationMode; } int CPU::BPL(uint24_t valueAddr, AddressingMode) { if (!this->_registers.p.n) - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return !this->_registers.p.n + this->_isEmulationMode; } int CPU::BRA(uint24_t valueAddr, AddressingMode) { - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return this->_isEmulationMode; } int CPU::BRL(uint24_t valueAddr, AddressingMode) { - unsigned value = this->_bus->read(valueAddr); - value += this->_bus->read(valueAddr + 1) << 8u; + unsigned value = this->_bus.read(valueAddr); + value += this->_bus.read(valueAddr + 1) << 8u; this->_registers.pc += static_cast(value); return 0; @@ -283,14 +283,14 @@ namespace ComSquare::CPU int CPU::BVC(uint24_t valueAddr, AddressingMode) { if (!this->_registers.p.v) - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return !this->_registers.p.v + this->_isEmulationMode; } int CPU::BVS(uint24_t valueAddr, AddressingMode) { if (this->_registers.p.v) - this->_registers.pc += static_cast(this->_bus->read(valueAddr)); + this->_registers.pc += static_cast(this->_bus.read(valueAddr)); return this->_registers.p.v + this->_isEmulationMode; } diff --git a/sources/CPU/Instructions/MathematicalOperations.cpp b/sources/CPU/Instructions/MathematicalOperations.cpp index 7d95161..f102399 100644 --- a/sources/CPU/Instructions/MathematicalOperations.cpp +++ b/sources/CPU/Instructions/MathematicalOperations.cpp @@ -9,9 +9,9 @@ namespace ComSquare::CPU { int CPU::ADC(uint24_t valueAddr, AddressingMode mode) { - unsigned value = this->_bus->read(valueAddr) + this->_registers.p.c; + unsigned value = this->_bus.read(valueAddr) + this->_registers.p.c; if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; unsigned maxValue = this->_registers.p.m ? UINT8_MAX : UINT16_MAX; @@ -52,9 +52,9 @@ namespace ComSquare::CPU int CPU::SBC(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus->read(valueAddr); + unsigned value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; bool oldCarry = this->_registers.p.c; this->_registers.p.c = this->_registers.a >= value; @@ -94,9 +94,9 @@ namespace ComSquare::CPU int CPU::ORA(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus->read(valueAddr); + unsigned value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; this->_registers.a |= value; this->_registers.p.z = this->_registers.a == 0; this->_registers.p.n = this->_registers.a & negativeMask; @@ -151,9 +151,9 @@ namespace ComSquare::CPU int CPU::CMP(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus->read(valueAddr); + unsigned value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; unsigned result = this->_registers.a - value; if (this->_registers.p.m) result %= 0x100; @@ -214,7 +214,7 @@ namespace ComSquare::CPU int CPU::CPX(uint24_t valueAddr, AddressingMode mode) { - unsigned value = this->_bus->read(valueAddr++); + unsigned value = this->_bus.read(valueAddr++); if (this->_registers.p.x_b) { uint8_t x = this->_registers.x; @@ -222,7 +222,7 @@ namespace ComSquare::CPU this->_registers.p.z = x == 0; this->_registers.p.n = x & 0x80u; } else { - value += this->_bus->read(valueAddr) << 8u; + value += this->_bus.read(valueAddr) << 8u; uint16_t x = this->_registers.x; x -= value; this->_registers.p.z = x == 0; @@ -234,7 +234,7 @@ namespace ComSquare::CPU int CPU::CPY(uint24_t valueAddr, AddressingMode mode) { - unsigned value = this->_bus->read(valueAddr++); + unsigned value = this->_bus.read(valueAddr++); this->_registers.p.c = this->_registers.y >= value; if (this->_registers.p.x_b) { @@ -243,7 +243,7 @@ namespace ComSquare::CPU this->_registers.p.z = y == 0; this->_registers.p.n = y & 0x80u; } else { - value += this->_bus->read(valueAddr) << 8u; + value += this->_bus.read(valueAddr) << 8u; uint16_t y = this->_registers.y; y -= value; this->_registers.p.z = y == 0; @@ -255,9 +255,9 @@ namespace ComSquare::CPU int CPU::AND(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus->read(valueAddr); + unsigned value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; this->_registers.a &= value; this->_registers.p.n = this->_registers.a & negativeMask; @@ -297,15 +297,15 @@ namespace ComSquare::CPU this->_registers.ah = 0; result = this->_registers.a; } else if (!this->_registers.p.m) { - result = this->_bus->read(valueAddr); - result += this->_bus->read(valueAddr + 1) << 8u; + result = this->_bus.read(valueAddr); + result += this->_bus.read(valueAddr + 1) << 8u; result = (uint16_t)(result + 1); - this->_bus->write(valueAddr, result); - this->_bus->write(valueAddr + 1, result << 8u); + this->_bus.write(valueAddr, result); + this->_bus.write(valueAddr + 1, result << 8u); } else { - result = this->_bus->read(valueAddr); + result = this->_bus.read(valueAddr); result = (uint8_t)(result + 1); - this->_bus->write(valueAddr, result); + this->_bus.write(valueAddr, result); } this->_registers.p.z = result == 0; @@ -337,15 +337,15 @@ namespace ComSquare::CPU this->_registers.ah = 0; result = this->_registers.a; } else if (!this->_registers.p.m) { - result = this->_bus->read(valueAddr); - result += this->_bus->read(valueAddr + 1) << 8u; + result = this->_bus.read(valueAddr); + result += this->_bus.read(valueAddr + 1) << 8u; result = (uint16_t)(result - 1); - this->_bus->write(valueAddr, result); - this->_bus->write(valueAddr + 1, result << 8u); + this->_bus.write(valueAddr, result); + this->_bus.write(valueAddr + 1, result << 8u); } else { - result = this->_bus->read(valueAddr); + result = this->_bus.read(valueAddr); result = (uint8_t)(result - 1); - this->_bus->write(valueAddr, result); + this->_bus.write(valueAddr, result); } this->_registers.p.z = result == 0; @@ -369,9 +369,9 @@ namespace ComSquare::CPU int CPU::EOR(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; - unsigned value = this->_bus->read(valueAddr); + unsigned value = this->_bus.read(valueAddr); if (!this->_registers.p.m) - value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_bus.read(valueAddr + 1) << 8u; this->_registers.a ^= value; this->_registers.p.z = this->_registers.a == 0; this->_registers.p.n = this->_registers.a & negativeMask; diff --git a/sources/CPU/Instructions/MemoryInstructions.cpp b/sources/CPU/Instructions/MemoryInstructions.cpp index f102d90..92253ff 100644 --- a/sources/CPU/Instructions/MemoryInstructions.cpp +++ b/sources/CPU/Instructions/MemoryInstructions.cpp @@ -9,10 +9,10 @@ namespace ComSquare::CPU int CPU::STA(uint24_t addr, AddressingMode mode) { if (this->_registers.p.m) - this->_bus->write(addr, this->_registers.al); + this->_bus.write(addr, this->_registers.al); else { - this->_bus->write(addr, this->_registers.al); - this->_bus->write(addr + 1, this->_registers.ah); + this->_bus.write(addr, this->_registers.al); + this->_bus.write(addr + 1, this->_registers.ah); } int cycles = !this->_registers.p.m; @@ -34,10 +34,10 @@ namespace ComSquare::CPU int CPU::STX(uint24_t addr, AddressingMode mode) { if (this->_registers.p.x_b) - this->_bus->write(addr, this->_registers.xl); + this->_bus.write(addr, this->_registers.xl); else { - this->_bus->write(addr, this->_registers.xl); - this->_bus->write(addr + 1, this->_registers.xh); + this->_bus.write(addr, this->_registers.xl); + this->_bus.write(addr + 1, this->_registers.xh); } return !this->_registers.p.x_b + (mode != Absolute && this->_registers.dl != 0); } @@ -45,19 +45,19 @@ namespace ComSquare::CPU int CPU::STY(uint24_t addr, AddressingMode mode) { if (this->_registers.p.x_b) - this->_bus->write(addr, this->_registers.yl); + this->_bus.write(addr, this->_registers.yl); else { - this->_bus->write(addr, this->_registers.yl); - this->_bus->write(addr + 1, this->_registers.yh); + this->_bus.write(addr, this->_registers.yl); + this->_bus.write(addr + 1, this->_registers.yh); } return !this->_registers.p.x_b + (mode != Absolute && this->_registers.dl != 0); } int CPU::STZ(uint24_t addr, AddressingMode mode) { - this->_bus->write(addr, 0x00); + this->_bus.write(addr, 0x00); if (!this->_registers.p.m) - this->_bus->write(addr + 1, 0x00); + this->_bus.write(addr + 1, 0x00); if (mode == Absolute || mode == AbsoluteIndexedByX) return !this->_registers.p.m; return !this->_registers.p.m + this->_registers.dl != 0; @@ -66,11 +66,11 @@ namespace ComSquare::CPU int CPU::LDA(uint24_t addr, AddressingMode mode) { if (this->_registers.p.m) { - this->_registers.a = this->_bus->read(addr); + this->_registers.a = this->_bus.read(addr); this->_registers.p.n = this->_registers.al & 0xF0u; } else { - this->_registers.al = this->_bus->read(addr); - this->_registers.ah = this->_bus->read(addr + 1); + this->_registers.al = this->_bus.read(addr); + this->_registers.ah = this->_bus.read(addr + 1); this->_registers.p.n = this->_registers.a & 0xF000u; } this->_registers.p.z = this->_registers.a == 0x0; @@ -101,11 +101,11 @@ namespace ComSquare::CPU int CPU::LDX(uint24_t addr, AddressingMode mode) { if (this->_registers.p.x_b) { - this->_registers.x = this->_bus->read(addr); + this->_registers.x = this->_bus.read(addr); this->_registers.p.n = this->_registers.xl & 0xF0u; } else { - this->_registers.xl = this->_bus->read(addr); - this->_registers.xh = this->_bus->read(addr + 1); + this->_registers.xl = this->_bus.read(addr); + this->_registers.xh = this->_bus.read(addr + 1); this->_registers.p.n = this->_registers.x & 0xF000u; } this->_registers.p.z = this->_registers.x == 0x0; @@ -128,11 +128,11 @@ namespace ComSquare::CPU int CPU::LDY(uint24_t addr, AddressingMode mode) { if (this->_registers.p.x_b) { - this->_registers.y = this->_bus->read(addr); + this->_registers.y = this->_bus.read(addr); this->_registers.p.n = this->_registers.yl & 0xF0u; } else { - this->_registers.yl = this->_bus->read(addr); - this->_registers.yh = this->_bus->read(addr + 1); + this->_registers.yl = this->_bus.read(addr); + this->_registers.yh = this->_bus.read(addr + 1); this->_registers.p.n = this->_registers.y & 0xF000u; } this->_registers.p.z = this->_registers.y == 0x0; diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp index 496a5d6..95b2aff 100644 --- a/sources/CPU/Instructions/TransferRegisters.cpp +++ b/sources/CPU/Instructions/TransferRegisters.cpp @@ -160,8 +160,8 @@ namespace ComSquare::CPU this->_registers.dbr = destBank; while (this->_registers.a != 0xFFFF) { - uint8_t data = this->_bus->read(srcBank << 24u | this->_registers.x); - this->_bus->write(destBank << 24u | this->_registers.y, data); + uint8_t data = this->_bus.read(srcBank << 24u | this->_registers.x); + this->_bus.write(destBank << 24u | this->_registers.y, data); this->_registers.x++; this->_registers.y++; this->_registers.a--; @@ -177,12 +177,18 @@ namespace ComSquare::CPU this->_registers.dbr = destBank; while (this->_registers.a != 0xFFFF) { - uint8_t data = this->_bus->read(srcBank << 24u | this->_registers.x); - this->_bus->write(destBank << 24u | this->_registers.y, data); + uint8_t data = this->_bus.read(srcBank << 24u | this->_registers.x); + this->_bus.write(destBank << 24u | this->_registers.y, data); this->_registers.x--; this->_registers.y--; this->_registers.a--; } return 7 * length; } + + std::string CPU::getValueName(uint24_t) const + { + // TODO implement this method + return "???"; + } } \ No newline at end of file diff --git a/sources/CPU/Registers.hpp b/sources/CPU/Registers.hpp new file mode 100644 index 0000000..95b012c --- /dev/null +++ b/sources/CPU/Registers.hpp @@ -0,0 +1,192 @@ +// +// Created by Zoe Roux on 2021-07-03. +// + + +#pragma once + +#include "Models/Int24.hpp" + +namespace ComSquare::CPU +{ + //! @brief Struct containing registers for the main CPU. + struct Registers + { + //! @brief The Accumulator + union + { + struct + { + uint8_t al; + uint8_t ah; + }; + uint16_t a; + }; + //! @brief The Data Bank Register; + uint8_t dbr; + //! @brief The Direct Page register; + union + { + struct + { + uint8_t dl; + uint8_t dh; + }; + uint16_t d; + }; + union + { + struct + { + //! @brief The Program Counter; + union + { + struct + { + uint8_t pcl; + uint8_t pch; + }; + uint16_t pc; + }; + //! @brief The Program Bank Register; + uint8_t pbr; + }; + //! @brief The current Program Address Counter (does not exist in a snes but is useful here). + uint24_t pac; + }; + //! @brief The Stack pointer + union + { + struct + { + uint8_t sl; + uint8_t sh; + }; + uint16_t s; + }; + //! @brief The X index register + union + { + struct + { + uint8_t xl; + uint8_t xh; + }; + uint16_t x; + }; + //! @brief The Y index register + union + { + struct + { + uint8_t yl; + uint8_t yh; + }; + uint16_t y; + }; + + //! @brief The Processor status register; + union + { + struct + { + //! @brief The Carry flag + bool c: 1; + //! @brief The Zero flag + bool z: 1; + //! @brief The Interrupt request disable flag + bool i: 1; + //! @brief The Decimal mode flag + bool d: 1; + //! @brief The indeX register width flag (in native mode only) - 0 = 16 bits mode, 1 = 8 bits mode OR the Break flag (in emulation mode only) + bool x_b: 1; + //! @brief The accumulator and Memory width flag (in native mode only) - 0 = 16 bits mode, 1 = 8 bits mode. + bool m: 1; + //! @brief The oVerflow flag + bool v: 1; + //! @brief The Negative flag + bool n: 1; + }; + uint8_t flags; + } p; + }; + + //! @brief Struct containing internal registers of the CPU. + struct InternalRegisters + { + //! @brief Interrupt Enable Register + uint8_t nmitimen; + + //! @brief IO Port Write Register + uint8_t wrio; + + //! @brief Multiplicand Register A + uint8_t wrmpya; + //! @brief Multiplicand Register B + uint8_t wrmpyb; + + //! @brief Divisor & Dividend Registers (A - Low) + uint8_t wrdivl; + //! @brief Divisor & Dividend Registers (A - High) + uint8_t wrdivh; + //! @brief Divisor & Dividend Registers (B) + uint8_t wrdivb; + + //! @brief IRQ Timer Registers (Horizontal - Low) + uint8_t htimel; + //! @brief IRQ Timer Registers (Horizontal - High) + uint8_t htimeh; + + //! @brief IRQ Timer Registers (Vertical - Low) + uint8_t vtimel; + //! @brief IRQ Timer Registers (Vertical - High) + uint8_t vtimeh; + + //! @brief HDMA Enable Register + uint8_t hdmaen; + + //! @brief ROM Speed Register + uint8_t memsel; + + //! @brief Interrupt Flag Registers + uint8_t rdnmi; + //! @brief Interrupt Flag Registers - TimeUp + uint8_t timeup; + + //! @brief PPU Status Register + uint8_t hvbjoy; + + //! @brief IO Port Read Register + uint8_t rdio; + + //! @brief Divide Result Registers (can sometimes be used as multiplication result register) - LOW + uint8_t rddivl; + //! @brief Divide Result Registers (can sometimes be used as multiplication result register) - HIGH + uint8_t rddivh; + + //! @brief Multiplication Result Registers (can sometimes be used as divide result register) - LOW + uint8_t rdmpyl; + //! @brief Multiplication Result Registers (can sometimes be used as divide result register) - HIGH + uint8_t rdmpyh; + + //! @brief Controller Port Data Registers (Pad 1 - Low) + uint8_t joy1l; + //! @brief Controller Port Data Registers (Pad 1 - High) + uint8_t joy1h; + + //! @brief Controller Port Data Registers (Pad 2 - Low) + uint8_t joy2l; + //! @brief Controller Port Data Registers (Pad 2 - High) + uint8_t joy2h; + + //! @brief Controller Port Data Registers (Pad 3 - Low) + uint8_t joy3l; + //! @brief Controller Port Data Registers (Pad 3 - High) + uint8_t joy3h; + + //! @brief Controller Port Data Registers (Pad 4 - Low) + uint8_t joy4l; + //! @brief Controller Port Data Registers (Pad 4 - High) + uint8_t joy4h; + }; +} \ No newline at end of file diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp index 6f50e11..32477dc 100644 --- a/sources/Cartridge/Cartridge.cpp +++ b/sources/Cartridge/Cartridge.cpp @@ -2,28 +2,36 @@ // Created by anonymus-raccoon on 1/27/20. // -#include -#include #include "Cartridge.hpp" -#include "../Exceptions/InvalidAddress.hpp" -#include "../Exceptions/InvalidRom.hpp" -#include "../Exceptions/InvalidAction.hpp" +#include "Exceptions/InvalidAction.hpp" +#include "Exceptions/InvalidAddress.hpp" +#include "Exceptions/InvalidRom.hpp" +#include +#include +#include namespace ComSquare::Cartridge { constexpr unsigned HeaderSize = 0x40u; + Cartridge::Cartridge() + : Ram::Ram(0, Rom, "Cartridge") + {} + Cartridge::Cartridge(const std::string &romPath) - : Ram::Ram(0, Rom, "Cartridge"), - _romPath(romPath) + : Ram::Ram(0, Rom, "Cartridge"), + _romPath(romPath) { - if (romPath.empty()) - throw InvalidRomException("Path is empty."); - size_t size = Cartridge::getRomSize(romPath); - FILE *rom = fopen(romPath.c_str(), "rb"); + this->loadRom(romPath); + } + + void Cartridge::loadRom(const std::string &path) + { + size_t size = Cartridge::getRomSize(path); + FILE *rom = fopen(path.c_str(), "rb"); if (!rom) - throw InvalidRomException("Could not open the rom file at " + romPath + ". " + strerror(errno)); + throw InvalidRomException("Could not open the rom file at " + path + ". " + strerror(errno)); this->_size = size; this->_data = new uint8_t[size]; std::memset(this->_data, 0, size); @@ -62,7 +70,7 @@ namespace ComSquare::Cartridge headerAddress -= 0xC0u; ADDMAPPINGMODE(head.mappingMode, this->_data[headerAddress + 0xD5u] & 0x10u ? FastRom : SlowRom); - ADDMAPPINGMODE(head.mappingMode, this->_data[headerAddress + 0xD5u] & 0x1u ? HiRom : LoRom); + ADDMAPPINGMODE(head.mappingMode, this->_data[headerAddress + 0xD5u] & 0x1u ? HiRom : LoRom); if (this->_data[headerAddress + 0xD5u] & 0x2u || this->_data[headerAddress + 0xD5u] & 0x4u) ADDMAPPINGMODE(head.mappingMode, ExRom); head.romType = this->_data[headerAddress + 0xD6u]; @@ -133,25 +141,25 @@ namespace ComSquare::Cartridge continue; uint8_t resetOpCode = this->_data[info.emulationInterrupts.reset - 0x8000u]; switch (resetOpCode) { - case 0x18: //CLI - case 0x78: //SEI - case 0x4C: //JMP - case 0x5C: //JMP - case 0x20: //JSR - case 0x22: //JSL - case 0x9C: //STZ - score+= 8; + case 0x18://CLI + case 0x78://SEI + case 0x4C://JMP + case 0x5C://JMP + case 0x20://JSR + case 0x22://JSL + case 0x9C://STZ + score += 8; break; - case 0xC2: //REP - case 0xE2: //SEP - case 0xA9: //LDA - case 0xA2: //LDX - case 0xA0: //LDY + case 0xC2://REP + case 0xE2://SEP + case 0xA9://LDA + case 0xA2://LDX + case 0xA0://LDY score += 4; break; - case 0x00: //BRK - case 0xFF: //SBC - case 0xCC: //CPY + case 0x00://BRK + case 0xFF://SBC + case 0xCC://CPY score -= 8; break; default: @@ -209,4 +217,4 @@ namespace ComSquare::Cartridge { return this->_type; } -} \ No newline at end of file +}// namespace ComSquare::Cartridge \ No newline at end of file diff --git a/sources/Cartridge/Cartridge.hpp b/sources/Cartridge/Cartridge.hpp index d869c24..bab29b3 100644 --- a/sources/Cartridge/Cartridge.hpp +++ b/sources/Cartridge/Cartridge.hpp @@ -4,23 +4,25 @@ #pragma once -#include -#include -#include "Memory/AMemory.hpp" -#include "Models/Int24.hpp" -#include "Memory/ARectangleMemory.hpp" #include "InterruptVectors.hpp" +#include "Memory/AMemory.hpp" +#include "Memory/ARectangleMemory.hpp" +#include "Models/Int24.hpp" #include "Ram/Ram.hpp" +#include +#include namespace ComSquare::Cartridge { - enum CartridgeType { + enum CartridgeType + { Game, Audio }; - #define ADDMAPPINGMODE(x, flag) (x = static_cast(x | (flag))) - enum MappingMode { +#define ADDMAPPINGMODE(x, flag) (x = static_cast(x | (flag))) + enum MappingMode + { LoRom = 1u << 0u, HiRom = 1u << 1u, SlowRom = 1u << 2u, @@ -33,7 +35,7 @@ namespace ComSquare::Cartridge //! @brief The name of the game std::string gameName; //! @brief The memory mapping of the ROM. - MappingMode mappingMode{}; + MappingMode mappingMode {}; //! @brief The rom type (special information about the rom, still don't know what). uint8_t romType = 0; //! @brief The size (in bytes) of the ram @@ -41,26 +43,29 @@ namespace ComSquare::Cartridge //! @brief The size of the SRom inside the cartridge. unsigned sramSize = 0; //! @brief Creator license ID code. - union { + union + { uint8_t creatorIDs[2]; uint16_t creatorID = 0; }; //! @brief The version of the game uint8_t version = 0; //! @brief Checksum complement - union { + union + { uint8_t checksumComplements[2]; uint16_t checksumComplement = 0; }; //! @brief Checksum - union { + union + { uint8_t checksums[2]; uint16_t checksum = 0; }; //! @brief The interrupt vectors used to halt the CPU in native mode - InterruptVectors nativeInterrupts{}; + InterruptVectors nativeInterrupts {}; //! @brief The interrupt vectors used to halt the CPU in emulation mode - InterruptVectors emulationInterrupts{}; + InterruptVectors emulationInterrupts {}; Header() = default; Header(const Header &) = default; @@ -69,7 +74,8 @@ namespace ComSquare::Cartridge }; //! @brief Contains the rom's memory/instructions. - class Cartridge : public Ram::Ram { + class Cartridge : public Ram::Ram + { private: //! @brief The path of the currently loaded rom. std::string _romPath; @@ -93,10 +99,13 @@ namespace ComSquare::Cartridge //! @return A header struct representing the data at the memory address you passed. Header _mapHeader(uint32_t headerAddress); //! @brief Current type of the cartridge - CartridgeType _type; + CartridgeType _type = Game; //! @brief Magic Header string of a SPC Rom static constexpr std::string_view _magicSPC = "SNES-SPC700 Sound File Data v0.30"; + public: + //! @brief A default constructor that doesn't load anything. + Cartridge(); //! @brief Load a rom from it's path. explicit Cartridge(const std::string &romPath); //! @brief The cartridge can't be copied. @@ -108,13 +117,16 @@ namespace ComSquare::Cartridge //! @brief The header of the cartridge. Header header; + //! @brief Return current type of the cartridge CartridgeType getType(); + //! @brief Read from the rom. //! @param addr The address to read from. The address 0x0 should refer to the first byte of the rom's memory. //! @throw InvalidAddress will be thrown if the address is more than the size of the rom's memory. //! @return Return the data at the address. uint8_t read(uint24_t addr) override; + //! @brief Write data to the rom. //! @param addr The address to write to. The address 0x0 should refer to the first byte of the rom's memory. //! @param data The data to write. @@ -123,6 +135,11 @@ namespace ComSquare::Cartridge //! @brief The path of the rom file //! @return The path of the currently loaded rom file. - std::filesystem::path getRomPath() const; + [[nodiscard]] std::filesystem::path getRomPath() const; + + //! @brief Load the rom at the given path + //! @param rom The path of the rom. + //! @throws InvalidRomException If the rom is invalid, this exception is thrown. + void loadRom(const std::string& path); }; -} \ No newline at end of file +}// namespace ComSquare::Cartridge \ No newline at end of file diff --git a/sources/Cartridge/InterruptVectors.hpp b/sources/Cartridge/InterruptVectors.hpp index bd745bf..94056e3 100644 --- a/sources/Cartridge/InterruptVectors.hpp +++ b/sources/Cartridge/InterruptVectors.hpp @@ -2,43 +2,49 @@ // Created by anonymus-raccoon on 1/31/20. // -#ifndef COMSQUARE_INTERRUPTVECTORS_HPP -#define COMSQUARE_INTERRUPTVECTORS_HPP +#pragma once + +#include namespace ComSquare::Cartridge { - struct InterruptVectors { + struct InterruptVectors + { //! @brief The Co-Processor enable vector. - union { + union + { uint8_t cop8[2]; uint16_t cop; }; //! @brief The Break vector. - union { + union + { uint8_t brk8[2]; uint16_t brk; }; //! @brief The Abort vector. - union { + union + { uint8_t abort8[2]; uint16_t abort; }; //! @brief The non-maskable interrupt (The V-Blank interrupt). - union { + union + { uint8_t nmi8[2]; uint16_t nmi; }; //! @brief The Reset vector (execution of the SNES starts with this reset vector in emulation mode). - union { + union + { uint8_t reset8[2]; uint16_t reset; }; //! @brief The Interrupt Request vector. - union { + union + { uint8_t irq8[2]; uint16_t irq; }; }; -} - -#endif //COMSQUARE_INTERRUPTVECTORS_HPP +}// namespace ComSquare::Cartridge \ No newline at end of file diff --git a/sources/Debugger/CPU/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp index 61e848c..99fc106 100644 --- a/sources/Debugger/CPU/CPUDebug.cpp +++ b/sources/Debugger/CPU/CPUDebug.cpp @@ -25,7 +25,7 @@ namespace ComSquare::Debugger _painter(*this), _stackModel(this->_bus, *this), _snes(snes), - _labels(this->_loadLabels(snes.cartridge->getRomPath())) + _labels(this->_loadLabels(snes.cartridge.getRomPath())) { this->_window->setContextMenuPolicy(Qt::NoContextMenu); this->_window->setAttribute(Qt::WA_QuitOnClose, false); @@ -84,9 +84,10 @@ namespace ComSquare::Debugger try { unsigned cycles = 0; - for (auto &channel : this->_dmaChannels) + for (auto &channel : this->_dmaChannels) { if (channel.enabled) cycles += channel.run(INT_MAX); + } if (this->_isPaused) return 0xFF; @@ -300,11 +301,11 @@ namespace ComSquare::Debugger std::string CPUDebug::getProceededParameters() { uint24_t pac = this->_registers.pac; - this->_bus->forceSilence = true; + this->_bus.forceSilence = true; Instruction instruction = this->_instructions[this->readPC()]; uint24_t valueAddr = this->_getValueAddr(instruction); this->_registers.pac = pac; - this->_bus->forceSilence = false; + this->_bus.forceSilence = false; if (instruction.size == 1) return ""; return "[" + Utility::to_hex(valueAddr, Utility::AsmPrefix) + "]"; @@ -316,12 +317,12 @@ namespace ComSquare::Debugger std::string symbolPath = romPath.replace_extension(".sym"); std::ifstream sym(symbolPath); - if (sym) { - std::vector