Debugger: Added mode 7 / direct color support to tilemap viewer
This commit is contained in:
parent
113d440b3d
commit
c41e3458eb
6 changed files with 137 additions and 82 deletions
|
@ -82,6 +82,8 @@ PpuState Ppu::GetState()
|
|||
state.FrameCount = _frameCount;
|
||||
state.OverscanMode = _overscanMode;
|
||||
state.BgMode = _bgMode;
|
||||
state.DirectColorMode = _directColorMode;
|
||||
state.Mode7 = _mode7;
|
||||
state.Layers[0] = _layerConfig[0];
|
||||
state.Layers[1] = _layerConfig[1];
|
||||
state.Layers[2] = _layerConfig[2];
|
||||
|
|
|
@ -141,6 +141,7 @@ void PpuTools::GetTileView(GetTileViewOptions options, uint32_t *outBuffer)
|
|||
|
||||
for(int y = 0; y < 8; y++) {
|
||||
uint32_t pixelStart = addr + y * 16;
|
||||
|
||||
for(int x = 0; x < 8; x++) {
|
||||
uint8_t color = ram[(pixelStart + x * 2 + 1) & ramMask];
|
||||
|
||||
|
@ -198,6 +199,8 @@ void PpuTools::GetTilemap(GetTilemapOptions options, uint32_t* outBuffer)
|
|||
PpuState state = _ppu->GetState();
|
||||
options.BgMode = state.BgMode;
|
||||
|
||||
bool directColor = state.DirectColorMode && (options.BgMode == 3 || options.BgMode == 4 || options.BgMode == 7);
|
||||
|
||||
uint16_t basePaletteOffset = 0;
|
||||
if(options.BgMode == 0) {
|
||||
basePaletteOffset = options.Layer * 64;
|
||||
|
@ -207,10 +210,8 @@ void PpuTools::GetTilemap(GetTilemapOptions options, uint32_t* outBuffer)
|
|||
uint8_t *cgram = _ppu->GetCgRam();
|
||||
LayerConfig layer = state.Layers[options.Layer];
|
||||
|
||||
uint16_t bgColor = (cgram[1] << 8) | cgram[0];
|
||||
for(int i = 0; i < 512 * 512; i++) {
|
||||
outBuffer[i] = ToArgb(bgColor);
|
||||
}
|
||||
uint32_t bgColor = ToArgb((cgram[1] << 8) | cgram[0]);
|
||||
std::fill(outBuffer, outBuffer + 1024*1024, bgColor);
|
||||
|
||||
uint8_t bpp = layerBpp[options.BgMode][options.Layer];
|
||||
if(bpp == 0) {
|
||||
|
@ -220,37 +221,64 @@ void PpuTools::GetTilemap(GetTilemapOptions options, uint32_t* outBuffer)
|
|||
bool largeTileWidth = layer.LargeTiles || options.BgMode == 5 || options.BgMode == 6;
|
||||
bool largeTileHeight = layer.LargeTiles;
|
||||
|
||||
for(int row = 0; row < (layer.DoubleHeight ? 64 : 32); row++) {
|
||||
uint16_t addrVerticalScrollingOffset = layer.DoubleHeight ? ((row & 0x20) << (layer.DoubleWidth ? 6 : 5)) : 0;
|
||||
uint16_t baseOffset = (layer.TilemapAddress >> 1) + addrVerticalScrollingOffset + ((row & 0x1F) << 5);
|
||||
if(options.BgMode == 7) {
|
||||
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 column = 0; column < (layer.DoubleWidth ? 64 : 32); column++) {
|
||||
uint16_t addr = (baseOffset + (column & 0x1F) + (layer.DoubleWidth ? ((column & 0x20) << 5) : 0)) << 1;
|
||||
for(int y = 0; y < 8; y++) {
|
||||
uint32_t pixelStart = tileAddr + y * 16;
|
||||
|
||||
bool vMirror = (vram[addr + 1] & 0x80) != 0;
|
||||
bool hMirror = (vram[addr + 1] & 0x40) != 0;
|
||||
for(int x = 0; x < 8; x++) {
|
||||
uint8_t color = vram[pixelStart + x * 2 + 1];
|
||||
|
||||
uint16_t tileIndex = ((vram[addr + 1] & 0x03) << 8) | vram[addr];
|
||||
uint16_t tileStart = layer.ChrAddress + tileIndex * 8 * bpp;
|
||||
|
||||
if(largeTileWidth || largeTileHeight) {
|
||||
tileIndex = (
|
||||
tileIndex +
|
||||
(largeTileHeight ? ((row & 0x01) ? (vMirror ? 0 : 16) : (vMirror ? 16 : 0)) : 0) +
|
||||
(largeTileWidth ? ((column & 0x01) ? (hMirror ? 0 : 1) : (hMirror ? 1 : 0)) : 0)
|
||||
) & 0x3FF;
|
||||
if(color != 0) {
|
||||
uint32_t rgbColor;
|
||||
if(directColor) {
|
||||
rgbColor = ToArgb(((color & 0x07) << 2) | ((color & 0x38) << 4) | ((color & 0xC0) << 7));
|
||||
} else {
|
||||
rgbColor = GetRgbPixelColor(color, 0, 8, false, 0);
|
||||
}
|
||||
outBuffer[((row * 8) + y) * 1024 + column * 8 + x] = rgbColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int row = 0; row < (layer.DoubleHeight ? 64 : 32); row++) {
|
||||
uint16_t addrVerticalScrollingOffset = layer.DoubleHeight ? ((row & 0x20) << (layer.DoubleWidth ? 6 : 5)) : 0;
|
||||
uint16_t baseOffset = (layer.TilemapAddress >> 1) + addrVerticalScrollingOffset + ((row & 0x1F) << 5);
|
||||
|
||||
for(int y = 0; y < 8; y++) {
|
||||
uint8_t yOffset = vMirror ? (7 - y) : y;
|
||||
uint16_t pixelStart = tileStart + yOffset * 2;
|
||||
for(int column = 0; column < (layer.DoubleWidth ? 64 : 32); column++) {
|
||||
uint16_t addr = (baseOffset + (column & 0x1F) + (layer.DoubleWidth ? ((column & 0x20) << 5) : 0)) << 1;
|
||||
|
||||
for(int x = 0; x < 8; x++) {
|
||||
uint8_t shift = hMirror ? x : (7 - x);
|
||||
uint8_t color = GetTilePixelColor(vram, Ppu::VideoRamSize - 1, bpp, pixelStart, shift);
|
||||
if(color != 0) {
|
||||
uint8_t palette = bpp == 8 ? 0 : (vram[addr + 1] >> 2) & 0x07;
|
||||
outBuffer[((row * 8) + y) * 512 + column * 8 + x] = GetRgbPixelColor(color, palette, bpp, false, basePaletteOffset);
|
||||
bool vMirror = (vram[addr + 1] & 0x80) != 0;
|
||||
bool hMirror = (vram[addr + 1] & 0x40) != 0;
|
||||
|
||||
uint16_t tileIndex = ((vram[addr + 1] & 0x03) << 8) | vram[addr];
|
||||
uint16_t tileStart = layer.ChrAddress + tileIndex * 8 * bpp;
|
||||
|
||||
if(largeTileWidth || largeTileHeight) {
|
||||
tileIndex = (
|
||||
tileIndex +
|
||||
(largeTileHeight ? ((row & 0x01) ? (vMirror ? 0 : 16) : (vMirror ? 16 : 0)) : 0) +
|
||||
(largeTileWidth ? ((column & 0x01) ? (hMirror ? 0 : 1) : (hMirror ? 1 : 0)) : 0)
|
||||
) & 0x3FF;
|
||||
}
|
||||
|
||||
for(int y = 0; y < 8; y++) {
|
||||
uint8_t yOffset = vMirror ? (7 - y) : y;
|
||||
uint16_t pixelStart = tileStart + yOffset * 2;
|
||||
|
||||
for(int x = 0; x < 8; x++) {
|
||||
uint8_t shift = hMirror ? x : (7 - x);
|
||||
uint8_t color = GetTilePixelColor(vram, Ppu::VideoRamSize - 1, bpp, pixelStart, shift);
|
||||
if(color != 0) {
|
||||
uint8_t palette = bpp == 8 ? 0 : (vram[addr + 1] >> 2) & 0x07;
|
||||
outBuffer[((row * 8) + y) * 1024 + column * 8 + x] = GetRgbPixelColor(color, palette, bpp, directColor, basePaletteOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,8 +287,8 @@ void PpuTools::GetTilemap(GetTilemapOptions options, uint32_t* outBuffer)
|
|||
|
||||
if(options.ShowTileGrid) {
|
||||
constexpr uint32_t gridColor = 0xA0AAAAFF;
|
||||
for(int i = 0; i < 512 * 512; i++) {
|
||||
if((i & 0x07) == 0x07 || (i & 0x0E00) == 0x0E00) {
|
||||
for(int i = 0; i < 1024 * 1024; i++) {
|
||||
if((i & 0x07) == 0x07 || (i & 0x1C00) == 0x1C00) {
|
||||
BlendColors((uint8_t*)&outBuffer[i], (uint8_t*)&gridColor);
|
||||
}
|
||||
}
|
||||
|
@ -268,18 +296,22 @@ void PpuTools::GetTilemap(GetTilemapOptions options, uint32_t* outBuffer)
|
|||
|
||||
if(options.ShowScrollOverlay) {
|
||||
constexpr uint32_t overlayColor = 0x40FFFFFF;
|
||||
int widthMask = options.BgMode == 7 ? 0x3FF : (layer.DoubleWidth ? 0x1FF : 0xFF);
|
||||
int heightMask = options.BgMode == 7 ? 0x3FF : (layer.DoubleHeight ? 0x1FF : 0xFF);
|
||||
int hScroll = options.BgMode == 7 ? state.Mode7.HScroll : layer.HScroll;
|
||||
int vScroll = options.BgMode == 7 ? state.Mode7.VScroll : layer.VScroll;
|
||||
for(int y = 0; y < 240; y++) {
|
||||
for(int x = 0; x < 256; x++) {
|
||||
int xPos = layer.HScroll + x;
|
||||
int yPos = layer.VScroll + y;
|
||||
int xPos = hScroll + x;
|
||||
int yPos = vScroll + y;
|
||||
|
||||
xPos &= layer.DoubleWidth ? 0x1FF : 0xFF;
|
||||
yPos &= layer.DoubleHeight ? 0x1FF : 0xFF;
|
||||
xPos &= widthMask;
|
||||
yPos &= heightMask;
|
||||
|
||||
if(x == 0 || y == 0 || x == 255 || y == 239) {
|
||||
outBuffer[(yPos << 9) | xPos] = 0xAFFFFFFF;
|
||||
outBuffer[(yPos * 1024) | xPos] = 0xAFFFFFFF;
|
||||
} else {
|
||||
BlendColors((uint8_t*)&outBuffer[(yPos << 9) | xPos], (uint8_t*)&overlayColor);
|
||||
BlendColors((uint8_t*)&outBuffer[(yPos * 1024) | xPos], (uint8_t*)&overlayColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,17 +15,6 @@ struct LayerConfig
|
|||
bool LargeTiles;
|
||||
};
|
||||
|
||||
struct PpuState
|
||||
{
|
||||
uint16_t Cycle;
|
||||
uint16_t Scanline;
|
||||
uint32_t FrameCount;
|
||||
bool OverscanMode;
|
||||
|
||||
uint8_t BgMode;
|
||||
LayerConfig Layers[4];
|
||||
};
|
||||
|
||||
struct Mode7Config
|
||||
{
|
||||
int16_t Matrix[4];
|
||||
|
@ -44,6 +33,19 @@ struct Mode7Config
|
|||
bool ExtBgEnabled;
|
||||
};
|
||||
|
||||
struct PpuState
|
||||
{
|
||||
uint16_t Cycle;
|
||||
uint16_t Scanline;
|
||||
uint32_t FrameCount;
|
||||
bool OverscanMode;
|
||||
|
||||
uint8_t BgMode;
|
||||
bool DirectColorMode;
|
||||
Mode7Config Mode7;
|
||||
LayerConfig Layers[4];
|
||||
};
|
||||
|
||||
struct WindowConfig
|
||||
{
|
||||
bool ActiveLayers[6];
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace Mesen.GUI.Debugger
|
|||
cboFormat.SetEnumValue(TileFormat.Bpp4);
|
||||
ctrlPaletteViewer.SelectionMode = PaletteSelectionMode.SixteenColors;
|
||||
|
||||
_tileData = new byte[512 * 512 * 4];
|
||||
_tileImage = new Bitmap(512, 512, PixelFormat.Format32bppArgb);
|
||||
picTilemap.Image = _tileImage;
|
||||
|
||||
|
@ -91,7 +92,9 @@ namespace Mesen.GUI.Debugger
|
|||
private void RefreshData()
|
||||
{
|
||||
_options.Palette = ctrlPaletteViewer.SelectedPalette;
|
||||
_tileData = DebugApi.GetTileView(_options);
|
||||
lock(_tileData) {
|
||||
DebugApi.GetTileView(_options, _tileData);
|
||||
}
|
||||
ctrlPaletteViewer.RefreshData();
|
||||
}
|
||||
|
||||
|
@ -108,12 +111,14 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
|
||||
using(Graphics g = Graphics.FromImage(_tileImage)) {
|
||||
GCHandle handle = GCHandle.Alloc(_tileData, GCHandleType.Pinned);
|
||||
Bitmap source = new Bitmap(mapWidth, mapHeight, 4 * mapWidth, PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
|
||||
try {
|
||||
g.DrawImage(source, 0, 0);
|
||||
} finally {
|
||||
handle.Free();
|
||||
lock(_tileData) {
|
||||
GCHandle handle = GCHandle.Alloc(_tileData, GCHandleType.Pinned);
|
||||
Bitmap source = new Bitmap(mapWidth, mapHeight, 4 * mapWidth, PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
|
||||
try {
|
||||
g.DrawImage(source, 0, 0);
|
||||
} finally {
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ namespace Mesen.GUI.Debugger
|
|||
_notifListener = new NotificationListener();
|
||||
_notifListener.OnNotification += OnNotificationReceived;
|
||||
|
||||
_tilemapImage = new Bitmap(512, 512, PixelFormat.Format32bppArgb);
|
||||
_tilemapData = new byte[1024 * 1024 * 4];
|
||||
_tilemapImage = new Bitmap(1024, 1024, PixelFormat.Format32bppArgb);
|
||||
picTilemap.Image = _tilemapImage;
|
||||
|
||||
ctrlScanlineCycleSelect.Initialize(241, 0);
|
||||
|
@ -71,24 +72,28 @@ namespace Mesen.GUI.Debugger
|
|||
private void RefreshData()
|
||||
{
|
||||
_state = DebugApi.GetState();
|
||||
_tilemapData = DebugApi.GetTilemap(_options);
|
||||
lock(_tilemapData) {
|
||||
DebugApi.GetTilemap(_options, _tilemapData);
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshViewer()
|
||||
{
|
||||
int mapWidth = _state.Ppu.Layers[_options.Layer].DoubleWidth ? 512 : 256;
|
||||
int mapHeight = _state.Ppu.Layers[_options.Layer].DoubleHeight ? 512 : 256;
|
||||
int mapWidth = _state.Ppu.BgMode == 7 ? 1024 : _state.Ppu.Layers[_options.Layer].DoubleWidth ? 512 : 256;
|
||||
int mapHeight = _state.Ppu.BgMode == 7 ? 1024 : _state.Ppu.Layers[_options.Layer].DoubleHeight ? 512 : 256;
|
||||
if(_tilemapImage.Width != mapWidth || _tilemapImage.Height != mapHeight) {
|
||||
_tilemapImage = new Bitmap(mapWidth, mapHeight, PixelFormat.Format32bppArgb);
|
||||
picTilemap.Image = _tilemapImage;
|
||||
}
|
||||
using(Graphics g = Graphics.FromImage(_tilemapImage)) {
|
||||
GCHandle handle = GCHandle.Alloc(_tilemapData, GCHandleType.Pinned);
|
||||
Bitmap source = new Bitmap(512, 512, 4 * 512, PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
|
||||
try {
|
||||
g.DrawImage(source, 0, 0);
|
||||
} finally {
|
||||
handle.Free();
|
||||
lock(_tilemapData) {
|
||||
GCHandle handle = GCHandle.Alloc(_tilemapData, GCHandleType.Pinned);
|
||||
Bitmap source = new Bitmap(mapWidth, mapHeight, 4 * 1024, PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
|
||||
try {
|
||||
g.DrawImage(source, 0, 0);
|
||||
} finally {
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,8 +103,8 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
private void UpdateMapSize()
|
||||
{
|
||||
int mapWidth = _state.Ppu.Layers[_options.Layer].DoubleWidth ? 512 : 256;
|
||||
int mapHeight = _state.Ppu.Layers[_options.Layer].DoubleHeight ? 512 : 256;
|
||||
int mapWidth = _state.Ppu.BgMode == 7 ? 1024 : _state.Ppu.Layers[_options.Layer].DoubleWidth ? 512 : 256;
|
||||
int mapHeight = _state.Ppu.BgMode == 7 ? 1024 : _state.Ppu.Layers[_options.Layer].DoubleHeight ? 512 : 256;
|
||||
picTilemap.Width = _zoomed ? mapWidth * 2 : mapWidth;
|
||||
picTilemap.Height = _zoomed ? mapHeight * 2 : mapHeight;
|
||||
}
|
||||
|
|
|
@ -71,21 +71,8 @@ namespace Mesen.GUI
|
|||
return buffer;
|
||||
}
|
||||
|
||||
[DllImport(DllPath, EntryPoint = "GetTilemap")] private static extern void GetTilemapWrapper(GetTilemapOptions options, [In, Out] byte[] buffer);
|
||||
public static byte[] GetTilemap(GetTilemapOptions options)
|
||||
{
|
||||
byte[] buffer = new byte[512*512*4];
|
||||
DebugApi.GetTilemapWrapper(options, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
[DllImport(DllPath, EntryPoint = "GetTileView")] private static extern void GetTileViewWrapper(GetTileViewOptions options, [In, Out] byte[] buffer);
|
||||
public static byte[] GetTileView(GetTileViewOptions options)
|
||||
{
|
||||
byte[] buffer = new byte[512 * 512 * 4];
|
||||
DebugApi.GetTileViewWrapper(options, buffer);
|
||||
return buffer;
|
||||
}
|
||||
[DllImport(DllPath)] public static extern void GetTilemap(GetTilemapOptions options, [In, Out] byte[] buffer);
|
||||
[DllImport(DllPath)] public static extern void GetTileView(GetTileViewOptions options, [In, Out] byte[] buffer);
|
||||
|
||||
[DllImport(DllPath)] public static extern void SetViewerUpdateTiming(Int32 viewerId, Int32 scanline, Int32 cycle);
|
||||
|
||||
|
@ -188,6 +175,9 @@ namespace Mesen.GUI
|
|||
[MarshalAs(UnmanagedType.I1)] public bool OverscanMode;
|
||||
|
||||
public byte BgMode;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool DirectColorMode;
|
||||
|
||||
public Mode7Config Mode7;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public LayerConfig[] Layers;
|
||||
|
@ -207,6 +197,25 @@ namespace Mesen.GUI
|
|||
[MarshalAs(UnmanagedType.I1)] public bool LargeTiles;
|
||||
}
|
||||
|
||||
public struct Mode7Config
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public Int16[] Matrix;
|
||||
|
||||
public Int16 HScroll;
|
||||
public Int16 VScroll;
|
||||
public Int16 CenterX;
|
||||
public Int16 CenterY;
|
||||
|
||||
public Byte ValueLatch;
|
||||
|
||||
[MarshalAs(UnmanagedType.I1)] public bool LargeMap;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool FillWithTile0;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool HorizontalMirroring;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool VerticalMirroring;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool ExtBgEnabled;
|
||||
}
|
||||
|
||||
public struct DebugState
|
||||
{
|
||||
public CpuState Cpu;
|
||||
|
|
Loading…
Add table
Reference in a new issue