Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions include/Cartridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace sn
{
using Byte = std::uint8_t;
using Address = std::uint16_t;
using UShort = std::uint16_t;

class Cartridge
{
Expand All @@ -16,14 +17,16 @@ namespace sn
bool loadFromFile(std::string path);
const std::vector<Byte>& getROM();
const std::vector<Byte>& getVROM();
Byte getMapper();
UShort getMapper();
Byte getSubMapper();
Byte getNameTableMirroring();
bool hasExtendedRAM();
private:
std::vector<Byte> m_PRG_ROM;
std::vector<Byte> m_CHR_ROM;
Byte m_nameTableMirroring;
Byte m_mapperNumber;
UShort m_mapperNumber;
Byte m_subMapperNumber;
bool m_extendedRAM;
bool m_chrRAM;
};
Expand Down
6 changes: 6 additions & 0 deletions include/Mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace sn
AxROM = 7,
ColorDreams = 11,
GxROM = 66,
NROM474 = 474,
};

Mapper(Cartridge& cart, Type t) : m_cartridge(cart), m_type(t) {};
Expand All @@ -47,6 +48,11 @@ namespace sn
return m_cartridge.hasExtendedRAM();
}

Type inline getType()
{
return m_type;
}

virtual void scanlineIRQ(){}

static std::unique_ptr<Mapper> createMapper (Type mapper_t, Cartridge& cart, std::function<void()> interrupt_cb, std::function<void(void)> mirroring_cb);
Expand Down
24 changes: 24 additions & 0 deletions include/Mapper474.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef MAPPER474_H
#define MAPPER474_H
#include "Mapper.h"

namespace sn
{
class Mapper474 : public Mapper
{
public:
Mapper474(Cartridge& cart);
void writePRG (Address addr, Byte value);
Byte readPRG (Address addr);

Byte readCHR (Address addr);
void writeCHR (Address addr, Byte value);
private:
bool m_flavor474;
bool m_usesCharacterRAM;

std::vector<Byte> m_characterRAM;

};
}
#endif // MAPPERNROM_H
1 change: 1 addition & 0 deletions include/MapperNROM.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace sn
void writeCHR (Address addr, Byte value);
private:
bool m_oneBank;
bool m_flavor368;
bool m_usesCharacterRAM;

std::vector<Byte> m_characterRAM;
Expand Down
25 changes: 24 additions & 1 deletion src/Cartridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace sn
Cartridge::Cartridge() :
m_nameTableMirroring(0),
m_mapperNumber(0),
m_subMapperNumber(0),
m_extendedRAM(false)
{

Expand All @@ -23,11 +24,16 @@ namespace sn
return m_CHR_ROM;
}

Byte Cartridge::getMapper()
UShort Cartridge::getMapper()
{
return m_mapperNumber;
}

Byte Cartridge::getSubMapper()
{
return m_subMapperNumber;
}

Byte Cartridge::getNameTableMirroring()
{
return m_nameTableMirroring;
Expand All @@ -53,6 +59,7 @@ namespace sn

//Header
header.resize(0x10);
bool ver2_0 = false;
if (!romFile.read(reinterpret_cast<char*>(&header[0]), 0x10))
{
LOG(Error) << "Reading iNES header failed." << std::endl;
Expand All @@ -69,6 +76,16 @@ namespace sn

LOG(Info) << "Reading header, it dictates: \n";

if (((header[7] & 0xC) >> 2) == 2)
{
ver2_0 = true;
LOG(Info) << "ines 2.0" << std::endl;
}
else
{
LOG(Info) << "ines 1.0" << std::endl;
}

Byte banks = header[4];
LOG(Info) << "16KB PRG-ROM Banks: " << +banks << std::endl;
if (!banks)
Expand All @@ -92,7 +109,13 @@ namespace sn
}

m_mapperNumber = ((header[6] >> 4) & 0xf) | (header[7] & 0xf0);
if (ver2_0)
{
m_mapperNumber += ((header[8] & 0xf) << 8);
m_subMapperNumber = (header[8] >> 4) & 0xf;
}
LOG(Info) << "Mapper #: " << +m_mapperNumber << std::endl;
LOG(Info) << "Sub Mapper #: " << +m_subMapperNumber << std::endl;

m_extendedRAM = header[6] & 0x2;
LOG(Info) << "Extended (CPU) RAM: " << std::boolalpha << m_extendedRAM << std::endl;
Expand Down
77 changes: 68 additions & 9 deletions src/MainBus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,34 @@ namespace sn
}
else if (addr < 0x6000)
{
LOG(InfoVerbose) << "Expansion ROM read attempted. This is currently unsupported" << std::endl;
if (m_mapper->getType() == NROM474)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of the type check and simply call m_mapper? That we leave it to the mapper and the memory bus code remains generic.

{
if (m_mapper->hasExtendedRAM())
{
return m_extRAM[addr - 0x4000];
}
else
{
return m_mapper->readPRG(addr);
}
}
else
{
LOG(InfoVerbose) << "Expansion ROM read attempted. This is currently unsupported" << std::endl;
}
}
else if (addr < 0x8000)
{
if (m_mapper->hasExtendedRAM())
if (m_mapper->getType() == NROM474)
{
return m_mapper->readPRG(addr);
}
else
{
return m_extRAM[addr - 0x6000];
if (m_mapper->hasExtendedRAM())
{
return m_extRAM[addr - 0x6000];
}
}
}
else
Expand Down Expand Up @@ -88,13 +109,34 @@ namespace sn
}
else if (addr < 0x6000)
{
LOG(InfoVerbose) << "Expansion ROM access attempted. This is currently unsupported" << std::endl;
if (m_mapper->getType() == NROM474)
{
if (m_mapper->hasExtendedRAM())
{
m_extRAM[addr - 0x4000] = value;
}
else
{
m_mapper->writePRG(addr, value);
}
}
else
{
LOG(InfoVerbose) << "Expansion ROM access attempted. This is currently unsupported" << std::endl;
}
}
else if (addr < 0x8000)
{
if (m_mapper->hasExtendedRAM())
if (m_mapper->getType() == NROM474)
{
m_mapper->writePRG(addr, value);
}
else
{
m_extRAM[addr - 0x6000] = value;
if (m_mapper->hasExtendedRAM())
{
m_extRAM[addr - 0x6000] = value;
}
}
}
else
Expand All @@ -116,13 +158,30 @@ namespace sn
}
else if (addr < 0x6000)
{
LOG(Error) << "Expansion ROM access attempted, which is unsupported" << std::endl;
if (m_mapper->getType() == Mapper::Type::NROM474)
{
if (m_mapper->hasExtendedRAM())
{
return &m_extRAM[addr - 0x4000];
}
}
else
{
LOG(Error) << "Expansion ROM access attempted, which is unsupported" << std::endl;
}
}
else if (addr < 0x8000)
{
if (m_mapper->hasExtendedRAM())
if (m_mapper->getType() == Mapper::Type::NROM474)
{
LOG(Error) << "Unexpected DMA request: " << std::hex << "0x" << +addr << " (" << +page << ")" << std::dec << std::endl;
}
else
{
return &m_extRAM[addr - 0x6000];
if (m_mapper->hasExtendedRAM())
{
return &m_extRAM[addr - 0x6000];
}
}
}
else
Expand Down
7 changes: 7 additions & 0 deletions src/Mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "MapperAxROM.h"
#include "MapperColorDreams.h"
#include "MapperGxROM.h"
#include "Mapper474.h"

