diff --git a/src/BizHawk.Client.Common/tools/Watch/Watch.cs b/src/BizHawk.Client.Common/tools/Watch/Watch.cs index 18de8dd363..298f8eeed3 100644 --- a/src/BizHawk.Client.Common/tools/Watch/Watch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/Watch.cs @@ -638,5 +638,8 @@ namespace BizHawk.Client.Common _ => WatchDisplayType.Separator }; } + + public bool IsSplittable => Size is WatchSize.Word or WatchSize.DWord + && Type is WatchDisplayType.Hex or WatchDisplayType.Binary; } } diff --git a/src/BizHawk.Client.Common/tools/Watch/WatchSize.cs b/src/BizHawk.Client.Common/tools/Watch/WatchSize.cs index 57e4965396..0cdbf99b88 100644 --- a/src/BizHawk.Client.Common/tools/Watch/WatchSize.cs +++ b/src/BizHawk.Client.Common/tools/Watch/WatchSize.cs @@ -3,7 +3,7 @@ /// /// This enum specify the size of a /// - public enum WatchSize + public enum WatchSize : int { /// /// One byte (8 bits) diff --git a/src/BizHawk.Client.EmuHawk/Properties/Resources.cs b/src/BizHawk.Client.EmuHawk/Properties/Resources.cs index d762d2a511..a2a7f662f7 100644 --- a/src/BizHawk.Client.EmuHawk/Properties/Resources.cs +++ b/src/BizHawk.Client.EmuHawk/Properties/Resources.cs @@ -167,6 +167,7 @@ namespace BizHawk.Client.EmuHawk.Properties internal static readonly Bitmap Shark = ReadEmbeddedBitmap("Shark"); internal static readonly Icon SmsIcon = ReadEmbeddedIcon("sms-icon"); internal static readonly Bitmap Snes9X = ReadEmbeddedBitmap("snes9x"); + internal static readonly Bitmap Split = ReadEmbeddedBitmap("Split"); internal static readonly Bitmap Square = ReadEmbeddedBitmap("Square"); internal static readonly Bitmap SSE = ReadEmbeddedBitmap("SSE"); internal static readonly Bitmap SSW = ReadEmbeddedBitmap("SSW"); diff --git a/src/BizHawk.Client.EmuHawk/images/Split.png b/src/BizHawk.Client.EmuHawk/images/Split.png new file mode 100644 index 0000000000..14959a67a1 Binary files /dev/null and b/src/BizHawk.Client.EmuHawk/images/Split.png differ diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.Designer.cs index 4fc696ae1c..228c1af6fa 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.Designer.cs @@ -37,6 +37,7 @@ namespace BizHawk.Client.EmuHawk this.EditContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.RemoveContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DuplicateContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SplitContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.PokeContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.FreezeContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.UnfreezeAllContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -63,6 +64,7 @@ namespace BizHawk.Client.EmuHawk this.cutToolStripButton = new System.Windows.Forms.ToolStripButton(); this.clearChangeCountsToolStripButton = new System.Windows.Forms.ToolStripButton(); this.duplicateWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.SplitWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); this.PokeAddressToolBarItem = new System.Windows.Forms.ToolStripButton(); this.FreezeAddressToolBarItem = new System.Windows.Forms.ToolStripButton(); this.seperatorToolStripButton = new System.Windows.Forms.ToolStripButton(); @@ -87,6 +89,7 @@ namespace BizHawk.Client.EmuHawk this.EditWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.RemoveWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DuplicateWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SplitWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.PokeAddressMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.FreezeAddressMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.InsertSeparatorMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -123,6 +126,7 @@ namespace BizHawk.Client.EmuHawk this.EditContextMenuItem, this.RemoveContextMenuItem, this.DuplicateContextMenuItem, + this.SplitContextMenuItem, this.PokeContextMenuItem, this.FreezeContextMenuItem, this.UnfreezeAllContextMenuItem, @@ -163,6 +167,12 @@ namespace BizHawk.Client.EmuHawk this.DuplicateContextMenuItem.Text = "&Duplicate"; this.DuplicateContextMenuItem.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); // + // SplitContextMenuItem + // + this.SplitContextMenuItem.ShortcutKeyDisplayString = "Ctrl+L"; + this.SplitContextMenuItem.Text = "Sp&lit"; + this.SplitContextMenuItem.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); + // // PokeContextMenuItem // this.PokeContextMenuItem.ShortcutKeyDisplayString = "Ctrl+P"; @@ -264,6 +274,7 @@ namespace BizHawk.Client.EmuHawk this.cutToolStripButton, this.clearChangeCountsToolStripButton, this.duplicateWatchToolStripButton, + this.SplitWatchToolStripButton, this.PokeAddressToolBarItem, this.FreezeAddressToolBarItem, this.seperatorToolStripButton, @@ -351,6 +362,15 @@ namespace BizHawk.Client.EmuHawk this.duplicateWatchToolStripButton.Text = "Duplicate Watch"; this.duplicateWatchToolStripButton.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); // + // SplitWatchToolStripButton + // + this.SplitWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.SplitWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.SplitWatchToolStripButton.Name = "SplitWatchToolStripButton"; + this.SplitWatchToolStripButton.Size = new System.Drawing.Size(23, 22); + this.SplitWatchToolStripButton.Text = "Split Watch"; + this.SplitWatchToolStripButton.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); + // // PokeAddressToolBarItem // this.PokeAddressToolBarItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; @@ -468,6 +488,7 @@ namespace BizHawk.Client.EmuHawk this.EditWatchMenuItem, this.RemoveWatchMenuItem, this.DuplicateWatchMenuItem, + this.SplitWatchMenuItem, this.PokeAddressMenuItem, this.FreezeAddressMenuItem, this.InsertSeparatorMenuItem, @@ -512,6 +533,12 @@ namespace BizHawk.Client.EmuHawk this.DuplicateWatchMenuItem.Text = "&Duplicate Watch"; this.DuplicateWatchMenuItem.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); // + // SplitWatchMenuItem + // + this.SplitWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.L))); + this.SplitWatchMenuItem.Text = "Sp&lit Watch"; + this.SplitWatchMenuItem.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); + // // PokeAddressMenuItem // this.PokeAddressMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); @@ -678,6 +705,7 @@ namespace BizHawk.Client.EmuHawk private BizHawk.WinForms.Controls.ToolStripMenuItemEx EditWatchMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx RemoveWatchMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx DuplicateWatchMenuItem; + private BizHawk.WinForms.Controls.ToolStripMenuItemEx SplitWatchMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx PokeAddressMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx FreezeAddressMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx InsertSeparatorMenuItem; @@ -701,6 +729,7 @@ namespace BizHawk.Client.EmuHawk private System.Windows.Forms.ToolStripButton cutToolStripButton; private System.Windows.Forms.ToolStripButton clearChangeCountsToolStripButton; private System.Windows.Forms.ToolStripButton duplicateWatchToolStripButton; + private System.Windows.Forms.ToolStripButton SplitWatchToolStripButton; private System.Windows.Forms.ToolStripButton PokeAddressToolBarItem; private System.Windows.Forms.ToolStripButton FreezeAddressToolBarItem; private System.Windows.Forms.ToolStripButton seperatorToolStripButton; @@ -714,6 +743,7 @@ namespace BizHawk.Client.EmuHawk private BizHawk.WinForms.Controls.ToolStripMenuItemEx EditContextMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx RemoveContextMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx DuplicateContextMenuItem; + private BizHawk.WinForms.Controls.ToolStripMenuItemEx SplitContextMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx PokeContextMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx FreezeContextMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx UnfreezeAllContextMenuItem; diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs index b8483ea5cd..bb59bbd46e 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs @@ -40,6 +40,7 @@ namespace BizHawk.Client.EmuHawk EditContextMenuItem.Image = Resources.Cut; RemoveContextMenuItem.Image = Resources.Delete; DuplicateContextMenuItem.Image = Resources.Duplicate; + SplitContextMenuItem.Image = Resources.Split; PokeContextMenuItem.Image = Resources.Poke; FreezeContextMenuItem.Image = Resources.Freeze; UnfreezeAllContextMenuItem.Image = Resources.Unfreeze; @@ -57,6 +58,7 @@ namespace BizHawk.Client.EmuHawk cutToolStripButton.Image = Resources.Delete; clearChangeCountsToolStripButton.Image = Resources.Placeholder; duplicateWatchToolStripButton.Image = Resources.Duplicate; + SplitWatchToolStripButton.Image = Resources.Split; PokeAddressToolBarItem.Image = Resources.Poke; FreezeAddressToolBarItem.Image = Resources.Freeze; seperatorToolStripButton.Image = Resources.InsertSeparator; @@ -70,6 +72,7 @@ namespace BizHawk.Client.EmuHawk EditWatchMenuItem.Image = Resources.Cut; RemoveWatchMenuItem.Image = Resources.Delete; DuplicateWatchMenuItem.Image = Resources.Duplicate; + SplitWatchMenuItem.Image = Resources.Split; PokeAddressMenuItem.Image = Resources.Poke; FreezeAddressMenuItem.Image = Resources.Freeze; InsertSeparatorMenuItem.Image = Resources.InsertSeparator; @@ -695,6 +698,7 @@ namespace BizHawk.Client.EmuHawk { EditWatchMenuItem.Enabled = DuplicateWatchMenuItem.Enabled = + SplitWatchMenuItem.Enabled = RemoveWatchMenuItem.Enabled = MoveUpMenuItem.Enabled = MoveDownMenuItem.Enabled = @@ -702,6 +706,8 @@ namespace BizHawk.Client.EmuHawk MoveBottomMenuItem.Enabled = SelectedIndices.Any(); + SplitWatchMenuItem.Enabled = MaySplitAllSelected; + PokeAddressMenuItem.Enabled = FreezeAddressMenuItem.Enabled = SelectedIndices.Any() && @@ -770,6 +776,38 @@ namespace BizHawk.Client.EmuHawk EditWatch(duplicate: true); } + private static (Watch A, Watch B) SplitWatch(Watch ab) + { + var newSize = ab.Size switch + { + WatchSize.DWord => WatchSize.Word, + WatchSize.Word => WatchSize.Byte, + _ => throw new Exception() + }; + var a = Watch.GenerateWatch(ab.Domain, ab.Address, newSize, ab.Type, ab.BigEndian, ab.Notes); + var b = Watch.GenerateWatch(ab.Domain, ab.Address + (int) newSize, newSize, ab.Type, ab.BigEndian, ab.Notes); + return ab.BigEndian ? (a, b) : (b, a); + } + + private void SplitWatchAt(int index) + { + var ab = _watches[index]; + if (!ab.IsSplittable) return; + var (a, b) = SplitWatch(ab); + _watches[index] = a; + _watches.Insert(index + 1, b); + } + + private void SplitWatchMenuItem_Click(object sender, EventArgs e) + { + var indices = SelectedIndices.ToList(); + for (var indexIndex = indices.Count - 1; indexIndex >= 0; indexIndex--) SplitWatchAt(indices[indexIndex]); + Changes(); + UpdateWatchCount(); + WatchListView.RowCount = _watches.Count; + GeneralUpdate(); + } + private void PokeAddressMenuItem_Click(object sender, EventArgs e) { if (SelectedWatches.Any()) @@ -1034,6 +1072,8 @@ namespace BizHawk.Client.EmuHawk } } + private bool MaySplitAllSelected => SelectedIndices.Any() && SelectedWatches.All(static w => w.IsSplittable); + private void ListViewContextMenu_Opening(object sender, CancelEventArgs e) { var indexes = WatchListView.SelectedRows.ToList(); @@ -1041,6 +1081,7 @@ namespace BizHawk.Client.EmuHawk EditContextMenuItem.Visible = RemoveContextMenuItem.Visible = DuplicateContextMenuItem.Visible = + SplitContextMenuItem.Visible = PokeContextMenuItem.Visible = FreezeContextMenuItem.Visible = Separator4.Visible = @@ -1062,6 +1103,8 @@ namespace BizHawk.Client.EmuHawk Debuggable.MemoryCallbacksAvailable() && SelectedWatches.All(w => w.Domain.Name == (MemoryDomains != null ? MemoryDomains.SystemBus.Name : "")); + SplitContextMenuItem.Enabled = MaySplitAllSelected; + PokeContextMenuItem.Enabled = FreezeContextMenuItem.Visible = SelectedIndices.Any()