Adding some logic for MMC1 mapper
This commit is contained in:
parent
f07633a69e
commit
e6e8c71794
@ -28,7 +28,9 @@ add_executable(nes
|
|||||||
examples/sdl/SdlKeyboardController.cpp
|
examples/sdl/SdlKeyboardController.cpp
|
||||||
examples/sdl/SdlKeyboardController.h src/Dma.cpp src/Dma.h
|
examples/sdl/SdlKeyboardController.h src/Dma.cpp src/Dma.h
|
||||||
src/Oam.cpp
|
src/Oam.cpp
|
||||||
src/Oam.h)
|
src/Oam.h
|
||||||
|
src/Mapper/Mapper1.cpp
|
||||||
|
src/Mapper/Mapper1.h)
|
||||||
|
|
||||||
find_package(SDL2 CONFIG REQUIRED)
|
find_package(SDL2 CONFIG REQUIRED)
|
||||||
find_package(fmt REQUIRED)
|
find_package(fmt REQUIRED)
|
||||||
|
|||||||
@ -11,7 +11,7 @@ int main() {
|
|||||||
|
|
||||||
nes::System device;
|
nes::System device;
|
||||||
nes::SdlWindow window(nes::Ppu::SCREEN_WIDTH, nes::Ppu::SCREEN_HEIGHT);
|
nes::SdlWindow window(nes::Ppu::SCREEN_WIDTH, nes::Ppu::SCREEN_HEIGHT);
|
||||||
window.setSize(nes::Ppu::SCREEN_WIDTH * 4, nes::Ppu::SCREEN_HEIGHT * 4);
|
window.setSize(nes::Ppu::SCREEN_WIDTH, nes::Ppu::SCREEN_HEIGHT);
|
||||||
|
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
bool frameRendered = false;
|
bool frameRendered = false;
|
||||||
@ -22,7 +22,7 @@ int main() {
|
|||||||
});
|
});
|
||||||
device.connect(std::make_shared<SdlKeyboardController>());
|
device.connect(std::make_shared<SdlKeyboardController>());
|
||||||
//device.insertCartridge("/home/selim/Downloads/dk.nes");
|
//device.insertCartridge("/home/selim/Downloads/dk.nes");
|
||||||
device.insertCartridge("/Users/selim/Documents/ff.nes");
|
device.insertCartridge("/Users/selim/Documents/smb.nes");
|
||||||
//device.insertCartridge("C:\\Users\\selim\\Documents\\nestest.nes");
|
//device.insertCartridge("C:\\Users\\selim\\Documents\\nestest.nes");
|
||||||
|
|
||||||
auto frameStart = std::chrono::steady_clock::now();
|
auto frameStart = std::chrono::steady_clock::now();
|
||||||
|
|||||||
@ -3,9 +3,12 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "Cartridge.h"
|
#include "Cartridge.h"
|
||||||
|
#include "Mapper/Mapper0.h"
|
||||||
|
#include "Mapper/Mapper1.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
namespace nes {
|
namespace nes {
|
||||||
|
|
||||||
@ -21,13 +24,28 @@ namespace nes {
|
|||||||
// when it become available
|
// when it become available
|
||||||
_header = reinterpret_cast<RomHeader*>(_romData.get());
|
_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 prgSize = _header->prgChunks*PRG_CHUNK_SIZE;
|
||||||
const size_t chrSize = _header->chrChunks*CHR_CHUNK_SIZE;
|
const size_t chrSize = _header->chrChunks*CHR_CHUNK_SIZE;
|
||||||
|
|
||||||
_prgRom = std::span<uint8_t>(_romData.get() + sizeof(RomHeader), prgSize);
|
_prgRom = std::span(_romData.get() + sizeof(RomHeader), prgSize);
|
||||||
_chrRom = std::span<uint8_t>(_romData.get() + sizeof(RomHeader) + prgSize, chrSize);
|
_chrRom = std::span(_romData.get() + sizeof(RomHeader) + prgSize, chrSize);
|
||||||
|
|
||||||
|
switch (_header->flags.mapper) {
|
||||||
|
case 0:
|
||||||
_mapper = std::make_unique<Mapper0>(_header->prgChunks, _header->chrChunks);
|
_mapper = std::make_unique<Mapper0>(_header->prgChunks, _header->chrChunks);
|
||||||
|
case 1:
|
||||||
|
_mapper = std::make_unique<Mapper1>(_header->prgChunks, _header->chrChunks);
|
||||||
|
default:
|
||||||
|
_mapper = std::make_unique<Mapper0>(_header->prgChunks, _header->chrChunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto ramSize = _mapper->ramSize(); ramSize > 0) {
|
||||||
|
_ram = std::make_unique<uint8_t[]>(ramSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Cartridge::readPrg(uint16_t address) {
|
uint8_t Cartridge::readPrg(uint16_t address) {
|
||||||
@ -40,6 +58,11 @@ namespace nes {
|
|||||||
return _chrRom[mappedAddress];
|
return _chrRom[mappedAddress];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t Cartridge::readRam(uint16_t address) {
|
||||||
|
uint32_t mappedAddress = _mapper->mapRam(address);
|
||||||
|
return _ram[mappedAddress];
|
||||||
|
}
|
||||||
|
|
||||||
Cartridge::Mirroring Cartridge::mirroring() const {
|
Cartridge::Mirroring Cartridge::mirroring() const {
|
||||||
return _header->flags.mirroring;
|
return _header->flags.mirroring;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
#ifndef NES_CARTRIDGE_H
|
#ifndef NES_CARTRIDGE_H
|
||||||
#define NES_CARTRIDGE_H
|
#define NES_CARTRIDGE_H
|
||||||
|
|
||||||
#include "Mapper/Mapper0.h"
|
#include "Mapper/Mapper.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -15,13 +15,13 @@ namespace nes {
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
constexpr uint32_t ROM_MAGIC = 0x4E45531A;
|
constexpr uint8_t ROM_MAGIC[4] = { 'N', 'E', 'S', 0x1a };
|
||||||
constexpr size_t PRG_CHUNK_SIZE = 16*1024;
|
constexpr size_t PRG_CHUNK_SIZE = 16*1024;
|
||||||
constexpr size_t CHR_CHUNK_SIZE = 8*1024;
|
constexpr size_t CHR_CHUNK_SIZE = 8*1024;
|
||||||
|
|
||||||
class Cartridge {
|
class Cartridge {
|
||||||
public:
|
public:
|
||||||
enum Mirroring {
|
enum Mirroring: uint8_t {
|
||||||
Horizontal = 0,
|
Horizontal = 0,
|
||||||
Vertical = 1
|
Vertical = 1
|
||||||
};
|
};
|
||||||
@ -35,7 +35,7 @@ namespace nes {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct RomHeader {
|
struct RomHeader {
|
||||||
uint32_t magic;
|
uint8_t magic[4];
|
||||||
uint8_t prgChunks;
|
uint8_t prgChunks;
|
||||||
uint8_t chrChunks;
|
uint8_t chrChunks;
|
||||||
Flags flags;
|
Flags flags;
|
||||||
@ -48,6 +48,7 @@ namespace nes {
|
|||||||
public:
|
public:
|
||||||
uint8_t readPrg(uint16_t address);
|
uint8_t readPrg(uint16_t address);
|
||||||
uint8_t readChr(uint16_t address);
|
uint8_t readChr(uint16_t address);
|
||||||
|
uint8_t readRam(uint16_t address);
|
||||||
Mirroring mirroring() const;
|
Mirroring mirroring() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -56,6 +57,7 @@ namespace nes {
|
|||||||
RomHeader* _header;
|
RomHeader* _header;
|
||||||
std::span<uint8_t> _prgRom;
|
std::span<uint8_t> _prgRom;
|
||||||
std::span<uint8_t> _chrRom;
|
std::span<uint8_t> _chrRom;
|
||||||
|
std::unique_ptr<uint8_t[]> _ram;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#define NES_MAPPER_H
|
#define NES_MAPPER_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
namespace nes {
|
namespace nes {
|
||||||
|
|
||||||
@ -17,6 +18,8 @@ namespace nes {
|
|||||||
public:
|
public:
|
||||||
virtual uint32_t mapPrg(uint16_t address) = 0;
|
virtual uint32_t mapPrg(uint16_t address) = 0;
|
||||||
virtual uint32_t mapChr(uint16_t address) = 0;
|
virtual uint32_t mapChr(uint16_t address) = 0;
|
||||||
|
virtual uint32_t mapRam(uint16_t address) = 0;
|
||||||
|
virtual size_t ramSize() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t _prgBanks;
|
uint8_t _prgBanks;
|
||||||
|
|||||||
@ -13,4 +13,12 @@ namespace nes {
|
|||||||
uint32_t Mapper0::mapChr(uint16_t address) {
|
uint32_t Mapper0::mapChr(uint16_t address) {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Mapper0::mapRam(uint16_t address) {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Mapper0::ramSize() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -17,6 +17,8 @@ namespace nes {
|
|||||||
public:
|
public:
|
||||||
uint32_t mapPrg(uint16_t address) override;
|
uint32_t mapPrg(uint16_t address) override;
|
||||||
uint32_t mapChr(uint16_t address) override;
|
uint32_t mapChr(uint16_t address) override;
|
||||||
|
uint32_t mapRam(uint16_t address) override;
|
||||||
|
size_t ramSize() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/Mapper/Mapper1.cpp
Normal file
31
src/Mapper/Mapper1.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 27.06.2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Mapper1.h"
|
||||||
|
|
||||||
|
namespace nes {
|
||||||
|
|
||||||
|
uint32_t Mapper1::mapPrg(uint16_t address) {
|
||||||
|
|
||||||
|
if(_controlReg.prgBankMode == FixFirst16 || _controlReg.prgBankMode == FixLast16) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Mapper1::mapChr(uint16_t address) {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Mapper1::mapRam(uint16_t address) {
|
||||||
|
return address & 0x1FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Mapper1::ramSize() {
|
||||||
|
return 32*1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/Mapper/Mapper1.h
Normal file
53
src/Mapper/Mapper1.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 27.06.2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MAPPER1_H
|
||||||
|
#define MAPPER1_H
|
||||||
|
|
||||||
|
#include "Mapper.h"
|
||||||
|
|
||||||
|
namespace nes {
|
||||||
|
|
||||||
|
class Mapper1 final : public Mapper {
|
||||||
|
public:
|
||||||
|
enum PrgBankMode: uint8_t {
|
||||||
|
FixFirst32 = 0,
|
||||||
|
FixLast32 = 1,
|
||||||
|
FixFirst16 = 2,
|
||||||
|
FixLast16 = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ChrBankMode: uint8_t {
|
||||||
|
Single8 = 0,
|
||||||
|
Double4 = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
union ControlRegister {
|
||||||
|
struct {
|
||||||
|
uint8_t reserved: 2;
|
||||||
|
PrgBankMode prgBankMode: 2;
|
||||||
|
ChrBankMode chrBankMode: 1;
|
||||||
|
};
|
||||||
|
uint8_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Mapper::Mapper;
|
||||||
|
~Mapper1() override = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint32_t mapPrg(uint16_t address) override;
|
||||||
|
uint32_t mapChr(uint16_t address) override;
|
||||||
|
uint32_t mapRam(uint16_t address) override;
|
||||||
|
size_t ramSize() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ControlRegister _controlReg = {};
|
||||||
|
uint8_t _shiftReg = 0;
|
||||||
|
uint8_t _writes = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MAPPER1_H
|
||||||
@ -92,6 +92,9 @@ namespace nes {
|
|||||||
else if(address >= 0x2000 && address < 0x4000) {
|
else if(address >= 0x2000 && address < 0x4000) {
|
||||||
return _ppu->read(address & 0x0007);
|
return _ppu->read(address & 0x0007);
|
||||||
}
|
}
|
||||||
|
else if (address >= 0x6000 && address < 0x8000) {
|
||||||
|
return _cartridge->readRam(address);
|
||||||
|
}
|
||||||
else if(address >= 0x8000) {
|
else if(address >= 0x8000) {
|
||||||
return _cartridge->readPrg(address);
|
return _cartridge->readPrg(address);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user