diff --git a/CMakeLists.txt b/CMakeLists.txt index ce2d3df..d4c9328 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/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) include_directories(ComSquare sources) diff --git a/sources/PPU/Background.hpp b/sources/PPU/Background.hpp index a68a0fd..d82b742 100644 --- a/sources/PPU/Background.hpp +++ b/sources/PPU/Background.hpp @@ -2,8 +2,7 @@ // Created by cbihan on 5/14/20. // -#ifndef COMSQUARE_BACKGROUND_HPP -#define COMSQUARE_BACKGROUND_HPP +#pragma once #include #include @@ -123,7 +122,4 @@ namespace ComSquare::PPU //! @brief Delete assignment operator Background &operator=(const Background &) = delete; }; -} - - -#endif //COMSQUARE_BACKGROUND_HPP \ No newline at end of file +} \ No newline at end of file diff --git a/sources/PPU/TileRenderer.cpp b/sources/PPU/TileRenderer.cpp new file mode 100644 index 0000000..2da2425 --- /dev/null +++ b/sources/PPU/TileRenderer.cpp @@ -0,0 +1,131 @@ +// +// Created by cbihan on 24/05/2021. +// + +#include +#include +#include "TileRenderer.hpp" +#include "PPU/PPU.hpp" +#include "PPU/Tile.hpp" +#include + +namespace ComSquare::PPU +{ + TileRenderer::TileRenderer() + : _ram(nullptr), + _cgram(nullptr), + _bpp(2), + _paletteIndex(0), + buffer({{{0}}}) + { + } + + void TileRenderer::setRam(std::shared_ptr ram) + { + this->_ram = std::move(ram); + } + + void TileRenderer::render(uint16_t tileAddress) + { + std::vector palette = this->getPalette(this->_paletteIndex); + int it = 0; + + for (auto &row : this->buffer) { + for (auto &pixel : row) { + pixel = getRealColor(palette[this->getPixelReferenceFromTile(tileAddress, it++)]); + } + } + } + + uint8_t TileRenderer::getPixelReferenceFromTile(uint16_t tileAddress, uint8_t pixelIndex) + { + uint8_t row = pixelIndex / Tile::NbPixelsWidth; + uint8_t column = pixelIndex % Tile::NbPixelsHeight; + + if (row >= Tile::NbPixelsHeight) { + tileAddress += 0x80 * this->_bpp; + row -= Tile::NbPixelsHeight; + } + if (column >= Tile::NbPixelsWidth) { + tileAddress += 0x8 * this->_bpp; + column -= Tile::NbPixelsWidth; + } + // TODO might not work with 8 bpp must check + tileAddress += 2 * row; + + return this->getPixelReferenceFromTileRow(tileAddress, column); + } + + 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); + } + + int TileRenderer::getBpp() const + { + return this->_bpp; + } + + int TileRenderer::getPaletteIndex() const + { + return this->_paletteIndex; + } +} \ No newline at end of file diff --git a/sources/PPU/TileRenderer.hpp b/sources/PPU/TileRenderer.hpp new file mode 100644 index 0000000..7e9a10d --- /dev/null +++ b/sources/PPU/TileRenderer.hpp @@ -0,0 +1,56 @@ +// +// Created by cbihan on 24/05/2021. +// + +#pragma once + +#include +#include "Ram/Ram.hpp" + +namespace ComSquare::PPU +{ + class TileRenderer { + 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; + public: + // todo background or ppu should have constexpr to explain it (16) + //! @brief internal buffer max rendered tiles are 16x16 + std::array, 8> buffer; + //! @brief Set the palette to use for render (index of palette) + void setPaletteIndex(int paletteIndex); + //! @brief Set the ram to look for color references + void setCgram(std::shared_ptr ram); + //! @brief Set the bpp to render graphics + void setBpp(int bpp); + //! @brief The ram to render + void setRam(std::shared_ptr ram); + //! @brief Get the current bpp + int getBpp() const; + //! @brief Get the index of the current palette used + int getPaletteIndex() const; + //! @brief Gives the reference of pixel using the tileAddress and the pixelIndex + //! @note This function is wrapper of getPixelReferenceFromTileRow + uint8_t getPixelReferenceFromTile(uint16_t tileAddress, uint8_t pixelIndex); + //! @brief get the pixel color reference to use in the selected palette + uint8_t getPixelReferenceFromTileRow(uint16_t tileRowAddress, uint8_t pixelIndex); + //! @brief Gives the actual selected palette with all of it's colors + //! @warning Values are CGRAM colors use PPU::getRealColor function to get the actual real color + std::vector getPalette(int nbPalette); + //! @brief read the 2bpp value for a pixel (used multple times for 4bpp and 8bpp) + uint8_t read2BPPValue(uint16_t tileRowAddress, uint8_t pixelIndex); + //! @brief render the tile (8x8) at the tileAddress + //! @param tileAddress The address of the tile to render + void render(uint16_t tileAddress); + TileRenderer(); + TileRenderer(const TileRenderer &) = default; + ~TileRenderer() = default; + TileRenderer &operator=(const TileRenderer &) = default; + }; +} \ No newline at end of file