diff --git a/Core/NES/HdPacks/HdData.h b/Core/NES/HdPacks/HdData.h index 2024782e..42fe941c 100644 --- a/Core/NES/HdPacks/HdData.h +++ b/Core/NES/HdPacks/HdData.h @@ -94,26 +94,19 @@ struct HdPpuTileInfo : public HdTileKey struct HdPpuPixelInfo { HdPpuTileInfo Tile; - vector Sprite; - int SpriteCount; + HdPpuTileInfo Sprite[4]; uint16_t TmpVideoRamAddr; uint8_t XScroll; uint8_t EmphasisBits; bool Grayscale; - - HdPpuPixelInfo() - { - for(int i = 0; i < 4; i++) { - Sprite.push_back(HdPpuTileInfo()); - } - } + uint8_t SpriteCount; }; struct HdScreenInfo { HdPpuPixelInfo* ScreenTiles; - std::unordered_map WatchedAddressValues; + unordered_map WatchedAddressValues; uint32_t FrameNumber; HdScreenInfo(const HdScreenInfo& that) = delete; @@ -291,7 +284,7 @@ struct HdPackTileInfo : public HdTileKey struct HdPackBitmapInfo { - vector PixelData; + vector PixelData; uint32_t Width; uint32_t Height; }; diff --git a/Core/NES/HdPacks/HdNesPack.cpp b/Core/NES/HdPacks/HdNesPack.cpp index 1e2b4378..c76f68f8 100644 --- a/Core/NES/HdPacks/HdNesPack.cpp +++ b/Core/NES/HdPacks/HdNesPack.cpp @@ -4,13 +4,15 @@ #include "NES/HdPacks/HdNesPack.h" #include "NES/HdPacks/HdPackLoader.h" #include "NES/NesConsole.h" +#include "NES/NesDefaultVideoFilter.h" #include "Shared/MessageManager.h" #include "Shared/EmuSettings.h" #include "Utilities/FolderUtilities.h" #include "Utilities/PNGHelper.h" -HdNesPack::HdNesPack(HdPackData* hdData) +HdNesPack::HdNesPack(EmuSettings* settings, HdPackData* hdData) { + _settings = settings; _hdData = hdData; } @@ -190,17 +192,16 @@ int32_t HdNesPack::GetLayerIndex(uint8_t priority) return -1; } -uint32_t palette[512] = {}; - void HdNesPack::OnBeforeApplyFilter() { - _palette = palette; - //TODO - //_palette = _hdData->Palette.size() == 0x40 ? _hdData->Palette.data() : _settings->GetRgbPalette(); + if(_hdData->Palette.size() == 0x40) { + memcpy(_palette, _hdData->Palette.data(), 0x40 * sizeof(uint32_t)); + } else { + NesDefaultVideoFilter::GetFullPalette(_palette, _settings->GetNesConfig(), PpuModel::Ppu2C02); + } _cacheEnabled = (_hdData->OptionFlags & (int)HdPackOptions::DisableCache) == 0; //TODO - /* - if(_hdData->OptionFlags & (int)HdPackOptions::NoSpriteLimit) { + /*if(_hdData->OptionFlags & (int)HdPackOptions::NoSpriteLimit) { _settings->SetFlags(EmulationFlags::RemoveSpriteLimit | EmulationFlags::AdaptiveSpriteLimit); }*/ diff --git a/Core/NES/HdPacks/HdNesPack.h b/Core/NES/HdPacks/HdNesPack.h index 6a894545..044a97a1 100644 --- a/Core/NES/HdPacks/HdNesPack.h +++ b/Core/NES/HdPacks/HdNesPack.h @@ -2,6 +2,8 @@ #include "stdafx.h" #include "NES/HdPacks/HdData.h" +class EmuSettings; + class HdNesPack { private: @@ -14,19 +16,20 @@ private: int16_t BgMaxX = -1; }; - HdPackData* _hdData; - static constexpr uint8_t PriorityLevelsPerLayer = 10; static constexpr uint8_t BehindBgSpritesPriority = 0 * PriorityLevelsPerLayer; static constexpr uint8_t BehindBgPriority = 1 * PriorityLevelsPerLayer; static constexpr uint8_t BehindFgSpritesPriority = 2 * PriorityLevelsPerLayer; static constexpr uint8_t ForegroundPriority = 3 * PriorityLevelsPerLayer; + EmuSettings* _settings = nullptr; + HdPackData* _hdData = nullptr; + uint8_t _activeBgCount[4] = {}; HdBgConfig _bgConfig[40] = {}; HdScreenInfo *_hdScreenInfo = nullptr; - uint32_t* _palette = nullptr; + uint32_t _palette[512] = {}; HdPackTileInfo* _cachedTile = nullptr; bool _cacheEnabled = false; bool _useCachedTile = false; @@ -52,7 +55,7 @@ private: public: static constexpr uint32_t CurrentVersion = 106; - HdNesPack(HdPackData* hdData); + HdNesPack(EmuSettings* settings, HdPackData* hdData); ~HdNesPack(); uint32_t GetScale(); diff --git a/Core/NES/HdPacks/HdNesPpu.cpp b/Core/NES/HdPacks/HdNesPpu.cpp index 8c36b4f4..2a81fbf9 100644 --- a/Core/NES/HdPacks/HdNesPpu.cpp +++ b/Core/NES/HdPacks/HdNesPpu.cpp @@ -12,10 +12,9 @@ HdNesPpu::HdNesPpu(NesConsole* console, HdPackData* hdData) : NesPpu(console) if(_hdData) { _version = _hdData->Version; - - bool isChrRamGame = !console->GetMapper()->HasChrRom(); - _screenInfo[0] = new HdScreenInfo(isChrRamGame); - _screenInfo[1] = new HdScreenInfo(isChrRamGame); + _isChrRam = !_console->GetMapper()->HasChrRom(); + _screenInfo[0] = new HdScreenInfo(_isChrRam); + _screenInfo[1] = new HdScreenInfo(_isChrRam); _info = _screenInfo[0]; } } diff --git a/Core/NES/HdPacks/HdNesPpu.h b/Core/NES/HdPacks/HdNesPpu.h index b0a24ed7..61508579 100644 --- a/Core/NES/HdPacks/HdNesPpu.h +++ b/Core/NES/HdPacks/HdNesPpu.h @@ -26,6 +26,7 @@ class HdNesPpu final : public NesPpu HdScreenInfo* _screenInfo[2] = {}; HdScreenInfo* _info = nullptr; uint32_t _version = 0; + bool _isChrRam = false; HdPackData* _hdData = nullptr; NesSpriteInfoEx _exSpriteInfo[64] = {}; NesTileInfoEx _previousTileEx = {}; @@ -71,14 +72,12 @@ public: _lastSprite = nullptr; if(IsRenderingEnabled() || ((_videoRamAddr & 0x3F00) != 0x3F00)) { - bool isChrRam = !_console->GetMapper()->HasChrRom(); - BaseMapper* mapper = _console->GetMapper(); - uint32_t color = GetPixelColor(); pixel = (_paletteRAM[color & 0x03 ? color : 0] & _paletteRamMask) | _intensifyColorBits; - uint8_t tilePalette = (_xScroll + ((_cycle - 1) & 0x07) < 8) ? _previousTilePalette : _currentTilePalette; - NesTileInfoEx& lastTileEx = (_xScroll + ((_cycle - 1) & 0x07) < 8) ? _previousTileEx : _currentTileEx; + bool usePrev = (_xScroll + ((_cycle - 1) & 0x07) < 8); + uint8_t tilePalette = usePrev ? _previousTilePalette : _currentTilePalette; + NesTileInfoEx& lastTileEx = usePrev ? _previousTileEx : _currentTileEx; uint32_t backgroundColor = 0; if(_backgroundEnabled && _cycle > _minimumDrawBgCycle) { backgroundColor = (((_lowBitShift << _xScroll) & 0x8000) >> 15) | (((_highBitShift << _xScroll) & 0x8000) >> 14); @@ -107,8 +106,8 @@ public: NesSpriteInfoEx& spriteEx = _exSpriteInfo[i]; if(shift >= 0 && shift < 8) { tileInfo.Sprite[j].TileIndex = spriteEx.AbsoluteTileAddr / 16; - if(isChrRam) { - mapper->CopyChrTile(spriteEx.AbsoluteTileAddr & 0xFFFFFFF0, tileInfo.Sprite[j].TileData); + if(_isChrRam) { + _console->GetMapper()->CopyChrTile(spriteEx.AbsoluteTileAddr & 0xFFFFFFF0, tileInfo.Sprite[j].TileData); } if(_version >= 100) { tileInfo.Sprite[j].PaletteColors = 0xFF000000 | _paletteRAM[sprite.PaletteOffset + 3] | (_paletteRAM[sprite.PaletteOffset + 2] << 8) | (_paletteRAM[sprite.PaletteOffset + 1] << 16); @@ -155,8 +154,8 @@ public: if(_backgroundEnabled && _cycle > _minimumDrawBgCycle) { tileInfo.Tile.TileIndex = lastTileEx.AbsoluteTileAddr / 16; - if(isChrRam) { - mapper->CopyChrTile(lastTileEx.AbsoluteTileAddr & 0xFFFFFFF0, tileInfo.Tile.TileData); + if(_isChrRam) { + _console->GetMapper()->CopyChrTile(lastTileEx.AbsoluteTileAddr & 0xFFFFFFF0, tileInfo.Tile.TileData); } if(_version >= 100) { tileInfo.Tile.PaletteColors = _paletteRAM[tilePalette + 3] | (_paletteRAM[tilePalette + 2] << 8) | (_paletteRAM[tilePalette + 1] << 16) | (_paletteRAM[0] << 24); diff --git a/Core/NES/HdPacks/HdPackLoader.cpp b/Core/NES/HdPacks/HdPackLoader.cpp index 0090dbc5..a82688eb 100644 --- a/Core/NES/HdPacks/HdPackLoader.cpp +++ b/Core/NES/HdPacks/HdPackLoader.cpp @@ -209,13 +209,17 @@ bool HdPackLoader::ProcessImgTag(string src) vector fileData; vector pixelData; LoadFile(src, fileData); - - _hdNesBitmaps.push_back({}); - HdPackBitmapInfo& bitmapInfo = _hdNesBitmaps.back(); - if(PNGHelper::ReadPNG(fileData, bitmapInfo.PixelData, bitmapInfo.Width, bitmapInfo.Height)) { + uint32_t width, height; + if(PNGHelper::ReadPNG(fileData, pixelData, width, height)) { + _hdNesBitmaps.push_back({}); + HdPackBitmapInfo& bitmapInfo = _hdNesBitmaps.back(); + bitmapInfo.Width = width; + bitmapInfo.Height = height; + bitmapInfo.PixelData.resize(pixelData.size() / 4); + memcpy(bitmapInfo.PixelData.data(), pixelData.data(), bitmapInfo.PixelData.size() * sizeof(bitmapInfo.PixelData[0])); + PremultiplyAlpha(bitmapInfo.PixelData); return true; } else { - _hdNesBitmaps.pop_back(); MessageManager::Log("[HDPack] Error loading HDPack: PNG file " + src + " could not be read."); return false; } @@ -225,7 +229,6 @@ void HdPackLoader::PremultiplyAlpha(vector &pixelData) { for(size_t i = 0; i < pixelData.size(); i++) { if(pixelData[i] < 0xFF000000) { - //If not fully opaque, pre-multiply alpha with R/G/B to avoid having to do this while running uint8_t* output = (uint8_t*)(pixelData.data() + i); uint8_t alpha = output[3] + 1; output[0] = (uint8_t)((alpha * output[0]) >> 8); @@ -372,30 +375,13 @@ void HdPackLoader::ProcessTileTag(vector &tokens, vectorBitmapIndex < _hdNesBitmaps.size(), "[HDPack] Invalid bitmap index: " + std::to_string(tileInfo->BitmapIndex)); HdPackBitmapInfo &bitmapInfo = _hdNesBitmaps[tileInfo->BitmapIndex]; - - uint32_t bitmapOffset = (tileInfo->Y * bitmapInfo.Width + tileInfo->X) * sizeof(uint32_t); - uint8_t* pngData = bitmapInfo.PixelData.data(); + uint32_t bitmapOffset = tileInfo->Y * bitmapInfo.Width + tileInfo->X; + uint32_t* pngData = (uint32_t*)bitmapInfo.PixelData.data(); tileInfo->HdTileData.resize(64 * _data->Scale * _data->Scale); for(uint32_t y = 0; y < 8 * _data->Scale; y++) { - for(uint32_t x = 0; x < 8 * _data->Scale; x++) { - uint8_t r = pngData[bitmapOffset]; - uint8_t g = pngData[bitmapOffset + 1]; - uint8_t b = pngData[bitmapOffset + 2]; - uint8_t a = pngData[bitmapOffset + 3]; - - if(a < 0xFF) { - //If not fully opaque, pre-multiply alpha with R/G/B to avoid having to do this while running - uint8_t alpha = a + 1; - r = (uint8_t)((alpha * r) >> 8); - g = (uint8_t)((alpha * g) >> 8); - b = (uint8_t)((alpha * b) >> 8); - } - - tileInfo->HdTileData[y * 8 * _data->Scale + x] = (a << 24) | (r << 16) | (g << 8) | b; - bitmapOffset += sizeof(uint32_t); - } - bitmapOffset += (bitmapInfo.Width - (8 * _data->Scale)) * sizeof(uint32_t); + memcpy(tileInfo->HdTileData.data() + (y * 8 * _data->Scale), pngData + bitmapOffset, 8 * _data->Scale * sizeof(uint32_t)); + bitmapOffset += bitmapInfo.Width; } tileInfo->UpdateFlags(); diff --git a/Core/NES/HdPacks/HdVideoFilter.cpp b/Core/NES/HdPacks/HdVideoFilter.cpp index 9cb6b894..ac591b71 100644 --- a/Core/NES/HdPacks/HdVideoFilter.cpp +++ b/Core/NES/HdPacks/HdVideoFilter.cpp @@ -3,12 +3,13 @@ #include "NES/HdPacks/HdVideoFilter.h" #include "NES/NesConsole.h" #include "NES/NesConstants.h" +#include "Shared/Emulator.h" #include "Shared/Video/BaseVideoFilter.h" HdVideoFilter::HdVideoFilter(Emulator* emu, HdPackData* hdData) : BaseVideoFilter(emu) { _hdData = hdData; - _hdNesPack.reset(new HdNesPack(hdData)); + _hdNesPack.reset(new HdNesPack(emu->GetSettings(), hdData)); } FrameInfo HdVideoFilter::GetFrameInfo() diff --git a/Utilities/PNGHelper.cpp b/Utilities/PNGHelper.cpp index 2c781a40..04f2b065 100644 --- a/Utilities/PNGHelper.cpp +++ b/Utilities/PNGHelper.cpp @@ -54,10 +54,10 @@ bool PNGHelper::ReadPNG(vector input, vector &output, uint32_t if(DecodePNG(output, width, height, input.data(), input.size()) == 0) { uint32_t *pngDataPtr = (uint32_t*)output.data(); - /*for(size_t i = 0, len = output.size() / 4; i < len; i++) { + for(size_t i = 0, len = output.size() / 4; i < len; i++) { //ABGR to ARGB pngDataPtr[i] = (pngDataPtr[i] & 0xFF00FF00) | ((pngDataPtr[i] & 0xFF0000) >> 16) | ((pngDataPtr[i] & 0xFF) << 16); - }*/ + } pngWidth = width; pngHeight = height;