Cleaning up rom data

This commit is contained in:
Zoe Roux
2021-07-06 23:06:02 +02:00
parent 0d0dbc9b02
commit 44361c8482
10 changed files with 85 additions and 75 deletions

View File

@@ -7,6 +7,7 @@
#include "Exceptions/InvalidOpcode.hpp"
#include <cstring>
#include <iostream>
#include <algorithm>
namespace ComSquare::APU
{
@@ -814,17 +815,17 @@ namespace ComSquare::APU
void APU::loadFromSPC(Cartridge::Cartridge &cartridge)
{
const uint8_t *data = cartridge.getData();
std::span<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<const char *>(data + 0x2E), 0x20);
std::string game = std::string(reinterpret_cast<const char *>(data + 0x4E), 0x20);
std::string dumper = std::string(reinterpret_cast<const char *>(data + 0x6E), 0x10);
std::string comment = std::string(reinterpret_cast<const char *>(data + 0x7E), 0x20);
std::string date = std::string(reinterpret_cast<const char *>(data + 0x9E), 0x0B);
std::string artist = std::string(reinterpret_cast<const char *>(data + 0xB1), 0x20);
std::string song = std::string(reinterpret_cast<const char *>(data.data() + 0x2E), 0x20);
std::string game = std::string(reinterpret_cast<const char *>(data.data() + 0x4E), 0x20);
std::string dumper = std::string(reinterpret_cast<const char *>(data.data() + 0x6E), 0x10);
std::string comment = std::string(reinterpret_cast<const char *>(data.data() + 0x7E), 0x20);
std::string date = std::string(reinterpret_cast<const char *>(data.data() + 0x9E), 0x0B);
std::string artist = std::string(reinterpret_cast<const char *>(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);

View File

@@ -7,18 +7,19 @@
#include "Exceptions/InvalidRom.hpp"
#include <cstring>
#include <sys/stat.h>
#include <fstream>
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<char *>(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<uint32_t> 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<char *>(this->_data), 0x21);
std::string str = std::string(reinterpret_cast<char *>(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<char *>(&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<MappingMode>(static_cast<int>(self) | static_cast<int>(other));

View File

@@ -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.

View File

@@ -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<DisassembledInstruction> 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<int>(next - this->disassembled.begin());
if (this->disassembled.empty())
return;
int row = static_cast<int>(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) + "]";

View File

@@ -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;
}

View File

@@ -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<uint8_t> Ram::getData()
{
return this->_data;
return std::span(this->_data);
}
std::span<const uint8_t> Ram::getData() const
{
return std::span(this->_data);
}
}

View File

@@ -6,6 +6,8 @@
#include "Memory/ARectangleMemory.hpp"
#include <string>
#include <span>
#include <vector>
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<uint8_t> _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<uint8_t> getData();
//! @brief Get the raw data of the RAM
//! @return A raw accessor to the data.
[[nodiscard]] std::span<const uint8_t> getData() const;
};
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -19,13 +19,7 @@
Renderer::NoRenderer norenderer(0, 0, 0); \
auto snesPtr = std::make_unique<SNES>(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);