From 44361c848289f308a9c183f5a7b3cedca578e93e Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 6 Jul 2021 23:06:02 +0200 Subject: [PATCH] Cleaning up rom data --- sources/APU/APU.cpp | 21 ++++++++-------- sources/Cartridge/Cartridge.cpp | 32 +++++++++++++------------ sources/Cartridge/Cartridge.hpp | 3 +++ sources/Debugger/CPU/CPUDebug.cpp | 24 ++++++++++++------- sources/Debugger/MemoryViewer.cpp | 3 +-- sources/Ram/Ram.cpp | 40 +++++++++++++++---------------- sources/Ram/Ram.hpp | 20 +++++++++++----- sources/SNES.cpp | 3 ++- tests/CPU/testDMA.cpp | 4 +--- tests/tests.hpp | 10 ++------ 10 files changed, 85 insertions(+), 75 deletions(-) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index 3069934..af703df 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -7,6 +7,7 @@ #include "Exceptions/InvalidOpcode.hpp" #include #include +#include namespace ComSquare::APU { @@ -814,17 +815,17 @@ namespace ComSquare::APU void APU::loadFromSPC(Cartridge::Cartridge &cartridge) { - const uint8_t *data = cartridge.getData(); + std::span 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); - 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); + std::string song = std::string(reinterpret_cast(data.data() + 0x2E), 0x20); + std::string game = std::string(reinterpret_cast(data.data() + 0x4E), 0x20); + std::string dumper = std::string(reinterpret_cast(data.data() + 0x6E), 0x10); + std::string comment = std::string(reinterpret_cast(data.data() + 0x7E), 0x20); + std::string date = std::string(reinterpret_cast(data.data() + 0x9E), 0x0B); + std::string artist = std::string(reinterpret_cast(data.data() + 0xB1), 0x20); this->_internalRegisters.pcl = cartridge.read(0x25); this->_internalRegisters.pch = cartridge.read(0x26); @@ -834,9 +835,9 @@ namespace ComSquare::APU 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()); + std::copy_n(data.begin() + 0x100, this->_map.Page0.getSize(), this->_map.Page0.getData().begin()); + std::copy_n(data.begin() + 0x200, this->_map.Page1.getSize(), this->_map.Page1.getData().begin()); + std::copy_n(data.begin() + 0x300, this->_map.Memory.getSize(), this->_map.Memory.getData().begin()); this->_registers.unknown = cartridge.read(0x100 + 0xF0); this->_registers.ctrlreg = cartridge.read(0x100 + 0xF1); diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp index 08efbab..204e0fc 100644 --- a/sources/Cartridge/Cartridge.cpp +++ b/sources/Cartridge/Cartridge.cpp @@ -7,18 +7,19 @@ #include "Exceptions/InvalidRom.hpp" #include #include +#include namespace ComSquare::Cartridge { constexpr unsigned HeaderSize = 0x40u; Cartridge::Cartridge() - : Ram::Ram(0, Rom, "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) { this->loadRom(romPath); } @@ -26,14 +27,12 @@ namespace ComSquare::Cartridge void Cartridge::loadRom(const std::string &path) { size_t size = Cartridge::getRomSize(path); - FILE *rom = fopen(path.c_str(), "rb"); + std::ifstream rom(path, std::ios::binary); if (!rom) 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); - fread(this->_data, 1, size, rom); + this->_data.resize(size); + rom.read(reinterpret_cast(this->_data.data()), size); this->_loadHeader(); } @@ -46,7 +45,6 @@ namespace ComSquare::Cartridge return info.st_size; } - uint8_t Cartridge::read(uint24_t addr) { return Ram::read(addr + this->_romStart); @@ -113,7 +111,7 @@ namespace ComSquare::Cartridge uint32_t Cartridge::_getHeaderAddress() { const std::vector address = {0x7FC0, 0xFFC0}; - unsigned int smc = this->_size % 1024; + unsigned int smc = this->getSize() % 1024; int bestScore = -1; uint32_t bestAddress = 0; @@ -121,7 +119,7 @@ namespace ComSquare::Cartridge int score = 0; addr += smc; - if (addr + 0x32u >= this->_size) + if (addr + 0x32u >= this->getSize()) continue; Header info = this->_mapHeader(addr); @@ -174,9 +172,9 @@ namespace ComSquare::Cartridge bool Cartridge::_isSPCFile() { - if (this->_size < 0x25) + if (this->getSize() < 0x25) return false; - std::string str = std::string(reinterpret_cast(this->_data), 0x21); + std::string str = std::string(reinterpret_cast(this->getData().data()), 0x21); if (str != Cartridge::_magicSPC) return false; @@ -198,14 +196,13 @@ namespace ComSquare::Cartridge this->_type = Game; uint32_t headerAddress = this->_getHeaderAddress(); - if (headerAddress + HeaderSize > this->_size) + if (headerAddress + HeaderSize > this->getSize()) return false; this->header = this->_mapHeader(headerAddress); this->header.gameName = std::string(reinterpret_cast(&this->_data[headerAddress]), 21); if ((headerAddress + 0x40u) & 0x200u) { this->_romStart = 0x200u; - this->_size -= 0x200u; return true; } return false; @@ -216,6 +213,11 @@ namespace ComSquare::Cartridge return this->_type; } + uint24_t Cartridge::getSize() const + { + return Ram::getSize() - this->_romStart; + } + MappingMode operator|(const MappingMode &self, const MappingMode &other) { return static_cast(static_cast(self) | static_cast(other)); diff --git a/sources/Cartridge/Cartridge.hpp b/sources/Cartridge/Cartridge.hpp index 2d2f288..3bc6475 100644 --- a/sources/Cartridge/Cartridge.hpp +++ b/sources/Cartridge/Cartridge.hpp @@ -138,6 +138,9 @@ namespace ComSquare::Cartridge //! @return The path of the currently loaded rom file. [[nodiscard]] std::filesystem::path getRomPath() const; + //! @brief Get the size of the rom in bytes (without the smc header). + uint24_t getSize() const override; + //! @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. diff --git a/sources/Debugger/CPU/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp index cf017ae..1a5aad7 100644 --- a/sources/Debugger/CPU/CPUDebug.cpp +++ b/sources/Debugger/CPU/CPUDebug.cpp @@ -30,9 +30,10 @@ namespace ComSquare::Debugger::CPU this->_loadLabels(snes.cartridge.getRomPath()); this->_ui.setupUi(this->_window); + //Parse the first page of the ROM (the code can't reach the second page without a jump). - uint16_t reset = snes.cartridge.header.emulationInterrupts.reset; - this->_updateDisassembly(reset, 0xFFFF - reset); + uint16_t resetInter = snes.cartridge.header.emulationInterrupts.reset; + this->_updateDisassembly(resetInter, 0xFFFF - resetInter); this->_ui.disassembly->setModel(&this->_model); this->_ui.disassembly->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); @@ -65,7 +66,9 @@ namespace ComSquare::Debugger::CPU this->_cpu.isDisabled = true; this->_callback = this->_cpu.onReset.addCallback([this] { this->disassembled.clear(); - this->_updateDisassembly(0xFFFF - this->_cpu._cartridgeHeader.emulationInterrupts.reset); + //Parse the first page of the ROM (the code can't reach the second page without a jump). + uint16_t reset = this->_snes.cartridge.header.emulationInterrupts.reset; + this->_updateDisassembly(reset, 0xFFFF - reset); this->_updateRegistersPanel(); }); @@ -220,16 +223,16 @@ namespace ComSquare::Debugger::CPU auto end = std::find_if(this->disassembled.begin(), this->disassembled.end(), [start, refreshSize](DisassembledInstruction &i) { return i.address >= start + refreshSize; }); - this->disassembled.erase(first, end); + auto next = this->disassembled.erase(first, end); - auto next = std::find_if(this->disassembled.begin(), this->disassembled.end(), [start](DisassembledInstruction &i) { - return i.address >= start; - }); DisassemblyContext ctx = this->_getDisassemblyContext(); std::vector nextInstructions = this->_disassemble(start, refreshSize, ctx); - this->disassembled.insert(next, nextInstructions.begin(), nextInstructions.end()); + auto inserted = this->disassembled.insert(next, nextInstructions.begin(), nextInstructions.end()); - int row = static_cast(next - this->disassembled.begin()); + if (this->disassembled.empty()) + return; + + int row = static_cast(inserted - this->disassembled.begin()); if (this->_ui.disassembly->rowAt(0) > row || this->_ui.disassembly->rowAt(this->_ui.disassembly->height()) < row) { auto index = this->_model.index(row, 0); this->_ui.disassembly->scrollTo(index, QAbstractItemView::PositionAtCenter); @@ -260,9 +263,12 @@ namespace ComSquare::Debugger::CPU std::string CPUDebug::getProceededParameters() const { uint24_t pac = this->_cpu._registers.pac; + auto &bus = this->_cpu.getBus(); + this->_cpu.setBus(this->_snes.bus); const Instruction &instruction = this->_cpu.instructions[this->_cpu._readPC()]; uint24_t valueAddr = this->_cpu._getValueAddr(instruction); this->_cpu._registers.pac = pac; + this->_cpu.setBus(bus); if (instruction.size == 1) return ""; return "[" + Utility::to_hex(valueAddr, Utility::AsmPrefix) + "]"; diff --git a/sources/Debugger/MemoryViewer.cpp b/sources/Debugger/MemoryViewer.cpp index 47567df..d60d8ba 100644 --- a/sources/Debugger/MemoryViewer.cpp +++ b/sources/Debugger/MemoryViewer.cpp @@ -172,8 +172,7 @@ namespace ComSquare::Debugger if (addr > accessor->getSize()) { QMessageBox msgBox; msgBox.setIcon(QMessageBox::Critical); - msgBox.setText( - (std::string("The ") + accessor->getName() + " is too small to contain this address.").c_str()); + msgBox.setText((std::string("The ") + accessor->getName() + " is too small to contain this address.").c_str()); msgBox.exec(); return 0; } diff --git a/sources/Ram/Ram.cpp b/sources/Ram/Ram.cpp index 33c1b20..da1b17f 100644 --- a/sources/Ram/Ram.cpp +++ b/sources/Ram/Ram.cpp @@ -10,22 +10,10 @@ namespace ComSquare::Ram { Ram::Ram(size_t size, Component type, std::string ramName) - : _size(size), - _ramType(type), - _ramName(std::move(ramName)) - { - if (size == 0) - this->_data = nullptr; - else { - this->_data = new uint8_t[size]; - std::memset(this->_data, 0, size * sizeof(uint8_t)); - } - } - - Ram::~Ram() - { - delete[] this->_data; - } + : _data(size), + _ramType(type), + _ramName(std::move(ramName)) + { } uint8_t &Ram::operator[](uint24_t addr) { @@ -40,21 +28,26 @@ namespace ComSquare::Ram uint8_t Ram::read(uint24_t addr) { // TODO read/write after the size of the rom should noop or behave like a mirror. I don't really know. - if (addr >= this->_size) + if (addr >= this->_data.size()) throw InvalidAddress(this->getName() + " read", addr); return this->_data[addr]; } void Ram::write(uint24_t addr, uint8_t data) { - if (addr >= this->_size) + if (addr >= this->_data.size()) throw InvalidAddress(this->getName() + " write", addr); this->_data[addr] = data; } uint24_t Ram::getSize() const { - return this->_size; + return this->_data.size(); + } + + void Ram::setSize(uint24_t size) + { + this->_data.resize(size); } std::string Ram::getName() const @@ -67,8 +60,13 @@ namespace ComSquare::Ram return this->_ramType; } - uint8_t *Ram::getData() const + std::span Ram::getData() { - return this->_data; + return std::span(this->_data); + } + + std::span Ram::getData() const + { + return std::span(this->_data); } } diff --git a/sources/Ram/Ram.hpp b/sources/Ram/Ram.hpp index 96e6b10..ce540a8 100644 --- a/sources/Ram/Ram.hpp +++ b/sources/Ram/Ram.hpp @@ -6,6 +6,8 @@ #include "Memory/ARectangleMemory.hpp" #include +#include +#include namespace ComSquare::Ram { @@ -13,9 +15,7 @@ namespace ComSquare::Ram { protected: //! @brief The ram. (Can be used for WRam, SRam, VRam etc) - uint8_t *_data; - //! @brief The size of the ram (in bytes). - uint24_t _size; + std::vector _data; //! @brief An id identifying the type of memory this is (for the debugger) Component _ramType; //! @brief The name of this ram. @@ -28,7 +28,7 @@ namespace ComSquare::Ram //! @brief The ram can't be assigned. Ram &operator=(Ram &) = delete; //! @brief Destructor that free the ram. - ~Ram() override; + ~Ram() override = default; //! @brief Read data from the component. //! @param addr The local address to read from (0x0 should refer to the first byte of this component). @@ -59,8 +59,16 @@ namespace ComSquare::Ram //! @brief Get the size of the ram in bytes. [[nodiscard]] uint24_t getSize() const override; + //! @brief Change the size of this ram. + //! @brief size The new size of this ram. + void setSize(uint24_t size); + //! @brief Get the raw data of the RAM - //! @return A raw pointer to the data. - [[nodiscard]] uint8_t *getData() const; + //! @return A raw accessor to the data. + [[nodiscard]] std::span getData(); + + //! @brief Get the raw data of the RAM + //! @return A raw accessor to the data. + [[nodiscard]] std::span getData() const; }; } \ No newline at end of file diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 7f75592..304bb64 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -11,7 +11,7 @@ namespace ComSquare : bus(), cartridge(), wram(16384, WRam, "WRam"), - sram(this->cartridge.header.sramSize, SRam, "SRam"), + sram(0, SRam, "SRam"), cpu(this->bus, cartridge.header), ppu(renderer), apu(renderer) @@ -46,6 +46,7 @@ namespace ComSquare void SNES::loadRom(const std::string &path) { this->cartridge.loadRom(path); + this->sram.setSize(this->cartridge.header.sramSize); this->bus.mapComponents(*this); this->cpu.RESB(); this->apu.reset(); diff --git a/tests/CPU/testDMA.cpp b/tests/CPU/testDMA.cpp index dc4d600..ab5ada6 100644 --- a/tests/CPU/testDMA.cpp +++ b/tests/CPU/testDMA.cpp @@ -10,9 +10,7 @@ using namespace ComSquare; TEST_CASE("RomToVRAM DMA", "[DMA]") { Init() - snes.cartridge._size = 4000000; - delete[] snes.cartridge._data; - snes.cartridge._data = new uint8_t[snes.cartridge._size]; + snes.cartridge._data.resize(4000000); for (unsigned i = 0; i < 0x400; i++) { snes.cartridge._data[0x9be00 + i * 2] = i; snes.cartridge._data[0x9be00 + i * 2 + 1] = i >> 8; diff --git a/tests/tests.hpp b/tests/tests.hpp index 299c588..78bc620 100644 --- a/tests/tests.hpp +++ b/tests/tests.hpp @@ -19,13 +19,7 @@ Renderer::NoRenderer norenderer(0, 0, 0); \ auto snesPtr = std::make_unique(norenderer); \ SNES &snes = *snesPtr; \ - snes.cartridge._size = 100; \ - delete[] snes.cartridge._data; \ - snes.cartridge._data = new uint8_t[snes.cartridge._size]; \ - memset(snes.cartridge._data, 0, snes.cartridge._size); \ + snes.cartridge._data.resize(100); \ snes.cartridge.header.mappingMode = Cartridge::LoRom; \ - snes.sram._size = 100; \ - delete[] snes.sram._data; \ - snes.sram._data = new uint8_t[snes.sram._size]; \ - memset(snes.sram._data, 0, snes.cartridge._size); \ + snes.sram._data.resize(100); \ snes.bus.mapComponents(snes);