HD packs WIP

This commit is contained in:
Sour 2021-05-10 00:39:04 -04:00
parent 3e90df5ef4
commit 4ee43d8ba7
8 changed files with 48 additions and 66 deletions

View file

@ -94,26 +94,19 @@ struct HdPpuTileInfo : public HdTileKey
struct HdPpuPixelInfo
{
HdPpuTileInfo Tile;
vector<HdPpuTileInfo> 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<uint32_t, uint8_t> WatchedAddressValues;
unordered_map<uint32_t, uint8_t> WatchedAddressValues;
uint32_t FrameNumber;
HdScreenInfo(const HdScreenInfo& that) = delete;
@ -291,7 +284,7 @@ struct HdPackTileInfo : public HdTileKey
struct HdPackBitmapInfo
{
vector<uint8_t> PixelData;
vector<uint32_t> PixelData;
uint32_t Width;
uint32_t Height;
};

View file

@ -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);
}*/

View file

@ -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();

View file

@ -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];
}
}

View file

@ -26,6 +26,7 @@ class HdNesPpu final : public NesPpu<HdNesPpu>
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);

View file

@ -209,13 +209,17 @@ bool HdPackLoader::ProcessImgTag(string src)
vector<uint8_t> fileData;
vector<uint8_t> 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<uint32_t> &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<string> &tokens, vector<HdPackCondition
checkConstraint(tileInfo->BitmapIndex < _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();

View file

@ -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()

View file

@ -54,10 +54,10 @@ bool PNGHelper::ReadPNG(vector<uint8_t> input, vector<uint8_t> &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;