Debugger: Performance improvements for ppu viewers (30-75% faster in core)

This commit is contained in:
Sour 2022-08-06 13:45:40 -04:00
parent 7df142e420
commit a61e559c07
7 changed files with 201 additions and 158 deletions

View file

@ -14,65 +14,6 @@ PpuTools::PpuTools(Debugger* debugger, Emulator *emu)
_debugger = debugger;
}
uint8_t PpuTools::GetTilePixelColor(const uint8_t* ram, const uint32_t ramMask, uint32_t rowStart, uint8_t pixelIndex, const TileFormat format)
{
uint8_t shift = (7 - pixelIndex);
uint8_t color;
switch(format) {
case TileFormat::PceSpriteBpp4: {
shift = 15 - pixelIndex;
if(shift >= 8) {
shift -= 8;
rowStart++;
}
color = (((ram[(rowStart + 0) & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 32) & ramMask] >> shift) & 0x01) << 1);
color |= (((ram[(rowStart + 64) & ramMask] >> shift) & 0x01) << 2);
color |= (((ram[(rowStart + 96) & ramMask] >> shift) & 0x01) << 3);
return color;
}
case TileFormat::Bpp2:
color = (((ram[rowStart & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 1) & ramMask] >> shift) & 0x01) << 1);
return color;
case TileFormat::NesBpp2:
color = (((ram[(rowStart + 0) & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 8) & ramMask] >> shift) & 0x01) << 1);
return color;
case TileFormat::Bpp4:
color = (((ram[(rowStart + 0) & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 1) & ramMask] >> shift) & 0x01) << 1);
color |= (((ram[(rowStart + 16) & ramMask] >> shift) & 0x01) << 2);
color |= (((ram[(rowStart + 17) & ramMask] >> shift) & 0x01) << 3);
return color;
case TileFormat::Bpp8:
case TileFormat::DirectColor:
color = (((ram[(rowStart + 0) & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 1) & ramMask] >> shift) & 0x01) << 1);
color |= (((ram[(rowStart + 16) & ramMask] >> shift) & 0x01) << 2);
color |= (((ram[(rowStart + 17) & ramMask] >> shift) & 0x01) << 3);
color |= (((ram[(rowStart + 32) & ramMask] >> shift) & 0x01) << 4);
color |= (((ram[(rowStart + 33) & ramMask] >> shift) & 0x01) << 5);
color |= (((ram[(rowStart + 48) & ramMask] >> shift) & 0x01) << 6);
color |= (((ram[(rowStart + 49) & ramMask] >> shift) & 0x01) << 7);
return color;
case TileFormat::Mode7:
case TileFormat::Mode7DirectColor:
return ram[(rowStart + pixelIndex * 2 + 1) & ramMask];
case TileFormat::Mode7ExtBg:
return ram[(rowStart + pixelIndex * 2 + 1) & ramMask] & 0x7F;
default:
throw std::runtime_error("unsupported format");
}
}
void PpuTools::BlendColors(uint8_t output[4], uint8_t input[4])
{
int alpha = input[3] + 1;
@ -83,38 +24,23 @@ void PpuTools::BlendColors(uint8_t output[4], uint8_t input[4])
output[3] = 0xFF;
}
uint32_t PpuTools::GetRgbPixelColor(TileFormat format, const uint32_t* colors, uint8_t colorIndex, uint8_t palette)
void PpuTools::GetTileView(GetTileViewOptions options, uint8_t* source, uint32_t srcSize, const uint32_t* colors, uint32_t* outBuffer)
{
switch(format) {
case TileFormat::DirectColor:
return SnesDefaultVideoFilter::ToArgb(
((((colorIndex & 0x07) << 1) | (palette & 0x01)) << 1) |
(((colorIndex & 0x38) | ((palette & 0x02) << 1)) << 4) |
(((colorIndex & 0xC0) | ((palette & 0x04) << 3)) << 7)
);
case TileFormat::NesBpp2:
case TileFormat::Bpp2:
return colors[palette * 4 + colorIndex];
case TileFormat::Bpp4:
case TileFormat::PceSpriteBpp4:
return colors[palette * 16 + colorIndex];
case TileFormat::Bpp8:
case TileFormat::Mode7:
case TileFormat::Mode7ExtBg:
return colors[colorIndex];
case TileFormat::Mode7DirectColor:
return SnesDefaultVideoFilter::ToArgb(((colorIndex & 0x07) << 2) | ((colorIndex & 0x38) << 4) | ((colorIndex & 0xC0) << 7));
default:
throw std::runtime_error("unsupported format");
switch(options.Format) {
case TileFormat::Bpp2: InternalGetTileView<TileFormat::Bpp2>(options, source, srcSize, colors, outBuffer); break;
case TileFormat::Bpp4: InternalGetTileView<TileFormat::Bpp4>(options, source, srcSize, colors, outBuffer); break;
case TileFormat::Bpp8: InternalGetTileView<TileFormat::Bpp8>(options, source, srcSize, colors, outBuffer); break;
case TileFormat::DirectColor: InternalGetTileView<TileFormat::DirectColor>(options, source, srcSize, colors, outBuffer); break;
case TileFormat::Mode7: InternalGetTileView<TileFormat::Mode7>(options, source, srcSize, colors, outBuffer); break;
case TileFormat::Mode7DirectColor: InternalGetTileView<TileFormat::Mode7DirectColor>(options, source, srcSize, colors, outBuffer); break;
case TileFormat::Mode7ExtBg: InternalGetTileView<TileFormat::Mode7ExtBg>(options, source, srcSize, colors, outBuffer); break;
case TileFormat::NesBpp2: InternalGetTileView<TileFormat::NesBpp2>(options, source, srcSize, colors, outBuffer); break;
case TileFormat::PceSpriteBpp4: InternalGetTileView<TileFormat::PceSpriteBpp4>(options, source, srcSize, colors, outBuffer); break;
}
}
void PpuTools::GetTileView(GetTileViewOptions options, uint8_t *source, uint32_t srcSize, const uint32_t *colors, uint32_t *outBuffer)
template<TileFormat format>
void PpuTools::InternalGetTileView(GetTileViewOptions options, uint8_t *source, uint32_t srcSize, const uint32_t *colors, uint32_t *outBuffer)
{
constexpr uint32_t grayscaleColorsBpp2[4] = { 0xFF000000, 0xFF666666, 0xFFBBBBBB, 0xFFFFFFFF };
constexpr uint32_t grayscaleColorsBpp4[16] = {
@ -203,11 +129,11 @@ void PpuTools::GetTileView(GetTileViewOptions options, uint8_t *source, uint32_t
for(int y = 0; y < tileHeight; y++) {
uint32_t pixelStart = addr + y * rowOffset;
for(int x = 0; x < tileWidth; x++) {
uint8_t color = GetTilePixelColor(ram, ramMask, pixelStart, x, options.Format);
uint8_t color = GetTilePixelColor<format>(ram, ramMask, pixelStart, x);
if(color != 0 || options.Background == TileBackground::PaletteColor) {
uint32_t pos = baseOutputOffset + (y * options.Width * tileWidth) + x;
if(pos < outputSize) {
outBuffer[pos] = GetRgbPixelColor(options.Format, colors, color & colorMask, options.Palette);
outBuffer[pos] = GetRgbPixelColor<format>(colors, color & colorMask, options.Palette);
}
}
}

View file

@ -177,11 +177,10 @@ protected:
Debugger* _debugger;
unordered_map<uint32_t, ViewerRefreshConfig> _updateTimings;
uint8_t GetTilePixelColor(const uint8_t* ram, const uint32_t ramMask, uint32_t pixelStart, uint8_t shift, const TileFormat format);
void BlendColors(uint8_t output[4], uint8_t input[4]);
uint32_t GetRgbPixelColor(TileFormat format, const uint32_t* colors, uint8_t colorIndex, uint8_t palette);
template<TileFormat format> __forceinline uint32_t GetRgbPixelColor(const uint32_t* colors, uint8_t colorIndex, uint8_t palette);
template<TileFormat format> __forceinline uint8_t GetTilePixelColor(const uint8_t* ram, const uint32_t ramMask, uint32_t rowStart, uint8_t pixelIndex);
bool IsTileHidden(MemoryType memType, uint32_t addr, GetTileViewOptions& options);
@ -214,4 +213,97 @@ public:
{
return _updateTimings.size() > 0;
}
};
template<TileFormat format>
void InternalGetTileView(GetTileViewOptions options, uint8_t* source, uint32_t srcSize, const uint32_t* colors, uint32_t* outBuffer);
};
template<TileFormat format> uint32_t PpuTools::GetRgbPixelColor(const uint32_t* colors, uint8_t colorIndex, uint8_t palette)
{
switch(format) {
case TileFormat::DirectColor:
return SnesDefaultVideoFilter::ToArgb(
((((colorIndex & 0x07) << 1) | (palette & 0x01)) << 1) |
(((colorIndex & 0x38) | ((palette & 0x02) << 1)) << 4) |
(((colorIndex & 0xC0) | ((palette & 0x04) << 3)) << 7)
);
case TileFormat::NesBpp2:
case TileFormat::Bpp2:
return colors[palette * 4 + colorIndex];
case TileFormat::Bpp4:
case TileFormat::PceSpriteBpp4:
return colors[palette * 16 + colorIndex];
case TileFormat::Bpp8:
case TileFormat::Mode7:
case TileFormat::Mode7ExtBg:
return colors[colorIndex];
case TileFormat::Mode7DirectColor:
return SnesDefaultVideoFilter::ToArgb(((colorIndex & 0x07) << 2) | ((colorIndex & 0x38) << 4) | ((colorIndex & 0xC0) << 7));
default:
throw std::runtime_error("unsupported format");
}
}
template<TileFormat format> uint8_t PpuTools::GetTilePixelColor(const uint8_t* ram, const uint32_t ramMask, uint32_t rowStart, uint8_t pixelIndex)
{
uint8_t shift = (7 - pixelIndex);
uint8_t color;
switch(format) {
case TileFormat::PceSpriteBpp4:
{
shift = 15 - pixelIndex;
if(shift >= 8) {
shift -= 8;
rowStart++;
}
color = (((ram[(rowStart + 0) & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 32) & ramMask] >> shift) & 0x01) << 1);
color |= (((ram[(rowStart + 64) & ramMask] >> shift) & 0x01) << 2);
color |= (((ram[(rowStart + 96) & ramMask] >> shift) & 0x01) << 3);
return color;
}
case TileFormat::Bpp2:
color = (((ram[rowStart & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 1) & ramMask] >> shift) & 0x01) << 1);
return color;
case TileFormat::NesBpp2:
color = (((ram[(rowStart + 0) & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 8) & ramMask] >> shift) & 0x01) << 1);
return color;
case TileFormat::Bpp4:
color = (((ram[(rowStart + 0) & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 1) & ramMask] >> shift) & 0x01) << 1);
color |= (((ram[(rowStart + 16) & ramMask] >> shift) & 0x01) << 2);
color |= (((ram[(rowStart + 17) & ramMask] >> shift) & 0x01) << 3);
return color;
case TileFormat::Bpp8:
case TileFormat::DirectColor:
color = (((ram[(rowStart + 0) & ramMask] >> shift) & 0x01) << 0);
color |= (((ram[(rowStart + 1) & ramMask] >> shift) & 0x01) << 1);
color |= (((ram[(rowStart + 16) & ramMask] >> shift) & 0x01) << 2);
color |= (((ram[(rowStart + 17) & ramMask] >> shift) & 0x01) << 3);
color |= (((ram[(rowStart + 32) & ramMask] >> shift) & 0x01) << 4);
color |= (((ram[(rowStart + 33) & ramMask] >> shift) & 0x01) << 5);
color |= (((ram[(rowStart + 48) & ramMask] >> shift) & 0x01) << 6);
color |= (((ram[(rowStart + 49) & ramMask] >> shift) & 0x01) << 7);
return color;
case TileFormat::Mode7:
case TileFormat::Mode7DirectColor:
return ram[(rowStart + pixelIndex * 2 + 1) & ramMask];
case TileFormat::Mode7ExtBg:
return ram[(rowStart + pixelIndex * 2 + 1) & ramMask] & 0x7F;
default:
throw std::runtime_error("unsupported format");
}
}