namespace sn
{
Expand Down Expand Up @@ -45,6 +46,12 @@ namespace sn
case GxROM:
ret.reset(new MapperGxROM(cart, mirroring_cb));
break;
case NROM474:
if (cart.getROM().size() == 0xC000)
{
ret.reset(new Mapper474(cart));
}
break;
default:
break;
}
Expand Down
66 changes: 66 additions & 0 deletions src/Mapper474.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "Mapper474.h"
#include "Log.h"

namespace sn
{
Mapper474::Mapper474(Cartridge &cart) :
Mapper(cart, Mapper::NROM474)
{
if (cart.getROM().size() == 0xC000) // 3 banks
{
// this is the only correct ROM size for this mapper
m_flavor474 = true;
}
else
{
// fail
m_flavor474 = false;
LOG(Info) << "Incorrectly configured mapper" << std::endl;
}

if (cart.getVROM().size() == 0)
{
m_usesCharacterRAM = true;
m_characterRAM.resize(0x2000);
LOG(Info) << "Uses character RAM" << std::endl;
}
else
{
m_usesCharacterRAM = false;
}
}

Byte MapperNROM::readPRG(Address addr)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Byte MapperNROM::readPRG(Address addr)
Byte Mapper474::readPRG(Address addr)

Similar for the rest of the functions.

{
if (m_flavor474)
{
return m_cartridge.getROM()[addr - 0x4000];
}
else
{
LOG(InfoVerbose) << "ROM memory read attempt while mapper is not correctly configured." << std::endl;
return 0; // fail
}
}

void MapperNROM::writePRG(Address addr, Byte value)
{
LOG(InfoVerbose) << "ROM memory write attempt at " << +addr << " to set " << +value << std::endl;
}

Byte MapperNROM::readCHR(Address addr)
{
if (m_usesCharacterRAM)
return m_characterRAM[addr];
else
return m_cartridge.getVROM()[addr];
}

void MapperNROM::writeCHR(Address addr, Byte value)
{
if (m_usesCharacterRAM)
m_characterRAM[addr] = value;
else
LOG(Info) << "Read-only CHR memory write attempt at " << std::hex << addr << std::endl;
}
}
14 changes: 12 additions & 2 deletions src/MapperNROM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ namespace sn
{
m_oneBank = true;
}
else //2 banks
else //2 or 3 banks
{
m_oneBank = false;
}
if (cart.getROM().size() == 0xC000) // 3 banks
{
m_flavor368 = true;
}
else
{
m_flavor368 = false;
}

if (cart.getVROM().size() == 0)
{
Expand All @@ -27,7 +35,9 @@ namespace sn

Byte MapperNROM::readPRG(Address addr)
{
if (!m_oneBank)
if (m_flavor368)
return m_cartridge.getROM()[addr - 0x4000];
else if (!m_oneBank)
return m_cartridge.getROM()[addr - 0x8000];
else //mirrored
return m_cartridge.getROM()[(addr - 0x8000) & 0x3fff];
Expand Down