HD Packs: Fixed issues with background priority sprites

This commit is contained in:
Souryo 2017-08-15 19:18:00 -04:00
parent 5f47b402b5
commit fef31e6749
6 changed files with 65 additions and 50 deletions

View file

@ -25,6 +25,10 @@ protected:
_lastSprite = nullptr;
uint32_t color = GetPixelColor();
_currentOutputBuffer[(_scanline << 8) + _cycle - 1] = _paletteRAM[color & 0x03 ? color : 0];
uint32_t backgroundColor = 0;
if(_flags.BackgroundEnabled && _cycle > _minimumDrawBgCycle) {
backgroundColor = (((_state.LowBitShift << _state.XScroll) & 0x8000) >> 15) | (((_state.HighBitShift << _state.XScroll) & 0x8000) >> 14);
}
if(_needChrHash) {
uint16_t addr = 0;
@ -41,7 +45,17 @@ protected:
_needChrHash = false;
}
bool hasBgSprite = false;
if(_lastSprite && _flags.SpritesEnabled) {
if(backgroundColor == 0) {
for(uint8_t i = 0; i < _spriteCount; i++) {
if(_spriteTiles[i].BackgroundPriority) {
hasBgSprite = true;
break;
}
}
}
if(_lastSprite->AbsoluteTileAddr >= 0) {
sprite.TileIndex = (_isChrRam ? (_lastSprite->TileAddr & _chrRamIndexMask) : _lastSprite->AbsoluteTileAddr) / 16;
sprite.PaletteColors = ReadPaletteRAM(_lastSprite->PaletteOffset + 3) | (ReadPaletteRAM(_lastSprite->PaletteOffset + 2) << 8) | (ReadPaletteRAM(_lastSprite->PaletteOffset + 1) << 16) | 0xFF000000;
@ -50,7 +64,7 @@ protected:
sprite.TileData[i] = _mapper->GetMemoryValue(DebugMemoryType::ChrRom, _lastSprite->AbsoluteTileAddr / 16 * 16 + i);
}
_hdPackBuilder->ProcessTile(_cycle - 1, _scanline, _lastSprite->AbsoluteTileAddr, sprite, _mapper, false, _bankHashes[_lastSprite->TileAddr / _chrRamBankSize]);
_hdPackBuilder->ProcessTile(_cycle - 1, _scanline, _lastSprite->AbsoluteTileAddr, sprite, _mapper, false, _bankHashes[_lastSprite->TileAddr / _chrRamBankSize], false);
}
}
@ -64,7 +78,7 @@ protected:
tile.TileData[i] = _mapper->GetMemoryValue(DebugMemoryType::ChrRom, lastTile->AbsoluteTileAddr / 16 * 16 + i);
}
_hdPackBuilder->ProcessTile(_cycle - 1, _scanline, lastTile->AbsoluteTileAddr, tile, _mapper, false, _bankHashes[lastTile->TileAddr / _chrRamBankSize]);
_hdPackBuilder->ProcessTile(_cycle - 1, _scanline, lastTile->AbsoluteTileAddr, tile, _mapper, false, _bankHashes[lastTile->TileAddr / _chrRamBankSize], hasBgSprite);
}
}
} else {

View file

@ -226,6 +226,7 @@ struct HdPackTileInfo : public HdTileKey
bool DefaultTile;
bool Blank;
bool HasTransparentPixels;
bool TransparencyRequired;
bool IsFullyTransparent;
vector<uint32_t> HdTileData;
uint32_t ChrBankId;
@ -252,7 +253,7 @@ struct HdPackTileInfo : public HdTileKey
for(uint8_t j = 0; j < 8; j++) {
uint8_t color = ((lowByte >> (7 - j)) & 0x01) | (((highByte >> (7 - j)) & 0x01) << 1);
uint32_t rgbColor;
if(IsSpriteTile()) {
if(IsSpriteTile() || TransparencyRequired) {
rgbColor = color == 0 ? 0x00FFFFFF : palette[(PaletteColors >> ((3 - color) * 8)) & 0x3F];
} else {
rgbColor = palette[(PaletteColors >> ((3 - color) * 8)) & 0x3F];

View file

@ -64,22 +64,14 @@ void HdNesPack::DrawCustomBackground(uint32_t *outputBuffer, uint32_t x, uint32_
}
}
bool HdNesPack::DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo, uint32_t *outputBuffer, uint32_t screenWidth, bool drawBackground)
void HdNesPack::DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo, uint32_t *outputBuffer, uint32_t screenWidth)
{
if(tileInfo.BackgroundPriority && tileInfo.BgColorIndex != 0) {
//Nothing to draw, tile is hidden
return false;
if(hdPackTileInfo.IsFullyTransparent) {
return;
}
uint32_t bgColor = _palette[tileInfo.PpuBackgroundColor];
uint32_t scale = GetScale();
if(hdPackTileInfo.IsFullyTransparent) {
if(drawBackground) {
DrawColor(bgColor, outputBuffer, scale, screenWidth);
}
return false;
}
uint32_t *bitmapData = hdPackTileInfo.HdTileData.data();
uint32_t tileWidth = 8 * scale;
uint8_t tileOffsetX = tileInfo.HorizontalMirroring ? 7 - tileInfo.OffsetX : tileInfo.OffsetX;
@ -96,7 +88,6 @@ bool HdNesPack::DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo
bitmapLargeInc = (tileInfo.HorizontalMirroring ? (int32_t)scale : -(int32_t)scale) - (int32_t)tileWidth;
}
bool pixelDrawn = false;
uint32_t rgbValue;
if(hdPackTileInfo.HasTransparentPixels || hdPackTileInfo.Brightness < 255) {
for(uint32_t y = 0; y < scale; y++) {
@ -109,14 +100,9 @@ bool HdNesPack::DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo
if(!hdPackTileInfo.HasTransparentPixels || (bitmapData[bitmapOffset] & 0xFF000000) == 0xFF000000) {
*outputBuffer = rgbValue;
pixelDrawn = true;
} else {
if(drawBackground) {
*outputBuffer = bgColor;
}
if(bitmapData[bitmapOffset] & 0xFF000000) {
BlendColors((uint8_t*)outputBuffer, (uint8_t*)&rgbValue);
pixelDrawn = true;
}
}
outputBuffer++;
@ -135,10 +121,7 @@ bool HdNesPack::DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo
bitmapOffset += bitmapLargeInc;
outputBuffer += screenWidth - scale;
}
pixelDrawn = true;
}
return pixelDrawn;
}
uint32_t HdNesPack::GetScale()
@ -210,7 +193,15 @@ bool HdNesPack::IsNextToSprite(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t
}
};
for(int i = -1; i <= 1; i++) {
if(y + i < 0 || y + i >= PPU::ScreenHeight) {
continue;
}
for(int j = -1; j <= 1; j++) {
if(x + j < 0 || x + j >= PPU::ScreenWidth) {
continue;
}
if(!hasNonBackgroundSurrounding) {
processAdjacentTile(screenTiles[(i + y) * 256 + j + x]);
}
@ -244,21 +235,20 @@ void HdNesPack::GetPixels(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y, H
bool hasBgSprite = false;
int lowestBgSprite = 999;
bool needBg = true;
DrawColor(_palette[pixelInfo.Tile.PpuBackgroundColor], outputBuffer, hdData->Scale, screenWidth);
if(hasSprite) {
for(int k = pixelInfo.SpriteCount - 1; k >= 0; k--) {
if(pixelInfo.Sprite[k].BackgroundPriority) {
hasBgSprite = true;
lowestBgSprite = k;
if(pixelInfo.Tile.BgColorIndex == 0) {
hdPackSpriteInfo = GetMatchingTile(screenTiles, x, y, pixelInfo.Sprite[k]);
if(hdPackSpriteInfo) {
needBg &= !DrawTile(pixelInfo.Sprite[k], *hdPackSpriteInfo, outputBuffer, screenWidth, needBg);
} else if(pixelInfo.Sprite[k].SpriteColorIndex != 0) {
DrawColor(_palette[pixelInfo.Sprite[k].SpriteColor], outputBuffer, hdData->Scale, screenWidth);
needBg = false;
}
hdPackSpriteInfo = GetMatchingTile(screenTiles, x, y, pixelInfo.Sprite[k]);
if(hdPackSpriteInfo) {
DrawTile(pixelInfo.Sprite[k], *hdPackSpriteInfo, outputBuffer, screenWidth);
} else if(pixelInfo.Sprite[k].SpriteColorIndex != 0) {
DrawColor(_palette[pixelInfo.Sprite[k].SpriteColor], outputBuffer, hdData->Scale, screenWidth);
}
}
}
@ -270,18 +260,15 @@ void HdNesPack::GetPixels(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y, H
DrawCustomBackground(outputBuffer, x, y, hdData->Scale, screenWidth);
}
bool drawBg = !hasBgSprite || pixelInfo.Tile.BgColorIndex != 0 || needBg;
if(drawBg) {
if(hdPackTileInfo) {
DrawTile(pixelInfo.Tile, *hdPackTileInfo, outputBuffer, screenWidth, true);
} else {
//Draw regular SD background tile
bool useCustomBackground = !hasNonBackgroundSurrounding && hasCustomBackground && pixelInfo.Tile.BgColorIndex == 0;
if(useCustomBackground) {
DrawCustomBackground(outputBuffer, x, y, hdData->Scale, screenWidth);
} else {
DrawColor(_palette[pixelInfo.Tile.BgColor], outputBuffer, hdData->Scale, screenWidth);
}
if(hdPackTileInfo) {
DrawTile(pixelInfo.Tile, *hdPackTileInfo, outputBuffer, screenWidth);
} else {
//Draw regular SD background tile
bool useCustomBackground = !hasNonBackgroundSurrounding && hasCustomBackground && pixelInfo.Tile.BgColorIndex == 0;
if(useCustomBackground) {
DrawCustomBackground(outputBuffer, x, y, hdData->Scale, screenWidth);
} else if(pixelInfo.Tile.BgColorIndex != 0 || hasNonBackgroundSurrounding) {
DrawColor(_palette[pixelInfo.Tile.BgColor], outputBuffer, hdData->Scale, screenWidth);
}
}
@ -290,7 +277,7 @@ void HdNesPack::GetPixels(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y, H
if(!pixelInfo.Sprite[k].BackgroundPriority && lowestBgSprite > k) {
hdPackSpriteInfo = GetMatchingTile(screenTiles, x, y, pixelInfo.Sprite[k]);
if(hdPackSpriteInfo) {
DrawTile(pixelInfo.Sprite[k], *hdPackSpriteInfo, outputBuffer, screenWidth, false);
DrawTile(pixelInfo.Sprite[k], *hdPackSpriteInfo, outputBuffer, screenWidth);
} else if(pixelInfo.Sprite[k].SpriteColorIndex != 0) {
DrawColor(_palette[pixelInfo.Sprite[k].SpriteColor], outputBuffer, hdData->Scale, screenWidth);
}

View file

@ -11,7 +11,7 @@ private:
__forceinline void BlendColors(uint8_t output[4], uint8_t input[4]);
__forceinline uint32_t AdjustBrightness(uint8_t input[4], uint16_t brightness);
__forceinline void DrawColor(uint32_t color, uint32_t* outputBuffer, uint32_t scale, uint32_t screenWidth);
__forceinline bool DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo, uint32_t* outputBuffer, uint32_t screenWidth, bool drawBackground);
__forceinline void DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo, uint32_t* outputBuffer, uint32_t screenWidth);
__forceinline HdPackTileInfo* GetMatchingTile(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y, HdTileKey& key);
__forceinline bool IsNextToSprite(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y);

View file

@ -76,10 +76,11 @@ void HdPackBuilder::AddTile(HdPackTileInfo *tile, uint32_t usageCount)
paletteMap[palette][tile->TileIndex % 256] = tile;
}
_tilesByKey[tile->GetKey(false)] = tile;
_tileUsageCount[tile->GetKey(false)] = usageCount;
}
void HdPackBuilder::ProcessTile(uint32_t x, uint32_t y, uint16_t tileAddr, HdPpuTileInfo &tile, BaseMapper *mapper, bool isSprite, uint32_t chrBankHash)
void HdPackBuilder::ProcessTile(uint32_t x, uint32_t y, uint16_t tileAddr, HdPpuTileInfo &tile, BaseMapper *mapper, bool isSprite, uint32_t chrBankHash, bool transparencyRequired)
{
if(_flags & HdPackRecordFlags::IgnoreOverscan) {
OverscanDimensions overscan = EmulationSettings::GetOverscanDimensions();
@ -104,14 +105,20 @@ void HdPackBuilder::ProcessTile(uint32_t x, uint32_t y, uint16_t tileAddr, HdPpu
hdTile->IsChrRamTile = _isChrRam;
hdTile->Brightness = 255;
hdTile->ChrBankId = _isChrRam ? chrBankHash : (tileAddr / 16 / 256);
hdTile->TransparencyRequired = transparencyRequired;
memcpy(hdTile->TileData, tile.TileData, 16);
GenerateHdTile(hdTile);
hdTile->UpdateFlags();
_hdData.Tiles.push_back(unique_ptr<HdPackTileInfo>(hdTile));
AddTile(hdTile, 1);
} else {
if(transparencyRequired) {
auto existingTile = _tilesByKey.find(tile.GetKey(false));
if(existingTile != _tilesByKey.end()) {
existingTile->second->TransparencyRequired = true;
}
}
if(result->second < 0x7FFFFFFF) {
//Increase usage count
result->second++;
@ -166,6 +173,11 @@ void HdPackBuilder::GenerateHdTile(HdPackTileInfo *tile)
void HdPackBuilder::DrawTile(HdPackTileInfo *tile, int tileNumber, uint32_t *pngBuffer, int pageNumber, bool containsSpritesOnly)
{
if(tile->HdTileData.empty()) {
GenerateHdTile(tile);
tile->UpdateFlags();
}
if(containsSpritesOnly && (_flags & HdPackRecordFlags::UseLargeSprites)) {
int row = tileNumber / 16;
int column = tileNumber % 16;

View file

@ -21,6 +21,7 @@ private:
HdPackData _hdData;
std::unordered_map<HdTileKey, uint32_t> _tileUsageCount;
std::unordered_map<HdTileKey, HdPackTileInfo*> _tilesByKey;
std::map<uint32_t, std::map<uint32_t, vector<HdPackTileInfo*>>> _tilesByChrBankByPalette;
bool _isChrRam;
uint32_t _chrRamBankSize;
@ -41,7 +42,7 @@ public:
HdPackBuilder(string saveFolder, ScaleFilterType filterType, uint32_t scale, uint32_t flags, uint32_t chrRamBankSize, bool isChrRam);
~HdPackBuilder();
void ProcessTile(uint32_t x, uint32_t y, uint16_t tileAddr, HdPpuTileInfo& tile, BaseMapper* mapper, bool isSprite, uint32_t chrBankHash);
void ProcessTile(uint32_t x, uint32_t y, uint16_t tileAddr, HdPpuTileInfo& tile, BaseMapper* mapper, bool isSprite, uint32_t chrBankHash, bool transparencyRequired);
void SaveHdPack();
static void GetChrBankList(uint32_t *banks);