diff --git a/Core/Debugger/PpuTools.h b/Core/Debugger/PpuTools.h index d78c3d73..a31763f2 100644 --- a/Core/Debugger/PpuTools.h +++ b/Core/Debugger/PpuTools.h @@ -308,7 +308,7 @@ template uint32_t PpuTools::GetRgbPixelColor(const uint32_t* } } -template uint8_t PpuTools::GetTilePixelColor(const uint8_t* ram, const uint32_t ramMask, uint32_t rowStart, uint8_t pixelIndex) +template __forceinline 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; diff --git a/Core/SNES/Debugger/SnesPpuTools.cpp b/Core/SNES/Debugger/SnesPpuTools.cpp index ff5801a9..182b8f12 100644 --- a/Core/SNES/Debugger/SnesPpuTools.cpp +++ b/Core/SNES/Debugger/SnesPpuTools.cpp @@ -5,6 +5,7 @@ #include "Shared/SettingTypes.h" #include "SNES/SnesPpu.h" #include "Shared/ColorUtilities.h" +#include "Shared/MessageManager.h" static constexpr uint8_t layerBpp[8][4] = { { 2,2,2,2 }, { 4,4,2,0 }, { 4,4,0,0 }, { 8,4,0,0 }, { 8,2,0,0 }, { 4,2,0,0 }, { 4,0,0,0 }, { 8,8,0,0 } @@ -138,6 +139,24 @@ DebugTilemapInfo SnesPpuTools::GetTilemap(GetTilemapOptions options, BaseState& template void SnesPpuTools::RenderTilemap(GetTilemapOptions& options, int rowCount, LayerConfig& layer, int columnCount, uint8_t* vram, int tileHeight, int tileWidth, bool largeTileHeight, bool largeTileWidth, uint8_t bpp, uint32_t* outBuffer, FrameInfo outputSize, const uint32_t* palette, uint16_t basePaletteOffset) +{ + if(largeTileHeight) { + if(largeTileWidth) { + RenderTilemap(options, rowCount, layer, columnCount, vram, tileHeight, tileWidth, bpp, outBuffer, outputSize, palette, basePaletteOffset); + } else { + RenderTilemap(options, rowCount, layer, columnCount, vram, tileHeight, tileWidth, bpp, outBuffer, outputSize, palette, basePaletteOffset); + } + } else { + if(largeTileWidth) { + RenderTilemap(options, rowCount, layer, columnCount, vram, tileHeight, tileWidth, bpp, outBuffer, outputSize, palette, basePaletteOffset); + } else { + RenderTilemap(options, rowCount, layer, columnCount, vram, tileHeight, tileWidth, bpp, outBuffer, outputSize, palette, basePaletteOffset); + } + } +} + +template +void SnesPpuTools::RenderTilemap(GetTilemapOptions& options, int rowCount, LayerConfig& layer, int columnCount, uint8_t* vram, int tileHeight, int tileWidth, uint8_t bpp, uint32_t* outBuffer, FrameInfo outputSize, const uint32_t* palette, uint16_t basePaletteOffset) { uint8_t colorMask = 0xFF; bool grayscale = options.DisplayMode == TilemapDisplayMode::Grayscale; @@ -159,10 +178,11 @@ void SnesPpuTools::RenderTilemap(GetTilemapOptions& options, int rowCount, Layer for(int y = 0; y < tileHeight; y++) { uint8_t yOffset = vMirror ? (7 - (y & 0x07)) : (y & 0x07); + uint8_t yTileOffset = (largeTileHeight ? ((y & 0x08) ? (vMirror ? 0 : 16) : (vMirror ? 16 : 0)) : 0); for(int x = 0; x < tileWidth; x++) { uint16_t tileOffset = ( - (largeTileHeight ? ((y & 0x08) ? (vMirror ? 0 : 16) : (vMirror ? 16 : 0)) : 0) + + yTileOffset + (largeTileWidth ? ((x & 0x08) ? (hMirror ? 0 : 1) : (hMirror ? 1 : 0)) : 0) ); diff --git a/Core/SNES/Debugger/SnesPpuTools.h b/Core/SNES/Debugger/SnesPpuTools.h index 79f7554a..367bc186 100644 --- a/Core/SNES/Debugger/SnesPpuTools.h +++ b/Core/SNES/Debugger/SnesPpuTools.h @@ -32,6 +32,7 @@ class SnesPpuTools final : public PpuTools template void RenderMode7Tilemap(GetTilemapOptions& options, uint8_t* vram, uint32_t* outBuffer, const uint32_t* palette); template void RenderTilemap(GetTilemapOptions& options, int rowCount, LayerConfig& layer, int columnCount, uint8_t* vram, int tileHeight, int tileWidth, bool largeTileHeight, bool largeTileWidth, uint8_t bpp, uint32_t* outBuffer, FrameInfo outputSize, const uint32_t* palette, uint16_t basePaletteOffset); + template void RenderTilemap(GetTilemapOptions& options, int rowCount, LayerConfig& layer, int columnCount, uint8_t* vram, int tileHeight, int tileWidth, uint8_t bpp, uint32_t* outBuffer, FrameInfo outputSize, const uint32_t* palette, uint16_t basePaletteOffset); DebugTilemapInfo RenderScreenView(uint8_t layer, uint32_t* outBuffer); void GetSpritePreview(GetSpritePreviewOptions options, BaseState& state, BaseState& ppuToolsState, DebugSpriteInfo* sprites, uint32_t* spritePreviews, uint32_t* palette, uint32_t* outBuffer); diff --git a/UI/Debugger/ViewModels/EventViewerViewModel.cs b/UI/Debugger/ViewModels/EventViewerViewModel.cs index 9f1a8320..e1efc5fd 100644 --- a/UI/Debugger/ViewModels/EventViewerViewModel.cs +++ b/UI/Debugger/ViewModels/EventViewerViewModel.cs @@ -53,6 +53,7 @@ public class EventViewerViewModel : DisposableViewModel [Reactive] public List ToolbarItems { get; private set; } = new(); private PictureViewer _picViewer; + private bool _refreshPending; [Obsolete("For designer only")] public EventViewerViewModel() : this(CpuType.Nes, new PictureViewer(), null!, null) { } @@ -269,24 +270,35 @@ public void RefreshData(bool forAutoRefresh = false) public void RefreshUi(bool forAutoRefresh) { + if(_refreshPending) { + return; + } + + _refreshPending = true; Dispatcher.UIThread.Post(() => { - if(Disposed) { - return; - } + InternalRefreshUi(forAutoRefresh); + _refreshPending = false; + }); + } - InitBitmap(); - using(var bitmapLock = ViewerBitmap.Lock()) { - DebugApi.GetEventViewerOutput(CpuType, bitmapLock.FrameBuffer.Address, (uint)(ViewerBitmap.Size.Width * ViewerBitmap.Size.Height * sizeof(UInt32))); - } + private void InternalRefreshUi(bool forAutoRefresh) + { + if(Disposed) { + return; + } - if(ShowListView) { - DateTime now = DateTime.Now; - if(!forAutoRefresh || (now - _lastListRefresh).TotalMilliseconds >= 66) { - _lastListRefresh = now; - ListView.RefreshList(); - } + InitBitmap(); + using(var bitmapLock = ViewerBitmap.Lock()) { + DebugApi.GetEventViewerOutput(CpuType, bitmapLock.FrameBuffer.Address, (uint)(ViewerBitmap.Size.Width * ViewerBitmap.Size.Height * sizeof(UInt32))); + } + + if(ShowListView) { + DateTime now = DateTime.Now; + if(!forAutoRefresh || (now - _lastListRefresh).TotalMilliseconds >= 66) { + _lastListRefresh = now; + ListView.RefreshList(); } - }); + } } private PixelPoint GetEventLocation(DebugEventInfo evt) diff --git a/UI/Debugger/ViewModels/SpriteViewerViewModel.cs b/UI/Debugger/ViewModels/SpriteViewerViewModel.cs index 0e55e3a2..9b97f084 100644 --- a/UI/Debugger/ViewModels/SpriteViewerViewModel.cs +++ b/UI/Debugger/ViewModels/SpriteViewerViewModel.cs @@ -70,6 +70,7 @@ public class SpriteViewerViewModel : DisposableViewModel, ICpuTypeModel, IMouseO private DebugSpriteInfo[] _spriteList = Array.Empty(); private UInt32[] _spritePreviews = Array.Empty(); + private bool _refreshPending; [Obsolete("For designer only")] public SpriteViewerViewModel() : this(CpuType.Snes, new PictureViewer(), new Grid(), new Control(), null) { } @@ -530,76 +531,87 @@ public void RefreshData() private void RefreshTab() { + if(_refreshPending) { + return; + } + + _refreshPending = true; Dispatcher.UIThread.Post(() => { - if(Disposed) { - return; - } + InternalRefreshTab(); + _refreshPending = false; + }); + } - lock(_updateLock) { - _coreData.CopyTo(_data); - } + private void InternalRefreshTab() + { + if(Disposed) { + return; + } - if(_data.PpuState == null || _data.Palette == null || _data.PpuToolsState == null) { - return; - } + lock(_updateLock) { + _coreData.CopyTo(_data); + } + + if(_data.PpuState == null || _data.Palette == null || _data.PpuToolsState == null) { + return; + } - GetSpritePreviewOptions options = new GetSpritePreviewOptions() { - Background = Config.Background - }; + GetSpritePreviewOptions options = new GetSpritePreviewOptions() { + Background = Config.Background + }; - DebugSpritePreviewInfo previewInfo = DebugApi.GetSpritePreviewInfo(CpuType, options, _data.PpuState, _data.PpuToolsState); - InitBitmap((int)previewInfo.Width, (int)previewInfo.Height); + DebugSpritePreviewInfo previewInfo = DebugApi.GetSpritePreviewInfo(CpuType, options, _data.PpuState, _data.PpuToolsState); + InitBitmap((int)previewInfo.Width, (int)previewInfo.Height); - UInt32[] palette = _data.Palette.Value.GetRgbPalette(); + UInt32[] palette = _data.Palette.Value.GetRgbPalette(); - LeftClipSize = Config.ShowOffscreenRegions ? 0 : (int)previewInfo.VisibleX; - RightClipSize = Config.ShowOffscreenRegions ? 0 : (int)(previewInfo.Width - (previewInfo.VisibleWidth + previewInfo.VisibleX)); - TopClipSize = Config.ShowOffscreenRegions ? 0 : (int)previewInfo.VisibleY; - BottomClipSize = Config.ShowOffscreenRegions ? 0 : (int)(previewInfo.Height - (previewInfo.VisibleHeight + previewInfo.VisibleY)); + LeftClipSize = Config.ShowOffscreenRegions ? 0 : (int)previewInfo.VisibleX; + RightClipSize = Config.ShowOffscreenRegions ? 0 : (int)(previewInfo.Width - (previewInfo.VisibleWidth + previewInfo.VisibleX)); + TopClipSize = Config.ShowOffscreenRegions ? 0 : (int)previewInfo.VisibleY; + BottomClipSize = Config.ShowOffscreenRegions ? 0 : (int)(previewInfo.Height - (previewInfo.VisibleHeight + previewInfo.VisibleY)); - using(var framebuffer = ViewerBitmap.Lock(true)) { - DebugApi.GetSpriteList(ref _spriteList, ref _spritePreviews, CpuType, options, _data.PpuState, _data.PpuToolsState, _data.Vram, _data.SpriteRam, palette, framebuffer.FrameBuffer.Address); - } + using(var framebuffer = ViewerBitmap.Lock(true)) { + DebugApi.GetSpriteList(ref _spriteList, ref _spritePreviews, CpuType, options, _data.PpuState, _data.PpuToolsState, _data.Vram, _data.SpriteRam, palette, framebuffer.FrameBuffer.Address); + } + + InitPreviews(_spriteList, _spritePreviews, previewInfo); - InitPreviews(_spriteList, _spritePreviews, previewInfo); - - if(Config.ShowOutline) { - List spriteRects = new List(); - foreach(SpritePreviewModel sprite in SpritePreviews) { - (Rect mainRect, Rect alt1, Rect alt2, Rect alt3) = sprite.GetPreviewRect(); - spriteRects.Add(mainRect); - if(alt1 != default) { - spriteRects.Add(alt1); - } - if(alt2 != default) { - spriteRects.Add(alt2); - } - if(alt3 != default) { - spriteRects.Add(alt3); - } + if(Config.ShowOutline) { + List spriteRects = new List(); + foreach(SpritePreviewModel sprite in SpritePreviews) { + (Rect mainRect, Rect alt1, Rect alt2, Rect alt3) = sprite.GetPreviewRect(); + spriteRects.Add(mainRect); + if(alt1 != default) { + spriteRects.Add(alt1); + } + if(alt2 != default) { + spriteRects.Add(alt2); + } + if(alt3 != default) { + spriteRects.Add(alt3); } - ViewerBitmap.HighlightRects = spriteRects; - } else { - ViewerBitmap.HighlightRects = null; } + ViewerBitmap.HighlightRects = spriteRects; + } else { + ViewerBitmap.HighlightRects = null; + } - ViewerBitmap.Invalidate(); + ViewerBitmap.Invalidate(); - int selectedIndex = SelectedSprite?.SpriteIndex ?? -1; - if(selectedIndex >= 0 && selectedIndex < SpritePreviews.Count) { - SelectedSprite = SpritePreviews[selectedIndex]; - UpdateSelectionPreview(); - } else { - SelectedSprite = null; - } + int selectedIndex = SelectedSprite?.SpriteIndex ?? -1; + if(selectedIndex >= 0 && selectedIndex < SpritePreviews.Count) { + SelectedSprite = SpritePreviews[selectedIndex]; + UpdateSelectionPreview(); + } else { + SelectedSprite = null; + } - ListView.RefreshList(); + ListView.RefreshList(); - UpdateTooltips(); - UpdateSelection(SelectedSprite); + UpdateTooltips(); + UpdateSelection(SelectedSprite); - UpdateMouseOverRect(); - }); + UpdateMouseOverRect(); } private void UpdateSelectionPreview() diff --git a/UI/Debugger/ViewModels/TileViewerViewModel.cs b/UI/Debugger/ViewModels/TileViewerViewModel.cs index 443e8b88..d0615df2 100644 --- a/UI/Debugger/ViewModels/TileViewerViewModel.cs +++ b/UI/Debugger/ViewModels/TileViewerViewModel.cs @@ -71,6 +71,7 @@ public class TileViewerViewModel : DisposableViewModel, ICpuTypeModel, IMouseOve private object _updateLock = new(); private byte[] _coreSourceData = Array.Empty(); private byte[] _sourceData = Array.Empty(); + private bool _refreshPending; [Obsolete("For designer only")] public TileViewerViewModel() : this(CpuType.Snes, new PictureViewer(), null) { } @@ -465,31 +466,42 @@ private void RefreshPalette() private void RefreshTab() { + if(_refreshPending) { + return; + } + + _refreshPending = true; Dispatcher.UIThread.Post(() => { - if(Disposed) { - return; - } + InternalRefreshTab(); + _refreshPending = false; + }); + } + + private void InternalRefreshTab() + { + if(Disposed) { + return; + } - InitBitmap(); + InitBitmap(); - lock(_updateLock) { - Array.Resize(ref _sourceData, _coreSourceData.Length); - Array.Copy(_coreSourceData, _sourceData, _coreSourceData.Length); - } + lock(_updateLock) { + Array.Resize(ref _sourceData, _coreSourceData.Length); + Array.Copy(_coreSourceData, _sourceData, _coreSourceData.Length); + } - using(var framebuffer = ViewerBitmap.Lock()) { - DebugApi.GetTileView(CpuType, GetOptions(), _sourceData, _sourceData.Length, PaletteColors, framebuffer.FrameBuffer.Address); - } + using(var framebuffer = ViewerBitmap.Lock()) { + DebugApi.GetTileView(CpuType, GetOptions(), _sourceData, _sourceData.Length, PaletteColors, framebuffer.FrameBuffer.Address); + } - if(IsNesChrModeEnabled) { - DrawNesChrPageDelimiters(); - } else { - PageDelimiters = null; - } + if(IsNesChrModeEnabled) { + DrawNesChrPageDelimiters(); + } else { + PageDelimiters = null; + } - UpdatePreviewPanel(); - LoadSelectedPreset(true); - }); + UpdatePreviewPanel(); + LoadSelectedPreset(true); } private int GetTileAddress(PixelPoint pixelPosition) diff --git a/UI/Debugger/ViewModels/TilemapViewerViewModel.cs b/UI/Debugger/ViewModels/TilemapViewerViewModel.cs index cdc120e0..2b686ad5 100644 --- a/UI/Debugger/ViewModels/TilemapViewerViewModel.cs +++ b/UI/Debugger/ViewModels/TilemapViewerViewModel.cs @@ -62,6 +62,7 @@ public class TilemapViewerViewModel : DisposableViewModel, ICpuTypeModel, IMouse private PictureViewer _picViewer; private bool _refreshDataOnTabChange; private bool _inGameLoaded; + private bool _refreshPending; [Obsolete("For designer only")] public TilemapViewerViewModel() : this(CpuType.Snes, new PictureViewer(), null) { } @@ -479,79 +480,93 @@ public void RefreshData() private void RefreshTab() { + if(_refreshPending) { + return; + } + + _refreshPending = true; Dispatcher.UIThread.Post(() => { - if(Disposed) { - return; - } + InternalRefreshTab(); + _refreshPending = false; + }); + } - lock(_updateLock) { - _coreData.CopyTo(_data); - } + private void InternalRefreshTab() + { + if(Disposed) { + return; + } - if(_data.PpuState == null || _data.PpuToolsState == null) { - return; - } + lock(_updateLock) { + _coreData.CopyTo(_data); + } - GetTilemapOptions options; - FrameInfo size; + if(_data.PpuState == null || _data.PpuToolsState == null) { + _refreshPending = false; + return; + } - foreach(TilemapViewerTab tab in Tabs) { - options = GetOptions(tab); - size = DebugApi.GetTilemapSize(CpuType, options, _data.PpuState); - tab.Enabled = size.Width != 0 && size.Height != 0; - } + GetTilemapOptions options; + FrameInfo size; - if(!SelectedTab.Enabled) { - foreach(TilemapViewerTab tab in Tabs) { - if(tab.Enabled) { - SelectedTab = tab; - break; - } + foreach(TilemapViewerTab tab in Tabs) { + options = GetOptions(tab); + size = DebugApi.GetTilemapSize(CpuType, options, _data.PpuState); + tab.Enabled = size.Width != 0 && size.Height != 0; + } + + if(!SelectedTab.Enabled) { + foreach(TilemapViewerTab tab in Tabs) { + if(tab.Enabled) { + SelectedTab = tab; + break; } } + } - options = GetOptions(SelectedTab, _data.PrevVram, _data.AccessCounters); - options.MasterClock = Interlocked.Read(ref _data.MasterClock); + options = GetOptions(SelectedTab, _data.PrevVram, _data.AccessCounters); + options.MasterClock = Interlocked.Read(ref _data.MasterClock); - size = DebugApi.GetTilemapSize(CpuType, options, _data.PpuState); - InitBitmap((int)size.Width, (int)size.Height); + size = DebugApi.GetTilemapSize(CpuType, options, _data.PpuState); + InitBitmap((int)size.Width, (int)size.Height); - using(var framebuffer = ViewerBitmap.Lock()) { - _data.TilemapInfo = DebugApi.GetTilemap(CpuType, options, _data.PpuState, _data.PpuToolsState, _data.Vram, _data.RgbPalette, framebuffer.FrameBuffer.Address); - } + using(var framebuffer = ViewerBitmap.Lock()) { + _data.TilemapInfo = DebugApi.GetTilemap(CpuType, options, _data.PpuState, _data.PpuToolsState, _data.Vram, _data.RgbPalette, framebuffer.FrameBuffer.Address); + } - if(_data.TilemapInfo.Bpp == 0) { - GridSizeX = 8; - GridSizeY = 8; - ScrollOverlayRect = default; - OverlayLines = null; - PreviewPanel = null; - IsTilemapInfoVisible = false; - return; - } + if(_data.TilemapInfo.Bpp == 0) { + GridSizeX = 8; + GridSizeY = 8; + ScrollOverlayRect = default; + OverlayLines = null; + PreviewPanel = null; + IsTilemapInfoVisible = false; + return; + } - IsTilemapInfoVisible = true; + IsTilemapInfoVisible = true; - GridSizeX = (int)_data.TilemapInfo.TileWidth; - GridSizeY = (int)_data.TilemapInfo.TileHeight; + GridSizeX = (int)_data.TilemapInfo.TileWidth; + GridSizeY = (int)_data.TilemapInfo.TileHeight; - UpdatePreviewPanel(); - UpdateTilemapInfo(); + UpdatePreviewPanel(); + UpdateTilemapInfo(); - if(Config.ShowScrollOverlay) { - ScrollOverlayRect = new Rect( - _data.TilemapInfo.ScrollX % size.Width, - _data.TilemapInfo.ScrollY % size.Height, - _data.TilemapInfo.ScrollWidth, - _data.TilemapInfo.ScrollHeight - ); + if(Config.ShowScrollOverlay) { + ScrollOverlayRect = new Rect( + _data.TilemapInfo.ScrollX % size.Width, + _data.TilemapInfo.ScrollY % size.Height, + _data.TilemapInfo.ScrollWidth, + _data.TilemapInfo.ScrollHeight + ); - DrawMode7Overlay(); - } else { - ScrollOverlayRect = default; - OverlayLines = null; - } - }); + DrawMode7Overlay(); + } else { + ScrollOverlayRect = default; + OverlayLines = null; + } + + _refreshPending = false; } private void UpdateTilemapInfo()