mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
Debugger: Performance improvements for ppu viewers (30-75% faster in core)
This commit is contained in:
parent
7df142e420
commit
a61e559c07
7 changed files with 201 additions and 158 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue