From e715eb5e85366d6127cba7cb8185e11aecb67282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Mon, 25 May 2020 15:47:16 +0200 Subject: [PATCH] adding backgrounds function to background class --- sources/PPU/Background.cpp | 135 ++++++++++++++++++++++++++++++++++--- sources/PPU/Background.hpp | 32 +++++++-- 2 files changed, 153 insertions(+), 14 deletions(-) diff --git a/sources/PPU/Background.cpp b/sources/PPU/Background.cpp index 3b461c9..3fa7cd7 100644 --- a/sources/PPU/Background.cpp +++ b/sources/PPU/Background.cpp @@ -3,26 +3,145 @@ // #include "Background.hpp" +#include "PPUUtils.hpp" namespace ComSquare::PPU { - /*void PPU::renderBackground(int bgNumber, Vector2 characterSize, int bpp, bool priority) + Background::Background(int bpp, Vector2 backgroundSize, Vector2 characterSize, bool directColor, bool highRes, bool priority, uint16_t vramAddress, uint16_t graphicVramAddress): + _bpp(bpp), + _backgroundSize(backgroundSize), + _characterSize(characterSize), + _highRes(highRes), + _directColor(directColor), + _priority(priority), + _vramAddress(vramAddress), + _graphicVramAddress(graphicVramAddress) { - int nbBgHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 2 : 1; - int nbBgWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 2 : 1; - uint16_t vramAddress = this->_registers._bgsc[bgNumber - 1].tilemapAddress << 1U; + } + + + void Background::renderBackground(void) + { + uint16_t vramAddress = this->_vramAddress; Vector2 offset(0, 0); for (int i = 0; i < 4; i++) { - if (!(i == 1 && nbBgWidth == 1) && !(i > 1 && nbBgHeight == 1)) { - drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); + if (!(i == 1 && this->_backgroundSize.x == 1) && !(i > 1 && this->_backgroundSize.y == 1)) { + drawBasicTileMap(vramAddress, offset); } vramAddress+= 0x800; - offset.x += 32 * characterSize.x; + offset.x += 32 * this->_characterSize.x; if (i == 2) { offset.x = 0; - offset.y += 32 * characterSize.y; + offset.y += 32 * this->_characterSize.y; } } + } + + /*uint16_t Background::getGraphicVramAddress(int x, int y, int bg, int bpp) + { + uint16_t baseAddress = this->_registers._bgnba[bg > 2].raw; + int step = bpp * 8; + + baseAddress = (bg % 2) ? baseAddress & 0xFU : (baseAddress & 0xFU) >> 4U; + baseAddress = baseAddress << 12U; + return baseAddress + (x * 16 * step) + (y * step); }*/ + + void Background::drawBgTile(uint16_t data, Vector2 pos) + { + uint16_t graphicAddress; + union TileMapData tileData; + std::vector palette; + int index = 0; + uint8_t reference = 0; + uint32_t color = 0; + + tileData.raw = data; + graphicAddress = this->_graphicVramAddress; + for (int i = 0; i < this->_characterSize.y; i++) { + for (int j = 0; j < this->_characterSize.x; j++) { + palette = getPalette(tileData.palette); + reference = getTilePixelReference(graphicAddress, index); + color = getRealColor(palette[reference]); + this->_renderer.putPixel(pos.x, pos.y, color); + index++; + pos.x++; + if (index == (8 / this->_bpp) - 1) { + index = 0; + graphicAddress++; + } + } + index = 0; + pos.x -= this->_characterSize.x; + pos.y++; + } + } + + std::vector Background::getPalette(int nbPalette) + { + std::vector palette(0xF); + + uint16_t addr = nbPalette * 0x10; + for (int i = 0; i < 0xF; i++) { + palette[i] = this->cgramRead(addr); + palette[i] += this->cgramRead(addr + 1) << 8U; + } + return palette; + } + + uint32_t Background::getRealColor(uint16_t color) + { + uint8_t blue; + uint8_t red; + uint8_t green; + uint32_t pixelTmp; + + blue = (color & 0x7D00U) >> 10U; + green = (color & 0x03E0U) >> 5U; + red = (color & 0x001FU); + + pixelTmp = 0xFFFF; + pixelTmp += (red * 255U / 31U) << 24U; + pixelTmp += (green * 255U / 31U) << 16U; + pixelTmp += (blue * 255U / 31U) << 8U; + return pixelTmp; + } + + uint8_t Background::getTilePixelReference(uint16_t addr, int nb) + { + uint8_t reference = this->vram->read_internal(addr); + + switch (this->_bpp) { + case 8: + return reference; + case 4: + return (reference & (0xFU << ((1 - nb) * 4U))) >> (1 - nb) * 4U; + case 2: + return (reference & (0x3U << ((3 - nb) * 2U))) >> (3 - nb) * 2U; + default: + break; + } + return 0; + } + + void Background::drawBasicTileMap(uint16_t baseAddress, Vector2 offset) + { + uint16_t tileMapValue = 0; + Vector2 pos(0,0); + uint16_t vramAddress = baseAddress; + + while (vramAddress < 0x800 + baseAddress) { + tileMapValue = this->vram->read_internal(vramAddress); + tileMapValue += this->vram->read_internal(vramAddress + 1) << 8U; + vramAddress += 2; + drawBgTile(tileMapValue, {(pos.x * this->_characterSize.x) + offset.x, (pos.y * this->_characterSize.y) + offset.y}, this->_bpp); + if (pos.x % 31 == 0 && pos.x) { + pos.y++; + pos.x = 0; + } + else + pos.x++; + } + } } \ No newline at end of file diff --git a/sources/PPU/Background.hpp b/sources/PPU/Background.hpp index 33a6e4b..67fb32d 100644 --- a/sources/PPU/Background.hpp +++ b/sources/PPU/Background.hpp @@ -7,17 +7,37 @@ #include #include +#include #include "../Models/Vector2.hpp" namespace ComSquare::PPU { class Background { - int width; - int height; - int bpp; - bool directColor; - bool highRes; - std::array, 1024> buffer; + private: + Vector2 _backgroundSize; + Vector2 _characterSize; + int _bpp; + bool _directColor; + bool _highRes; + bool _priority; + uint16_t _vramAddress; + uint16_t _graphicVramAddress; + + std::array, 1024> _buffer; + public: + Background(int bpp, Vector2 backgroundSize, Vector2 characterSize, bool directColor, bool highRes, bool priority, uint16_t vramAddress, uint16_t graphicVramAddress); + //! @brief Render a background on the screen + void renderBackground(void); + //! @brief Draw a tile on the screen at x y pos + void drawBgTile(uint16_t data, Vector2 pos); + //! @brief Get a palette from the number of the palette (0 - 7) + std::vector getPalette(int nbPalette); + //! @brief Transform SNES color code BGR to uint32_t RGB + uint32_t getRealColor(uint16_t color); + //! @brief Get the color reference of a nb pixel tile + uint8_t getTilePixelReference(uint16_t addr, int nb); + //! @brief draw a tilemap 32x32 starting at baseAddress + void drawBasicTileMap(uint16_t baseAddress, Vector2 offset); }; }