diff --git a/sources/Cartridge/Cartridge.cpp b/sources/Cartridge/Cartridge.cpp index 4b57ad3..d854eb7 100644 --- a/sources/Cartridge/Cartridge.cpp +++ b/sources/Cartridge/Cartridge.cpp @@ -172,10 +172,7 @@ namespace ComSquare::Cartridge uint32_t headerAddress = this->_getHeaderAddress(); this->header = this->_mapHeader(headerAddress); - char name[22]; - std::memcpy(name, &this->_data[headerAddress], 21); - name[21] = '\0'; - this->header.gameName = std::string(name); + this->header.gameName = std::string(reinterpret_cast(&this->_data[headerAddress]), 21); if (headerAddress & 0x200u) { this->_romStart = 0x200u; this->_size -= 0x200u; diff --git a/sources/Memory/MemoryBus.cpp b/sources/Memory/MemoryBus.cpp index 097da73..b920e3c 100644 --- a/sources/Memory/MemoryBus.cpp +++ b/sources/Memory/MemoryBus.cpp @@ -48,10 +48,10 @@ namespace ComSquare::Memory void MemoryBus::_mirrorComponents(SNES &console, int i) { - this->_memoryAccessors.push_back(Memory::MemoryShadow::createShadow(console.wram, i, i + 0x2000)); - this->_memoryAccessors.push_back(Memory::MemoryShadow::createShadow(console.ppu, i + 0x2100, i + 0x2140)); - this->_memoryAccessors.push_back(Memory::MemoryShadow::createShadow(console.apu, i + 0x2140, i + 0x2144)); - this->_memoryAccessors.push_back(Memory::MemoryShadow::createShadow(console.cpu, i + 0x4200, i + 0x4220)); + this->_memoryAccessors.emplace_back(new Memory::MemoryShadow(console.wram, i, i + 0x2000)); + this->_memoryAccessors.emplace_back(new Memory::MemoryShadow(console.ppu, i + 0x2100, i + 0x2140)); + this->_memoryAccessors.emplace_back(new Memory::MemoryShadow(console.apu, i + 0x2140, i + 0x2144)); + this->_memoryAccessors.emplace_back(new Memory::MemoryShadow(console.cpu, i + 0x4200, i + 0x4220)); } void MemoryBus::mapComponents(SNES &console) @@ -84,7 +84,10 @@ namespace ComSquare::Memory if (console.cartridge->header.mappingMode & Cartridge::LoRom) { console.cartridge->setMemoryRegion(0x80, 0xFF, 0x8000, 0xFFFF); this->_memoryAccessors.push_back(console.cartridge); - this->_memoryAccessors.push_back(Memory::RectangleShadow::createShadow(console.cartridge, 0x0, 0x7D, 0x8000, 0xFFFF)); + // Mirror on the Q1 and Q2. + this->_memoryAccessors.emplace_back(new Memory::RectangleShadow(console.cartridge, 0x00, 0x7D, 0x8000, 0xFFFF)); + // Mirror on the lower half of the Q2. + this->_memoryAccessors.emplace_back((new Memory::RectangleShadow(console.cartridge, 0x40, 0x6F, 0x0000, 0x7FFF))->setBankOffset(0x40)); } } } \ No newline at end of file diff --git a/sources/Memory/MemoryShadow.cpp b/sources/Memory/MemoryShadow.cpp index c9c14d0..a80a81e 100644 --- a/sources/Memory/MemoryShadow.cpp +++ b/sources/Memory/MemoryShadow.cpp @@ -14,11 +14,6 @@ namespace ComSquare::Memory this->setMemoryRegion(start, end); } - std::shared_ptr MemoryShadow::createShadow(std::shared_ptr initial, uint24_t start, uint24_t end) - { - return static_cast>(new MemoryShadow(std::move(initial), start, end)); - } - uint8_t MemoryShadow::read(uint24_t addr) { return this->_initial->read(addr); diff --git a/sources/Memory/MemoryShadow.hpp b/sources/Memory/MemoryShadow.hpp index e848a3e..e6f4db7 100644 --- a/sources/Memory/MemoryShadow.hpp +++ b/sources/Memory/MemoryShadow.hpp @@ -18,7 +18,6 @@ namespace ComSquare::Memory //! @brief Create a shadow for the memory given as parameter. explicit MemoryShadow(std::shared_ptr initial, uint24_t start, uint24_t end); - static std::shared_ptr createShadow(std::shared_ptr initial, uint24_t start, uint24_t end); //! @brief Read from the initial IMemory given. //! @param addr The address to read from. The address 0x0 should refer to the first byte of the initial IMemory. //! @throw InvalidAddress will be thrown if the address is more than the size of the initial IMemory. diff --git a/sources/Memory/RectangleShadow.cpp b/sources/Memory/RectangleShadow.cpp index b831fa2..4840283 100644 --- a/sources/Memory/RectangleShadow.cpp +++ b/sources/Memory/RectangleShadow.cpp @@ -14,13 +14,9 @@ namespace ComSquare::Memory this->setMemoryRegion(startBank, endBank, startPage, endPage); } - std::shared_ptr RectangleShadow::createShadow(std::shared_ptr initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage) - { - return static_cast>(new RectangleShadow(std::move(initial), startBank, endBank, startPage, endPage)); - } - uint8_t RectangleShadow::read_internal(uint24_t addr) { + // TODO implement read/write bank offset. return this->_initial->read_internal(addr); } @@ -28,4 +24,10 @@ namespace ComSquare::Memory { this->_initial->write_internal(addr, data); } + + RectangleShadow *RectangleShadow::setBankOffset(uint8_t bankOffset) + { + this->_bankOffset = bankOffset; + return this; + } } \ No newline at end of file diff --git a/sources/Memory/RectangleShadow.hpp b/sources/Memory/RectangleShadow.hpp index 95dcf42..781f0e9 100644 --- a/sources/Memory/RectangleShadow.hpp +++ b/sources/Memory/RectangleShadow.hpp @@ -14,11 +14,12 @@ namespace ComSquare::Memory private: //! @brief Memory to shadow from. std::shared_ptr _initial; + //! @brief The number of banks to add to the memory before accessing it from the initial data. + uint8_t _bankOffset; public: //! @brief Create a shadow for the memory given as parameter. explicit RectangleShadow(std::shared_ptr initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage); - static std::shared_ptr createShadow(std::shared_ptr initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage); //! @brief Internal component read. Implement this as you would implement a basic IMemory's read. //! @param addr The local address to read from. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. @@ -29,6 +30,9 @@ namespace ComSquare::Memory //! @param data The new data to write. //! @throw This function should thrown an InvalidAddress for address that are not mapped to the component. void write_internal(uint24_t addr, uint8_t data) override; + + + RectangleShadow *setBankOffset(uint8_t bankOffset); }; } diff --git a/sources/Renderer/IRenderer.hpp b/sources/Renderer/IRenderer.hpp index c175e57..875d97a 100644 --- a/sources/Renderer/IRenderer.hpp +++ b/sources/Renderer/IRenderer.hpp @@ -21,7 +21,7 @@ namespace ComSquare::Renderer //! @param x The x position of the window (0, 0 is the top left corner). //! @param y The y position of the window (0, 0 is the top left corner). //! @param rgba The color of the pixel (red, green, blue, alpha). - virtual void putPixel(int x, int y, uint32_t rgba) = 0; + virtual void putPixel(unsigned x, unsigned y, uint32_t rgba) = 0; }; } diff --git a/sources/Renderer/SFRenderer.cpp b/sources/Renderer/SFRenderer.cpp index cdbfb94..281706e 100644 --- a/sources/Renderer/SFRenderer.cpp +++ b/sources/Renderer/SFRenderer.cpp @@ -25,8 +25,13 @@ namespace ComSquare::Renderer this->window.display(); } - void SFRenderer::putPixel(int y, int x, uint32_t rgba) + void SFRenderer::putPixel(unsigned y, unsigned x, uint32_t rgba) { + if (x >= this->videoMode.width) + throw InvalidPixelPosition("Width", x, this->videoMode.width); + if (y >= this->videoMode.height) + throw InvalidPixelPosition("Height", y, this->videoMode.height); + sf::Color pixels; pixels.r = rgba >> 24U; pixels.g = rgba >> 16U; diff --git a/sources/Renderer/SFRenderer.hpp b/sources/Renderer/SFRenderer.hpp index ad9ca41..f7b403c 100644 --- a/sources/Renderer/SFRenderer.hpp +++ b/sources/Renderer/SFRenderer.hpp @@ -14,6 +14,15 @@ namespace ComSquare::Renderer { + class InvalidPixelPosition : public std::exception { + private: + std::string _msg; + public: + explicit InvalidPixelPosition(const std::string &name, unsigned int x, unsigned int width) + : _msg("Trying to place a pixel at an invalid " + name + " (" + std::to_string(x) + ">=" + std::to_string(width) + ")") {} + const char *what() const noexcept override { return this->_msg.c_str(); } + }; + class SFRenderer : public IRenderer { private: //! @brief The Renderer for the window. @@ -36,7 +45,7 @@ namespace ComSquare::Renderer //! @param X horizontal index. //! @param Y vertical index. //! @param rgba The color of the pixel. - void putPixel(int y, int x, uint32_t rgba) override ; + void putPixel(unsigned y, unsigned x, uint32_t rgba) override ; //! @brief Get the inputs from the Window void getEvents(); //! @brief Constructor that return the window component of the SFML.