diff --git a/CMakeLists.txt b/CMakeLists.txt index d4c9328..29b9efc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,7 +242,7 @@ add_executable(ComSquare sources/Renderer/QtRenderer/QtRenderSfml.hpp sources/Debugger/TileViewer/TileViewer.cpp sources/Debugger/TileViewer/TileViewer.hpp - sources/Debugger/TileViewer/TileRenderer.cpp sources/Debugger/TileViewer/TileRenderer.hpp sources/PPU/Tile.hpp sources/Renderer/QtRenderer/QtSfmlTileRenderer.cpp sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp sources/PPU/TileRenderer.cpp sources/PPU/TileRenderer.hpp) + sources/Debugger/TileViewer/RAMTileRenderer.cpp sources/Debugger/TileViewer/RAMTileRenderer.hpp sources/PPU/Tile.hpp sources/Renderer/QtRenderer/QtSfmlTileRenderer.cpp sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp sources/PPU/TileRenderer.cpp sources/PPU/TileRenderer.hpp) include_directories(ComSquare sources) diff --git a/sources/Debugger/TileViewer/RAMTileRenderer.cpp b/sources/Debugger/TileViewer/RAMTileRenderer.cpp new file mode 100644 index 0000000..c635e6d --- /dev/null +++ b/sources/Debugger/TileViewer/RAMTileRenderer.cpp @@ -0,0 +1,111 @@ +// +// Created by cbihan on 24/05/2021. +// + +#include +#include +#include "RAMTileRenderer.hpp" +#include "PPU/PPU.hpp" +#include "PPU/Tile.hpp" +#include + +namespace ComSquare::Debugger +{ + RAMTileRenderer::RAMTileRenderer() + : _ram(nullptr), + _renderSize(0x5000), + _nbColumns(16), + _ramOffset(0), + _bpp(2), + buffer({{{0}}}) + { + } + + void RAMTileRenderer::setRam(std::shared_ptr ram) + { + this->_ram = ram; + this->_tileRenderer.setRam(ram); + } + + void RAMTileRenderer::render() + { + int bufX = 0; + int bufY = 0; + int nbTilesDrawn = 0; + int resetX = bufX; + for (auto &i : buffer) + i.fill(0); + uint24_t limit = fmin(this->_ram->getSize(), this->_renderSize) + this->_ramOffset; + + for (uint24_t i = this->_ramOffset; i < limit; i += PPU::Tile::BaseByteSize * this->_bpp, nbTilesDrawn++) { + if (bufX > 1024 || bufY > 1024) + break; + + this->_tileRenderer.render(i); + if (nbTilesDrawn) { + resetX += PPU::Tile::NbPixelsWidth; + bufX = resetX; + bufY -= PPU::Tile::NbPixelsHeight; + } + if (nbTilesDrawn && nbTilesDrawn % this->_nbColumns == 0) { + nbTilesDrawn = 0; + resetX = 0; + bufX = resetX; + bufY += PPU::Tile::NbPixelsHeight; + } + + for (const auto &raw : this->_tileRenderer.buffer) { + for (const auto &pixel : raw) { + buffer[bufX++][bufY] = pixel; + } + bufY++; + bufX = resetX; + } + } + } + + void RAMTileRenderer::setPaletteIndex(int paletteIndex) + { + this->_tileRenderer.setPaletteIndex(paletteIndex); + } + + void RAMTileRenderer::setBpp(int bpp) + { + this->_tileRenderer.setBpp(bpp); + } + + void RAMTileRenderer::setCgram(std::shared_ptr ram) + { + this->_tileRenderer.setCgram(ram); + } + + void RAMTileRenderer::setRenderSize(int size) + { + this->_renderSize = size; + } + + void RAMTileRenderer::setNbColumns(int nbColumns) + { + this->_nbColumns = nbColumns; + } + + int RAMTileRenderer::getBpp() const + { + return this->_tileRenderer.getBpp(); + } + + int RAMTileRenderer::getPaletteIndex() const + { + return this->_tileRenderer.getPaletteIndex(); + } + + int RAMTileRenderer::getNbColumns() const + { + return this->_nbColumns; + } + + void RAMTileRenderer::setRamOffset(int offset) + { + this->_ramOffset = offset; + } +} \ No newline at end of file diff --git a/sources/Debugger/TileViewer/TileRenderer.hpp b/sources/Debugger/TileViewer/RAMTileRenderer.hpp similarity index 70% rename from sources/Debugger/TileViewer/TileRenderer.hpp rename to sources/Debugger/TileViewer/RAMTileRenderer.hpp index e12b1c5..8c4eeb0 100644 --- a/sources/Debugger/TileViewer/TileRenderer.hpp +++ b/sources/Debugger/TileViewer/RAMTileRenderer.hpp @@ -5,26 +5,25 @@ #pragma once #include +#include "PPU/TileRenderer.hpp" #include "Ram/Ram.hpp" namespace ComSquare::Debugger { - class TileRenderer { + class RAMTileRenderer { private: //! @brief ram to render std::shared_ptr _ram; - //! @brief cgram to access the colors - std::shared_ptr _cgram; - //! @brief The bpp to use while rendering - int _bpp; - //! @brief The palette number to use while rendering - int _paletteIndex; //! @brief The size to render in the ram int _renderSize; //! @brief The number of tile columns to display int _nbColumns; //! @brief Bytes to skip from the start of the ram int _ramOffset; + //! @brief The actual bpp to render + int _bpp; + //! @brief The class tha actually render the tile + PPU::TileRenderer _tileRenderer; public: //! @brief internal buffer std::array, 1024> buffer; @@ -48,15 +47,16 @@ namespace ComSquare::Debugger int getPaletteIndex() const; //! @brief Get the numbr of maximum tile columns to render int getNbColumns() const; - uint8_t getPixelReferenceFromTileRow(uint16_t tileRowAddress, uint8_t pixelIndex); - std::vector getPalette(int nbPalette); - uint8_t read2BPPValue(uint16_t tileRowAddress, uint8_t pixelIndex); //! @brief render the selected ram void render(); - TileRenderer(); - TileRenderer(const TileRenderer &) = default; - ~TileRenderer() = default; - TileRenderer &operator=(const TileRenderer &) = default; + //! @brief ctor + RAMTileRenderer(); + //! @brief copy ctor + RAMTileRenderer(const RAMTileRenderer &) = default; + //! @brief dtor + ~RAMTileRenderer() = default; + //! @brief assignment operator + RAMTileRenderer &operator=(const RAMTileRenderer &) = default; }; } diff --git a/sources/Debugger/TileViewer/TileRenderer.cpp b/sources/Debugger/TileViewer/TileRenderer.cpp deleted file mode 100644 index 570e35d..0000000 --- a/sources/Debugger/TileViewer/TileRenderer.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// Created by cbihan on 24/05/2021. -// - -#include -#include -#include "TileRenderer.hpp" -#include "PPU/PPU.hpp" -#include "PPU/Tile.hpp" -#include - -namespace ComSquare::Debugger -{ - TileRenderer::TileRenderer() - : _ram(nullptr), - _cgram(nullptr), - _bpp(2), - _paletteIndex(0), - _renderSize(0x5000), - _nbColumns(16), - buffer({{{0}}}) - { - } - - void TileRenderer::setRam(std::shared_ptr ram) - { - this->_ram = std::move(ram); - } - - void TileRenderer::render() - { - uint8_t colorReference; - uint24_t color; - std::vector palette = this->getPalette(this->_paletteIndex); - int bufX = 0; - int bufY = 0; - int nbTilesDrawn = 0; - int resetX = bufX; - int it = 0; - for (auto &i : buffer) - i.fill(0); - - for (uint24_t i = this->_ramOffset; i < fmin(this->_ram->getSize(), this->_renderSize) + this->_ramOffset; i += 2, it++) { - if (bufX > 1024 || bufY > 1024) - break; - if (it && it % 8 == 0) { - resetX += PPU::Tile::NbPixelsWidth; - bufX = resetX; - bufY -= PPU::Tile::NbPixelsHeight; - i += (this->_bpp - 2) * 0x8; - nbTilesDrawn++; - } - if (nbTilesDrawn && nbTilesDrawn % this->_nbColumns == 0) { - nbTilesDrawn = 0; - resetX = 0; - bufX = resetX; - bufY += PPU::Tile::NbPixelsHeight; - } - for (int j = 0; j < 8; j++) { - colorReference = this->getPixelReferenceFromTileRow(i, j); - color = PPU::getRealColor(palette[colorReference]); - buffer[bufX++][bufY] = color; - } - bufY++; - bufX = resetX; - } - } - - void TileRenderer::setPaletteIndex(int paletteIndex) - { - this->_paletteIndex = paletteIndex; - } - - void TileRenderer::setBpp(int bpp) - { - this->_bpp = bpp; - } - - uint8_t TileRenderer::read2BPPValue(uint16_t tileRowAddress, uint8_t pixelIndex) - { - // TODO unit test this - size_t size = this->_ram->getSize(); - uint8_t highByte = this->_ram->read(tileRowAddress % size); - uint8_t lowByte = this->_ram->read((tileRowAddress + 1) % size); - uint8_t shift = 8 - 1U - pixelIndex; - - return ((highByte & (1U << shift)) | ((lowByte & (1U << shift)) << 1U)) >> shift; - } - - uint8_t TileRenderer::getPixelReferenceFromTileRow(uint16_t tileRowAddress, uint8_t pixelIndex) - { - // TODO unit test this - uint16_t result = 0; - // TODO do a constexpr - const int TileByteSizeRow = 16; - - switch (this->_bpp) { - case 8: - result += this->read2BPPValue(tileRowAddress + TileByteSizeRow * 2, pixelIndex) << 4; - result += this->read2BPPValue(tileRowAddress + TileByteSizeRow * 3, pixelIndex) << 6; - FALLTHROUGH - case 4: - result += this->read2BPPValue(tileRowAddress + TileByteSizeRow, pixelIndex) << 2; - FALLTHROUGH - case 2: - result += this->read2BPPValue(tileRowAddress, pixelIndex); - default: - break; - } - return result; - } - - std::vector TileRenderer::getPalette(int nbPalette) - { - uint16_t nbColors = std::pow(2, this->_bpp); - uint16_t addr = nbPalette * this->_bpp * this->_bpp * 2; // 2 because it's 2 addr for 1 color - std::vector palette(nbColors); - - for (int i = 0; i < nbColors; i++) { - palette[i] = this->_cgram->read(addr); - palette[i] += this->_cgram->read(addr + 1) << 8U; - addr += 2; - } - return palette; - } - - void TileRenderer::setCgram(std::shared_ptr ram) - { - this->_cgram = std::move(ram); - } - - void TileRenderer::setRenderSize(int size) - { - this->_renderSize = size; - } - - void TileRenderer::setNbColumns(int nbColumns) - { - this->_nbColumns = nbColumns; - } - - int TileRenderer::getBpp() const - { - return this->_bpp; - } - - int TileRenderer::getPaletteIndex() const - { - return this->_paletteIndex; - } - - int TileRenderer::getNbColumns() const - { - return this->_nbColumns; - } - - void TileRenderer::setRamOffset(int offset) - { - this->_ramOffset = offset; - } -} \ No newline at end of file diff --git a/sources/Debugger/TileViewer/TileViewer.cpp b/sources/Debugger/TileViewer/TileViewer.cpp index 1bfe041..e74033b 100644 --- a/sources/Debugger/TileViewer/TileViewer.cpp +++ b/sources/Debugger/TileViewer/TileViewer.cpp @@ -15,7 +15,7 @@ namespace ComSquare::Renderer #include #include #include "Utility/Utility.hpp" -#include "TileRenderer.hpp" +#include "RAMTileRenderer.hpp" #include "PPU/PPU.hpp" namespace ComSquare::Debugger diff --git a/sources/Debugger/TileViewer/TileViewer.hpp b/sources/Debugger/TileViewer/TileViewer.hpp index 52482d3..f01fb86 100644 --- a/sources/Debugger/TileViewer/TileViewer.hpp +++ b/sources/Debugger/TileViewer/TileViewer.hpp @@ -18,7 +18,7 @@ namespace ComSquare::PPU #include "Renderer/QtRenderer/QtSfmlTileRenderer.hpp" #include "../../../ui/ui_tileView.h" #include "Ram/Ram.hpp" -#include "TileRenderer.hpp" +#include "RAMTileRenderer.hpp" namespace ComSquare::Debugger { @@ -37,7 +37,7 @@ namespace ComSquare::Debugger //! @brief the window std::unique_ptr _sfWidget; //! @brief The tile renderer - TileRenderer _tileRenderer; + RAMTileRenderer _tileRenderer; //! @brief Change the bpp from the index given by the ui (QT combo box) void _bppChangeUIHandler(int index); public: diff --git a/sources/PPU/Background.cpp b/sources/PPU/Background.cpp index ecdb64e..38320c0 100644 --- a/sources/PPU/Background.cpp +++ b/sources/PPU/Background.cpp @@ -23,12 +23,13 @@ namespace ComSquare::PPU _tilesetAddress(ppu.getTilesetAddress(backGroundNumber)), _priority(hasPriority), _bgNumber(backGroundNumber), + _tileBuffer({{{0}}}), _vram(ppu.vram), _cgram(ppu.cgram), buffer({{{0}}}) { - this->tileRenderer.setRam(this->_vram); - this->tileRenderer.setCgram(this->_cgram); + this->_tileRenderer.setRam(this->_vram); + this->_tileRenderer.setCgram(this->_cgram); } void Background::renderBackground() @@ -53,7 +54,6 @@ namespace ComSquare::PPU void Background::drawBgTile(uint16_t data, Vector2 pos) { - uint16_t graphicAddress; union TileMapData tileData; tileData.raw = data; @@ -61,18 +61,19 @@ namespace ComSquare::PPU if (tileData.tilePriority != this->_priority) return; + uint16_t graphicAddress; Vector2i tileOffset = {0, 0}; // X horizontal // Y vertical - this->tileRenderer.setPaletteIndex(tileData.palette); + this->_tileRenderer.setPaletteIndex(tileData.palette); for (int i = 0; i < this->_characterNbPixels.y; i += 8) { for (int j = 0; j < this->_characterNbPixels.x; j += 8) { graphicAddress = this->_tilesetAddress + - ((tileData.posY + tileOffset.y) * NbTilePerRow * this->_bpp * TileBaseByteSize) + - ((tileData.posX + tileOffset.x) * this->_bpp * TileBaseByteSize); - this->tileRenderer.render(graphicAddress); - merge2DArray(this->tileBuffer, this->tileRenderer.buffer, {j, i}); + ((tileData.posY + tileOffset.y) * NbTilePerRow * this->_bpp * Tile::BaseByteSize) + + ((tileData.posX + tileOffset.x) * this->_bpp * Tile::BaseByteSize); + this->_tileRenderer.render(graphicAddress); + merge2DArray(this->_tileBuffer, this->_tileRenderer.buffer, {j, i}); tileOffset.x += 1; } tileOffset.x = 0; @@ -81,12 +82,12 @@ namespace ComSquare::PPU // todo check why i need to invert vertical and horizontal flips if (tileData.verticalFlip) - HFlipArray(this->tileBuffer, {this->_characterNbPixels.x, this->_characterNbPixels.y}); + HFlipArray(this->_tileBuffer, {this->_characterNbPixels.x, this->_characterNbPixels.y}); if (tileData.horizontalFlip) - VFlipArray(this->tileBuffer, {this->_characterNbPixels.x, this->_characterNbPixels.y}); + VFlipArray(this->_tileBuffer, {this->_characterNbPixels.x, this->_characterNbPixels.y}); for (int i = 0; i < this->_characterNbPixels.y; i++) { for (int j = 0; j < this->_characterNbPixels.x; j++) { - this->buffer[pos.x][pos.y] = this->tileBuffer[i][j]; + this->buffer[pos.x][pos.y] = this->_tileBuffer[i][j]; pos.x++; } pos.x -= this->_characterNbPixels.x; @@ -203,7 +204,7 @@ namespace ComSquare::PPU this->_bpp = bpp; else this->_bpp = 2; - this->tileRenderer.setBpp(this->_bpp); + this->_tileRenderer.setBpp(this->_bpp); } void Background::setTilemaps(Vector2 tileMaps) diff --git a/sources/PPU/Background.hpp b/sources/PPU/Background.hpp index 9707839..932fb13 100644 --- a/sources/PPU/Background.hpp +++ b/sources/PPU/Background.hpp @@ -17,16 +17,10 @@ namespace ComSquare::PPU class PPU; class Background { private: - TileRenderer tileRenderer; - std::array, 16> tileBuffer = {{{0}}}; - //! @brief The number of character a TileMap has in width static constexpr int NbCharacterWidth = 32; //! @brief The number of character a TileMap has in height static constexpr int NbCharacterHeight = 32; - //! @brief The number of bytes used by a range of pixels (1 pixel per byte) - //! @note Used like: bpp * TileBaseByteSize to get the size of byte of 1 row of pixels - static constexpr unsigned TileBaseByteSize = 8; //! @brief The number of rows in one line of VRAM //! @note If you're lost by this description, open a tile viewer in an emulator, and set the number of tiles in width to 16 graphics static constexpr unsigned NbTilePerRow = 16; @@ -55,6 +49,10 @@ namespace ComSquare::PPU bool _priority; //! @brief The bg number (used to get the corresponding scroll) int _bgNumber; + //! @brief Class that actually render a tile + TileRenderer _tileRenderer; + //! @brief Buffer if we have tiles that are more than 8x8 + std::array, 16> _tileBuffer; //! @brief the access to vram std::shared_ptr _vram; //! @brief The access to cgram diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index b43cdb8..a8fbe0a 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -9,7 +9,7 @@ #include "Exceptions/InvalidAddress.hpp" #include "Ram/Ram.hpp" #include "Models/Vector2.hpp" -#include "Debugger/TileViewer/TileRenderer.hpp" +#include "Debugger/TileViewer/RAMTileRenderer.hpp" #include namespace ComSquare::PPU diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index a6acb79..7a3be53 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -13,7 +13,7 @@ #include "Models/Vector2.hpp" #include "Background.hpp" #include "PPUUtils.hpp" -#include "Debugger/TileViewer/TileRenderer.hpp" +#include "Debugger/TileViewer/RAMTileRenderer.hpp" #define FALLTHROUGH __attribute__((fallthrough)); diff --git a/sources/PPU/Tile.hpp b/sources/PPU/Tile.hpp index 52025a5..779ce6e 100644 --- a/sources/PPU/Tile.hpp +++ b/sources/PPU/Tile.hpp @@ -13,6 +13,9 @@ namespace ComSquare::PPU static constexpr int NbPixelsWidth = 8; //! @brief The number of pixel a base tile can have in height static constexpr int NbPixelsHeight = 8; + //! @brief A base tile size in byte is 0x8 + //! @note Used like: bpp * BaseByteSize to get the byte size of 1 tile + static constexpr int BaseByteSize = 0x8; }; } \ No newline at end of file diff --git a/sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp b/sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp index a8c4b55..a3a95a9 100644 --- a/sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp +++ b/sources/Renderer/QtRenderer/QtSfmlTileRenderer.hpp @@ -7,7 +7,7 @@ #include #include #include "QtWidgetSFML.hpp" -#include "Debugger/TileViewer/TileRenderer.hpp" +#include "Debugger/TileViewer/RAMTileRenderer.hpp" namespace ComSquare::Renderer {