diff --git a/sources/PPU/Background.cpp b/sources/PPU/Background.cpp index 234fbb4..d86aefb 100644 --- a/sources/PPU/Background.cpp +++ b/sources/PPU/Background.cpp @@ -7,6 +7,7 @@ #include "Background.hpp" #include #include "Tile.hpp" +#include "PPUUtils.hpp" #include "Models/Vector2.hpp" namespace ComSquare::PPU @@ -26,6 +27,8 @@ namespace ComSquare::PPU _cgram(ppu.cgram), buffer({{{0}}}) { + this->tileRenderer.setRam(this->_vram); + this->tileRenderer.setCgram(this->_cgram); } void Background::renderBackground() @@ -58,11 +61,34 @@ namespace ComSquare::PPU uint32_t color = 0; tileData.raw = data; - palette = getPalette(tileData.palette); + + if (tileData.tilePriority != this->_priority) + return; // X horizontal // Y vertical + + this->tileRenderer.setPaletteIndex(tileData.palette); graphicAddress = this->_tilesetAddress + (tileData.posY * NbTilePerRow * this->_bpp * TileBaseByteSize) + (tileData.posX * this->_bpp * TileBaseByteSize); + for (int i = 0; i < this->_characterNbPixels.y; i += 8) { + for (int j = 0; j < this->_characterNbPixels.x; j += 8) { + this->tileRenderer.render(graphicAddress); + merge2DArray(this->tileBuffer, this->tileRenderer.buffer, {i, j}); + } + } + + if (tileData.verticalFlip) + VFlipArray(this->tileBuffer); + if (tileData.horizontalFlip) + HFlipArray(this->tileBuffer); 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]; + pos.x++; + } + pos.x -= this->_characterNbPixels.x; + pos.y++; + } + /*for (int i = 0; i < this->_characterNbPixels.y; i++) { index = i * this->_characterNbPixels.x; if (tileData.verticalFlip) index = (this->_characterNbPixels.y - 1 - i) * this->_characterNbPixels.x; @@ -78,7 +104,7 @@ namespace ComSquare::PPU } pos.x -= this->_characterNbPixels.x; pos.y++; - } + }*/ } std::vector Background::getPalette(int nbPalette) @@ -190,6 +216,7 @@ namespace ComSquare::PPU this->_bpp = bpp; else this->_bpp = 2; + this->tileRenderer.setBpp(this->_bpp); } void Background::setTilemaps(Vector2 tileMaps) diff --git a/sources/PPU/Background.hpp b/sources/PPU/Background.hpp index d82b742..9707839 100644 --- a/sources/PPU/Background.hpp +++ b/sources/PPU/Background.hpp @@ -8,17 +8,18 @@ #include #include #include "../Models/Vector2.hpp" +#include "TileRenderer.hpp" #include "../Ram/Ram.hpp" #include "PPU.hpp" -//! @brief Transform SNES color code BGR to uint32_t RGB -uint32_t getRealColor(uint16_t color); - 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 diff --git a/sources/PPU/PPUUtils.cpp b/sources/PPU/PPUUtils.cpp index be10b14..8a1c5d8 100644 --- a/sources/PPU/PPUUtils.cpp +++ b/sources/PPU/PPUUtils.cpp @@ -9,16 +9,11 @@ namespace ComSquare::PPU uint32_t getRealColor(uint16_t color) { - uint8_t blue; - uint8_t red; - uint8_t green; - uint32_t pixelTmp; + uint8_t blue = (color & 0x7D00U) >> 10U; + uint8_t green = (color & 0x03E0U) >> 5U; + uint8_t red = (color & 0x001FU); + uint32_t pixelTmp = 0xFF; - blue = (color & 0x7D00U) >> 10U; - green = (color & 0x03E0U) >> 5U; - red = (color & 0x001FU); - - pixelTmp = 0xFF; pixelTmp += (red * 255U / 31U) << 24U; pixelTmp += (green * 255U / 31U) << 16U; pixelTmp += (blue * 255U / 31U) << 8U; diff --git a/sources/PPU/PPUUtils.hpp b/sources/PPU/PPUUtils.hpp index 06de286..52d66ae 100644 --- a/sources/PPU/PPUUtils.hpp +++ b/sources/PPU/PPUUtils.hpp @@ -6,9 +6,15 @@ #define COMSQUARE_PPU_UTILS_HPP #include +#include +#include +#include "Models//Vector2.hpp" namespace ComSquare::PPU { + + //! @brief Transform SNES color code BGR to uint32_t RGB + uint32_t getRealColor(uint16_t color); //! @brief Used to parse easily VRAM Tile information union TileMapData { struct { @@ -36,5 +42,31 @@ namespace ComSquare::PPU uint8_t hScrollPrevValue; }; + template + void merge2DArray(std::array, DEST_SIZE_Y> &bufferDest, + const std::array, SRC_SIZE_Y> &bufferSrc, + const Vector2 &offset = {0, 0}) + { + for (int i = offset.y; i < bufferSrc.size(); i++) { + for (int j = offset.x; j < bufferSrc[i].size(); j++) { + bufferDest[i][j] = bufferSrc[i][j]; + } + } + } + + template + void VFlipArray(std::array, SRC_SIZE_Y> &array) + { + for (auto &row : array) { + std::reverse(row.begin(), row.end()); + } + } + + template + void HFlipArray(std::array, SRC_SIZE_Y> &array) + { + std::reverse(array.begin(), array.end()); + } + } #endif //COMSQUARE_PPU_UTILS_HPP \ No newline at end of file diff --git a/sources/PPU/TileRenderer.cpp b/sources/PPU/TileRenderer.cpp index 2da2425..348049d 100644 --- a/sources/PPU/TileRenderer.cpp +++ b/sources/PPU/TileRenderer.cpp @@ -29,10 +29,12 @@ namespace ComSquare::PPU { std::vector palette = this->getPalette(this->_paletteIndex); int it = 0; + this->buffer = {{{0}}}; for (auto &row : this->buffer) { for (auto &pixel : row) { - pixel = getRealColor(palette[this->getPixelReferenceFromTile(tileAddress, it++)]); + uint8_t pixelReference = this->getPixelReferenceFromTile(tileAddress, it++); + pixel = pixelReference ? getRealColor(palette[pixelReference]) : 0; } } } @@ -102,6 +104,7 @@ namespace ComSquare::PPU std::vector TileRenderer::getPalette(int nbPalette) { + // todo if needed the tile renderer could cache the palette to avoid recompute this every render 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);