// // Created by Selim Mustafaev on 09.08.2023. // #include "Cartridge.h" #include "Mapper/Mapper0.h" #include "Mapper/Mapper1.h" #include #include #include #include namespace nes { Cartridge::Cartridge(const fs::path &path) { auto romSize = fs::file_size(path); _romData = std::make_unique(romSize); std::ifstream rom(path, std::ios::binary); rom.read(reinterpret_cast(_romData.get()), static_cast(romSize)); _header = reinterpret_cast(_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(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(_header->prgChunks, _header->chrChunks); break; case 1: _mapper = std::make_unique(_header->prgChunks, _header->chrChunks); break; default: throw std::runtime_error("unknown mapper"); } if (const auto ramSize = _mapper->ramSize(); ramSize > 0) { _ram = std::make_unique(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; } }