View file

@ -44,7 +44,7 @@ DebugTilemapInfo GbPpuTools::GetTilemap(GetTilemapOptions options, BaseState& ba
uint16_t pixelStart = tileStart + (vMirror ? (7 - y) : y) * 2;
for(int x = 0; x < 8; x++) {
uint8_t pixelIndex = hMirror ? (7 - x) : x;
uint8_t color = GetTilePixelColor(vram, vramMask, pixelStart, pixelIndex, TileFormat::Bpp2);
uint8_t color = GetTilePixelColor<TileFormat::Bpp2>(vram, vramMask, pixelStart, pixelIndex);
outBuffer[((row * 8) + y) * 256 + column * 8 + x] = palette[bgPalette + color];
}
@ -213,7 +213,7 @@ void GbPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint16_t i, GetSpritePre
bool isCgb = state.CgbEnabled;
for(int x = 0; x < 8; x++) {
uint8_t shift = sprite.HorizontalMirror ? (7 - x) : x;
uint8_t color = GetTilePixelColor(vram, 0x3FFF, pixelStart, shift, TileFormat::Bpp2);
uint8_t color = GetTilePixelColor<TileFormat::Bpp2>(vram, 0x3FFF, pixelStart, shift);
uint32_t outOffset = (y * 8) + x;
if(color > 0) {

View file

@ -326,7 +326,7 @@ void NesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t i, GetSpritePr
for(int x = 0; x < 8; x++) {
uint8_t shift = sprite.HorizontalMirror ? (7 - x) : x;
uint8_t color = GetTilePixelColor(vram, 0x3FFF, pixelStart, shift, TileFormat::NesBpp2);
uint8_t color = GetTilePixelColor<TileFormat::NesBpp2>(vram, 0x3FFF, pixelStart, shift);
uint32_t outOffset = (y * 8) + x;
if(color > 0) {

View file

@ -89,7 +89,7 @@ DebugTilemapInfo PceVdcTools::GetTilemap(GetTilemapOptions options, BaseState& b
for(int y = 0; y < 8; y++) {
uint16_t tileAddr = tileIndex * 32 + y * 2;
for(int x = 0; x < 8; x++) {
uint8_t color = GetTilePixelColor(vram, 0xFFFF, tileAddr, x, TileFormat::Bpp4);
uint8_t color = GetTilePixelColor<TileFormat::Bpp4>(vram, 0xFFFF, tileAddr, x);
uint16_t palAddr = color == 0 ? 0 : (palIndex * 16 + color);
uint32_t outPos = (row * 8 + y) * state.ColumnCount * 8 + column * 8 + x;
outBuffer[outPos] = palette[palAddr];
@ -243,7 +243,7 @@ void PceVdcTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint16_t spriteIndex, G
//Display specific pattern when open bus, to make problem obvious in sprite viewer
color = xOffset;
} else {
color = GetTilePixelColor(vram, 0xFFFF, pixelStart * 2, xOffset, TileFormat::PceSpriteBpp4);
color = GetTilePixelColor<TileFormat::PceSpriteBpp4>(vram, 0xFFFF, pixelStart * 2, xOffset);
}
if(color != 0) {

View file

@ -12,7 +12,6 @@ static constexpr uint8_t layerBpp[8][4] = {
SnesPpuTools::SnesPpuTools(Debugger* debugger, Emulator *emu) : PpuTools(debugger, emu)
{
_state = {};
}
void SnesPpuTools::GetPpuToolsState(BaseState& state)
@ -65,72 +64,35 @@ DebugTilemapInfo SnesPpuTools::GetTilemap(GetTilemapOptions options, BaseState&
rowCount = 128;
if(options.Layer == 1) {
format = TileFormat::Mode7ExtBg;
RenderMode7Tilemap<TileFormat::Mode7ExtBg>(vram, outBuffer, palette);
} else if(directColor) {
format = TileFormat::Mode7DirectColor;
RenderMode7Tilemap<TileFormat::Mode7DirectColor>(vram, outBuffer, palette);
} else {
format = directColor ? TileFormat::Mode7DirectColor : TileFormat::Mode7;
}
for(int row = 0; row < 128; row++) {
for(int column = 0; column < 128; column++) {
uint32_t tileIndex = vram[row * 256 + column * 2];
uint32_t tileAddr = tileIndex * 128;
for(int y = 0; y < 8; y++) {
uint32_t pixelStart = tileAddr + y * 16;
for(int x = 0; x < 8; x++) {
uint8_t color = GetTilePixelColor(vram, SnesPpu::VideoRamSize - 1, pixelStart, x, format);
if(color != 0) {
uint32_t rgbColor = GetRgbPixelColor(format, palette, color, 0);
outBuffer[((row * 8) + y) * outputSize.Width + column * 8 + x] = rgbColor;
}
}
}
}
format = TileFormat::Mode7;
RenderMode7Tilemap<TileFormat::Mode7>(vram, outBuffer, palette);
}
} else {
if(directColor) {
format = TileFormat::DirectColor;
RenderTilemap<TileFormat::DirectColor>(rowCount, layer, columnCount, vram, tileHeight, tileWidth, largeTileHeight, largeTileWidth, bpp, outBuffer, outputSize, palette, basePaletteOffset);
} else {
switch(bpp) {
default:
case 2: format = TileFormat::Bpp2; break;
case 4: format = TileFormat::Bpp4; break;
case 8: format = TileFormat::Bpp8; break;
}
}
case 2:
format = TileFormat::Bpp2;
RenderTilemap<TileFormat::Bpp2>(rowCount, layer, columnCount, vram, tileHeight, tileWidth, largeTileHeight, largeTileWidth, bpp, outBuffer, outputSize, palette, basePaletteOffset);
break;
for(int row = 0; row < rowCount; row++) {
uint16_t addrVerticalScrollingOffset = layer.DoubleHeight ? ((row & 0x20) << (layer.DoubleWidth ? 6 : 5)) : 0;
uint16_t baseOffset = layer.TilemapAddress + addrVerticalScrollingOffset + ((row & 0x1F) << 5);
case 4:
format = TileFormat::Bpp4;
RenderTilemap<TileFormat::Bpp4>(rowCount, layer, columnCount, vram, tileHeight, tileWidth, largeTileHeight, largeTileWidth, bpp, outBuffer, outputSize, palette, basePaletteOffset);
break;
for(int column = 0; column < columnCount; column++) {
uint16_t addr = (baseOffset + (column & 0x1F) + (layer.DoubleWidth ? ((column & 0x20) << 5) : 0)) << 1;
bool vMirror = (vram[addr + 1] & 0x80) != 0;
bool hMirror = (vram[addr + 1] & 0x40) != 0;
uint16_t tileIndex = ((vram[addr + 1] & 0x03) << 8) | vram[addr];
for(int y = 0; y < tileHeight; y++) {
uint8_t yOffset = vMirror ? (7 - (y & 0x07)) : (y & 0x07);
for(int x = 0; x < tileWidth; x++) {
uint16_t tileOffset = (
(largeTileHeight ? ((y & 0x08) ? (vMirror ? 0 : 16) : (vMirror ? 16 : 0)) : 0) +
(largeTileWidth ? ((x & 0x08) ? (hMirror ? 0 : 1) : (hMirror ? 1 : 0)) : 0)
);
uint16_t tileStart = (layer.ChrAddress << 1) + ((tileIndex + tileOffset) & 0x3FF) * 8 * bpp;
uint16_t pixelStart = tileStart + yOffset * 2;
uint8_t pixelIndex = hMirror ? (7 - (x & 0x07)) : (x & 0x07);
uint8_t color = GetTilePixelColor(vram, SnesPpu::VideoRamSize - 1, pixelStart, pixelIndex, format);
if(color != 0) {
uint8_t paletteIndex = bpp == 8 ? 0 : (vram[addr + 1] >> 2) & 0x07;
outBuffer[((row * tileHeight) + y) * outputSize.Width + column * tileWidth + x] = GetRgbPixelColor(format, palette + basePaletteOffset, color, paletteIndex);
}
}
}
case 8:
format = TileFormat::Bpp8;
RenderTilemap<TileFormat::Bpp8>(rowCount, layer, columnCount, vram, tileHeight, tileWidth, largeTileHeight, largeTileWidth, bpp, outBuffer, outputSize, palette, basePaletteOffset);
break;
}
}
}
@ -158,6 +120,64 @@ DebugTilemapInfo SnesPpuTools::GetTilemap(GetTilemapOptions options, BaseState&
return result;
}
template<TileFormat format>
void SnesPpuTools::RenderTilemap(int rowCount, LayerConfig& layer, int columnCount, uint8_t* vram, int tileHeight, int tileWidth, bool largeTileHeight, bool largeTileWidth, const uint8_t& bpp, uint32_t* outBuffer, FrameInfo& outputSize, uint32_t* palette, const uint16_t& basePaletteOffset)
{
for(int row = 0; row < rowCount; row++) {
uint16_t addrVerticalScrollingOffset = layer.DoubleHeight ? ((row & 0x20) << (layer.DoubleWidth ? 6 : 5)) : 0;
uint16_t baseOffset = layer.TilemapAddress + addrVerticalScrollingOffset + ((row & 0x1F) << 5);
for(int column = 0; column < columnCount; column++) {
uint16_t addr = (baseOffset + (column & 0x1F) + (layer.DoubleWidth ? ((column & 0x20) << 5) : 0)) << 1;
bool vMirror = (vram[addr + 1] & 0x80) != 0;
bool hMirror = (vram[addr + 1] & 0x40) != 0;
uint16_t tileIndex = ((vram[addr + 1] & 0x03) << 8) | vram[addr];
for(int y = 0; y < tileHeight; y++) {
uint8_t yOffset = vMirror ? (7 - (y & 0x07)) : (y & 0x07);
for(int x = 0; x < tileWidth; x++) {
uint16_t tileOffset = (
(largeTileHeight ? ((y & 0x08) ? (vMirror ? 0 : 16) : (vMirror ? 16 : 0)) : 0) +
(largeTileWidth ? ((x & 0x08) ? (hMirror ? 0 : 1) : (hMirror ? 1 : 0)) : 0)
);
uint16_t tileStart = (layer.ChrAddress << 1) + ((tileIndex + tileOffset) & 0x3FF) * 8 * bpp;
uint16_t pixelStart = tileStart + yOffset * 2;
uint8_t pixelIndex = hMirror ? (7 - (x & 0x07)) : (x & 0x07);
uint8_t color = GetTilePixelColor<format>(vram, SnesPpu::VideoRamSize - 1, pixelStart, pixelIndex);
if(color != 0) {
uint8_t paletteIndex = bpp == 8 ? 0 : (vram[addr + 1] >> 2) & 0x07;
outBuffer[((row * tileHeight) + y) * outputSize.Width + column * tileWidth + x] = GetRgbPixelColor<format>(palette + basePaletteOffset, color, paletteIndex);
}
}
}
}
}
}
template<TileFormat format>
void SnesPpuTools::RenderMode7Tilemap(uint8_t* vram, uint32_t* outBuffer, uint32_t* palette)
{
for(int row = 0; row < 1024; row++) {
for(int column = 0; column < 128; column++) {
uint32_t tileIndex = vram[(row>>3) * 256 + column * 2];
uint32_t tileAddr = tileIndex * 128;
uint32_t pixelStart = tileAddr + (row & 0x7) * 16;
for(int x = 0; x < 8; x++) {
uint8_t color = GetTilePixelColor<format>(vram, SnesPpu::VideoRamSize - 1, pixelStart, x);
if(color != 0) {
outBuffer[row * 1024 + column * 8 + x] = GetRgbPixelColor<format>(palette, color, 0);
}
}
}
}
}
static constexpr uint8_t _oamSizes[8][2][2] = {
{ { 1, 1 }, { 2, 2 } }, //8x8 + 16x16
{ { 1, 1 }, { 4, 4 } }, //8x8 + 32x32
@ -310,9 +330,9 @@ void SnesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint16_t spriteIndex,
uint8_t tileIndex = (row << 4) | column;
uint16_t tileStart = ((state.OamBaseAddress + (tileIndex << 4) + (useSecondTable ? state.OamAddressOffset : 0)) & 0x7FFF) << 1;
uint8_t color = GetTilePixelColor(vram, SnesPpu::VideoRamSize - 1, tileStart + yOffset * 2, xOffset, TileFormat::Bpp4);
uint8_t color = GetTilePixelColor<TileFormat::Bpp4>(vram, SnesPpu::VideoRamSize - 1, tileStart + yOffset * 2, xOffset);
if(color != 0) {
sprite.SpritePreview[outOffset] = GetRgbPixelColor(TileFormat::Bpp4, palette, color, sprite.Palette + 8);
sprite.SpritePreview[outOffset] = GetRgbPixelColor<TileFormat::Bpp4>(palette, color, sprite.Palette + 8);
} else {
sprite.SpritePreview[outOffset] = 0;
}

View file

@ -5,6 +5,8 @@
class Debugger;
class Emulator;
struct BaseState;
struct LayerConfig;
struct FrameInfo;
struct SnesPpuToolsState
{
@ -18,9 +20,12 @@ struct SnesPpuToolsState
class SnesPpuTools final : public PpuTools
{
private:
SnesPpuToolsState _state;
SnesPpuToolsState _state = {};
void GetSpriteInfo(DebugSpriteInfo& sprite, uint16_t spriteIndex, GetSpritePreviewOptions& options, SnesPpuState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette);
template<TileFormat format> void RenderMode7Tilemap(uint8_t* vram, uint32_t* outBuffer, uint32_t* palette);
template<TileFormat format> void RenderTilemap(int rowCount, LayerConfig& layer, int columnCount, uint8_t* vram, int tileHeight, int tileWidth, bool largeTileHeight, bool largeTileWidth, const uint8_t& bpp, uint32_t* outBuffer, FrameInfo& outputSize, uint32_t* palette, const uint16_t& basePaletteOffset);
public:
SnesPpuTools(Debugger* debugger, Emulator *emu);