From d4b3046bbe127b407f010f2ae82e6eb49e840abf Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Tue, 9 Mar 2021 10:39:54 +0100 Subject: [PATCH 1/8] Parsing header of SPC file format and stop update (for now) --- sources/Cartridge/Cartridge.cpp | 29 ++++++++++++++++++++++++++++- sources/Cartridge/Cartridge.hpp | 11 +++++++++++ sources/SNES.cpp | 3 +++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp index ead9363..cdbd5a5 100644 --- a/sources/Cartridge/Cartridge.cpp +++ b/sources/Cartridge/Cartridge.cpp @@ -98,13 +98,15 @@ namespace ComSquare::Cartridge uint32_t Cartridge::_getHeaderAddress() { - const std::vector address = {0x7FC0, 0xFFC0, 0x81C0, 0x101C0}; + const std::vector address = {0x7FC0, 0xFFC0}; + unsigned int smc = this->_size % 1024; int bestScore = -1; uint32_t bestAddress = 0; for (uint32_t addr : address) { int score = 0; + addr += smc; if (addr + 0x32u >= this->_size) continue; @@ -156,10 +158,30 @@ namespace ComSquare::Cartridge return bestAddress; } + bool Cartridge::_isSPCFile() + { + std::string str = std::string(reinterpret_cast(this->_data), 0x21); + + if (str != "SNES-SPC700 Sound File Data v0.30") + return false; + if (this->_data[0x21] != 0x1A || this->_data[0x22] != 0x1A) + return false; + if (this->_data[0x23] != 0x1A && this->_data[0x23] != 0x1B) + return false; + if (this->_data[0x24] != 0x1E) + return false; + return true; + } + bool Cartridge::_loadHeader() { + if (this->_isSPCFile()) { + this->_type = Audio; + return false; + } uint32_t headerAddress = this->_getHeaderAddress(); + this->_type = Game; this->header = this->_mapHeader(headerAddress); this->header.gameName = std::string(reinterpret_cast(&this->_data[headerAddress]), 21); if ((headerAddress + 0x40u) & 0x200u) { @@ -169,4 +191,9 @@ namespace ComSquare::Cartridge } return false; } + + CartridgeType Cartridge::getType() + { + return this->_type; + } } \ No newline at end of file diff --git a/sources/Cartridge/Cartridge.hpp b/sources/Cartridge/Cartridge.hpp index 90562e8..99f1639 100644 --- a/sources/Cartridge/Cartridge.hpp +++ b/sources/Cartridge/Cartridge.hpp @@ -13,6 +13,11 @@ namespace ComSquare::Cartridge { + enum CartridgeType { + Game, + Audio + }; + #define ADDMAPPINGMODE(x, flag) (x = static_cast(x | (flag))) enum MappingMode { LoRom = 1u << 0u, @@ -75,6 +80,8 @@ namespace ComSquare::Cartridge //! @brief Set the public variable header by parsing the header in the ROM. //! @return True if this cartridge has a SCM header, false otherwise. bool _loadHeader(); + //! @brief Check if the cartridge is not a game but a SPC audio dump + bool _isSPCFile(); //! @brief Get the address of the header. //! @return The address of this cartridge header. uint32_t _getHeaderAddress(); @@ -82,6 +89,8 @@ namespace ComSquare::Cartridge //! @param headerAddress The address you want to parse. //! @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; public: //! @brief Load a rom from it's path. explicit Cartridge(const std::string &romPath); @@ -94,6 +103,8 @@ 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. diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 3ad1cb4..0d2b9c3 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -28,6 +28,9 @@ namespace ComSquare void SNES::update() { + if (this->cartridge->getType() == Cartridge::Audio) + return; + unsigned cycleCount = this->cpu->update(); this->ppu->update(cycleCount); this->apu->update(cycleCount); From 044aae174dcda3ef3696da90543c8c2e271dd275 Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Thu, 25 Mar 2021 11:22:26 +0100 Subject: [PATCH 2/8] Parsing SPC ROM data into APU & fixing operands of two MOV instructions --- .gitignore | 4 +- sources/APU/APU.cpp | 73 ++++++++++++++++++++++++++++++++- sources/APU/APU.hpp | 32 ++++++++------- sources/Debugger/APUDebug.cpp | 77 ++++++++++++++++++----------------- sources/Ram/Ram.cpp | 5 +++ sources/Ram/Ram.hpp | 3 ++ sources/SNES.cpp | 5 +++ 7 files changed, 144 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index 5468f3d..bdb7501 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .idea/* cmake-build-debug/* -ui/*.h \ No newline at end of file +ui/*.h +out/ +.vs/ \ No newline at end of file diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index 8613883..7e2cf67 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -3,6 +3,7 @@ // #include +#include #include "APU.hpp" #include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" @@ -650,7 +651,7 @@ namespace ComSquare::APU case 0xE3: return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 7); case 0xE4: - return this->MOV(this->_getDirectAddr(), this->_internalRegisters.a, 3); + return this->MOV(this->_internalRead(this->_getDirectAddr()), this->_internalRegisters.a, 3); case 0xE5: return this->MOV(this->_getAbsoluteAddrByX(), this->_internalRegisters.a, 5); case 0xE6: @@ -682,7 +683,7 @@ namespace ComSquare::APU case 0xF3: return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 7); case 0xF4: - return this->MOV(this->_getDirectAddrByX(), this->_internalRegisters.a, 4); + return this->MOV(this->_internalRead(this->_getDirectAddrByX()), this->_internalRegisters.a, 4); case 0xF5: return this->MOV(this->_getAbsoluteAddrByX(), this->_internalRegisters.a, 5); case 0xF6: @@ -731,6 +732,74 @@ namespace ComSquare::APU this->_renderer.playAudio(std::span{this->_soundBuffer}, samples / 2); } + void APU::loadFromSPC(const std::shared_ptr& cartridge) + { + const uint8_t *data = cartridge->getData(); + + std::string song = std::string(reinterpret_cast(data + 0x2E), 0x20); + std::string game = std::string(reinterpret_cast(data + 0x4E), 0x20); + std::string dumper = std::string(reinterpret_cast(data + 0x6E), 0x10); + std::string comment = std::string(reinterpret_cast(data + 0x7E), 0x20); + 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); + + 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); + + for (int i = 0x00; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x01; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x02; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x03; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x04; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x05; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x06; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x07; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x08; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x09; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x0C; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x0D; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + for (int i = 0x0F; i < 0x80; i += 0x10) + this->_dsp.write(i, cartridge->read(0x10100 + i)); + } + void APU::_setNZflags(uint8_t value) { this->_internalRegisters.n = value & 0x80u; diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index a56a0d6..28c0608 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -11,6 +11,7 @@ #include "../Ram/Ram.hpp" #include "IPL/IPL.hpp" #include "../Renderer/IRenderer.hpp" +#include "../Cartridge/Cartridge.hpp" namespace ComSquare::APU { @@ -45,22 +46,22 @@ namespace ComSquare::APU //! @brief Program Status Word register union { struct { - //! @brief Negative flag - bool n : 1; - //! @brief Overflow flag - bool v : 1; - //! @brief Direct page flag - bool p : 1; - //! @brief Break flag - bool b : 1; - //! @brief Half carry flag - bool h : 1; - //! @brief Interrupt enabled flag - bool i : 1; - //! @brief Zero flag - bool z : 1; //! @brief Carry flag bool c : 1; + //! @brief Zero flag + bool z : 1; + //! @brief Interrupt enabled flag + bool i : 1; + //! @brief Half carry flag + bool h : 1; + //! @brief Break flag + bool b : 1; + //! @brief Direct page flag + bool p : 1; + //! @brief Overflow flag + bool v : 1; + //! @brief Negative flag + bool n : 1; }; uint8_t psw; }; @@ -393,6 +394,9 @@ namespace ComSquare::APU //! @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); + //! @brief This function execute the instructions received until the maximum number of cycles is reached. //! @return The number of cycles that elapsed. virtual void update(unsigned cycles); diff --git a/sources/Debugger/APUDebug.cpp b/sources/Debugger/APUDebug.cpp index 3222f8d..4b2b521 100644 --- a/sources/Debugger/APUDebug.cpp +++ b/sources/Debugger/APUDebug.cpp @@ -81,7 +81,7 @@ namespace ComSquare::Debugger this->_ui.xIndexLineEdit->setText(Utility::to_hex(this->_internalRegisters.x).c_str()); this->_ui.yIndexLineEdit->setText(Utility::to_hex(this->_internalRegisters.y).c_str()); this->_ui.accumlatorLineEdit->setText(Utility::to_hex(this->_internalRegisters.a).c_str()); - this->_ui.programCounterLineEdit->setText(Utility::to_hex(this->_internalRegisters.pc + 0x0001u).c_str()); + this->_ui.programCounterLineEdit->setText(Utility::to_hex(this->_internalRegisters.pc).c_str()); this->_ui.programStatusWordLineEdit->setText(this->_getPSWString().c_str()); auto voices = this->_dsp.getVoices(); @@ -90,12 +90,13 @@ namespace ComSquare::Debugger auto noise = this->_dsp.getNoise(); auto brr = this->_dsp.getBrr(); auto latch = this->_dsp.getLatch(); + auto max = std::numeric_limits::max(); - this->_ui.mvolLprogressBar->setValue(master.volume[0]); - this->_ui.mvolRprogressBar->setValue(master.volume[1]); - this->_ui.evolLprogressBar->setValue(echo.volume[0]); - this->_ui.evolRprogressBar->setValue(echo.volume[1]); - this->_ui.echoprogressBar->setValue(echo.feedback); + this->_ui.mvolLprogressBar->setValue(master.volume[0] * 100 / max); + this->_ui.mvolRprogressBar->setValue(master.volume[1] * 100 / max); + this->_ui.evolLprogressBar->setValue(echo.volume[0] * 100 / max); + this->_ui.evolRprogressBar->setValue(echo.volume[1] * 100 / max); + this->_ui.echoprogressBar->setValue(echo.feedback * 100 / max); uint8_t flg = 0; flg += master.reset << 7; @@ -107,10 +108,10 @@ namespace ComSquare::Debugger this->_ui.echoBufferOffsetLineEdit->setText(Utility::to_hex(echo.data).c_str()); this->_ui.echoDelayLineEdit->setText(Utility::to_hex(echo.delay).c_str()); - this->_ui.VolumeLprogressBar->setValue(voices[0].volume[0]); - this->_ui.VolumeRprogressBar->setValue(voices[0].volume[1]); - this->_ui.WaveHeightprogressBar->setValue(latch.outx); - this->_ui.EchoFIRCoeffprogressBar->setValue(echo.FIR[0]); + this->_ui.VolumeLprogressBar->setValue(voices[0].volume[0] * 100 / max); + this->_ui.VolumeRprogressBar->setValue(voices[0].volume[1] * 100 / max); + this->_ui.WaveHeightprogressBar->setValue(latch.outx * 100 / max); + this->_ui.EchoFIRCoeffprogressBar->setValue(echo.FIR[0] * 100 / max); this->_ui.PitchlineEdit->setText(Utility::to_hex(voices[0].pitch).c_str()); this->_ui.sourceNumberLineEdit->setText(Utility::to_hex(voices[0].srcn).c_str()); this->_ui.GainlineEdit->setText(Utility::to_hex(voices[0].gain).c_str()); @@ -123,10 +124,10 @@ namespace ComSquare::Debugger this->_ui.SampleEndcheckBox->setChecked(voices[0].endx); this->_ui.PitchModulationcheckBox->setChecked(voices[0].pmon); - this->_ui.VolumeLprogressBar_2->setValue(voices[1].volume[0]); - this->_ui.VolumeRprogressBar_2->setValue(voices[1].volume[1]); - this->_ui.WaveHeightprogressBar_2->setValue(latch.outx); - this->_ui.EchoFIRCoeffprogressBar_2->setValue(echo.FIR[1]); + this->_ui.VolumeLprogressBar_2->setValue(voices[1].volume[0] * 100 / max); + this->_ui.VolumeRprogressBar_2->setValue(voices[1].volume[1] * 100 / max); + this->_ui.WaveHeightprogressBar_2->setValue(latch.outx * 100 / max); + this->_ui.EchoFIRCoeffprogressBar_2->setValue(echo.FIR[1] * 100 / max); this->_ui.PitchlineEdit_2->setText(Utility::to_hex(voices[1].pitch).c_str()); this->_ui.sourceNumberLineEdit_2->setText(Utility::to_hex(voices[1].srcn).c_str()); this->_ui.GainlineEdit_2->setText(Utility::to_hex(voices[1].gain).c_str()); @@ -139,10 +140,10 @@ namespace ComSquare::Debugger this->_ui.SampleEndcheckBox_2->setChecked(voices[1].endx); this->_ui.PitchModulationcheckBox_2->setChecked(voices[1].pmon); - this->_ui.VolumeLprogressBar_3->setValue(voices[2].volume[0]); - this->_ui.VolumeRprogressBar_3->setValue(voices[2].volume[1]); - this->_ui.WaveHeightprogressBar_3->setValue(latch.outx); - this->_ui.EchoFIRCoeffprogressBar_3->setValue(echo.FIR[2]); + this->_ui.VolumeLprogressBar_3->setValue(voices[2].volume[0] * 100 / max); + this->_ui.VolumeRprogressBar_3->setValue(voices[2].volume[1] * 100 / max); + this->_ui.WaveHeightprogressBar_3->setValue(latch.outx * 100 / max); + this->_ui.EchoFIRCoeffprogressBar_3->setValue(echo.FIR[2] * 100 / max); this->_ui.PitchlineEdit_3->setText(Utility::to_hex(voices[2].pitch).c_str()); this->_ui.sourceNumberLineEdit_3->setText(Utility::to_hex(voices[2].srcn).c_str()); this->_ui.GainlineEdit_3->setText(Utility::to_hex(voices[2].gain).c_str()); @@ -155,10 +156,10 @@ namespace ComSquare::Debugger this->_ui.SampleEndcheckBox_3->setChecked(voices[2].endx); this->_ui.PitchModulationcheckBox_3->setChecked(voices[2].pmon); - this->_ui.VolumeLprogressBar_4->setValue(voices[3].volume[0]); - this->_ui.VolumeRprogressBar_4->setValue(voices[3].volume[1]); - this->_ui.WaveHeightprogressBar_4->setValue(latch.outx); - this->_ui.EchoFIRCoeffprogressBar_4->setValue(echo.FIR[3]); + this->_ui.VolumeLprogressBar_4->setValue(voices[3].volume[0] * 100 / max); + this->_ui.VolumeRprogressBar_4->setValue(voices[3].volume[1] * 100 / max); + this->_ui.WaveHeightprogressBar_4->setValue(latch.outx * 100 / max); + this->_ui.EchoFIRCoeffprogressBar_4->setValue(echo.FIR[3] * 100 / max); this->_ui.PitchlineEdit_4->setText(Utility::to_hex(voices[3].pitch).c_str()); this->_ui.sourceNumberLineEdit_4->setText(Utility::to_hex(voices[3].srcn).c_str()); this->_ui.GainlineEdit_4->setText(Utility::to_hex(voices[3].gain).c_str()); @@ -171,10 +172,10 @@ namespace ComSquare::Debugger this->_ui.SampleEndcheckBox_4->setChecked(voices[3].endx); this->_ui.PitchModulationcheckBox_4->setChecked(voices[3].pmon); - this->_ui.VolumeLprogressBar_5->setValue(voices[4].volume[0]); - this->_ui.VolumeRprogressBar_5->setValue(voices[4].volume[1]); - this->_ui.WaveHeightprogressBar_5->setValue(latch.outx); - this->_ui.EchoFIRCoeffprogressBar_5->setValue(echo.FIR[4]); + this->_ui.VolumeLprogressBar_5->setValue(voices[4].volume[0] * 100 / max); + this->_ui.VolumeRprogressBar_5->setValue(voices[4].volume[1] * 100 / max); + this->_ui.WaveHeightprogressBar_5->setValue(latch.outx * 100 / max); + this->_ui.EchoFIRCoeffprogressBar_5->setValue(echo.FIR[4] * 100 / max); this->_ui.PitchlineEdit_5->setText(Utility::to_hex(voices[4].pitch).c_str()); this->_ui.sourceNumberLineEdit_5->setText(Utility::to_hex(voices[4].srcn).c_str()); this->_ui.GainlineEdit_5->setText(Utility::to_hex(voices[4].gain).c_str()); @@ -187,10 +188,10 @@ namespace ComSquare::Debugger this->_ui.SampleEndcheckBox_5->setChecked(voices[4].endx); this->_ui.PitchModulationcheckBox_5->setChecked(voices[4].pmon); - this->_ui.VolumeLprogressBar_6->setValue(voices[5].volume[0]); - this->_ui.VolumeRprogressBar_6->setValue(voices[5].volume[1]); - this->_ui.WaveHeightprogressBar_6->setValue(latch.outx); - this->_ui.EchoFIRCoeffprogressBar_6->setValue(echo.FIR[5]); + this->_ui.VolumeLprogressBar_6->setValue(voices[5].volume[0] * 100 / max); + this->_ui.VolumeRprogressBar_6->setValue(voices[5].volume[1] * 100 / max); + this->_ui.WaveHeightprogressBar_6->setValue(latch.outx * 100 / max); + this->_ui.EchoFIRCoeffprogressBar_6->setValue(echo.FIR[5] * 100 / max); this->_ui.PitchlineEdit_6->setText(Utility::to_hex(voices[5].pitch).c_str()); this->_ui.sourceNumberLineEdit_6->setText(Utility::to_hex(voices[5].srcn).c_str()); this->_ui.GainlineEdit_6->setText(Utility::to_hex(voices[5].gain).c_str()); @@ -203,10 +204,10 @@ namespace ComSquare::Debugger this->_ui.SampleEndcheckBox_6->setChecked(voices[5].endx); this->_ui.PitchModulationcheckBox_6->setChecked(voices[5].pmon); - this->_ui.VolumeLprogressBar_7->setValue(voices[6].volume[0]); - this->_ui.VolumeRprogressBar_7->setValue(voices[6].volume[1]); - this->_ui.WaveHeightprogressBar_7->setValue(latch.outx); - this->_ui.EchoFIRCoeffprogressBar_7->setValue(echo.FIR[6]); + this->_ui.VolumeLprogressBar_7->setValue(voices[6].volume[0] * 100 / max); + this->_ui.VolumeRprogressBar_7->setValue(voices[6].volume[1] * 100 / max); + this->_ui.WaveHeightprogressBar_7->setValue(latch.outx * 100 / max); + this->_ui.EchoFIRCoeffprogressBar_7->setValue(echo.FIR[6] * 100 / max); this->_ui.PitchlineEdit_7->setText(Utility::to_hex(voices[6].pitch).c_str()); this->_ui.sourceNumberLineEdit_7->setText(Utility::to_hex(voices[6].srcn).c_str()); this->_ui.GainlineEdit_7->setText(Utility::to_hex(voices[6].gain).c_str()); @@ -219,10 +220,10 @@ namespace ComSquare::Debugger this->_ui.SampleEndcheckBox_7->setChecked(voices[6].endx); this->_ui.PitchModulationcheckBox_7->setChecked(voices[6].pmon); - this->_ui.VolumeLprogressBar_8->setValue(voices[7].volume[0]); - this->_ui.VolumeRprogressBar_8->setValue(voices[7].volume[1]); - this->_ui.WaveHeightprogressBar_8->setValue(latch.outx); - this->_ui.EchoFIRCoeffprogressBar_8->setValue(echo.FIR[7]); + this->_ui.VolumeLprogressBar_8->setValue(voices[7].volume[0] * 100 / max); + this->_ui.VolumeRprogressBar_8->setValue(voices[7].volume[1] * 100 / max); + this->_ui.WaveHeightprogressBar_8->setValue(latch.outx * 100 / max); + this->_ui.EchoFIRCoeffprogressBar_8->setValue(echo.FIR[7] * 100 / max); this->_ui.PitchlineEdit_8->setText(Utility::to_hex(voices[7].pitch).c_str()); this->_ui.sourceNumberLineEdit_8->setText(Utility::to_hex(voices[7].srcn).c_str()); this->_ui.GainlineEdit_8->setText(Utility::to_hex(voices[7].gain).c_str()); diff --git a/sources/Ram/Ram.cpp b/sources/Ram/Ram.cpp index de8dc98..85951a7 100644 --- a/sources/Ram/Ram.cpp +++ b/sources/Ram/Ram.cpp @@ -56,4 +56,9 @@ namespace ComSquare::Ram { return this->_ramType; } + + uint8_t *Ram::getData() const + { + return this->_data; + } } diff --git a/sources/Ram/Ram.hpp b/sources/Ram/Ram.hpp index d3e4916..52c498c 100644 --- a/sources/Ram/Ram.hpp +++ b/sources/Ram/Ram.hpp @@ -50,6 +50,9 @@ namespace ComSquare::Ram //! @brief Get the size of the ram in bytes. uint24_t getSize() const override; + + //! @brief Get the raw data of the RAM + uint8_t *getData() const; }; } diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 0d2b9c3..5323310 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -24,12 +24,17 @@ namespace ComSquare apu(new APU::APU(renderer)) { this->bus->mapComponents(*this); + if (this->cartridge->getType() == Cartridge::Audio) + this->apu->loadFromSPC(this->cartridge); } void SNES::update() { if (this->cartridge->getType() == Cartridge::Audio) + { + this->apu->update(0x01); return; + } unsigned cycleCount = this->cpu->update(); this->ppu->update(cycleCount); From 06cdafbf164c21558967444fb41ea8fdf6328276 Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Thu, 1 Apr 2021 14:20:02 +0200 Subject: [PATCH 3/8] Replace logger with basic disassembly in APU debugger (& fixing Absolute By X Address operand?) --- sources/APU/APU.cpp | 2 +- sources/APU/Operand.cpp | 8 +- sources/Debugger/APUDebug.cpp | 343 +++++++++--------------------- sources/Debugger/APUDebug.hpp | 308 ++++++++++++++++++++++++++- tests/APU/testAPUInstructions.cpp | 2 + tests/APU/testOperand.cpp | 3 +- ui/apuView.ui | 185 +++++++++++----- 7 files changed, 543 insertions(+), 308 deletions(-) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index 7e2cf67..93ff6ee 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -191,7 +191,7 @@ namespace ComSquare::APU int APU::_executeInstruction() { - uint8_t opcode = this->_internalRead(this->_internalRegisters.pc++); + uint8_t opcode = this->_getImmediateData(); switch (opcode) { case 0x00: diff --git a/sources/APU/Operand.cpp b/sources/APU/Operand.cpp index 4242612..2c2adf3 100644 --- a/sources/APU/Operand.cpp +++ b/sources/APU/Operand.cpp @@ -65,8 +65,12 @@ namespace ComSquare::APU uint24_t APU::_getAbsoluteByXAddr() { - uint24_t addr1 = this->_getImmediateData() + this->_internalRegisters.x; - uint24_t addr2 = this->_getImmediateData() + this->_internalRegisters.x++; + uint24_t addr1 = this->_getImmediateData(); + uint24_t addr2 = this->_getImmediateData(); + uint24_t full = (addr2 << 8) | addr1; + + addr1 = this->_internalRead(full + this->_internalRegisters.x); + addr2 = this->_internalRead(full + this->_internalRegisters.x + 1); return (addr2 << 8u) | addr1; } diff --git a/sources/Debugger/APUDebug.cpp b/sources/Debugger/APUDebug.cpp index 4b2b521..994a887 100644 --- a/sources/Debugger/APUDebug.cpp +++ b/sources/Debugger/APUDebug.cpp @@ -23,6 +23,11 @@ namespace ComSquare::Debugger this->_ui.setupUi(this->_window); QMainWindow::connect(this->_ui.resumeButton, &QPushButton::clicked, this, &APUDebug::pause); QMainWindow::connect(this->_ui.stepButton, &QPushButton::clicked, this, &APUDebug::step); + this->_ui.logger->setRowCount(0x20); + this->_ui.logger->setColumnCount(3); + this->_ui.logger->horizontalHeader()->setHidden(true); + this->_ui.logger->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + this->_ui.logger->setShowGrid(false); this->_window->show(); this->_updatePanel(); } @@ -82,7 +87,14 @@ namespace ComSquare::Debugger this->_ui.yIndexLineEdit->setText(Utility::to_hex(this->_internalRegisters.y).c_str()); this->_ui.accumlatorLineEdit->setText(Utility::to_hex(this->_internalRegisters.a).c_str()); this->_ui.programCounterLineEdit->setText(Utility::to_hex(this->_internalRegisters.pc).c_str()); - this->_ui.programStatusWordLineEdit->setText(this->_getPSWString().c_str()); + this->_ui.bFlagCheckBox->setChecked(this->_internalRegisters.b); + this->_ui.nFlagCheckBox->setChecked(this->_internalRegisters.n); + this->_ui.pFlagCheckBox->setChecked(this->_internalRegisters.p); + this->_ui.hFlagCheckBox->setChecked(this->_internalRegisters.h); + this->_ui.vFlagCheckBox->setChecked(this->_internalRegisters.v); + this->_ui.iFlagCheckBox->setChecked(this->_internalRegisters.i); + this->_ui.zFlagCheckBox->setChecked(this->_internalRegisters.z); + this->_ui.cFlagCheckBox->setChecked(this->_internalRegisters.c); auto voices = this->_dsp.getVoices(); auto master = this->_dsp.getMaster(); @@ -235,256 +247,94 @@ namespace ComSquare::Debugger this->_ui.EchocheckBox_8->setChecked(voices[7].eon); this->_ui.SampleEndcheckBox_8->setChecked(voices[7].endx); this->_ui.PitchModulationcheckBox_8->setChecked(voices[7].pmon); + + this->_updateLogger(); } - std::string APUDebug::_getPSWString() + void APUDebug::_updateLogger() { - std::string str; - str += this->_internalRegisters.n ? 'n' : '-'; - str += this->_internalRegisters.v ? 'v' : '-'; - str += this->_internalRegisters.p ? 'p' : '-'; - str += this->_internalRegisters.b ? 'b' : '-'; - str += this->_internalRegisters.h ? 'h' : '-'; - str += this->_internalRegisters.i ? 'i' : '-'; - str += this->_internalRegisters.z ? 'z' : '-'; - str += this->_internalRegisters.c ? 'c' : '-'; - return str; - } + QStringList labels = QStringList(); + uint16_t offset = 0; - std::string APUDebug::_getInstructionString() - { - uint8_t opcode = this->_internalRead(this->_internalRegisters.pc); + for (uint16_t i = 0; i < 0x20; i++) + { + auto pc = this->_internalRegisters.pc; + auto instruction = this->_getInstruction(); + std::string operand; - switch (opcode) { - case 0x00: - return "NOP"; - case 0x10: - return "BPL"; - case 0x20: - return "CLRP"; - case 0x30: - return "BMI"; - case 0x40: - return "SETP"; - case 0x50: - return "BVC"; - case 0x60: - return "CLRC"; - case 0x70: - return "BVS"; - case 0x80: - return "SETC"; - case 0x90: - return "BCC"; - case 0xA0: - return "EI"; - case 0xB0: - return "BCS"; - case 0xC0: - return "DI"; - case 0xD0: - return "BNE"; - case 0xE0: - return "CLRV"; - case 0xF0: - return "BEQ"; - case 0x01: - case 0x11: - case 0x21: - case 0x31: - case 0x41: - case 0x51: - case 0x61: - case 0x71: - case 0x81: - case 0x91: - case 0xA1: - case 0xB1: - case 0xC1: - case 0xD1: - case 0xE1: - case 0xF1: - return "TCALL"; - case 0x02: - case 0x22: - case 0x42: - case 0x62: - case 0x82: - case 0xA2: - case 0xC2: - case 0xE2: - return "SET1"; - case 0x12: - case 0x32: - case 0x52: - case 0x72: - case 0x92: - case 0xB2: - case 0xD2: - case 0xF2: - return "CLR1"; - case 0x03: - case 0x13: - case 0x23: - case 0x33: - case 0x43: - case 0x53: - case 0x63: - case 0x73: - case 0x83: - case 0x93: - case 0xA3: - case 0xB3: - case 0xC3: - case 0xD3: - case 0xE3: - case 0xF3: - return "BBC"; - case 0x04 ... 0x09: - case 0x14 ... 0x19: - return "OR"; - case 0x24 ... 0x29: - case 0x34 ... 0x39: - return "AND"; - case 0x44 ... 0x49: - case 0x54 ... 0x59: - return "EOR"; - case 0x64 ... 0x69: - case 0x74 ... 0x79: - case 0xC8: - case 0xAD: - case 0x1E: - case 0x3E: - case 0x5E: - case 0x7E: - return "CMP"; - case 0x84 ... 0x89: - case 0x94 ... 0x99: - return "ADC"; - case 0xA4 ... 0xA9: - case 0xB4 ... 0xB9: - return "SBC"; - case 0xC4 ... 0xC7: - case 0xCB ... 0xCD: - case 0xD4 ... 0xD9: - case 0xE4 ... 0xE9: - case 0xEB ... 0xEC: - case 0xF4 ... 0xFB: - case 0xDB: - case 0xC9: - case 0x5D: - case 0x7D: - case 0x8D: - case 0x9D: - case 0xBD: - case 0xDD: - case 0xFD: - case 0x8F: - case 0xAF: - case 0xBF: - return "MOV"; - case 0x0A: - case 0x2A: - return "OR1"; - case 0x1A: - return "DECW"; - case 0x3A: - return "INCW"; - case 0x4A: - case 0x6A: - return "AND1"; - case 0x5A: - return "CMPW"; - case 0x7A: - return "ADDW"; - case 0x8A: - return "EOR1"; - case 0x9A: - return "SUBW"; - case 0xAA: - case 0xCA: - return "MOV1"; - case 0xBA: - case 0xDA: - return "MOVW"; - case 0xEA: - return "NOT1"; - case 0x0B ... 0x0C: - case 0x1B ... 0x1C: - return "ASL"; - case 0x2B ... 0x2C: - case 0x3B ... 0x3C: - return "ROL"; - case 0x4B ... 0x4C: - case 0x5B ... 0x5C: - return "LSR"; - case 0x6B ... 0x6C: - case 0x7B ... 0x7C: - return "ROR"; - case 0x8B ... 0x8C: - case 0x9B ... 0x9C: - case 0xDC: - case 0x1D: - return "DEC"; - case 0xAB ... 0xAC: - case 0xBB ... 0xBC: - case 0xFC: - case 0x3D: - return "INC"; - case 0x0D: - case 0x2D: - case 0x4D: - case 0x6D: - return "PUSH"; - case 0xED: - return "NOTC"; - case 0x0E: - return "TSET1"; - case 0x2E: - case 0xDE: - return "CBNE"; - case 0x4E: - return "TCLR1"; - case 0x6E: - case 0xFE: - return "DBNZ"; - case 0x8E: - case 0xAE: - case 0xCE: - case 0xEE: - return "POP"; - case 0x9E: - return "DIV"; - case 0xBE: - return "DAS"; - case 0x0F: - return "BRK"; - case 0x1F: - case 0x5F: - return "JMP"; - case 0x2F: - return "BRA"; - case 0x3F: - return "CALL"; - case 0x4F: - return "PCALL"; - case 0x6F: - return "RET"; - case 0x7F: - return "RETI"; - case 0x9F: - return "XCN"; - case 0xCF: - return "MUL"; - case 0xDF: - return "DAA"; - case 0xEF: - return "SLEEP"; - case 0xFF: - return "STOP"; - default: - return "Unknown"; + this->_ui.logger->setItem(i, 0, new QTableWidgetItem(instruction.name.c_str())); + + operand = this->_getOperand(std::get<0>(instruction.operands)); + this->_ui.logger->setItem(i, 1, new QTableWidgetItem(operand.c_str())); + if (operand.empty()) + this->_ui.logger->item(i, 1)->setData(Qt::BackgroundRole, QColor(220, 220, 220)); + + operand = this->_getOperand(std::get<1>(instruction.operands)); + this->_ui.logger->setItem(i, 2, new QTableWidgetItem(operand.c_str())); + if (operand.empty()) + this->_ui.logger->item(i, 2)->setData(Qt::BackgroundRole, QColor(220, 220, 220)); + + labels.append(Utility::to_hex(pc).c_str()); + offset += instruction.size; } + this->_ui.logger->setVerticalHeaderLabels(labels); + for (int i = 0; i < 3; i++) + this->_ui.logger->item(0, i)->setData(Qt::BackgroundRole, QColor(200, 255, 148)); + this->_internalRegisters.pc -= offset; + } + + std::string APUDebug::_getOperand(Operand ope) + { + switch (ope) { + case None: + return ""; + case A: + return Utility::to_hex(this->_internalRegisters.a); + case X: + return Utility::to_hex(this->_internalRegisters.x); + case Y: + return Utility::to_hex(this->_internalRegisters.y); + case SP: + return Utility::to_hex(this->_internalRegisters.sp); + case PSW: + return Utility::to_hex(this->_internalRegisters.psw); + case ImmediateData: + return Utility::to_hex(this->_getImmediateData()); + case IndexXAddr: + return Utility::to_hex(this->_getIndexXAddr()); + case IndexYAddr: + return Utility::to_hex(this->_getIndexYAddr()); + case AbsoluteAddr: + return Utility::to_hex(this->_getAbsoluteAddr()); + case AbsoluteBit: { + auto pair = this->_getAbsoluteBit(); + return Utility::to_hex(std::get<0>(pair)) + Utility::to_hex(std::get<1>(pair)); + } + case AbsoluteAddrByX: + return Utility::to_hex(this->_getAbsoluteAddrByX()); + case AbsoluteAddrByY: + return Utility::to_hex(this->_getAbsoluteAddrByY()); + case AbsoluteByXAddr: + return Utility::to_hex(this->_getAbsoluteByXAddr()); + case AbsoluteDirectByXAddr: + return Utility::to_hex(this->_getAbsoluteDirectByXAddr()); + case AbsoluteDirectAddrByY: + return Utility::to_hex(this->_getAbsoluteDirectAddrByY()); + case DirectAddr: + return Utility::to_hex(this->_getDirectAddr()); + case DirectAddrByX: + return Utility::to_hex(this->_getDirectAddrByX()); + case DirectAddrByY: + return Utility::to_hex(this->_getDirectAddrByY()); + } + return "UNKNOWN"; + } + + Instruction &APUDebug::_getInstruction() + { + uint8_t opcode = this->_getImmediateData(); + + return this->_instructions[opcode]; } int APUDebug::_executeInstruction() @@ -497,7 +347,6 @@ namespace ComSquare::Debugger this->_isStepping = false; this->_isPaused = true; } - this->_ui.logger->append(APUDebug::_getInstructionString().c_str()); cycles = APU::_executeInstruction(); this->_updatePanel(); return cycles; @@ -511,7 +360,7 @@ namespace ComSquare::Debugger APU::update(cycles); } catch (InvalidOpcode &e) { this->pause(); - this->_ui.logger->append(e.what()); + //this->_ui.logger->append(e.what()); } } diff --git a/sources/Debugger/APUDebug.hpp b/sources/Debugger/APUDebug.hpp index f907208..44f7ead 100644 --- a/sources/Debugger/APUDebug.hpp +++ b/sources/Debugger/APUDebug.hpp @@ -11,8 +11,301 @@ namespace ComSquare::Debugger { - class APUDebug : public APU::APU, public QObject { + //! @brief List of all types of operands used by the instructions + enum Operand + { + None, + A, + X, + Y, + SP, + PSW, + ImmediateData, + IndexXAddr, + IndexYAddr, + AbsoluteBit, + AbsoluteAddr, + AbsoluteAddrByX, + AbsoluteAddrByY, + AbsoluteByXAddr, + AbsoluteDirectByXAddr, + AbsoluteDirectAddrByY, + DirectAddr, + DirectAddrByX, + DirectAddrByY + }; + + //! @brief Small structure to store some values on the instructions + struct Instruction + { + std::string name; + int size; + std::tuple operands; + }; + + class APUDebug : public APU::APU, public QObject + { private: + //! @brief List of instructions and their information + std::array _instructions {{ + {"NOP", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"OR", 2, {DirectAddr, None}}, + {"OR", 3, {AbsoluteAddr, None}}, + {"OR", 1, {IndexXAddr, None}}, + {"OR", 2, {AbsoluteDirectByXAddr, None}}, + {"OR", 2, {ImmediateData, None}}, + {"OR", 3, {DirectAddr, DirectAddr}}, + {"OR1", 3, {AbsoluteBit, None}}, + {"ASL", 2, {DirectAddr, None}}, + {"ASL", 3, {AbsoluteAddr, None}}, + {"PUSH", 1, {PSW, None}}, + {"TSET1", 3, {AbsoluteAddr, None}}, + {"BRK", 1, {None, None}}, + {"BPL", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"OR", 2, {DirectAddrByX, None}}, + {"OR", 3, {AbsoluteAddrByX, None}}, + {"OR", 3, {AbsoluteAddrByY, None}}, + {"OR", 2, {AbsoluteDirectAddrByY, None}}, + {"OR", 3, {DirectAddr, ImmediateData}}, + {"OR", 1, {IndexYAddr, IndexYAddr}}, + {"DECW", 2, {DirectAddr, None}}, + {"ASL", 2, {DirectAddrByX, None}}, + {"ASL", 1, {A, None}}, + {"DEC", 1, {X, None}}, + {"CMP", 3, {X, AbsoluteAddr}}, + {"JMP", 3, {AbsoluteByXAddr, None}}, + {"CLRP", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"AND", 2, {DirectAddr, None}}, + {"AND", 3, {AbsoluteAddr, None}}, + {"AND", 1, {IndexXAddr, None}}, + {"AND", 2, {AbsoluteDirectByXAddr, None}}, + {"AND", 2, {ImmediateData, None}}, + {"AND", 3, {DirectAddr, DirectAddr}}, + {"OR1", 3, {AbsoluteBit, None}}, + {"ROL", 2, {DirectAddr, None}}, + {"ROL", 3, {AbsoluteAddr, None}}, + {"PUSH", 1, {A, None}}, + {"CBNE", 3, {ImmediateData, ImmediateData}}, + {"BRA", 2, {ImmediateData, None}}, + {"BMI", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"AND", 2, {DirectAddrByX, None}}, + {"AND", 3, {AbsoluteAddrByX, None}}, + {"AND", 3, {AbsoluteAddrByY, None}}, + {"AND", 2, {AbsoluteDirectAddrByY, None}}, + {"AND", 3, {DirectAddr, ImmediateData}}, + {"AND", 1, {IndexXAddr, IndexYAddr}}, + {"INCW", 2, {DirectAddr, None}}, + {"ROL", 2, {AbsoluteAddrByX, None}}, + {"ROL", 1, {A, None}}, + {"INC", 1, {X, None}}, + {"CMP", 2, {X, DirectAddr}}, + {"CALL", 3, {AbsoluteAddr, None}}, + {"SETP", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"EOR", 2, {DirectAddr, None}}, + {"EOR", 3, {AbsoluteAddr, None}}, + {"EOR", 1, {IndexXAddr, None}}, + {"EOR", 2, {AbsoluteDirectByXAddr, None}}, + {"EOR", 2, {ImmediateData, None}}, + {"EOR", 3, {DirectAddr, DirectAddr}}, + {"AND1", 3, {AbsoluteBit, None}}, + {"LSR", 2, {DirectAddr, None}}, + {"LSR", 3, {AbsoluteAddr, None}}, + {"PUSH", 1, {X, None}}, + {"TCLR1", 3, {AbsoluteAddr, None}}, + {"PCALL", 3, {None, None}}, + {"BVC", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"EOR", 2, {DirectAddrByX, None}}, + {"EOR", 3, {AbsoluteAddrByX, None}}, + {"EOR", 3, {AbsoluteAddrByY, None}}, + {"EOR", 2, {AbsoluteDirectAddrByY, None}}, + {"EOR", 3, {DirectAddr, ImmediateData}}, + {"EOR", 1, {IndexXAddr, IndexYAddr}}, + {"CMPW", 2, {DirectAddr, None}}, + {"LSR", 2, {DirectAddrByX, None}}, + {"LSR", 1, {A, None}}, + {"MOV", 1, {A, X}}, + {"CMP", 3, {Y, AbsoluteAddr}}, + {"JMP", 3, {AbsoluteAddr, None}}, + {"CLRC", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"CMP", 2, {A, DirectAddr}}, + {"CMP", 3, {A, AbsoluteAddr}}, + {"CMP", 1, {A, IndexXAddr,}}, + {"CMP", 2, {A, AbsoluteDirectByXAddr}}, + {"CMP", 2, {A, ImmediateData}}, + {"CMP", 3, {DirectAddr, DirectAddr}}, + {"AND1", 3, {AbsoluteBit, None}}, + {"ROR", 2, {DirectAddr , None}}, + {"ROR", 3, {AbsoluteAddr, None}}, + {"PUSH", 1, {Y, None}}, + {"DBNZ", 3, {ImmediateData, None}}, + {"RET", 1, {None, None}}, + {"BVS", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"CMP", 2, {A, DirectAddrByX}}, + {"CMP", 3, {A, AbsoluteAddrByX}}, + {"CMP", 3, {A, AbsoluteAddrByY}}, + {"CMP", 2, {A, AbsoluteDirectAddrByY}}, + {"CMP", 3, {DirectAddr, ImmediateData}}, + {"CMP", 1, {IndexXAddr, IndexYAddr}}, + {"ADDW", 2, {DirectAddr, None}}, + {"ROR", 2, {DirectAddrByX, None}}, + {"ROR", 1, {A, None}}, + {"MOV", 1, {X, A}}, + {"CMP", 3, {Y, DirectAddr}}, + {"RETI", 1, {None, None}}, + {"SETC", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"ADC", 2, {DirectAddr, None}}, + {"ADC", 3, {AbsoluteAddr, None}}, + {"ADC", 1, {IndexXAddr, None}}, + {"ADC", 2, {AbsoluteDirectByXAddr, None}}, + {"ADC", 2, {ImmediateData, None}}, + {"ADC", 3, {DirectAddr, DirectAddr}}, + {"EOR1", 3, {AbsoluteBit, None}}, + {"DEC", 2, {DirectAddr, None}}, + {"DEC", 3, {AbsoluteAddr, None}}, + {"MOV", 2, {ImmediateData, Y}}, + {"POP", 1, {PSW, None}}, + {"MOV", 3, {DirectAddr, ImmediateData}}, + {"BCC", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"ADC", 2, {DirectAddrByX, None}}, + {"ADC", 3, {AbsoluteAddrByX, None}}, + {"ADC", 3, {AbsoluteAddrByY, None}}, + {"ADC", 2, {AbsoluteDirectAddrByY, None}}, + {"ADC", 3, {DirectAddr, ImmediateData}}, + {"ADC", 1, {IndexXAddr, IndexYAddr}}, + {"SUBW", 2, {DirectAddr, None}}, + {"DEC", 2, {DirectAddrByX, None}}, + {"DEC", 1, {A, None}}, + {"MOV", 1, {SP, X}}, + {"DIV", 1, {None, None}}, + {"XCN", 1, {None, None}}, + {"EI", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"SBC", 2, {DirectAddr, None}}, + {"SBC", 3, {AbsoluteAddr, None}}, + {"SBC", 1, {IndexXAddr, None}}, + {"SBC", 2, {AbsoluteDirectByXAddr, None}}, + {"SBC", 2, {ImmediateData, None}}, + {"SBC", 3, {DirectAddr, DirectAddr}}, + {"MOV1", 3, {AbsoluteBit, None}}, + {"INC", 2, {DirectAddr, None}}, + {"INC", 3, {AbsoluteAddr, None}}, + {"CMP", 2, {Y, ImmediateData}}, + {"POP", 1, {A, None}}, + {"MOV", 1, {A, IndexXAddr}}, + {"BCS", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"SBC", 2, {DirectAddrByX, None}}, + {"SBC", 3, {AbsoluteAddrByX, None}}, + {"SBC", 3, {AbsoluteAddrByY, None}}, + {"SBC", 2, {AbsoluteDirectAddrByY, None}}, + {"SBC", 2, {DirectAddr, ImmediateData}}, + {"SBC", 1, {IndexXAddr, IndexYAddr}}, + {"MOVW", 2, {DirectAddr, None}}, + {"INC", 2, {DirectAddrByX, None}}, + {"INC", 1, {A, None}}, + {"MOV", 1, {X, SP}}, + {"DAS", 1, {None, None}}, + {"MOV", 1, {IndexXAddr, A}}, + {"DI", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"MOV", 2, {A, DirectAddr}}, + {"MOV", 3, {A, AbsoluteAddr}}, + {"MOV", 1, {A, IndexXAddr}}, + {"MOV", 2, {A, AbsoluteDirectByXAddr}}, + {"CMP", 2, {X, ImmediateData}}, + {"MOV", 3, {X, AbsoluteAddr}}, + {"MOV1", 3, {AbsoluteBit, None}}, + {"MOV", 2, {Y, DirectAddr}}, + {"MOV", 3, {Y, AbsoluteAddr}}, + {"MOV", 2, {ImmediateData, X}}, + {"POP", 1, {X, None}}, + {"MUL", 1, {None, None}}, + {"BNE", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"MOV", 2, {A, DirectAddrByX}}, + {"MOV", 3, {A, AbsoluteAddrByX}}, + {"MOV", 3, {A, AbsoluteAddrByY}}, + {"MOV", 2, {A, AbsoluteDirectAddrByY}}, + {"MOV", 2, {X, DirectAddr}}, + {"MOV", 2, {X, DirectAddrByY}}, + {"MOVW", 2, {DirectAddr, None}}, + {"MOV", 2, {Y, DirectAddrByX}}, + {"DEC", 1, {Y, None}}, + {"MOV", 1, {Y, A}}, + {"CBNE", 3, {DirectAddrByX, ImmediateData}}, + {"DAA", 1, {None, None}}, + {"CLRV", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"MOV", 2, {DirectAddr, A}}, + {"MOV", 3, {AbsoluteAddrByX, A}}, + {"MOV", 1, {IndexXAddr, A}}, + {"MOV", 2, {AbsoluteDirectByXAddr, A}}, + {"MOV", 2, {ImmediateData, A}}, + {"MOV", 3, {AbsoluteAddr, X}}, + {"NOT1", 3, {AbsoluteBit, None}}, + {"MOV", 2, {DirectAddr, Y}}, + {"MOV", 3, {AbsoluteAddr, Y}}, + {"NOTC", 1, {None, None}}, + {"POP", 1, {Y, None}}, + {"SLEEP", 1, {None, None}}, + {"BEQ", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"MOV", 2, {DirectAddrByX, A}}, + {"MOV", 3, {AbsoluteAddrByX, A}}, + {"MOV", 3, {AbsoluteAddrByY, A}}, + {"MOV", 2, {AbsoluteDirectAddrByY, A}}, + {"MOV", 2, {DirectAddr, X}}, + {"MOV", 2, {DirectAddrByY, X}}, + {"MOV", 3, {DirectAddr, DirectAddr}}, + {"MOV", 2, {DirectAddrByX, Y}}, + {"INC", 1, {Y, None}}, + {"MOV", 1, {A, Y}}, + {"DBNZ", 3, {ImmediateData, None}}, + {"STOP", 1, {None, None}} + }}; + //! @brief The QT window for this debugger. ClosableWindow *_window; @@ -30,14 +323,18 @@ namespace ComSquare::Debugger //! @brief Update the debugger panel values void _updatePanel(); - //! @brief Convert CPU APU flags to a string. - std::string _getPSWString(); + //! @brief Updates the object that serves as the disassembly + void _updateLogger(); //! @brief Replace original _executeInstruction to write to the logger. int _executeInstruction() override; - //! @brief return the mnemonic of the current instruction done. - std::string _getInstructionString(); + //! @brief Retrieves the instruction from the SP location + Instruction &_getInstruction(); + + //! @brief Returns an operand in text format + std::string _getOperand(Operand ope); + public slots: //! @brief Pause/Resume the APU. void pause(); @@ -55,7 +352,6 @@ namespace ComSquare::Debugger //! @brief Override the apu's update to disable debugging. void update(unsigned cycles) override; - //! @brief Return true if the CPU is overloaded with debugging features. bool isDebugger() const override; diff --git a/tests/APU/testAPUInstructions.cpp b/tests/APU/testAPUInstructions.cpp index 4ee153b..1f47f26 100644 --- a/tests/APU/testAPUInstructions.cpp +++ b/tests/APU/testAPUInstructions.cpp @@ -736,6 +736,8 @@ Test(ProgramFlow, JMP) cr_assert_eq(apu->_internalRegisters.pc, 61455); apu->_internalRegisters.pc = 0x32; apu->_internalRegisters.x = 0b000000001; + apu->_internalWrite(0b1111000000001111 + 1, 0b00010000); + apu->_internalWrite(0b1111000000001111 + 2, 0b11110001); result = apu->JMP(apu->_getAbsoluteByXAddr(), true); cr_assert_eq(result, 6); cr_assert_eq(apu->_internalRegisters.pc, 61712); diff --git a/tests/APU/testOperand.cpp b/tests/APU/testOperand.cpp index 076c60c..b1abba3 100644 --- a/tests/APU/testOperand.cpp +++ b/tests/APU/testOperand.cpp @@ -94,7 +94,8 @@ Test(apu_get, absolutebyx) apu->_internalRegisters.x = 10; apu->_internalWrite(0x32, 0b00001111); apu->_internalWrite(0x33, 0b11110000); - cr_assert_eq(apu->_getAbsoluteByXAddr(), 64025); + apu->_internalWrite(0b1111000000001111 + 10, 255); + cr_assert_eq(apu->_getAbsoluteByXAddr(), 255); } Test(apu_get, absoluteaddrbyx) diff --git a/ui/apuView.ui b/ui/apuView.ui index 71a242d..5ea9e4f 100644 --- a/ui/apuView.ui +++ b/ui/apuView.ui @@ -6,8 +6,8 @@ 0 0 - 740 - 868 + 483 + 673 @@ -31,7 +31,7 @@ QTabWidget::Rounded - 0 + 1 @@ -329,23 +329,70 @@ CPU - - - - - - - Instructions History - - - Qt::AlignCenter - - + + + + + + + + + + SP + + + + + + + A + + + + + + + X + + + + + + + + + + + + + Y + + + + + + + + + + + + + PC + + + + + + + + true + Resume @@ -368,70 +415,106 @@ - - - - + + + + + + Qt::RightToLeft + - Stack Pointer + B - - - - - - - - - - - + + + + Qt::RightToLeft + - X Index + P - - + + + + Qt::RightToLeft + - Accumlator + Z - - - - - + + + + true + + + false + + + Qt::RightToLeft + + + C + + - - - - + + + Qt::RightToLeft + - Y Index + V - - + + + + Qt::RightToLeft + - Program Counter + H - - + + + + Qt::RightToLeft + - Program Status Word + I + + + + + + + Qt::RightToLeft + + + N + + + + Instructions History + + + Qt::AlignCenter + + + From eec17c932180e9614a4ce4297f4a37a005482e01 Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Mon, 7 Jun 2021 17:45:05 +0200 Subject: [PATCH 4/8] Fixing call to some isntructions --- sources/APU/APU.cpp | 249 +++++++++++++++++++++++----------- sources/APU/APU.hpp | 2 +- sources/APU/DSP/DSP.hpp | 2 +- sources/Debugger/APUDebug.cpp | 49 ++++--- sources/Debugger/APUDebug.hpp | 8 +- 5 files changed, 213 insertions(+), 97 deletions(-) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index 93ff6ee..edd1c9c 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -200,8 +200,11 @@ namespace ComSquare::APU return this->TCALL(0); case 0x02: return this->SET1(this->_getDirectAddr(), 0); - case 0x03: - return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 0); + case 0x03: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBS(addr, offset, 0); + } case 0x04: return this->ORacc(this->_getDirectAddr(), 3); case 0x05: @@ -212,8 +215,11 @@ namespace ComSquare::APU return this->ORacc(this->_getAbsoluteDirectByXAddr(), 6); case 0x08: return this->ORacc(this->_getImmediateData(), 2); - case 0x09: - return this->OR(this->_getDirectAddr(), this->_getDirectAddr(), 6); + case 0x09: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getDirectAddr(); + return this->OR(ope1, ope2, 6); + } case 0x0A: return this->OR1(this->_getAbsoluteBit()); case 0x0B: @@ -232,8 +238,11 @@ namespace ComSquare::APU return this->TCALL(1); case 0x12: return this->CLR1(this->_getDirectAddr(), 0); - case 0x13: - return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 0); + case 0x13: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getImmediateData(); + return this->BBC(ope1, ope2, 0); + } case 0x14: return this->ORacc(this->_getDirectAddrByX(), 4); case 0x15: @@ -242,8 +251,11 @@ namespace ComSquare::APU return this->ORacc(this->_getAbsoluteAddrByY(), 5); case 0x17: return this->ORacc(this->_getAbsoluteDirectAddrByY(), 6); - case 0x18: - return this->OR(this->_getDirectAddr(), this->_getImmediateData(), 5); + case 0x18: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getImmediateData(); + return this->OR(ope1, ope2, 5); + } case 0x19: return this->OR(this->_getIndexXAddr(), this->_getIndexYAddr(), 5); case 0x1A: @@ -264,8 +276,11 @@ namespace ComSquare::APU return this->TCALL(2); case 0x22: return this->SET1(this->_getDirectAddr(), 1); - case 0x23: - return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 1); + case 0x23: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getImmediateData(); + return this->BBS(ope1, ope2, 1); + } case 0x24: return this->ANDacc(this->_getDirectAddr(), 3); case 0x25: @@ -276,8 +291,11 @@ namespace ComSquare::APU return this->ANDacc(this->_getAbsoluteDirectByXAddr(), 6); case 0x28: return this->ANDacc(this->_getImmediateData(), 2); - case 0x29: - return this->AND(this->_getDirectAddr(), this->_getDirectAddr(), 6); + case 0x29: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getDirectAddr(); + return this->AND(ope1, ope2, 6); + } case 0x2A: return this->OR1(this->_getAbsoluteBit(), true); case 0x2B: @@ -286,8 +304,11 @@ namespace ComSquare::APU return this->ROL(this->_getAbsoluteAddr(), 5); case 0x2D: return this->PUSH(this->_internalRegisters.a); - case 0x2E: - return this->CBNE(this->_getImmediateData(), this->_getImmediateData()); + case 0x2E: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->CBNE(addr, offset); + } case 0x2F: return this->BRA(this->_getImmediateData()); case 0x30: @@ -296,8 +317,11 @@ namespace ComSquare::APU return this->TCALL(3); case 0x32: return this->CLR1(this->_getDirectAddr(), 1); - case 0x33: - return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 1); + case 0x33: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBC(addr, offset, 1); + } case 0x34: return this->ANDacc(this->_getDirectAddrByX(), 4); case 0x35: @@ -306,8 +330,11 @@ namespace ComSquare::APU return this->ANDacc(this->_getAbsoluteAddrByY(), 5); case 0x37: return this->ANDacc(this->_getAbsoluteDirectAddrByY(), 6); - case 0x38: - return this->AND(this->_getDirectAddr(), this->_getImmediateData(), 5); + case 0x38: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getImmediateData(); + return this->AND(ope1, ope2, 5); + } case 0x39: return this->AND(this->_getIndexXAddr(), this->_getIndexYAddr(), 5); case 0x3A: @@ -328,8 +355,11 @@ namespace ComSquare::APU return this->TCALL(4); case 0x42: return this->SET1(this->_getDirectAddr(), 2); - case 0x43: - return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 2); + case 0x43: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBS(addr, offset, 2); + } case 0x44: return this->EORacc(this->_getDirectAddr(), 3); case 0x45: @@ -340,8 +370,11 @@ namespace ComSquare::APU return this->EORacc(this->_getAbsoluteDirectByXAddr(), 6); case 0x48: return this->EORacc(this->_getImmediateData(), 2); - case 0x49: - return this->EOR(this->_getDirectAddr(), this->_getDirectAddr(), 6); + case 0x49: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getDirectAddr(); + return this->EOR(ope1, ope2, 6); + } case 0x4A: return this->AND1(this->_getAbsoluteBit()); case 0x4B: @@ -360,8 +393,11 @@ namespace ComSquare::APU return this->TCALL(5); case 0x52: return this->CLR1(this->_getDirectAddr(), 2); - case 0x53: - return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 2); + case 0x53: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBC(addr, offset, 2); + } case 0x54: return this->EORacc(this->_getDirectAddrByX(), 4); case 0x55: @@ -370,8 +406,11 @@ namespace ComSquare::APU return this->EORacc(this->_getAbsoluteAddrByY(), 5); case 0x57: return this->EORacc(this->_getAbsoluteDirectAddrByY(), 6); - case 0x58: - return this->EOR(this->_getDirectAddr(), this->_getImmediateData(), 5); + case 0x58: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getImmediateData(); + return this->EOR(ope1, ope2, 5); + } case 0x59: return this->EOR(this->_getIndexXAddr(), this->_getIndexYAddr(), 5); case 0x5A: @@ -392,8 +431,11 @@ namespace ComSquare::APU return this->TCALL(6); case 0x62: return this->SET1(this->_getDirectAddr(), 3); - case 0x63: - return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 3); + case 0x63: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBS(addr, offset, 3); + } case 0x64: return this->CMPreg(this->_internalRegisters.a, this->_getDirectAddr(), 3); case 0x65: @@ -404,8 +446,11 @@ namespace ComSquare::APU return this->CMPreg(this->_internalRegisters.a, this->_getAbsoluteDirectByXAddr(), 6); case 0x68: return this->CMPreg(this->_internalRegisters.a, this->_getImmediateData(), 2); - case 0x69: - return this->CMP(this->_getDirectAddr(), this->_getDirectAddr(), 6); + case 0x69: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getDirectAddr(); + return this->CMP(ope1, ope2, 6); + } case 0x6A: return this->AND1(this->_getAbsoluteBit(), true); case 0x6B: @@ -424,8 +469,11 @@ namespace ComSquare::APU return this->TCALL(7); case 0x72: return this->CLR1(this->_getDirectAddr(), 3); - case 0x73: - return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 3); + case 0x73: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBC(addr, offset, 3); + } case 0x74: return this->CMPreg(this->_internalRegisters.a, this->_getDirectAddrByX(), 4); case 0x75: @@ -434,8 +482,11 @@ namespace ComSquare::APU return this->CMPreg(this->_internalRegisters.a, this->_getAbsoluteAddrByY(), 5); case 0x77: return this->CMPreg(this->_internalRegisters.a, this->_getAbsoluteDirectAddrByY(), 6); - case 0x78: - return this->CMP(this->_getDirectAddr(), this->_getImmediateData(), 5); + case 0x78: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getImmediateData(); + return this->CMP(ope1, ope2, 5); + } case 0x79: return this->CMP(this->_getIndexXAddr(), this->_getIndexYAddr(), 5); case 0x7A: @@ -456,8 +507,11 @@ namespace ComSquare::APU return this->TCALL(8); case 0x82: return this->SET1(this->_getDirectAddr(), 4); - case 0x83: - return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 4); + case 0x83: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBS(addr, offset, 4); + } case 0x84: return this->ADCacc(this->_getDirectAddr(), 3); case 0x85: @@ -468,8 +522,11 @@ namespace ComSquare::APU return this->ADCacc(this->_getAbsoluteDirectByXAddr(), 6); case 0x88: return this->ADCacc(this->_getImmediateData(), 2); - case 0x89: - return this->ADC(this->_getDirectAddr(), this->_getDirectAddr(), 6); + case 0x89: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getDirectAddr(); + return this->ADC(ope1, ope2, 6); + } case 0x8A: return this->EOR1(this->_getAbsoluteBit()); case 0x8B: @@ -480,16 +537,22 @@ namespace ComSquare::APU return this->MOV(this->_getImmediateData(), this->_internalRegisters.y, 2); case 0x8E: return this->POP(this->_internalRegisters.psw); - case 0x8F: - return this->MOV(this->_getDirectAddr(), this->_getImmediateData()); + case 0x8F: { + auto to = this->_getDirectAddr(); + auto from = this->_getImmediateData(); + return this->MOV(to, from); + } case 0x90: return this->BCC(this->_getImmediateData()); case 0x91: return this->TCALL(9); case 0x92: return this->CLR1(this->_getDirectAddr(), 4); - case 0x93: - return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 4); + case 0x93: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBC(addr, offset, 4); + } case 0x94: return this->ADCacc(this->_getDirectAddrByX(), 4); case 0x95: @@ -498,8 +561,11 @@ namespace ComSquare::APU return this->ADCacc(this->_getAbsoluteAddrByY(), 5); case 0x97: return this->ADCacc(this->_getAbsoluteDirectAddrByY(), 6); - case 0x98: - return this->ADC(this->_getDirectAddr(), this->_getImmediateData(), 5); + case 0x98: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getImmediateData(); + return this->ADC(ope1, ope2, 5); + } case 0x99: return this->ADC(this->_getIndexXAddr(), this->_getIndexYAddr(), 3); case 0x9A: @@ -520,8 +586,11 @@ namespace ComSquare::APU return this->TCALL(10); case 0xA2: return this->SET1(this->_getDirectAddr(), 5); - case 0xA3: - return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 5); + case 0xA3: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBS(addr, offset, 5); + } case 0xA4: return this->SBCacc(this->_getDirectAddr(), 3); case 0xA5: @@ -532,8 +601,11 @@ namespace ComSquare::APU return this->SBCacc(this->_getAbsoluteDirectByXAddr(), 6); case 0xA8: return this->SBCacc(this->_getImmediateData(), 2); - case 0xA9: - return this->SBC(this->_getDirectAddr(), this->_getDirectAddr(), 6); + case 0xA9: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getDirectAddr(); + return this->SBC(ope1, ope2, 6); + } case 0xAA: return this->MOV1(this->_getAbsoluteBit(), true); case 0xAB: @@ -552,8 +624,11 @@ namespace ComSquare::APU return this->TCALL(11); case 0xB2: return this->CLR1(this->_getDirectAddr(), 5); - case 0xB3: - return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 5); + case 0xB3: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBC(addr, offset, 5); + } case 0xB4: return this->SBCacc(this->_getDirectAddrByX(), 4); case 0xB5: @@ -562,8 +637,11 @@ namespace ComSquare::APU return this->SBCacc(this->_getAbsoluteAddrByY(), 5); case 0xB7: return this->SBCacc(this->_getAbsoluteDirectAddrByY(), 6); - case 0xB8: - return this->SBC(this->_getDirectAddr(), this->_getImmediateData(), 5); + case 0xB8: { + auto ope1 = this->_getDirectAddr(); + auto ope2 = this->_getImmediateData(); + return this->SBC(ope1, ope2, 5); + } case 0xB9: return this->SBC(this->_getIndexXAddr(), this->_getIndexYAddr(), 5); case 0xBA: @@ -584,8 +662,11 @@ namespace ComSquare::APU return this->TCALL(12); case 0xC2: return this->SET1(this->_getDirectAddr(), 6); - case 0xC3: - return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 6); + case 0xC3: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBS(addr, offset, 6); + } case 0xC4: return this->MOV(this->_internalRegisters.a, this->_getDirectAddr(), 4); case 0xC5: @@ -616,8 +697,11 @@ namespace ComSquare::APU return this->TCALL(13); case 0xD2: return this->CLR1(this->_getDirectAddr(), 6); - case 0xD3: - return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 6); + case 0xD3: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBC(addr, offset, 6); + } case 0xD4: return this->MOV(this->_internalRegisters.a, this->_getDirectAddrByX(), 5); case 0xD5: @@ -638,8 +722,11 @@ namespace ComSquare::APU return this->DECreg(this->_internalRegisters.y); case 0xDD: return this->MOV(this->_internalRegisters.y, this->_internalRegisters.a); - case 0xDE: - return this->CBNE(this->_getDirectAddrByX(), this->_getImmediateData(), true); + case 0xDE: { + auto addr = this->_getDirectAddrByX(); + auto offset = this->_getImmediateData(); + return this->CBNE(addr, offset, true); + } case 0xDF: return this->DAA(); case 0xE0: @@ -648,26 +735,29 @@ namespace ComSquare::APU return this->TCALL(14); case 0xE2: return this->SET1(this->_getDirectAddr(), 7); - case 0xE3: - return this->BBS(this->_getDirectAddr(), this->_getImmediateData(), 7); + case 0xE3: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBS(addr, offset, 7); + } case 0xE4: - return this->MOV(this->_internalRead(this->_getDirectAddr()), this->_internalRegisters.a, 3); + return this->MOV(this->_internalRegisters.a, this->_internalRead(this->_getDirectAddr()), 3); case 0xE5: - return this->MOV(this->_getAbsoluteAddrByX(), this->_internalRegisters.a, 5); + return this->MOV(this->_internalRegisters.a, this->_getAbsoluteAddrByX(), 5); case 0xE6: - return this->MOV(this->_getIndexXAddr(), this->_internalRegisters.a, 3); + return this->MOV(this->_internalRegisters.a, this->_getIndexXAddr(), 3); case 0xE7: - return this->MOV(this->_getAbsoluteDirectByXAddr(), this->_internalRegisters.a, 6); + return this->MOV(this->_internalRegisters.a, this->_getAbsoluteDirectByXAddr(), 6); case 0xE8: - return this->MOV(this->_getImmediateData(), this->_internalRegisters.a, 2); + return this->MOV(this->_internalRegisters.a, this->_getImmediateData(), 2); case 0xE9: - return this->MOV(this->_getAbsoluteAddr(), this->_internalRegisters.x, 4); + return this->MOV(this->_internalRegisters.x, this->_getAbsoluteAddr(),4); case 0xEA: return this->NOT1(this->_getAbsoluteBit()); case 0xEB: - return this->MOV(this->_internalRead(this->_getDirectAddr()), this->_internalRegisters.y, 3); + return this->MOV(this->_internalRegisters.y, this->_getDirectAddr(),3); case 0xEC: - return this->MOV(this->_getAbsoluteAddr(), this->_internalRegisters.y, 4); + return this->MOV(this->_internalRegisters.y, this->_getAbsoluteAddr(), 4); case 0xED: return this->NOTC(); case 0xEE: @@ -680,28 +770,31 @@ namespace ComSquare::APU return this->TCALL(15); case 0xF2: return this->CLR1(this->_getDirectAddr(), 7); - case 0xF3: - return this->BBC(this->_getDirectAddr(), this->_getImmediateData(), 7); + case 0xF3: { + auto addr = this->_getDirectAddr(); + auto offset = this->_getImmediateData(); + return this->BBC(addr, offset, 7); + } case 0xF4: - return this->MOV(this->_internalRead(this->_getDirectAddrByX()), this->_internalRegisters.a, 4); + return this->MOV(this->_internalRegisters.a, this->_internalRead(this->_getDirectAddrByX()), 4); case 0xF5: - return this->MOV(this->_getAbsoluteAddrByX(), this->_internalRegisters.a, 5); + return this->MOV(this->_internalRegisters.a, this->_internalRead(this->_getAbsoluteAddrByX()), 5); case 0xF6: - return this->MOV(this->_getAbsoluteAddrByY(), this->_internalRegisters.a, 5); + return this->MOV(this->_internalRegisters.a, this->_getAbsoluteAddrByY(), 5); case 0xF7: - return this->MOV(this->_getAbsoluteDirectAddrByY(), this->_internalRegisters.a, 6); + return this->MOV(this->_internalRegisters.a, this->_getAbsoluteDirectAddrByY(), 6); case 0xF8: - return this->MOV(this->_getDirectAddr(), this->_internalRegisters.x, 3); + return this->MOV(this->_internalRegisters.x, this->_getDirectAddr(), 3); case 0xF9: - return this->MOV(this->_getDirectAddrByY(), this->_internalRegisters.x, 4); + return this->MOV(this->_internalRegisters.x, this->_getDirectAddrByY(), 4); case 0xFA: return this->MOV(this->_getDirectAddr(), this->_getDirectAddr()); case 0xFB: - return this->MOV(this->_getDirectAddrByX(), this->_internalRegisters.y, 4); + return this->MOV(this->_internalRegisters.y, this->_getDirectAddrByX(), 4); case 0xFC: return this->INCreg(this->_internalRegisters.y); case 0xFD: - return this->MOV(this->_internalRegisters.a, this->_internalRegisters.y); + return this->MOV(this->_internalRegisters.y, this->_internalRegisters.a); case 0xFE: return this->DBNZ(this->_getImmediateData()); case 0xFF: diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index 28c0608..8056f65 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -365,7 +365,7 @@ namespace ComSquare::APU int MOV(uint8_t ®From, uint8_t ®To, bool setFlags = true); int MOV(uint8_t ®From, uint24_t memTo, int cycles, bool incrementX = false); int MOV(uint24_t memFrom, uint8_t ®To, int cycles, bool incrementX = false); - int MOV(uint24_t memTo, uint24_t memFrom); + int MOV(uint24_t memFrom, uint24_t memTo); public: explicit APU(Renderer::IRenderer &renderer); APU(const APU &) = default; diff --git a/sources/APU/DSP/DSP.hpp b/sources/APU/DSP/DSP.hpp index 216df36..d8defa0 100644 --- a/sources/APU/DSP/DSP.hpp +++ b/sources/APU/DSP/DSP.hpp @@ -200,7 +200,7 @@ namespace ComSquare::APU::DSP //! @brief Size of buffer uint32_t bufferSize; //! @brief Current position in the buffer of samples - uint32_t bufferOffset; + uint32_t bufferOffset = 0; }; struct Timer { diff --git a/sources/Debugger/APUDebug.cpp b/sources/Debugger/APUDebug.cpp index 994a887..ccc6ad3 100644 --- a/sources/Debugger/APUDebug.cpp +++ b/sources/Debugger/APUDebug.cpp @@ -256,33 +256,49 @@ namespace ComSquare::Debugger QStringList labels = QStringList(); uint16_t offset = 0; - for (uint16_t i = 0; i < 0x20; i++) + if (this->_pc != 0) { auto pc = this->_internalRegisters.pc; - auto instruction = this->_getInstruction(); - std::string operand; - this->_ui.logger->setItem(i, 0, new QTableWidgetItem(instruction.name.c_str())); - - operand = this->_getOperand(std::get<0>(instruction.operands)); - this->_ui.logger->setItem(i, 1, new QTableWidgetItem(operand.c_str())); - if (operand.empty()) - this->_ui.logger->item(i, 1)->setData(Qt::BackgroundRole, QColor(220, 220, 220)); - - operand = this->_getOperand(std::get<1>(instruction.operands)); - this->_ui.logger->setItem(i, 2, new QTableWidgetItem(operand.c_str())); - if (operand.empty()) - this->_ui.logger->item(i, 2)->setData(Qt::BackgroundRole, QColor(220, 220, 220)); + this->_internalRegisters.pc = this->_pc; + this->_appendInstruction(0); + labels.append(Utility::to_hex(this->_pc).c_str()); + this->_internalRegisters.pc = pc; + } + else + labels.append("$0000"); + for (uint16_t i = 1; i < 0x20; i++) + { + auto pc = this->_internalRegisters.pc; + offset += this->_appendInstruction(i); labels.append(Utility::to_hex(pc).c_str()); - offset += instruction.size; } this->_ui.logger->setVerticalHeaderLabels(labels); for (int i = 0; i < 3; i++) - this->_ui.logger->item(0, i)->setData(Qt::BackgroundRole, QColor(200, 255, 148)); + this->_ui.logger->item(1, i)->setData(Qt::BackgroundRole, QColor(200, 255, 148)); this->_internalRegisters.pc -= offset; } + int APUDebug::_appendInstruction(int row) + { + auto instruction = this->_getInstruction(); + std::string operand; + + this->_ui.logger->setItem(row, 0, new QTableWidgetItem(instruction.name.c_str())); + + operand = this->_getOperand(std::get<0>(instruction.operands)); + this->_ui.logger->setItem(row, 1, new QTableWidgetItem(operand.c_str())); + if (operand.empty()) + this->_ui.logger->item(row, 1)->setData(Qt::BackgroundRole, QColor(220, 220, 220)); + + operand = this->_getOperand(std::get<1>(instruction.operands)); + this->_ui.logger->setItem(row, 2, new QTableWidgetItem(operand.c_str())); + if (operand.empty()) + this->_ui.logger->item(row, 2)->setData(Qt::BackgroundRole, QColor(220, 220, 220)); + return instruction.size; + } + std::string APUDebug::_getOperand(Operand ope) { switch (ope) { @@ -354,6 +370,7 @@ namespace ComSquare::Debugger void APUDebug::update(unsigned cycles) { + this->_pc = this->_internalRegisters.pc; try { if (this->_isPaused) return; diff --git a/sources/Debugger/APUDebug.hpp b/sources/Debugger/APUDebug.hpp index 44f7ead..569bf36 100644 --- a/sources/Debugger/APUDebug.hpp +++ b/sources/Debugger/APUDebug.hpp @@ -94,7 +94,7 @@ namespace ComSquare::Debugger {"ROL", 2, {DirectAddr, None}}, {"ROL", 3, {AbsoluteAddr, None}}, {"PUSH", 1, {A, None}}, - {"CBNE", 3, {ImmediateData, ImmediateData}}, + {"CBNE", 3, {DirectAddrByX, ImmediateData}}, {"BRA", 2, {ImmediateData, None}}, {"BMI", 2, {ImmediateData, None}}, {"TCALL", 1, {None, None}}, @@ -306,6 +306,12 @@ namespace ComSquare::Debugger {"STOP", 1, {None, None}} }}; + //! @brief Position of the last instruction executed + uint16_t _pc; + + //! @brief Add instruction to disassembly + int _appendInstruction(int row); + //! @brief The QT window for this debugger. ClosableWindow *_window; From cb1d35c288bd082523979f5dc95453c86eaba0bf Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Wed, 23 Jun 2021 21:49:18 +0200 Subject: [PATCH 5/8] Checking rom size --- sources/APU/APU.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index c7b851b..6179c4e 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -828,6 +828,9 @@ namespace ComSquare::APU void APU::loadFromSPC(const std::shared_ptr& cartridge) { const uint8_t *data = cartridge->getData(); + uint24_t size = cartridge->getSize(); + if (size < 0x101C0) + throw InvalidAddress("Cartridge is not the right size", size); std::string song = std::string(reinterpret_cast(data + 0x2E), 0x20); std::string game = std::string(reinterpret_cast(data + 0x4E), 0x20); From ca94b0fbaad10cc432a2953730e4395500d7a645 Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Wed, 23 Jun 2021 21:56:38 +0200 Subject: [PATCH 6/8] Using a constexpr for the magic header string of a SPC rom --- sources/Cartridge/Cartridge.cpp | 2 +- sources/Cartridge/Cartridge.hpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp index 4e81819..af53541 100644 --- a/sources/Cartridge/Cartridge.cpp +++ b/sources/Cartridge/Cartridge.cpp @@ -162,7 +162,7 @@ namespace ComSquare::Cartridge { std::string str = std::string(reinterpret_cast(this->_data), 0x21); - if (str != "SNES-SPC700 Sound File Data v0.30") + if (str != Cartridge::_magicSPC) return false; if (this->_data[0x21] != 0x1A || this->_data[0x22] != 0x1A) return false; diff --git a/sources/Cartridge/Cartridge.hpp b/sources/Cartridge/Cartridge.hpp index 9541053..bef122e 100644 --- a/sources/Cartridge/Cartridge.hpp +++ b/sources/Cartridge/Cartridge.hpp @@ -91,6 +91,8 @@ namespace ComSquare::Cartridge Header _mapHeader(uint32_t headerAddress); //! @brief Current type of the cartridge CartridgeType _type; + //! @brief Magic Header string of a SPC Rom + static constexpr std::string_view _magicSPC = "SNES-SPC700 Sound File Data v0.30"; public: //! @brief Load a rom from it's path. explicit Cartridge(const std::string &romPath); From bb156d600c3aa36c2b42380e7d1fde9c4859d515 Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Wed, 23 Jun 2021 22:02:32 +0200 Subject: [PATCH 7/8] Fixing space indent to tab --- sources/Debugger/APUDebug.hpp | 512 +++++++++++++++++----------------- 1 file changed, 256 insertions(+), 256 deletions(-) diff --git a/sources/Debugger/APUDebug.hpp b/sources/Debugger/APUDebug.hpp index 569bf36..ff00a54 100644 --- a/sources/Debugger/APUDebug.hpp +++ b/sources/Debugger/APUDebug.hpp @@ -48,262 +48,262 @@ namespace ComSquare::Debugger private: //! @brief List of instructions and their information std::array _instructions {{ - {"NOP", 1, {None, None}}, - {"TCALL", 1, {None, None}}, - {"SET1", 2, {DirectAddr, None}}, - {"BBS", 3, {DirectAddr, ImmediateData}}, - {"OR", 2, {DirectAddr, None}}, - {"OR", 3, {AbsoluteAddr, None}}, - {"OR", 1, {IndexXAddr, None}}, - {"OR", 2, {AbsoluteDirectByXAddr, None}}, - {"OR", 2, {ImmediateData, None}}, - {"OR", 3, {DirectAddr, DirectAddr}}, - {"OR1", 3, {AbsoluteBit, None}}, - {"ASL", 2, {DirectAddr, None}}, - {"ASL", 3, {AbsoluteAddr, None}}, - {"PUSH", 1, {PSW, None}}, - {"TSET1", 3, {AbsoluteAddr, None}}, - {"BRK", 1, {None, None}}, - {"BPL", 2, {ImmediateData, None}}, - {"TCALL", 1, {None, None}}, - {"CLR1", 2, {DirectAddr, None}}, - {"BBC", 3, {DirectAddr, ImmediateData}}, - {"OR", 2, {DirectAddrByX, None}}, - {"OR", 3, {AbsoluteAddrByX, None}}, - {"OR", 3, {AbsoluteAddrByY, None}}, - {"OR", 2, {AbsoluteDirectAddrByY, None}}, - {"OR", 3, {DirectAddr, ImmediateData}}, - {"OR", 1, {IndexYAddr, IndexYAddr}}, - {"DECW", 2, {DirectAddr, None}}, - {"ASL", 2, {DirectAddrByX, None}}, - {"ASL", 1, {A, None}}, - {"DEC", 1, {X, None}}, - {"CMP", 3, {X, AbsoluteAddr}}, - {"JMP", 3, {AbsoluteByXAddr, None}}, - {"CLRP", 1, {None, None}}, - {"TCALL", 1, {None, None}}, - {"SET1", 2, {DirectAddr, None}}, - {"BBS", 3, {DirectAddr, ImmediateData}}, - {"AND", 2, {DirectAddr, None}}, - {"AND", 3, {AbsoluteAddr, None}}, - {"AND", 1, {IndexXAddr, None}}, - {"AND", 2, {AbsoluteDirectByXAddr, None}}, - {"AND", 2, {ImmediateData, None}}, - {"AND", 3, {DirectAddr, DirectAddr}}, - {"OR1", 3, {AbsoluteBit, None}}, - {"ROL", 2, {DirectAddr, None}}, - {"ROL", 3, {AbsoluteAddr, None}}, - {"PUSH", 1, {A, None}}, - {"CBNE", 3, {DirectAddrByX, ImmediateData}}, - {"BRA", 2, {ImmediateData, None}}, - {"BMI", 2, {ImmediateData, None}}, - {"TCALL", 1, {None, None}}, - {"CLR1", 2, {DirectAddr, None}}, - {"BBC", 3, {DirectAddr, ImmediateData}}, - {"AND", 2, {DirectAddrByX, None}}, - {"AND", 3, {AbsoluteAddrByX, None}}, - {"AND", 3, {AbsoluteAddrByY, None}}, - {"AND", 2, {AbsoluteDirectAddrByY, None}}, - {"AND", 3, {DirectAddr, ImmediateData}}, - {"AND", 1, {IndexXAddr, IndexYAddr}}, - {"INCW", 2, {DirectAddr, None}}, - {"ROL", 2, {AbsoluteAddrByX, None}}, - {"ROL", 1, {A, None}}, - {"INC", 1, {X, None}}, - {"CMP", 2, {X, DirectAddr}}, - {"CALL", 3, {AbsoluteAddr, None}}, - {"SETP", 1, {None, None}}, - {"TCALL", 1, {None, None}}, - {"SET1", 2, {DirectAddr, None}}, - {"BBS", 3, {DirectAddr, ImmediateData}}, - {"EOR", 2, {DirectAddr, None}}, - {"EOR", 3, {AbsoluteAddr, None}}, - {"EOR", 1, {IndexXAddr, None}}, - {"EOR", 2, {AbsoluteDirectByXAddr, None}}, - {"EOR", 2, {ImmediateData, None}}, - {"EOR", 3, {DirectAddr, DirectAddr}}, - {"AND1", 3, {AbsoluteBit, None}}, - {"LSR", 2, {DirectAddr, None}}, - {"LSR", 3, {AbsoluteAddr, None}}, - {"PUSH", 1, {X, None}}, - {"TCLR1", 3, {AbsoluteAddr, None}}, - {"PCALL", 3, {None, None}}, - {"BVC", 2, {ImmediateData, None}}, - {"TCALL", 1, {None, None}}, - {"CLR1", 2, {DirectAddr, None}}, - {"BBC", 3, {DirectAddr, ImmediateData}}, - {"EOR", 2, {DirectAddrByX, None}}, - {"EOR", 3, {AbsoluteAddrByX, None}}, - {"EOR", 3, {AbsoluteAddrByY, None}}, - {"EOR", 2, {AbsoluteDirectAddrByY, None}}, - {"EOR", 3, {DirectAddr, ImmediateData}}, - {"EOR", 1, {IndexXAddr, IndexYAddr}}, - {"CMPW", 2, {DirectAddr, None}}, - {"LSR", 2, {DirectAddrByX, None}}, - {"LSR", 1, {A, None}}, - {"MOV", 1, {A, X}}, - {"CMP", 3, {Y, AbsoluteAddr}}, - {"JMP", 3, {AbsoluteAddr, None}}, - {"CLRC", 1, {None, None}}, - {"TCALL", 1, {None, None}}, - {"SET1", 2, {DirectAddr, None}}, - {"BBS", 3, {DirectAddr, ImmediateData}}, - {"CMP", 2, {A, DirectAddr}}, - {"CMP", 3, {A, AbsoluteAddr}}, - {"CMP", 1, {A, IndexXAddr,}}, - {"CMP", 2, {A, AbsoluteDirectByXAddr}}, - {"CMP", 2, {A, ImmediateData}}, - {"CMP", 3, {DirectAddr, DirectAddr}}, - {"AND1", 3, {AbsoluteBit, None}}, - {"ROR", 2, {DirectAddr , None}}, - {"ROR", 3, {AbsoluteAddr, None}}, - {"PUSH", 1, {Y, None}}, - {"DBNZ", 3, {ImmediateData, None}}, - {"RET", 1, {None, None}}, - {"BVS", 2, {ImmediateData, None}}, - {"TCALL", 1, {None, None}}, - {"CLR1", 2, {DirectAddr, None}}, - {"BBC", 3, {DirectAddr, ImmediateData}}, - {"CMP", 2, {A, DirectAddrByX}}, - {"CMP", 3, {A, AbsoluteAddrByX}}, - {"CMP", 3, {A, AbsoluteAddrByY}}, - {"CMP", 2, {A, AbsoluteDirectAddrByY}}, - {"CMP", 3, {DirectAddr, ImmediateData}}, - {"CMP", 1, {IndexXAddr, IndexYAddr}}, - {"ADDW", 2, {DirectAddr, None}}, - {"ROR", 2, {DirectAddrByX, None}}, - {"ROR", 1, {A, None}}, - {"MOV", 1, {X, A}}, - {"CMP", 3, {Y, DirectAddr}}, - {"RETI", 1, {None, None}}, - {"SETC", 1, {None, None}}, - {"TCALL", 1, {None, None}}, - {"SET1", 2, {DirectAddr, None}}, - {"BBS", 3, {DirectAddr, ImmediateData}}, - {"ADC", 2, {DirectAddr, None}}, - {"ADC", 3, {AbsoluteAddr, None}}, - {"ADC", 1, {IndexXAddr, None}}, - {"ADC", 2, {AbsoluteDirectByXAddr, None}}, - {"ADC", 2, {ImmediateData, None}}, - {"ADC", 3, {DirectAddr, DirectAddr}}, - {"EOR1", 3, {AbsoluteBit, None}}, - {"DEC", 2, {DirectAddr, None}}, - {"DEC", 3, {AbsoluteAddr, None}}, - {"MOV", 2, {ImmediateData, Y}}, - {"POP", 1, {PSW, None}}, - {"MOV", 3, {DirectAddr, ImmediateData}}, - {"BCC", 2, {ImmediateData, None}}, - {"TCALL", 1, {None, None}}, - {"CLR1", 2, {DirectAddr, None}}, - {"BBC", 3, {DirectAddr, ImmediateData}}, - {"ADC", 2, {DirectAddrByX, None}}, - {"ADC", 3, {AbsoluteAddrByX, None}}, - {"ADC", 3, {AbsoluteAddrByY, None}}, - {"ADC", 2, {AbsoluteDirectAddrByY, None}}, - {"ADC", 3, {DirectAddr, ImmediateData}}, - {"ADC", 1, {IndexXAddr, IndexYAddr}}, - {"SUBW", 2, {DirectAddr, None}}, - {"DEC", 2, {DirectAddrByX, None}}, - {"DEC", 1, {A, None}}, - {"MOV", 1, {SP, X}}, - {"DIV", 1, {None, None}}, - {"XCN", 1, {None, None}}, - {"EI", 1, {None, None}}, - {"TCALL", 1, {None, None}}, - {"SET1", 2, {DirectAddr, None}}, - {"BBS", 3, {DirectAddr, ImmediateData}}, - {"SBC", 2, {DirectAddr, None}}, - {"SBC", 3, {AbsoluteAddr, None}}, - {"SBC", 1, {IndexXAddr, None}}, - {"SBC", 2, {AbsoluteDirectByXAddr, None}}, - {"SBC", 2, {ImmediateData, None}}, - {"SBC", 3, {DirectAddr, DirectAddr}}, - {"MOV1", 3, {AbsoluteBit, None}}, - {"INC", 2, {DirectAddr, None}}, - {"INC", 3, {AbsoluteAddr, None}}, - {"CMP", 2, {Y, ImmediateData}}, - {"POP", 1, {A, None}}, - {"MOV", 1, {A, IndexXAddr}}, - {"BCS", 2, {ImmediateData, None}}, - {"TCALL", 1, {None, None}}, - {"CLR1", 2, {DirectAddr, None}}, - {"BBC", 3, {DirectAddr, ImmediateData}}, - {"SBC", 2, {DirectAddrByX, None}}, - {"SBC", 3, {AbsoluteAddrByX, None}}, - {"SBC", 3, {AbsoluteAddrByY, None}}, - {"SBC", 2, {AbsoluteDirectAddrByY, None}}, - {"SBC", 2, {DirectAddr, ImmediateData}}, - {"SBC", 1, {IndexXAddr, IndexYAddr}}, - {"MOVW", 2, {DirectAddr, None}}, - {"INC", 2, {DirectAddrByX, None}}, - {"INC", 1, {A, None}}, - {"MOV", 1, {X, SP}}, - {"DAS", 1, {None, None}}, - {"MOV", 1, {IndexXAddr, A}}, - {"DI", 1, {None, None}}, - {"TCALL", 1, {None, None}}, - {"SET1", 2, {DirectAddr, None}}, - {"BBS", 3, {DirectAddr, ImmediateData}}, - {"MOV", 2, {A, DirectAddr}}, - {"MOV", 3, {A, AbsoluteAddr}}, - {"MOV", 1, {A, IndexXAddr}}, - {"MOV", 2, {A, AbsoluteDirectByXAddr}}, - {"CMP", 2, {X, ImmediateData}}, - {"MOV", 3, {X, AbsoluteAddr}}, - {"MOV1", 3, {AbsoluteBit, None}}, - {"MOV", 2, {Y, DirectAddr}}, - {"MOV", 3, {Y, AbsoluteAddr}}, - {"MOV", 2, {ImmediateData, X}}, - {"POP", 1, {X, None}}, - {"MUL", 1, {None, None}}, - {"BNE", 2, {ImmediateData, None}}, - {"TCALL", 1, {None, None}}, - {"CLR1", 2, {DirectAddr, None}}, - {"BBC", 3, {DirectAddr, ImmediateData}}, - {"MOV", 2, {A, DirectAddrByX}}, - {"MOV", 3, {A, AbsoluteAddrByX}}, - {"MOV", 3, {A, AbsoluteAddrByY}}, - {"MOV", 2, {A, AbsoluteDirectAddrByY}}, - {"MOV", 2, {X, DirectAddr}}, - {"MOV", 2, {X, DirectAddrByY}}, - {"MOVW", 2, {DirectAddr, None}}, - {"MOV", 2, {Y, DirectAddrByX}}, - {"DEC", 1, {Y, None}}, - {"MOV", 1, {Y, A}}, - {"CBNE", 3, {DirectAddrByX, ImmediateData}}, - {"DAA", 1, {None, None}}, - {"CLRV", 1, {None, None}}, - {"TCALL", 1, {None, None}}, - {"SET1", 2, {DirectAddr, None}}, - {"BBS", 3, {DirectAddr, ImmediateData}}, - {"MOV", 2, {DirectAddr, A}}, - {"MOV", 3, {AbsoluteAddrByX, A}}, - {"MOV", 1, {IndexXAddr, A}}, - {"MOV", 2, {AbsoluteDirectByXAddr, A}}, - {"MOV", 2, {ImmediateData, A}}, - {"MOV", 3, {AbsoluteAddr, X}}, - {"NOT1", 3, {AbsoluteBit, None}}, - {"MOV", 2, {DirectAddr, Y}}, - {"MOV", 3, {AbsoluteAddr, Y}}, - {"NOTC", 1, {None, None}}, - {"POP", 1, {Y, None}}, - {"SLEEP", 1, {None, None}}, - {"BEQ", 2, {ImmediateData, None}}, - {"TCALL", 1, {None, None}}, - {"CLR1", 2, {DirectAddr, None}}, - {"BBC", 3, {DirectAddr, ImmediateData}}, - {"MOV", 2, {DirectAddrByX, A}}, - {"MOV", 3, {AbsoluteAddrByX, A}}, - {"MOV", 3, {AbsoluteAddrByY, A}}, - {"MOV", 2, {AbsoluteDirectAddrByY, A}}, - {"MOV", 2, {DirectAddr, X}}, - {"MOV", 2, {DirectAddrByY, X}}, - {"MOV", 3, {DirectAddr, DirectAddr}}, - {"MOV", 2, {DirectAddrByX, Y}}, - {"INC", 1, {Y, None}}, - {"MOV", 1, {A, Y}}, - {"DBNZ", 3, {ImmediateData, None}}, - {"STOP", 1, {None, None}} + {"NOP", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"OR", 2, {DirectAddr, None}}, + {"OR", 3, {AbsoluteAddr, None}}, + {"OR", 1, {IndexXAddr, None}}, + {"OR", 2, {AbsoluteDirectByXAddr, None}}, + {"OR", 2, {ImmediateData, None}}, + {"OR", 3, {DirectAddr, DirectAddr}}, + {"OR1", 3, {AbsoluteBit, None}}, + {"ASL", 2, {DirectAddr, None}}, + {"ASL", 3, {AbsoluteAddr, None}}, + {"PUSH", 1, {PSW, None}}, + {"TSET1", 3, {AbsoluteAddr, None}}, + {"BRK", 1, {None, None}}, + {"BPL", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"OR", 2, {DirectAddrByX, None}}, + {"OR", 3, {AbsoluteAddrByX, None}}, + {"OR", 3, {AbsoluteAddrByY, None}}, + {"OR", 2, {AbsoluteDirectAddrByY, None}}, + {"OR", 3, {DirectAddr, ImmediateData}}, + {"OR", 1, {IndexYAddr, IndexYAddr}}, + {"DECW", 2, {DirectAddr, None}}, + {"ASL", 2, {DirectAddrByX, None}}, + {"ASL", 1, {A, None}}, + {"DEC", 1, {X, None}}, + {"CMP", 3, {X, AbsoluteAddr}}, + {"JMP", 3, {AbsoluteByXAddr, None}}, + {"CLRP", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"AND", 2, {DirectAddr, None}}, + {"AND", 3, {AbsoluteAddr, None}}, + {"AND", 1, {IndexXAddr, None}}, + {"AND", 2, {AbsoluteDirectByXAddr, None}}, + {"AND", 2, {ImmediateData, None}}, + {"AND", 3, {DirectAddr, DirectAddr}}, + {"OR1", 3, {AbsoluteBit, None}}, + {"ROL", 2, {DirectAddr, None}}, + {"ROL", 3, {AbsoluteAddr, None}}, + {"PUSH", 1, {A, None}}, + {"CBNE", 3, {DirectAddrByX, ImmediateData}}, + {"BRA", 2, {ImmediateData, None}}, + {"BMI", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"AND", 2, {DirectAddrByX, None}}, + {"AND", 3, {AbsoluteAddrByX, None}}, + {"AND", 3, {AbsoluteAddrByY, None}}, + {"AND", 2, {AbsoluteDirectAddrByY, None}}, + {"AND", 3, {DirectAddr, ImmediateData}}, + {"AND", 1, {IndexXAddr, IndexYAddr}}, + {"INCW", 2, {DirectAddr, None}}, + {"ROL", 2, {AbsoluteAddrByX, None}}, + {"ROL", 1, {A, None}}, + {"INC", 1, {X, None}}, + {"CMP", 2, {X, DirectAddr}}, + {"CALL", 3, {AbsoluteAddr, None}}, + {"SETP", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"EOR", 2, {DirectAddr, None}}, + {"EOR", 3, {AbsoluteAddr, None}}, + {"EOR", 1, {IndexXAddr, None}}, + {"EOR", 2, {AbsoluteDirectByXAddr, None}}, + {"EOR", 2, {ImmediateData, None}}, + {"EOR", 3, {DirectAddr, DirectAddr}}, + {"AND1", 3, {AbsoluteBit, None}}, + {"LSR", 2, {DirectAddr, None}}, + {"LSR", 3, {AbsoluteAddr, None}}, + {"PUSH", 1, {X, None}}, + {"TCLR1", 3, {AbsoluteAddr, None}}, + {"PCALL", 3, {None, None}}, + {"BVC", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"EOR", 2, {DirectAddrByX, None}}, + {"EOR", 3, {AbsoluteAddrByX, None}}, + {"EOR", 3, {AbsoluteAddrByY, None}}, + {"EOR", 2, {AbsoluteDirectAddrByY, None}}, + {"EOR", 3, {DirectAddr, ImmediateData}}, + {"EOR", 1, {IndexXAddr, IndexYAddr}}, + {"CMPW", 2, {DirectAddr, None}}, + {"LSR", 2, {DirectAddrByX, None}}, + {"LSR", 1, {A, None}}, + {"MOV", 1, {A, X}}, + {"CMP", 3, {Y, AbsoluteAddr}}, + {"JMP", 3, {AbsoluteAddr, None}}, + {"CLRC", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"CMP", 2, {A, DirectAddr}}, + {"CMP", 3, {A, AbsoluteAddr}}, + {"CMP", 1, {A, IndexXAddr,}}, + {"CMP", 2, {A, AbsoluteDirectByXAddr}}, + {"CMP", 2, {A, ImmediateData}}, + {"CMP", 3, {DirectAddr, DirectAddr}}, + {"AND1", 3, {AbsoluteBit, None}}, + {"ROR", 2, {DirectAddr , None}}, + {"ROR", 3, {AbsoluteAddr, None}}, + {"PUSH", 1, {Y, None}}, + {"DBNZ", 3, {ImmediateData, None}}, + {"RET", 1, {None, None}}, + {"BVS", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"CMP", 2, {A, DirectAddrByX}}, + {"CMP", 3, {A, AbsoluteAddrByX}}, + {"CMP", 3, {A, AbsoluteAddrByY}}, + {"CMP", 2, {A, AbsoluteDirectAddrByY}}, + {"CMP", 3, {DirectAddr, ImmediateData}}, + {"CMP", 1, {IndexXAddr, IndexYAddr}}, + {"ADDW", 2, {DirectAddr, None}}, + {"ROR", 2, {DirectAddrByX, None}}, + {"ROR", 1, {A, None}}, + {"MOV", 1, {X, A}}, + {"CMP", 3, {Y, DirectAddr}}, + {"RETI", 1, {None, None}}, + {"SETC", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"ADC", 2, {DirectAddr, None}}, + {"ADC", 3, {AbsoluteAddr, None}}, + {"ADC", 1, {IndexXAddr, None}}, + {"ADC", 2, {AbsoluteDirectByXAddr, None}}, + {"ADC", 2, {ImmediateData, None}}, + {"ADC", 3, {DirectAddr, DirectAddr}}, + {"EOR1", 3, {AbsoluteBit, None}}, + {"DEC", 2, {DirectAddr, None}}, + {"DEC", 3, {AbsoluteAddr, None}}, + {"MOV", 2, {ImmediateData, Y}}, + {"POP", 1, {PSW, None}}, + {"MOV", 3, {DirectAddr, ImmediateData}}, + {"BCC", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"ADC", 2, {DirectAddrByX, None}}, + {"ADC", 3, {AbsoluteAddrByX, None}}, + {"ADC", 3, {AbsoluteAddrByY, None}}, + {"ADC", 2, {AbsoluteDirectAddrByY, None}}, + {"ADC", 3, {DirectAddr, ImmediateData}}, + {"ADC", 1, {IndexXAddr, IndexYAddr}}, + {"SUBW", 2, {DirectAddr, None}}, + {"DEC", 2, {DirectAddrByX, None}}, + {"DEC", 1, {A, None}}, + {"MOV", 1, {SP, X}}, + {"DIV", 1, {None, None}}, + {"XCN", 1, {None, None}}, + {"EI", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"SBC", 2, {DirectAddr, None}}, + {"SBC", 3, {AbsoluteAddr, None}}, + {"SBC", 1, {IndexXAddr, None}}, + {"SBC", 2, {AbsoluteDirectByXAddr, None}}, + {"SBC", 2, {ImmediateData, None}}, + {"SBC", 3, {DirectAddr, DirectAddr}}, + {"MOV1", 3, {AbsoluteBit, None}}, + {"INC", 2, {DirectAddr, None}}, + {"INC", 3, {AbsoluteAddr, None}}, + {"CMP", 2, {Y, ImmediateData}}, + {"POP", 1, {A, None}}, + {"MOV", 1, {A, IndexXAddr}}, + {"BCS", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"SBC", 2, {DirectAddrByX, None}}, + {"SBC", 3, {AbsoluteAddrByX, None}}, + {"SBC", 3, {AbsoluteAddrByY, None}}, + {"SBC", 2, {AbsoluteDirectAddrByY, None}}, + {"SBC", 2, {DirectAddr, ImmediateData}}, + {"SBC", 1, {IndexXAddr, IndexYAddr}}, + {"MOVW", 2, {DirectAddr, None}}, + {"INC", 2, {DirectAddrByX, None}}, + {"INC", 1, {A, None}}, + {"MOV", 1, {X, SP}}, + {"DAS", 1, {None, None}}, + {"MOV", 1, {IndexXAddr, A}}, + {"DI", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"MOV", 2, {A, DirectAddr}}, + {"MOV", 3, {A, AbsoluteAddr}}, + {"MOV", 1, {A, IndexXAddr}}, + {"MOV", 2, {A, AbsoluteDirectByXAddr}}, + {"CMP", 2, {X, ImmediateData}}, + {"MOV", 3, {X, AbsoluteAddr}}, + {"MOV1", 3, {AbsoluteBit, None}}, + {"MOV", 2, {Y, DirectAddr}}, + {"MOV", 3, {Y, AbsoluteAddr}}, + {"MOV", 2, {ImmediateData, X}}, + {"POP", 1, {X, None}}, + {"MUL", 1, {None, None}}, + {"BNE", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"MOV", 2, {A, DirectAddrByX}}, + {"MOV", 3, {A, AbsoluteAddrByX}}, + {"MOV", 3, {A, AbsoluteAddrByY}}, + {"MOV", 2, {A, AbsoluteDirectAddrByY}}, + {"MOV", 2, {X, DirectAddr}}, + {"MOV", 2, {X, DirectAddrByY}}, + {"MOVW", 2, {DirectAddr, None}}, + {"MOV", 2, {Y, DirectAddrByX}}, + {"DEC", 1, {Y, None}}, + {"MOV", 1, {Y, A}}, + {"CBNE", 3, {DirectAddrByX, ImmediateData}}, + {"DAA", 1, {None, None}}, + {"CLRV", 1, {None, None}}, + {"TCALL", 1, {None, None}}, + {"SET1", 2, {DirectAddr, None}}, + {"BBS", 3, {DirectAddr, ImmediateData}}, + {"MOV", 2, {DirectAddr, A}}, + {"MOV", 3, {AbsoluteAddrByX, A}}, + {"MOV", 1, {IndexXAddr, A}}, + {"MOV", 2, {AbsoluteDirectByXAddr, A}}, + {"MOV", 2, {ImmediateData, A}}, + {"MOV", 3, {AbsoluteAddr, X}}, + {"NOT1", 3, {AbsoluteBit, None}}, + {"MOV", 2, {DirectAddr, Y}}, + {"MOV", 3, {AbsoluteAddr, Y}}, + {"NOTC", 1, {None, None}}, + {"POP", 1, {Y, None}}, + {"SLEEP", 1, {None, None}}, + {"BEQ", 2, {ImmediateData, None}}, + {"TCALL", 1, {None, None}}, + {"CLR1", 2, {DirectAddr, None}}, + {"BBC", 3, {DirectAddr, ImmediateData}}, + {"MOV", 2, {DirectAddrByX, A}}, + {"MOV", 3, {AbsoluteAddrByX, A}}, + {"MOV", 3, {AbsoluteAddrByY, A}}, + {"MOV", 2, {AbsoluteDirectAddrByY, A}}, + {"MOV", 2, {DirectAddr, X}}, + {"MOV", 2, {DirectAddrByY, X}}, + {"MOV", 3, {DirectAddr, DirectAddr}}, + {"MOV", 2, {DirectAddrByX, Y}}, + {"INC", 1, {Y, None}}, + {"MOV", 1, {A, Y}}, + {"DBNZ", 3, {ImmediateData, None}}, + {"STOP", 1, {None, None}} }}; //! @brief Position of the last instruction executed From caf41970338f23a6247ada52d8a0d8a7e40f5994 Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Wed, 23 Jun 2021 22:04:07 +0200 Subject: [PATCH 8/8] Checking rom size before checking SPC header --- sources/Cartridge/Cartridge.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp index af53541..cf224d4 100644 --- a/sources/Cartridge/Cartridge.cpp +++ b/sources/Cartridge/Cartridge.cpp @@ -160,6 +160,8 @@ namespace ComSquare::Cartridge bool Cartridge::_isSPCFile() { + if (this->_size < 0x25) + return false; std::string str = std::string(reinterpret_cast(this->_data), 0x21); if (str != Cartridge::_magicSPC)