From 89c947640da1d389cfdeadbe119385a9057f5b31 Mon Sep 17 00:00:00 2001 From: Amish Naidu Date: Tue, 4 Oct 2016 17:49:43 +0530 Subject: [PATCH 1/4] Added (not-working) MMC1 --- include/Mapper.h | 4 +- include/MapperSxROM.h | 34 ++++++++++ src/Cartridge.cpp | 4 +- src/Mapper.cpp | 4 ++ src/MapperSxROM.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 include/MapperSxROM.h create mode 100644 src/MapperSxROM.cpp diff --git a/include/Mapper.h b/include/Mapper.h index 8874d06..96fe627 100644 --- a/include/Mapper.h +++ b/include/Mapper.h @@ -18,8 +18,8 @@ namespace sn public: enum Type { - NROM = 0, - MMC1 = 1, + NROM = 0, + SxROM = 1, UxROM = 2, CNROM = 3, }; diff --git a/include/MapperSxROM.h b/include/MapperSxROM.h new file mode 100644 index 0000000..5524cff --- /dev/null +++ b/include/MapperSxROM.h @@ -0,0 +1,34 @@ +#ifndef MAPPERSXROM_H +#define MAPPERSXROM_H +#include "Mapper.h" + +namespace sn +{ + class MapperSxROM : public Mapper + { + public: + MapperSxROM(Cartridge& cart); + void writePRG (Address addr, Byte value); + Byte readPRG (Address addr); + const Byte* getPagePtr(Address addr); + + Byte readCHR (Address addr); + void writeCHR (Address addr, Byte value); + private: + bool m_usesCharacterRAM; + int m_modeCHR; + int m_modePRG; + + Byte m_tempRegister; + int m_writeCounter; + + const Byte* m_firstBankPRG; + const Byte* m_secondBankPRG; + + const Byte* m_firstBankCHR; + const Byte* m_secondBankCHR; + + std::vector m_characterRAM; + }; +} +#endif // MAPPERSXROM_H diff --git a/src/Cartridge.cpp b/src/Cartridge.cpp index 9922091..3008886 100644 --- a/src/Cartridge.cpp +++ b/src/Cartridge.cpp @@ -68,7 +68,7 @@ namespace sn LOG(Info) << "Reading header, it dictates: \n"; Byte banks = header[4]; - LOG(Info) << "PRG-ROM Banks: " << +banks << std::endl; + LOG(Info) << "16KB PRG-ROM Banks: " << +banks << std::endl; if (!banks) { LOG(Error) << "ROM has no PRG-ROM banks. Loading ROM failed." << std::endl; @@ -76,7 +76,7 @@ namespace sn } Byte vbanks = header[5]; - LOG(Info) << "CHR-ROM Banks: " << +vbanks << std::endl; + LOG(Info) << "8KB CHR-ROM Banks: " << +vbanks << std::endl; m_nameTableMirroring = header[6] & 0xB; LOG(Info) << "Name Table Mirroring: " << +m_nameTableMirroring << std::endl; diff --git a/src/Mapper.cpp b/src/Mapper.cpp index f12a1d6..58092b6 100644 --- a/src/Mapper.cpp +++ b/src/Mapper.cpp @@ -1,5 +1,6 @@ #include "Mapper.h" #include "MapperNROM.h" +#include "MapperSxROM.h" #include "MapperUxROM.h" #include "MapperCNROM.h" @@ -13,6 +14,9 @@ namespace sn case NROM: ret.reset(new MapperNROM(cart)); break; + case SxROM: + ret.reset(new MapperSxROM(cart)); + break; case UxROM: ret.reset(new MapperUxROM(cart)); break; diff --git a/src/MapperSxROM.cpp b/src/MapperSxROM.cpp new file mode 100644 index 0000000..29c7030 --- /dev/null +++ b/src/MapperSxROM.cpp @@ -0,0 +1,141 @@ +#include "MapperSxROM.h" +#include "Log.h" + +namespace sn +{ + MapperSxROM::MapperSxROM(Cartridge &cart) : + Mapper(cart, Mapper::SxROM), + m_modeCHR(0), + m_modePRG(3), + m_tempRegister(0), + m_writeCounter(0), + m_firstBankPRG(nullptr), + m_secondBankPRG(nullptr), + m_firstBankCHR(nullptr), + m_secondBankCHR(nullptr) + { + if (cart.getVROM().size() == 0) + { + m_usesCharacterRAM = true; + m_characterRAM.resize(0x2000); + LOG(Info) << "Uses character RAM" << std::endl; + } + else + { + LOG(Info) << "Using CHR-ROM" << std::endl; + m_usesCharacterRAM = false; + m_firstBankCHR = &cart.getVROM()[0]; + m_secondBankCHR = &cart.getVROM()[0x1000]; + } + + m_firstBankPRG = &cart.getROM()[0]; //first bank + m_secondBankPRG = &cart.getROM()[/*cart.getROM().size() - 0x4000*/0x2000 * 0x0e]; //last bank + } + + Byte MapperSxROM::readPRG(Address addr) + { + if (addr < 0xc000) + return *(m_firstBankPRG + (addr & 0x3fff)); + else + return *(m_secondBankPRG + (addr & 0x3fff)); + } + + void MapperSxROM::writePRG(Address addr, Byte value) + { + if (!(value & 0x80)) //if reset bit is NOT set + { + m_tempRegister = (m_tempRegister >> 1) | ((value & 1) << 4); + ++m_writeCounter; + + if (m_writeCounter == 5) + { + if (addr < 0xa000) + { + m_modeCHR = (m_tempRegister & 0x10) >> 4; + m_modePRG = (m_tempRegister & 0xc) >> 2; + LOG(Info) << "CHR mode: " << m_modeCHR << std::endl; + LOG(Info) << "PRG mode: " << m_modePRG << std::endl; + //TODO Mirroring? + } + else if (addr < 0xc000) + { + if (m_modeCHR == 0) //if 8KB switchable + m_tempRegister |= 1; + + m_firstBankCHR = &m_cartridge.getVROM()[0x1000 * m_tempRegister]; + if (m_modeCHR == 0) + m_secondBankCHR = m_firstBankCHR + 0x1000; + } + else if (addr < 0xe000) + { +// if(m_modeCHR == 1) + m_secondBankCHR = &m_cartridge.getVROM()[0x1000 * m_tempRegister]; + +// else +// LOG(Info) << "This doesn't make sense now" << std::endl; + } + else + { + //TODO PRG-RAM + if ((m_tempRegister & 0x10) == 0x10) + { + LOG(Info) << "PRG-RAM activated" << std::endl; + } + + m_tempRegister &= 0xf; + + if (m_modePRG <= 1) //32KB changeable + { + m_firstBankPRG = &m_cartridge.getROM()[0x4000 * (m_tempRegister | 1)]; + m_secondBankPRG = m_firstBankPRG + 0x4000; //add 16KB + } + else if (m_modePRG == 2) //fix first switch second + { + m_firstBankPRG = &m_cartridge.getROM()[0]; + m_secondBankPRG = m_firstBankPRG + 0x4000 * m_tempRegister; + } + else //switch first fix second + { + m_firstBankPRG = &m_cartridge.getROM()[0x4000 * m_tempRegister]; + m_secondBankPRG = &m_cartridge.getROM()[/*m_cartridge.getROM().size() - 0x4000*/0x2000 * 0x0e]; + } + } + + m_tempRegister = 0; + m_writeCounter = 0; + } + } + else //reset + { + m_tempRegister = 0; + m_writeCounter = 0; + m_modePRG = 3; + } + } + + const Byte* MapperSxROM::getPagePtr(Address addr) + { + if (addr < 0xc000) + return (m_firstBankPRG + (addr & 0x3fff)); + else + return (m_secondBankPRG + (addr & 0x3fff)); + } + + Byte MapperSxROM::readCHR(Address addr) + { + if (m_usesCharacterRAM) + return m_characterRAM[addr]; + else if (addr < 0x1000) + return *(m_firstBankCHR + addr); + else + return *(m_secondBankCHR + (addr & 0xfff)); + } + + void MapperSxROM::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; + } +} \ No newline at end of file From b2823bf1ec1e856f79042b9bb697635492c23457 Mon Sep 17 00:00:00 2001 From: Amish Naidu Date: Sun, 16 Oct 2016 11:19:14 +0530 Subject: [PATCH 2/4] Fix erraneous vector use Wrong subtrahend caused out-of-bound memory access --- src/MainBus.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MainBus.cpp b/src/MainBus.cpp index e26faa2..b991b9f 100644 --- a/src/MainBus.cpp +++ b/src/MainBus.cpp @@ -94,7 +94,7 @@ namespace sn { if (m_mapper->hasExtendedRAM()) { - m_extRAM[addr - 0x8000] = value; + m_extRAM[addr - 0x6000] = value; } } else @@ -120,7 +120,7 @@ namespace sn { if (m_mapper->hasExtendedRAM()) { - return &m_extRAM[addr - 0x8000]; + return &m_extRAM[addr - 0x6000]; } } else From 5aa1f1729e2732d153f2139e22af4fcefe85515e Mon Sep 17 00:00:00 2001 From: Amish Naidu Date: Sun, 16 Oct 2016 11:23:35 +0530 Subject: [PATCH 3/4] Added explicit registers to SxROM --- include/MapperSxROM.h | 5 +++ src/MapperSxROM.cpp | 84 ++++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/include/MapperSxROM.h b/include/MapperSxROM.h index 5524cff..641e8bc 100644 --- a/include/MapperSxROM.h +++ b/include/MapperSxROM.h @@ -15,6 +15,7 @@ namespace sn Byte readCHR (Address addr); void writeCHR (Address addr, Byte value); private: + void calculatePRGPointers(); bool m_usesCharacterRAM; int m_modeCHR; int m_modePRG; @@ -22,6 +23,10 @@ namespace sn Byte m_tempRegister; int m_writeCounter; + Byte m_regPRG; + Byte m_regCHR0; + Byte m_regCHR1; + const Byte* m_firstBankPRG; const Byte* m_secondBankPRG; diff --git a/src/MapperSxROM.cpp b/src/MapperSxROM.cpp index 29c7030..2fe706e 100644 --- a/src/MapperSxROM.cpp +++ b/src/MapperSxROM.cpp @@ -9,6 +9,9 @@ namespace sn m_modePRG(3), m_tempRegister(0), m_writeCounter(0), + m_regPRG(0), + m_regCHR0(0), + m_regCHR1(0), m_firstBankPRG(nullptr), m_secondBankPRG(nullptr), m_firstBankCHR(nullptr), @@ -25,11 +28,11 @@ namespace sn LOG(Info) << "Using CHR-ROM" << std::endl; m_usesCharacterRAM = false; m_firstBankCHR = &cart.getVROM()[0]; - m_secondBankCHR = &cart.getVROM()[0x1000]; + m_secondBankCHR = &cart.getVROM()[0x1000 * m_regCHR1]; } m_firstBankPRG = &cart.getROM()[0]; //first bank - m_secondBankPRG = &cart.getROM()[/*cart.getROM().size() - 0x4000*/0x2000 * 0x0e]; //last bank + m_secondBankPRG = &cart.getROM()[cart.getROM().size() - 0x4000/*0x2000 * 0x0e*/]; //last bank } Byte MapperSxROM::readPRG(Address addr) @@ -49,30 +52,39 @@ namespace sn if (m_writeCounter == 5) { - if (addr < 0xa000) + if (addr <= 0x9fff) { + //TODO Mirroring and Name table mapped with mapper m_modeCHR = (m_tempRegister & 0x10) >> 4; m_modePRG = (m_tempRegister & 0xc) >> 2; - LOG(Info) << "CHR mode: " << m_modeCHR << std::endl; - LOG(Info) << "PRG mode: " << m_modePRG << std::endl; - //TODO Mirroring? + calculatePRGPointers(); + //Recalculate CHR pointers + if (m_modeCHR == 0) //one 8KB bank + { + m_firstBankCHR = &m_cartridge.getVROM()[0x1000 * (m_regCHR0 | 1)]; //ignore last bit + m_secondBankCHR = m_firstBankCHR + 0x1000; + } + else //two 4KB banks + { + m_firstBankCHR = &m_cartridge.getVROM()[0x1000 * m_regCHR0]; + m_secondBankCHR = &m_cartridge.getVROM()[0x1000 * m_regCHR1]; + } + LOG(Info) << "CHR mode : " << m_modeCHR << std::endl; + LOG(Info) << "PRG mode : " << m_modePRG << std::endl; + LOG(Info) << "Mirroring: " << (m_tempRegister & 0x3) << std::endl; } - else if (addr < 0xc000) + else if (addr <= 0xbfff) //CHR Reg 0 { - if (m_modeCHR == 0) //if 8KB switchable - m_tempRegister |= 1; - - m_firstBankCHR = &m_cartridge.getVROM()[0x1000 * m_tempRegister]; + m_regCHR0 = m_tempRegister; + m_firstBankCHR = &m_cartridge.getVROM()[0x1000 * (m_tempRegister | (1 - m_modeCHR))]; //OR 1 if 8KB mode if (m_modeCHR == 0) m_secondBankCHR = m_firstBankCHR + 0x1000; } - else if (addr < 0xe000) + else if (addr <= 0xdfff) { -// if(m_modeCHR == 1) - m_secondBankCHR = &m_cartridge.getVROM()[0x1000 * m_tempRegister]; - -// else -// LOG(Info) << "This doesn't make sense now" << std::endl; + m_regCHR1 = m_tempRegister; + if(m_modeCHR == 1) + m_secondBankCHR = &m_cartridge.getVROM()[0x1000 * m_tempRegister]; } else { @@ -83,22 +95,8 @@ namespace sn } m_tempRegister &= 0xf; - - if (m_modePRG <= 1) //32KB changeable - { - m_firstBankPRG = &m_cartridge.getROM()[0x4000 * (m_tempRegister | 1)]; - m_secondBankPRG = m_firstBankPRG + 0x4000; //add 16KB - } - else if (m_modePRG == 2) //fix first switch second - { - m_firstBankPRG = &m_cartridge.getROM()[0]; - m_secondBankPRG = m_firstBankPRG + 0x4000 * m_tempRegister; - } - else //switch first fix second - { - m_firstBankPRG = &m_cartridge.getROM()[0x4000 * m_tempRegister]; - m_secondBankPRG = &m_cartridge.getROM()[/*m_cartridge.getROM().size() - 0x4000*/0x2000 * 0x0e]; - } + m_regPRG = m_tempRegister; + calculatePRGPointers(); } m_tempRegister = 0; @@ -110,6 +108,26 @@ namespace sn m_tempRegister = 0; m_writeCounter = 0; m_modePRG = 3; + calculatePRGPointers(); + } + } + + void MapperSxROM::calculatePRGPointers() + { + if (m_modePRG <= 1) //32KB changeable + { + m_firstBankPRG = &m_cartridge.getROM()[0x4000 * (m_regPRG | 1)]; + m_secondBankPRG = m_firstBankPRG + 0x4000; //add 16KB + } + else if (m_modePRG == 2) //fix first switch second + { + m_firstBankPRG = &m_cartridge.getROM()[0]; + m_secondBankPRG = m_firstBankPRG + 0x4000 * m_regPRG; + } + else //switch first fix second + { + m_firstBankPRG = &m_cartridge.getROM()[0x4000 * m_regPRG]; + m_secondBankPRG = &m_cartridge.getROM()[m_cartridge.getROM().size() - 0x4000/*0x2000 * 0x0e*/]; } } From 0bf9170f76e18efe5c96f57806ad3fc8d4351167 Mon Sep 17 00:00:00 2001 From: Amish Naidu Date: Sun, 16 Oct 2016 12:56:24 +0530 Subject: [PATCH 4/4] Mirroring can now be controlled by mappers. --- include/Mapper.h | 11 +++++------ include/MapperSxROM.h | 8 +++++++- include/PictureBus.h | 2 ++ src/Emulator.cpp | 4 +++- src/MainBus.cpp | 4 ++-- src/Mapper.cpp | 9 +++++++-- src/MapperSxROM.cpp | 25 ++++++++++++++++++++----- src/PictureBus.cpp | 34 ++++++++++++++++++++++------------ 8 files changed, 68 insertions(+), 29 deletions(-) diff --git a/include/Mapper.h b/include/Mapper.h index 96fe627..09750e5 100644 --- a/include/Mapper.h +++ b/include/Mapper.h @@ -10,6 +10,8 @@ namespace sn Horizontal = 0, Vertical = 1, FourScreen = 8, + OneScreenLower, + OneScreenHigher, }; @@ -32,17 +34,14 @@ namespace sn virtual Byte readCHR (Address addr) = 0; virtual void writeCHR (Address addr, Byte value) = 0; + virtual NameTableMirroring getNameTableMirroring(); + bool inline hasExtendedRAM() { return m_cartridge.hasExtendedRAM(); } - NameTableMirroring inline getNameTableMirroring() - { - return static_cast(m_cartridge.getNameTableMirroring()); - } - - static std::unique_ptr createMapper (Type mapper_t, Cartridge& cart); + static std::unique_ptr createMapper (Type mapper_t, Cartridge& cart, std::function mirroring_cb); protected: Cartridge& m_cartridge; diff --git a/include/MapperSxROM.h b/include/MapperSxROM.h index 641e8bc..7cbd4dc 100644 --- a/include/MapperSxROM.h +++ b/include/MapperSxROM.h @@ -7,15 +7,21 @@ namespace sn class MapperSxROM : public Mapper { public: - MapperSxROM(Cartridge& cart); + MapperSxROM(Cartridge& cart, std::function mirroring_cb); void writePRG (Address addr, Byte value); Byte readPRG (Address addr); const Byte* getPagePtr(Address addr); Byte readCHR (Address addr); void writeCHR (Address addr, Byte value); + + NameTableMirroring getNameTableMirroring(); private: void calculatePRGPointers(); + + std::function m_mirroringCallback; + NameTableMirroring m_mirroing; + bool m_usesCharacterRAM; int m_modeCHR; int m_modePRG; diff --git a/include/PictureBus.h b/include/PictureBus.h index ccc9633..ec67d7b 100644 --- a/include/PictureBus.h +++ b/include/PictureBus.h @@ -15,6 +15,8 @@ namespace sn bool setMapper(Mapper *mapper); Byte readPalette(Byte paletteAddr); + + void updateMirroring(); private: std::vector m_RAM; std::size_t NameTable0, NameTable1, NameTable2, NameTable3; //indices where they start in RAM vector diff --git a/src/Emulator.cpp b/src/Emulator.cpp index cda28a1..a401f0d 100644 --- a/src/Emulator.cpp +++ b/src/Emulator.cpp @@ -43,7 +43,9 @@ namespace sn if (!m_cartridge.loadFromFile(rom_path)) return; - m_mapper = Mapper::createMapper(static_cast(m_cartridge.getMapper()), m_cartridge); + m_mapper = Mapper::createMapper(static_cast(m_cartridge.getMapper()), + m_cartridge, + [&](){ m_pictureBus.updateMirroring(); }); if (!m_mapper) { LOG(Error) << "Creating Mapper failed. Probably unsupported." << std::endl; diff --git a/src/MainBus.cpp b/src/MainBus.cpp index b991b9f..6b2e639 100644 --- a/src/MainBus.cpp +++ b/src/MainBus.cpp @@ -152,7 +152,7 @@ namespace sn LOG(Error) << "callback argument is nullptr" << std::endl; return false; } - return m_writeCallbacks.insert({reg, callback}).second; + return m_writeCallbacks.emplace(reg, callback).second; } bool MainBus::setReadCallback(IORegisters reg, std::function callback) @@ -162,7 +162,7 @@ namespace sn LOG(Error) << "callback argument is nullptr" << std::endl; return false; } - return m_readCallbacks.insert({reg, callback}).second; + return m_readCallbacks.emplace(reg, callback).second; } }; diff --git a/src/Mapper.cpp b/src/Mapper.cpp index 58092b6..6b62a80 100644 --- a/src/Mapper.cpp +++ b/src/Mapper.cpp @@ -6,7 +6,12 @@ namespace sn { - std::unique_ptr Mapper::createMapper(Mapper::Type mapper_t, sn::Cartridge& cart) + NameTableMirroring Mapper::getNameTableMirroring() + { + return static_cast(m_cartridge.getNameTableMirroring()); + } + + std::unique_ptr Mapper::createMapper(Mapper::Type mapper_t, sn::Cartridge& cart, std::function mirroring_cb) { std::unique_ptr ret(nullptr); switch (mapper_t) @@ -15,7 +20,7 @@ namespace sn ret.reset(new MapperNROM(cart)); break; case SxROM: - ret.reset(new MapperSxROM(cart)); + ret.reset(new MapperSxROM(cart, mirroring_cb)); break; case UxROM: ret.reset(new MapperUxROM(cart)); diff --git a/src/MapperSxROM.cpp b/src/MapperSxROM.cpp index 2fe706e..50e4716 100644 --- a/src/MapperSxROM.cpp +++ b/src/MapperSxROM.cpp @@ -3,8 +3,9 @@ namespace sn { - MapperSxROM::MapperSxROM(Cartridge &cart) : + MapperSxROM::MapperSxROM(Cartridge &cart, std::function mirroring_cb) : Mapper(cart, Mapper::SxROM), + m_mirroringCallback(mirroring_cb), m_modeCHR(0), m_modePRG(3), m_tempRegister(0), @@ -43,6 +44,11 @@ namespace sn return *(m_secondBankPRG + (addr & 0x3fff)); } + NameTableMirroring MapperSxROM::getNameTableMirroring() + { + return m_mirroing; + } + void MapperSxROM::writePRG(Address addr, Byte value) { if (!(value & 0x80)) //if reset bit is NOT set @@ -54,10 +60,22 @@ namespace sn { if (addr <= 0x9fff) { - //TODO Mirroring and Name table mapped with mapper + LOG(Info) << "CHR mode : " << m_modeCHR << std::endl; + LOG(Info) << "PRG mode : " << m_modePRG << std::endl; + LOG(Info) << "Mirroring: " << (m_tempRegister & 0x3) << std::endl; + switch (m_tempRegister & 0x3) + { + case 0: m_mirroing = OneScreenLower; break; + case 1: m_mirroing = OneScreenHigher; break; + case 2: m_mirroing = Vertical; break; + case 3: m_mirroing = Horizontal; break; + } + m_mirroringCallback(); + m_modeCHR = (m_tempRegister & 0x10) >> 4; m_modePRG = (m_tempRegister & 0xc) >> 2; calculatePRGPointers(); + //Recalculate CHR pointers if (m_modeCHR == 0) //one 8KB bank { @@ -69,9 +87,6 @@ namespace sn m_firstBankCHR = &m_cartridge.getVROM()[0x1000 * m_regCHR0]; m_secondBankCHR = &m_cartridge.getVROM()[0x1000 * m_regCHR1]; } - LOG(Info) << "CHR mode : " << m_modeCHR << std::endl; - LOG(Info) << "PRG mode : " << m_modePRG << std::endl; - LOG(Info) << "Mirroring: " << (m_tempRegister & 0x3) << std::endl; } else if (addr <= 0xbfff) //CHR Reg 0 { diff --git a/src/PictureBus.cpp b/src/PictureBus.cpp index f3b9e23..942c3e3 100644 --- a/src/PictureBus.cpp +++ b/src/PictureBus.cpp @@ -67,16 +67,8 @@ namespace sn } } - bool PictureBus::setMapper(Mapper *mapper) + void PictureBus::updateMirroring() { - if (!mapper) - { - LOG(Error) << "Mapper argument is nullptr" << std::endl; - return false; - } - - m_mapper = mapper; - switch (m_mapper->getNameTableMirroring()) { case Horizontal: @@ -89,13 +81,31 @@ namespace sn NameTable1 = NameTable3 = 0x400; LOG(Info) << "Vertical Name Table mirroring set. (Horizontal Scrolling)" << std::endl; break; + case OneScreenLower: + NameTable0 = NameTable1 = NameTable2 = NameTable3 = 0; + LOG(Info) << "Single Screen mirroring set with lower bank." << std::endl; + break; + case OneScreenHigher: + NameTable0 = NameTable1 = NameTable2 = NameTable3 = 0x400; + LOG(Info) << "Single Screen mirroring set with higher bank." << std::endl; + break; default: - LOG(Error) << "Unsupported Name Table mirroring." << std::endl; - return false; + NameTable0 = NameTable1 = NameTable2 = NameTable3 = 0; + LOG(Error) << "Unsupported Name Table mirroring : " << m_mapper->getNameTableMirroring() << std::endl; } + } + bool PictureBus::setMapper(Mapper *mapper) + { + if (!mapper) + { + LOG(Error) << "Mapper argument is nullptr" << std::endl; + return false; + } + + m_mapper = mapper; + updateMirroring(); return true; } - }