diff --git a/Core/Debugger/DebugTypes.h b/Core/Debugger/DebugTypes.h
index 58c6be5a..54c341b9 100644
--- a/Core/Debugger/DebugTypes.h
+++ b/Core/Debugger/DebugTypes.h
@@ -213,11 +213,12 @@ enum class TileLayout
enum class TileBackground
{
- Default = 0,
- PaletteColor = 1,
- Black = 2,
- White = 3,
- Magenta = 4
+ Default,
+ Transparent,
+ PaletteColor,
+ Black,
+ White,
+ Magenta,
};
enum class TileFilter
@@ -246,6 +247,11 @@ struct GetSpritePreviewOptions
int32_t SelectedSprite;
};
+struct GetPaletteInfoOptions
+{
+ TileFormat Format;
+};
+
enum class StackFrameFlags
{
None = 0,
diff --git a/Core/Debugger/PpuTools.cpp b/Core/Debugger/PpuTools.cpp
index 4965f3ec..3b94a08c 100644
--- a/Core/Debugger/PpuTools.cpp
+++ b/Core/Debugger/PpuTools.cpp
@@ -164,6 +164,7 @@ void PpuTools::GetTileView(GetTileViewOptions options, uint8_t *source, uint32_t
case TileBackground::Black: bgColor = 0xFF000000; break;
case TileBackground::White: bgColor = 0xFFFFFFFF; break;
case TileBackground::Magenta: bgColor = 0xFFFF00FF; break;
+ case TileBackground::Transparent: bgColor = 0; break;
}
uint32_t outputSize = tileCount * tileWidth * tileHeight;
@@ -244,6 +245,96 @@ void PpuTools::RemoveViewer(uint32_t viewerId)
_updateTimings.erase(viewerId);
}
+void PpuTools::SetTilePixel(AddressInfo tileAddress, TileFormat format, int32_t x, int32_t y, int32_t color)
+{
+ ConsoleMemoryInfo memInfo = _emu->GetMemory(tileAddress.Type);
+ if(!memInfo.Memory || memInfo.Size == 0) {
+ return;
+ }
+
+ int rowOffset;
+ switch(format) {
+ default: rowOffset = 2; break;
+ case TileFormat::Mode7:
+ case TileFormat::Mode7DirectColor:
+ case TileFormat::Mode7ExtBg:
+ rowOffset = 16;
+ break;
+
+ case TileFormat::NesBpp2: rowOffset = 1; break;
+ case TileFormat::PceSpriteBpp4: rowOffset = 2; break;
+ }
+
+ uint8_t* ram = (uint8_t*)memInfo.Memory;
+ int rowStart = tileAddress.Address + (y * rowOffset);
+ int ramMask = (memInfo.Size - 1);
+
+ uint8_t shift = (7 - x);
+
+ auto setBit = [&](uint32_t addr, uint8_t bitNumber, uint8_t bitValue) {
+ ram[addr & ramMask] &= ~(1 << bitNumber);
+ ram[addr & ramMask] |= (bitValue & 0x01) << bitNumber;
+ };
+
+ switch(format) {
+ case TileFormat::PceSpriteBpp4:
+ {
+ shift = 15 - x;
+ if(shift >= 8) {
+ shift -= 8;
+ rowStart++;
+ }
+
+ setBit(rowStart, shift, color & 0x01);
+ setBit(rowStart + 32, shift, (color & 0x02) >> 1);
+ setBit(rowStart + 64, shift, (color & 0x04) >> 2);
+ setBit(rowStart + 96, shift, (color & 0x08) >> 3);
+ break;
+ }
+
+ case TileFormat::Bpp2:
+ setBit(rowStart, shift, color & 0x01);
+ setBit(rowStart + 1, shift, (color & 0x02) >> 1);
+ break;
+
+ case TileFormat::NesBpp2:
+ setBit(rowStart, shift, color & 0x01);
+ setBit(rowStart + 8, shift, (color & 0x02) >> 1);
+ break;
+
+ case TileFormat::Bpp4:
+ setBit(rowStart, shift, color & 0x01);
+ setBit(rowStart + 1, shift, (color & 0x02) >> 1);
+ setBit(rowStart + 16, shift, (color & 0x04) >> 2);
+ setBit(rowStart + 17, shift, (color & 0x08) >> 3);
+ break;
+
+ case TileFormat::Bpp8:
+ case TileFormat::DirectColor:
+ setBit(rowStart, shift, color & 0x01);
+ setBit(rowStart + 1, shift, (color & 0x02) >> 1);
+ setBit(rowStart + 16, shift, (color & 0x04) >> 2);
+ setBit(rowStart + 17, shift, (color & 0x08) >> 3);
+ setBit(rowStart + 32, shift, (color & 0x10) >> 4);
+ setBit(rowStart + 33, shift, (color & 0x20) >> 5);
+ setBit(rowStart + 48, shift, (color & 0x40) >> 6);
+ setBit(rowStart + 49, shift, (color & 0x80) >> 7);
+ break;
+
+ case TileFormat::Mode7:
+ case TileFormat::Mode7DirectColor:
+ ram[(rowStart + x * 2 + 1) & ramMask] = color;
+ break;
+
+ case TileFormat::Mode7ExtBg:
+ ram[(rowStart + x * 2 + 1) & ramMask] = color;
+ break;
+
+ default:
+ throw std::runtime_error("unsupported format");
+ }
+}
+
void PpuTools::UpdateViewers(uint16_t scanline, uint16_t cycle)
{
for(auto updateTiming : _updateTimings) {
diff --git a/Core/Debugger/PpuTools.h b/Core/Debugger/PpuTools.h
index e7f37d06..f2f181ff 100644
--- a/Core/Debugger/PpuTools.h
+++ b/Core/Debugger/PpuTools.h
@@ -57,6 +57,8 @@ struct DebugSpriteInfo
bool UseExtendedVram;
NullableBoolean UseSecondTable;
+ uint32_t TileCount;
+ uint32_t TileAddresses[8 * 8];
uint32_t SpritePreview[64 * 64];
public:
@@ -65,6 +67,7 @@ public:
TileIndex = -1;
TileAddress = -1;
PaletteAddress = -1;
+ Format = {};
SpriteIndex = -1;
X = -1;
Y = -1;
@@ -78,7 +81,9 @@ public:
HorizontalMirror = false;
VerticalMirror = false;
Visible = false;
+ UseExtendedVram = false;
UseSecondTable = NullableBoolean::Undefined;
+ TileCount = 0;
}
};
@@ -180,7 +185,7 @@ protected:
public:
PpuTools(Debugger* debugger, Emulator *emu);
- virtual DebugPaletteInfo GetPaletteInfo() = 0;
+ virtual DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) = 0;
void GetTileView(GetTileViewOptions options, uint8_t *source, uint32_t srcSize, const uint32_t* palette, uint32_t *outBuffer);
@@ -192,6 +197,8 @@ public:
virtual void GetSpritePreview(GetSpritePreviewOptions options, BaseState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, uint32_t* outBuffer) = 0;
virtual void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[]) = 0;
+ void SetTilePixel(AddressInfo tileAddress, TileFormat format, int32_t x, int32_t y, int32_t color);
+
virtual void SetViewerUpdateTiming(uint32_t viewerId, uint16_t scanline, uint16_t cycle);
void RemoveViewer(uint32_t viewerId);
diff --git a/Core/Gameboy/Debugger/GbPpuTools.cpp b/Core/Gameboy/Debugger/GbPpuTools.cpp
index 621c5d78..295adaff 100644
--- a/Core/Gameboy/Debugger/GbPpuTools.cpp
+++ b/Core/Gameboy/Debugger/GbPpuTools.cpp
@@ -107,7 +107,7 @@ FrameInfo GbPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& state
DebugTilemapTileInfo GbPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
{
- DebugTilemapTileInfo result;
+ DebugTilemapTileInfo result = {};
FrameInfo size = GetTilemapSize(options, baseState);
@@ -192,11 +192,18 @@ void GbPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint16_t i, GetSpritePre
uint8_t tileIndex = (uint8_t)sprite.TileIndex;
uint16_t tileBank = useSecondTable ? 0x2000 : 0x0000;
+ uint16_t tileStart;
if(state.LargeSprites) {
- tileIndex &= 0xFE;
+ tileStart = (tileIndex & 0xFE) * 16;
+ sprite.TileAddresses[0] = tileStart;
+ sprite.TileAddresses[1] = tileStart + 16;
+ sprite.TileCount = 2;
+ } else {
+ tileStart = tileIndex * 16;
+ sprite.TileAddresses[0] = tileStart;
+ sprite.TileCount = 1;
}
- uint16_t tileStart = tileIndex * 16;
tileStart |= tileBank;
sprite.TileAddress = tileStart;
@@ -231,7 +238,7 @@ void GbPpuTools::GetSpriteList(GetSpritePreviewOptions options, BaseState& baseS
}
}
-DebugPaletteInfo GbPpuTools::GetPaletteInfo()
+DebugPaletteInfo GbPpuTools::GetPaletteInfo(GetPaletteInfoOptions options)
{
DebugPaletteInfo info = {};
GbPpuState state;
diff --git a/Core/Gameboy/Debugger/GbPpuTools.h b/Core/Gameboy/Debugger/GbPpuTools.h
index 1f4a1373..9fef5a6b 100644
--- a/Core/Gameboy/Debugger/GbPpuTools.h
+++ b/Core/Gameboy/Debugger/GbPpuTools.h
@@ -21,5 +21,5 @@ public:
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[]) override;
- DebugPaletteInfo GetPaletteInfo() override;
+ DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
};
\ No newline at end of file
diff --git a/Core/NES/Debugger/NesPpuTools.cpp b/Core/NES/Debugger/NesPpuTools.cpp
index 1b475be0..df55d7f9 100644
--- a/Core/NES/Debugger/NesPpuTools.cpp
+++ b/Core/NES/Debugger/NesPpuTools.cpp
@@ -227,7 +227,7 @@ FrameInfo NesPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& stat
DebugTilemapTileInfo NesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
{
- DebugTilemapTileInfo result;
+ DebugTilemapTileInfo result = {};
FrameInfo size = GetTilemapSize(options, baseState);
if(x >= size.Width || y >= size.Height) {
@@ -308,8 +308,12 @@ void NesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint32_t i, GetSpritePr
} else {
tileStart = 0x0000 | (sprite.TileIndex * 16);
}
+ sprite.TileAddresses[0] = tileStart;
+ sprite.TileAddresses[1] = tileStart + 16;
+ sprite.TileCount = 2;
} else {
tileStart = (sprite.TileIndex * 16) | sprAddr;
+ sprite.TileCount = 1;
}
sprite.TileAddress = tileStart;
@@ -354,7 +358,7 @@ DebugSpritePreviewInfo NesPpuTools::GetSpritePreviewInfo(GetSpritePreviewOptions
return info;
}
-DebugPaletteInfo NesPpuTools::GetPaletteInfo()
+DebugPaletteInfo NesPpuTools::GetPaletteInfo(GetPaletteInfoOptions options)
{
DebugPaletteInfo info = {};
info.RawFormat = RawPaletteFormat::Indexed;
diff --git a/Core/NES/Debugger/NesPpuTools.h b/Core/NES/Debugger/NesPpuTools.h
index 0c53ba10..0cfd3a61 100644
--- a/Core/NES/Debugger/NesPpuTools.h
+++ b/Core/NES/Debugger/NesPpuTools.h
@@ -25,5 +25,5 @@ public:
void GetSpritePreview(GetSpritePreviewOptions options, BaseState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, uint32_t *outBuffer) override;
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[]) override;
- DebugPaletteInfo GetPaletteInfo() override;
+ DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
};
\ No newline at end of file
diff --git a/Core/PCE/Debugger/PceVdcTools.cpp b/Core/PCE/Debugger/PceVdcTools.cpp
index afec23ea..4fb7a1d0 100644
--- a/Core/PCE/Debugger/PceVdcTools.cpp
+++ b/Core/PCE/Debugger/PceVdcTools.cpp
@@ -31,7 +31,7 @@ FrameInfo PceVdcTools::GetTilemapSize(GetTilemapOptions options, BaseState& base
DebugTilemapTileInfo PceVdcTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
{
- DebugTilemapTileInfo result;
+ DebugTilemapTileInfo result = {};
FrameInfo size = GetTilemapSize(options, baseState);
if(x >= size.Width || y >= size.Height) {
@@ -196,8 +196,15 @@ void PceVdcTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint16_t spriteIndex, G
} else if(height == 64) {
tileIndex &= ~0x06;
}
-
+
sprite.TileAddress = tileIndex * 64 * 2;
+ sprite.TileCount = 0;
+ for(int i = 0, rowCount = height / 16; i < rowCount; i++) {
+ for(int j = 0, columnCount = width / 16; j < columnCount; j++) {
+ sprite.TileAddresses[sprite.TileCount] = sprite.TileAddress + (i * columnCount + j) * 128;
+ sprite.TileCount++;
+ }
+ }
uint8_t yOffset;
int rowOffset;
@@ -267,7 +274,7 @@ DebugSpritePreviewInfo PceVdcTools::GetSpritePreviewInfo(GetSpritePreviewOptions
return info;
}
-DebugPaletteInfo PceVdcTools::GetPaletteInfo()
+DebugPaletteInfo PceVdcTools::GetPaletteInfo(GetPaletteInfoOptions options)
{
DebugPaletteInfo info = {};
info.RawFormat = RawPaletteFormat::Rgb333;
diff --git a/Core/PCE/Debugger/PceVdcTools.h b/Core/PCE/Debugger/PceVdcTools.h
index fd43a310..5a86474d 100644
--- a/Core/PCE/Debugger/PceVdcTools.h
+++ b/Core/PCE/Debugger/PceVdcTools.h
@@ -27,5 +27,5 @@ public:
void GetSpritePreview(GetSpritePreviewOptions options, BaseState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, uint32_t *outBuffer) override;
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[]) override;
- DebugPaletteInfo GetPaletteInfo() override;
+ DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
};
\ No newline at end of file
diff --git a/Core/SNES/Debugger/SnesPpuTools.cpp b/Core/SNES/Debugger/SnesPpuTools.cpp
index 33b09965..8bed9932 100644
--- a/Core/SNES/Debugger/SnesPpuTools.cpp
+++ b/Core/SNES/Debugger/SnesPpuTools.cpp
@@ -253,6 +253,17 @@ void SnesPpuTools::GetSpriteInfo(DebugSpriteInfo& sprite, uint16_t spriteIndex,
int tileRow = (sprite.TileIndex & 0xF0) >> 4;
int tileColumn = sprite.TileIndex & 0x0F;
+
+ sprite.TileCount = 0;
+ for(int i = 0, rowCount = height / 8; i < rowCount; i++) {
+ int row = (i + tileRow) & 0x0F;
+ for(int j = 0, columnCount = width / 8; j < columnCount; j++) {
+ int col = (j + tileColumn) & 0x0F;
+ sprite.TileAddresses[sprite.TileCount] = ((state.OamBaseAddress + (row * 16 + col) * 16 + (useSecondTable ? state.OamAddressOffset : 0)) & 0x7FFF) << 1;
+ sprite.TileCount++;
+ }
+ }
+
uint8_t yOffset;
int rowOffset;
@@ -341,7 +352,7 @@ FrameInfo SnesPpuTools::GetTilemapSize(GetTilemapOptions options, BaseState& bas
DebugTilemapTileInfo SnesPpuTools::GetTilemapTileInfo(uint32_t x, uint32_t y, uint8_t* vram, GetTilemapOptions options, BaseState& baseState)
{
- DebugTilemapTileInfo result;
+ DebugTilemapTileInfo result = {};
FrameInfo size = GetTilemapSize(options, baseState);
if(x >= size.Width || y >= size.Height) {
@@ -417,7 +428,7 @@ DebugSpritePreviewInfo SnesPpuTools::GetSpritePreviewInfo(GetSpritePreviewOption
return info;
}
-DebugPaletteInfo SnesPpuTools::GetPaletteInfo()
+DebugPaletteInfo SnesPpuTools::GetPaletteInfo(GetPaletteInfoOptions options)
{
DebugPaletteInfo info = {};
info.RawFormat = RawPaletteFormat::Rgb555;
@@ -426,11 +437,23 @@ DebugPaletteInfo SnesPpuTools::GetPaletteInfo()
info.SpriteColorCount = 16 * 8;
info.ColorCount = info.BgColorCount + info.SpriteColorCount;
- uint8_t* cgram= _debugger->GetMemoryDumper()->GetMemoryBuffer(MemoryType::SnesCgRam);
- for(int i = 0; i < 256; i++) {
- info.RawPalette[i] = cgram[i*2] | (cgram[i*2+1] << 8);
- info.RgbPalette[i] = SnesDefaultVideoFilter::ToArgb(info.RawPalette[i]);
- }
+ switch(options.Format) {
+ case TileFormat::DirectColor:
+ case TileFormat::Mode7DirectColor:
+ for(int i = 0; i < 256; i++) {
+ info.RawPalette[i] = ((i & 0x07) << 2) | ((i & 0x38) << 4) | ((i & 0xC0) << 7);
+ info.RgbPalette[i] = SnesDefaultVideoFilter::ToArgb(info.RawPalette[i]);
+ }
+ break;
+ default:
+ uint8_t mask = options.Format == TileFormat::Mode7ExtBg ? 0x7F : 0xFF;
+ uint8_t* cgram = _debugger->GetMemoryDumper()->GetMemoryBuffer(MemoryType::SnesCgRam);
+ for(int i = 0; i < 256; i++) {
+ info.RawPalette[i] = cgram[(i & mask) * 2] | (cgram[(i & mask) * 2 + 1] << 8);
+ info.RgbPalette[i] = SnesDefaultVideoFilter::ToArgb(info.RawPalette[i]);
+ }
+ break;
+ }
return info;
}
diff --git a/Core/SNES/Debugger/SnesPpuTools.h b/Core/SNES/Debugger/SnesPpuTools.h
index 09333927..1e72b670 100644
--- a/Core/SNES/Debugger/SnesPpuTools.h
+++ b/Core/SNES/Debugger/SnesPpuTools.h
@@ -22,5 +22,5 @@ public:
void GetSpriteList(GetSpritePreviewOptions options, BaseState& baseState, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo outBuffer[]) override;
DebugSpritePreviewInfo GetSpritePreviewInfo(GetSpritePreviewOptions options, BaseState& state) override;
- DebugPaletteInfo GetPaletteInfo() override;
+ DebugPaletteInfo GetPaletteInfo(GetPaletteInfoOptions options) override;
};
\ No newline at end of file
diff --git a/InteropDLL/DebugApiWrapper.cpp b/InteropDLL/DebugApiWrapper.cpp
index f30385de..b1fe9dee 100644
--- a/InteropDLL/DebugApiWrapper.cpp
+++ b/InteropDLL/DebugApiWrapper.cpp
@@ -152,7 +152,8 @@ extern "C"
DllExport void __stdcall GetSpritePreview(CpuType cpuType, GetSpritePreviewOptions options, BaseState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, uint32_t* buffer) { WithToolVoid(GetPpuTools(cpuType), GetSpritePreview(options, state, vram, oamRam, palette, buffer)); }
DllExport void __stdcall GetSpriteList(CpuType cpuType, GetSpritePreviewOptions options, BaseState& state, uint8_t* vram, uint8_t* oamRam, uint32_t* palette, DebugSpriteInfo sprites[]) { WithToolVoid(GetPpuTools(cpuType), GetSpriteList(options, state, vram, oamRam, palette, sprites)); }
- DllExport DebugPaletteInfo __stdcall GetPaletteInfo(CpuType cpuType) { return WithTool(DebugPaletteInfo, GetPpuTools(cpuType), GetPaletteInfo()); }
+ DllExport DebugPaletteInfo __stdcall GetPaletteInfo(CpuType cpuType, GetPaletteInfoOptions options) { return WithTool(DebugPaletteInfo, GetPpuTools(cpuType), GetPaletteInfo(options)); }
+ DllExport void __stdcall SetTilePixel(AddressInfo tileAddress, TileFormat format, int32_t x, int32_t y, int32_t color) { WithToolVoid(GetPpuTools(DebugUtilities::ToCpuType(tileAddress.Type)), SetTilePixel(tileAddress, format, x, y, color)); }
DllExport void __stdcall SetViewerUpdateTiming(uint32_t viewerId, uint16_t scanline, uint16_t cycle, CpuType cpuType) { WithToolVoid(GetPpuTools(cpuType), SetViewerUpdateTiming(viewerId, scanline, cycle)); }
diff --git a/NewUI/App.axaml b/NewUI/App.axaml
index a1366e18..b08c71d1 100644
--- a/NewUI/App.axaml
+++ b/NewUI/App.axaml
@@ -9,6 +9,14 @@
+
+
+
+
+
+
+
+
diff --git a/NewUI/Config/Debugger/DebugConfig.cs b/NewUI/Config/Debugger/DebugConfig.cs
index b3468e76..5618c0e4 100644
--- a/NewUI/Config/Debugger/DebugConfig.cs
+++ b/NewUI/Config/Debugger/DebugConfig.cs
@@ -20,6 +20,7 @@ namespace Mesen.Config
public TilemapViewerConfig TilemapViewer { get; set; } = new TilemapViewerConfig();
public TileViewerConfig TileViewer { get; set; } = new TileViewerConfig();
public PaletteViewerConfig PaletteViewer { get; set; } = new PaletteViewerConfig();
+ public TileEditorConfig TileEditor { get; set; } = new TileEditorConfig();
public RegisterViewerConfig RegisterViewer { get; set; } = new RegisterViewerConfig();
public SpriteViewerConfig SpriteViewer { get; set; } = new SpriteViewerConfig();
public IntegrationConfig Integration { get; set; } = new IntegrationConfig();
diff --git a/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs b/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs
index baf758d4..f110f8bb 100644
--- a/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs
+++ b/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs
@@ -202,14 +202,17 @@ namespace Mesen.Config
Add(new() { Shortcut = DebuggerShortcut.ResetWorkspace, KeyBinding = new() });
Add(new() { Shortcut = DebuggerShortcut.TilemapViewer_ViewInMemoryViewer, KeyBinding = new(Key.F1) });
- Add(new() { Shortcut = DebuggerShortcut.TilemapViewer_ViewInTileViewer, KeyBinding = new(Key.F2) });
- Add(new() { Shortcut = DebuggerShortcut.TilemapViewer_EditTilemapBreakpoint, KeyBinding = new(Key.F3) });
- Add(new() { Shortcut = DebuggerShortcut.TilemapViewer_EditAttributeBreakpoint, KeyBinding = new(Key.F4) });
+ Add(new() { Shortcut = DebuggerShortcut.TilemapViewer_EditTile, KeyBinding = new(Key.F2) });
+ Add(new() { Shortcut = DebuggerShortcut.TilemapViewer_ViewInTileViewer, KeyBinding = new(Key.F3) });
+ Add(new() { Shortcut = DebuggerShortcut.TilemapViewer_EditTilemapBreakpoint, KeyBinding = new(Key.F4) });
+ Add(new() { Shortcut = DebuggerShortcut.TilemapViewer_EditAttributeBreakpoint, KeyBinding = new() });
Add(new() { Shortcut = DebuggerShortcut.SpriteViewer_ViewInMemoryViewer, KeyBinding = new(Key.F1) });
- Add(new() { Shortcut = DebuggerShortcut.SpriteViewer_ViewInTileViewer, KeyBinding = new(Key.F2) });
-
+ Add(new() { Shortcut = DebuggerShortcut.SpriteViewer_ViewInTileViewer, KeyBinding = new(Key.F3) });
+ Add(new() { Shortcut = DebuggerShortcut.SpriteViewer_EditSprite, KeyBinding = new(Key.F2) });
+
Add(new() { Shortcut = DebuggerShortcut.TileViewer_ViewInMemoryViewer, KeyBinding = new(Key.F1) });
+ Add(new() { Shortcut = DebuggerShortcut.TileViewer_EditTile, KeyBinding = new(Key.F2) });
//Memory Tools
//Add(new() { Shortcut = eDebuggerShortcut.MemoryViewer_Freeze, KeyBinding = new(KeyModifiers.Control, Key.Q) });
@@ -358,9 +361,12 @@ namespace Mesen.Config
TilemapViewer_EditAttributeBreakpoint,
TilemapViewer_ViewInTileViewer,
TilemapViewer_ViewInMemoryViewer,
+ TilemapViewer_EditTile,
SpriteViewer_ViewInMemoryViewer,
SpriteViewer_ViewInTileViewer,
+ SpriteViewer_EditSprite,
TileViewer_ViewInMemoryViewer,
+ TileViewer_EditTile,
}
public class DebuggerShortcutInfo : ViewModelBase
diff --git a/NewUI/Config/Debugger/TileEditorConfig.cs b/NewUI/Config/Debugger/TileEditorConfig.cs
new file mode 100644
index 00000000..98994437
--- /dev/null
+++ b/NewUI/Config/Debugger/TileEditorConfig.cs
@@ -0,0 +1,11 @@
+using Mesen.Interop;
+using ReactiveUI.Fody.Helpers;
+
+namespace Mesen.Config
+{
+ public class TileEditorConfig : BaseWindowConfig
+ {
+ [Reactive] public int ImageScale { get; set; } = 8;
+ [Reactive] public TileBackground Background { get; set; } = TileBackground.Transparent;
+ }
+}
diff --git a/NewUI/Config/Debugger/TileViewerConfig.cs b/NewUI/Config/Debugger/TileViewerConfig.cs
index bef09d11..7da83fcc 100644
--- a/NewUI/Config/Debugger/TileViewerConfig.cs
+++ b/NewUI/Config/Debugger/TileViewerConfig.cs
@@ -18,7 +18,6 @@ namespace Mesen.Config
[Reactive] public int RowCount { get; set; } = 64;
[Reactive] public int ColumnCount { get; set; } = 32;
[Reactive] public int StartAddress { get; set; } = 0;
- [Reactive] public int SelectedPalette { get; set; } = 0;
[Reactive] public bool UseGrayscalePalette { get; set; } = false;
[Reactive] public RefreshTimingConfig RefreshTiming { get; set; } = new();
diff --git a/NewUI/Debugger/Controls/DynamicTooltip.axaml b/NewUI/Debugger/Controls/DynamicTooltip.axaml
index 16742b0c..c56c6206 100644
--- a/NewUI/Debugger/Controls/DynamicTooltip.axaml
+++ b/NewUI/Debugger/Controls/DynamicTooltip.axaml
@@ -30,7 +30,7 @@
MinWidth="{Binding FirstColumnWidth, ElementName=root}"
IsVisible="{Binding Name.Length}"
Margin="0 3 10 2"
- />
+ />
diff --git a/NewUI/Debugger/Controls/PaletteSelector.cs b/NewUI/Debugger/Controls/PaletteSelector.cs
index 1144b74e..0be8f832 100644
--- a/NewUI/Debugger/Controls/PaletteSelector.cs
+++ b/NewUI/Debugger/Controls/PaletteSelector.cs
@@ -324,6 +324,9 @@ namespace Mesen.Debugger.Controls
RaiseEvent(new ColorClickEventArgs() { ColorIndex = paletteIndex, Color = Color.FromUInt32(PaletteColors[paletteIndex]) });
+ if(SelectionMode == PaletteSelectionMode.None) {
+ return;
+ }
if(SelectionMode == PaletteSelectionMode.SingleColor) {
paletteIndex /= 1;
} else if(SelectionMode == PaletteSelectionMode.FourColors) {
diff --git a/NewUI/Debugger/Controls/PictureViewer.cs b/NewUI/Debugger/Controls/PictureViewer.cs
index c4af87a7..55c8a438 100644
--- a/NewUI/Debugger/Controls/PictureViewer.cs
+++ b/NewUI/Debugger/Controls/PictureViewer.cs
@@ -214,12 +214,12 @@ namespace Mesen.Debugger.Controls
public void ZoomIn()
{
- Zoom = Math.Min(20, Math.Max(1, Zoom + 1));
+ Zoom = Math.Min(40, Math.Max(1, Zoom + 1));
}
public void ZoomOut()
{
- Zoom = Math.Min(20, Math.Max(1, Zoom - 1));
+ Zoom = Math.Min(40, Math.Max(1, Zoom - 1));
}
public async void ExportToPng()
@@ -247,12 +247,24 @@ namespace Mesen.Debugger.Controls
protected override void OnPointerMoved(PointerEventArgs e)
{
base.OnPointerMoved(e);
+ PixelPoint? p = GetGridPointFromMousePoint(e.GetCurrentPoint(this).Position);
+ if(p == null) {
+ e.Handled = true;
+ MouseOverRect = null;
+ return;
+ }
+
if(ShowMousePosition) {
- PixelPoint? p = GetGridPointFromMousePoint(e.GetCurrentPoint(this).Position);
- if(p != null) {
- MouseOverRect = GetTileRect(p.Value);
- } else {
- MouseOverRect = null;
+ MouseOverRect = GetTileRect(p.Value);
+ }
+
+ PointerPointProperties props = e.GetCurrentPoint(this).Properties;
+ if(props.IsLeftButtonPressed || props.IsRightButtonPressed) {
+ PositionClickedEventArgs args = new(p.Value, props, PositionClickedEvent);
+ RaiseEvent(args);
+
+ if(!args.Handled && AllowSelection) {
+ SelectionRect = GetTileRect(p.Value);
}
}
}
@@ -271,7 +283,7 @@ namespace Mesen.Debugger.Controls
return;
}
- PositionClickedEventArgs args = new() { RoutedEvent = PositionClickedEvent, Position = p.Value };
+ PositionClickedEventArgs args = new(p.Value, e.GetCurrentPoint(this).Properties, PositionClickedEvent);
RaiseEvent(args);
if(!args.Handled && AllowSelection) {
@@ -441,6 +453,14 @@ namespace Mesen.Debugger.Controls
public class PositionClickedEventArgs : RoutedEventArgs
{
public PixelPoint Position;
+ public PointerPointProperties Properties;
+
+ public PositionClickedEventArgs(PixelPoint position, PointerPointProperties properties, RoutedEvent evt)
+ {
+ Position = position;
+ Properties = properties;
+ RoutedEvent = evt;
+ }
}
public class GridRowColumn
diff --git a/NewUI/Debugger/Controls/ScrollPictureViewer.axaml b/NewUI/Debugger/Controls/ScrollPictureViewer.axaml
index 3def6677..bed8116b 100644
--- a/NewUI/Debugger/Controls/ScrollPictureViewer.axaml
+++ b/NewUI/Debugger/Controls/ScrollPictureViewer.axaml
@@ -9,7 +9,7 @@
x:Name="root"
x:Class="Mesen.Debugger.Controls.ScrollPictureViewer"
>
-
+
-
+
+
\ No newline at end of file
diff --git a/NewUI/Debugger/Controls/ScrollPictureViewer.axaml.cs b/NewUI/Debugger/Controls/ScrollPictureViewer.axaml.cs
index 6c4cdfab..cb375abf 100644
--- a/NewUI/Debugger/Controls/ScrollPictureViewer.axaml.cs
+++ b/NewUI/Debugger/Controls/ScrollPictureViewer.axaml.cs
@@ -25,6 +25,7 @@ namespace Mesen.Debugger.Controls
public static readonly StyledProperty AltGridSizeYProperty = AvaloniaProperty.Register(nameof(AltGridSizeY), 8);
public static readonly StyledProperty ShowAltGridProperty = AvaloniaProperty.Register(nameof(ShowAltGrid), false);
public static readonly StyledProperty AllowSelectionProperty = AvaloniaProperty.Register(nameof(AllowSelection), true);
+ public static readonly StyledProperty AllowClickDragProperty = AvaloniaProperty.Register(nameof(AllowClickDrag), true);
public static readonly StyledProperty GridHighlightProperty = AvaloniaProperty.Register(nameof(GridHighlight), null);
@@ -102,6 +103,12 @@ namespace Mesen.Debugger.Controls
set { SetValue(ShowAltGridProperty, value); }
}
+ public bool AllowClickDrag
+ {
+ get { return GetValue(AllowClickDragProperty); }
+ set { SetValue(AllowClickDragProperty, value); }
+ }
+
public Rect SelectionRect
{
get { return GetValue(SelectionRectProperty); }
@@ -141,6 +148,7 @@ namespace Mesen.Debugger.Controls
public ScrollPictureViewer()
{
InitializeComponent();
+ Background = new SolidColorBrush(0xFF202020);
}
private void InitializeComponent()
@@ -157,7 +165,7 @@ namespace Mesen.Debugger.Controls
private void Viewer_PointerMoved(object? sender, PointerEventArgs e)
{
- if(e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) {
+ if(AllowClickDrag && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) {
Vector offset = ScrollOffset;
offset -= e.GetPosition(this) - _lastPosition;
if(offset.X < 0) {
diff --git a/NewUI/Debugger/Utilities/ContextMenuAction.cs b/NewUI/Debugger/Utilities/ContextMenuAction.cs
index d0c193b1..d094484c 100644
--- a/NewUI/Debugger/Utilities/ContextMenuAction.cs
+++ b/NewUI/Debugger/Utilities/ContextMenuAction.cs
@@ -665,5 +665,12 @@ namespace Mesen.Debugger.Utilities
FindNext,
[IconFile("PreviousArrow")]
FindPrev,
+
+ [IconFile("Edit")]
+ EditTile,
+ [IconFile("Edit")]
+ EditTiles,
+ [IconFile("Edit")]
+ EditSprite,
}
}
diff --git a/NewUI/Debugger/Utilities/DebugWindowManager.cs b/NewUI/Debugger/Utilities/DebugWindowManager.cs
index b30c5bd6..7a29a9ca 100644
--- a/NewUI/Debugger/Utilities/DebugWindowManager.cs
+++ b/NewUI/Debugger/Utilities/DebugWindowManager.cs
@@ -16,7 +16,7 @@ namespace Mesen.Debugger.Utilities
private static object _windowNotifLock = new();
private static bool _loadingGame = false;
- public static T OpenDebugWindow(Func createWindow) where T : Window
+ public static T CreateDebugWindow(Func createWindow) where T : Window
{
if(Interlocked.Increment(ref _debugWindowCounter) == 1) {
//Opened a debug window and nothing else was opened, load the saved workspace
@@ -35,6 +35,12 @@ namespace Mesen.Debugger.Utilities
}
};
_openedWindows.TryAdd(wnd, true);
+ return wnd;
+ }
+
+ public static T OpenDebugWindow(Func createWindow) where T : Window
+ {
+ T wnd = CreateDebugWindow(createWindow);
wnd.Show();
return wnd;
}
diff --git a/NewUI/Debugger/ViewModels/DebuggerConfigWindowViewModel.cs b/NewUI/Debugger/ViewModels/DebuggerConfigWindowViewModel.cs
index 18c832a6..2ee9b6b8 100644
--- a/NewUI/Debugger/ViewModels/DebuggerConfigWindowViewModel.cs
+++ b/NewUI/Debugger/ViewModels/DebuggerConfigWindowViewModel.cs
@@ -109,9 +109,12 @@ namespace Mesen.Debugger.ViewModels
DebuggerShortcut.TilemapViewer_ViewInTileViewer,
DebuggerShortcut.TilemapViewer_EditTilemapBreakpoint,
DebuggerShortcut.TilemapViewer_EditAttributeBreakpoint,
+ DebuggerShortcut.TilemapViewer_EditTile,
DebuggerShortcut.TileViewer_ViewInMemoryViewer,
+ DebuggerShortcut.TileViewer_EditTile,
DebuggerShortcut.SpriteViewer_ViewInMemoryViewer,
- DebuggerShortcut.SpriteViewer_ViewInTileViewer
+ DebuggerShortcut.SpriteViewer_ViewInTileViewer,
+ DebuggerShortcut.SpriteViewer_EditSprite
});
DebuggerShortcuts = CreateShortcutList(new DebuggerShortcut[] {
diff --git a/NewUI/Debugger/ViewModels/SpritePreviewModel.cs b/NewUI/Debugger/ViewModels/SpritePreviewModel.cs
index e3e4d873..26aec5f0 100644
--- a/NewUI/Debugger/ViewModels/SpritePreviewModel.cs
+++ b/NewUI/Debugger/ViewModels/SpritePreviewModel.cs
@@ -32,6 +32,10 @@ namespace Mesen.Debugger.ViewModels
[Reactive] public bool HorizontalMirror { get; set; }
[Reactive] public bool VerticalMirror { get; set; }
[Reactive] public bool UseExtendedVram { get; set; }
+
+ public UInt32 TileCount { get; set; }
+ public UInt32[] TileAddresses { get; set; } = Array.Empty();
+
[Reactive] public NullableBoolean UseSecondTable { get; set; }
[Reactive] public DynamicBitmap? SpritePreview { get; set; }
@@ -60,6 +64,16 @@ namespace Mesen.Debugger.ViewModels
UseSecondTable = sprite.UseSecondTable;
UseExtendedVram = sprite.UseExtendedVram;
+ TileCount = sprite.TileCount;
+ fixed(UInt32* p = sprite.TileAddresses) {
+ if(TileAddresses == null || TileAddresses.Length < TileCount) {
+ TileAddresses = new UInt32[TileCount];
+ }
+ for(int i = 0; i < sprite.TileCount; i++) {
+ TileAddresses[i] = p[i];
+ }
+ }
+
fixed(UInt32* p = sprite.SpritePreview) {
if(SpritePreview == null || SpritePreview.PixelSize.Width != sprite.Width || SpritePreview.PixelSize.Height != sprite.Height) {
SpritePreview = new DynamicBitmap(new PixelSize(Width, Height), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Premul);
diff --git a/NewUI/Debugger/ViewModels/SpriteViewerViewModel.cs b/NewUI/Debugger/ViewModels/SpriteViewerViewModel.cs
index c6f2edb2..1e12b349 100644
--- a/NewUI/Debugger/ViewModels/SpriteViewerViewModel.cs
+++ b/NewUI/Debugger/ViewModels/SpriteViewerViewModel.cs
@@ -19,6 +19,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
namespace Mesen.Debugger.ViewModels
{
@@ -110,7 +111,12 @@ namespace Mesen.Debugger.ViewModels
},
});
+ if(Design.IsDesignMode || wnd == null) {
+ return;
+ }
+
DebugShortcutManager.CreateContextMenu(picViewer, new List