91 lines
2.7 KiB
C++
91 lines
2.7 KiB
C++
//
|
|
// Created by Selim Mustafaev on 09.08.2023.
|
|
//
|
|
|
|
#include "Cartridge.h"
|
|
#include "Mapper/Mapper0.h"
|
|
#include "Mapper/Mapper1.h"
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <cstddef>
|
|
|
|
namespace nes {
|
|
|
|
Cartridge::Cartridge(const fs::path &path) {
|
|
auto romSize = fs::file_size(path);
|
|
_romData = std::make_unique<uint8_t[]>(romSize);
|
|
|
|
std::ifstream rom(path, std::ios::binary);
|
|
rom.read(reinterpret_cast<char*>(_romData.get()), static_cast<std::streamsize>(romSize));
|
|
|
|
_header = reinterpret_cast<RomHeader*>(_romData.get());
|
|
|
|
if (memcmp(_header->magic, ROM_MAGIC, sizeof(ROM_MAGIC)) != 0) {
|
|
throw std::runtime_error("Wrong ROM magic");
|
|
}
|
|
|
|
const size_t prgSize = _header->prgChunks*PRG_CHUNK_SIZE;
|
|
const size_t chrSize = _header->chrChunks*CHR_CHUNK_SIZE;
|
|
|
|
_prgRom = std::span(_romData.get() + sizeof(RomHeader), prgSize);
|
|
|
|
if (chrSize == 0) {
|
|
_chrRam = std::make_unique<uint8_t[]>(CHR_CHUNK_SIZE);
|
|
_chrRom = std::span(_chrRam.get(), CHR_CHUNK_SIZE);
|
|
} else {
|
|
_chrRom = std::span(_romData.get() + sizeof(RomHeader) + prgSize, chrSize);
|
|
}
|
|
|
|
uint8_t mapper = _header->flags.mapper | (_header->flags2.upperMapper << 4);
|
|
|
|
switch (mapper) {
|
|
case 0:
|
|
_mapper = std::make_unique<Mapper0>(_header->prgChunks, _header->chrChunks);
|
|
break;
|
|
case 1:
|
|
_mapper = std::make_unique<Mapper1>(_header->prgChunks, _header->chrChunks);
|
|
break;
|
|
default:
|
|
throw std::runtime_error("unknown mapper");
|
|
}
|
|
|
|
if (const auto ramSize = _mapper->ramSize(); ramSize > 0) {
|
|
_ram = std::make_unique<uint8_t[]>(ramSize);
|
|
}
|
|
}
|
|
|
|
uint8_t Cartridge::readPrg(uint16_t address) {
|
|
uint32_t mappedAddress = _mapper->mapPrg(address);
|
|
return _prgRom[mappedAddress];
|
|
}
|
|
|
|
void Cartridge::writePrg(uint16_t address, uint8_t value) {
|
|
_mapper->write(address, value);
|
|
}
|
|
|
|
uint8_t Cartridge::readChr(uint16_t address) {
|
|
uint32_t mappedAddress = _mapper->mapChr(address);
|
|
return _chrRom[mappedAddress];
|
|
}
|
|
|
|
void Cartridge::writeChr(uint16_t address, uint8_t value) {
|
|
_chrRom[address] = value;
|
|
}
|
|
|
|
uint8_t Cartridge::readRam(uint16_t address) {
|
|
uint32_t mappedAddress = _mapper->mapRam(address);
|
|
return _ram[mappedAddress];
|
|
}
|
|
|
|
void Cartridge::writeRam(uint16_t address, uint8_t value) {
|
|
uint32_t mappedAddress = _mapper->mapRam(address);
|
|
_ram[mappedAddress] = value;
|
|
}
|
|
|
|
Cartridge::Mirroring Cartridge::mirroring() const {
|
|
return _header->flags.mirroring;
|
|
}
|
|
|
|
}
|