diff --git a/GUI.NET/Config/DebugInfo.cs b/GUI.NET/Config/DebugInfo.cs index e0e6e353..7bcf4d2a 100644 --- a/GUI.NET/Config/DebugInfo.cs +++ b/GUI.NET/Config/DebugInfo.cs @@ -325,6 +325,17 @@ namespace Mesen.GUI.Config public float AssemblerFontSize = BaseControl.DefaultFontSize; public int AssemblerZoom = 100; + public Point? TextHookerWindowLocation = null; + public bool TextHookerAutoRefresh = true; + public bool TextHookerRefreshOnBreak = true; + public int TextHookerDisplayCycle = 0; + public int TextHookerDisplayScanline = 241; + public List TextHookerCharMappings = new List(); + public DakutenMode TextHookerDakutenMode = DakutenMode.OnTop; + public bool TextHookerAdjustViewportScrolling = true; + public bool TextHookerIgnoreMirroredNametables = true; + public bool TextHookerAutoCopyToClipboard = false; + public DebuggerShortcutsConfig Shortcuts = new DebuggerShortcutsConfig(); public DebugImportConfig ImportConfig = new DebugImportConfig(); @@ -441,4 +452,19 @@ namespace Mesen.GUI.Config } } } + + public class CharMap + { + [XmlAttribute] + public string Key; + [XmlAttribute] + public string Value; + } + + public enum DakutenMode + { + Ignore, + OnTheRight, + OnTop + } } diff --git a/GUI.NET/Config/DebuggerShortcutsConfig.cs b/GUI.NET/Config/DebuggerShortcutsConfig.cs index fcd45a24..877f70f8 100644 --- a/GUI.NET/Config/DebuggerShortcutsConfig.cs +++ b/GUI.NET/Config/DebuggerShortcutsConfig.cs @@ -67,6 +67,8 @@ namespace Mesen.GUI.Config public XmlKeys OpenScriptWindow = Keys.Control | Keys.N; [ShortcutName("Open Trace Logger")] public XmlKeys OpenTraceLogger = Keys.Control | Keys.J; + [ShortcutName("Open Text Hooker")] + public XmlKeys OpenTextHooker = Keys.Control | Keys.H; //Debugger window [ShortcutName("Reset")] diff --git a/GUI.NET/Debugger/Controls/ctrlCharacterMapping.Designer.cs b/GUI.NET/Debugger/Controls/ctrlCharacterMapping.Designer.cs new file mode 100644 index 00000000..5fce98f6 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCharacterMapping.Designer.cs @@ -0,0 +1,323 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlCharacterMapping + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tlpTiles = new System.Windows.Forms.TableLayoutPanel(); + this.picTiles = new System.Windows.Forms.PictureBox(); + this.txtMapping0 = new System.Windows.Forms.TextBox(); + this.txtMapping1 = new System.Windows.Forms.TextBox(); + this.txtMapping6 = new System.Windows.Forms.TextBox(); + this.txtMapping7 = new System.Windows.Forms.TextBox(); + this.txtMapping8 = new System.Windows.Forms.TextBox(); + this.txtMapping9 = new System.Windows.Forms.TextBox(); + this.txtMapping10 = new System.Windows.Forms.TextBox(); + this.txtMapping11 = new System.Windows.Forms.TextBox(); + this.txtMapping12 = new System.Windows.Forms.TextBox(); + this.txtMapping13 = new System.Windows.Forms.TextBox(); + this.txtMapping14 = new System.Windows.Forms.TextBox(); + this.txtMapping15 = new System.Windows.Forms.TextBox(); + this.txtMapping2 = new System.Windows.Forms.TextBox(); + this.txtMapping3 = new System.Windows.Forms.TextBox(); + this.txtMapping5 = new System.Windows.Forms.TextBox(); + this.txtMapping4 = new System.Windows.Forms.TextBox(); + this.tlpTiles.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picTiles)).BeginInit(); + this.SuspendLayout(); + // + // tlpTiles + // + this.tlpTiles.ColumnCount = 17; + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTiles.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpTiles.Controls.Add(this.picTiles, 0, 0); + this.tlpTiles.Controls.Add(this.txtMapping0, 0, 1); + this.tlpTiles.Controls.Add(this.txtMapping1, 1, 1); + this.tlpTiles.Controls.Add(this.txtMapping6, 6, 1); + this.tlpTiles.Controls.Add(this.txtMapping7, 7, 1); + this.tlpTiles.Controls.Add(this.txtMapping8, 8, 1); + this.tlpTiles.Controls.Add(this.txtMapping9, 9, 1); + this.tlpTiles.Controls.Add(this.txtMapping10, 10, 1); + this.tlpTiles.Controls.Add(this.txtMapping11, 11, 1); + this.tlpTiles.Controls.Add(this.txtMapping12, 12, 1); + this.tlpTiles.Controls.Add(this.txtMapping13, 13, 1); + this.tlpTiles.Controls.Add(this.txtMapping14, 14, 1); + this.tlpTiles.Controls.Add(this.txtMapping15, 15, 1); + this.tlpTiles.Controls.Add(this.txtMapping2, 2, 1); + this.tlpTiles.Controls.Add(this.txtMapping3, 3, 1); + this.tlpTiles.Controls.Add(this.txtMapping5, 5, 1); + this.tlpTiles.Controls.Add(this.txtMapping4, 4, 1); + this.tlpTiles.Dock = System.Windows.Forms.DockStyle.Fill; + this.tlpTiles.Location = new System.Drawing.Point(0, 0); + this.tlpTiles.Margin = new System.Windows.Forms.Padding(0); + this.tlpTiles.Name = "tlpTiles"; + this.tlpTiles.RowCount = 3; + this.tlpTiles.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTiles.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTiles.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpTiles.Size = new System.Drawing.Size(416, 50); + this.tlpTiles.TabIndex = 0; + // + // picTiles + // + this.tlpTiles.SetColumnSpan(this.picTiles, 16); + this.picTiles.Location = new System.Drawing.Point(0, 0); + this.picTiles.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1); + this.picTiles.Name = "picTiles"; + this.picTiles.Size = new System.Drawing.Size(416, 20); + this.picTiles.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.picTiles.TabIndex = 0; + this.picTiles.TabStop = false; + // + // txtMapping0 + // + this.txtMapping0.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping0.Location = new System.Drawing.Point(2, 21); + this.txtMapping0.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping0.Name = "txtMapping0"; + this.txtMapping0.Size = new System.Drawing.Size(22, 20); + this.txtMapping0.TabIndex = 1; + this.txtMapping0.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping0.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping1 + // + this.txtMapping1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping1.Location = new System.Drawing.Point(28, 21); + this.txtMapping1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping1.Name = "txtMapping1"; + this.txtMapping1.Size = new System.Drawing.Size(22, 20); + this.txtMapping1.TabIndex = 2; + this.txtMapping1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping1.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping6 + // + this.txtMapping6.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping6.Location = new System.Drawing.Point(158, 21); + this.txtMapping6.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping6.Name = "txtMapping6"; + this.txtMapping6.Size = new System.Drawing.Size(22, 20); + this.txtMapping6.TabIndex = 7; + this.txtMapping6.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping6.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping7 + // + this.txtMapping7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping7.Location = new System.Drawing.Point(184, 21); + this.txtMapping7.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping7.Name = "txtMapping7"; + this.txtMapping7.Size = new System.Drawing.Size(22, 20); + this.txtMapping7.TabIndex = 8; + this.txtMapping7.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping7.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping8 + // + this.txtMapping8.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping8.Location = new System.Drawing.Point(210, 21); + this.txtMapping8.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping8.Name = "txtMapping8"; + this.txtMapping8.Size = new System.Drawing.Size(22, 20); + this.txtMapping8.TabIndex = 9; + this.txtMapping8.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping8.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping9 + // + this.txtMapping9.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping9.Location = new System.Drawing.Point(236, 21); + this.txtMapping9.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping9.Name = "txtMapping9"; + this.txtMapping9.Size = new System.Drawing.Size(22, 20); + this.txtMapping9.TabIndex = 10; + this.txtMapping9.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping9.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping10 + // + this.txtMapping10.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping10.Location = new System.Drawing.Point(262, 21); + this.txtMapping10.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping10.Name = "txtMapping10"; + this.txtMapping10.Size = new System.Drawing.Size(22, 20); + this.txtMapping10.TabIndex = 11; + this.txtMapping10.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping10.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping11 + // + this.txtMapping11.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping11.Location = new System.Drawing.Point(288, 21); + this.txtMapping11.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping11.Name = "txtMapping11"; + this.txtMapping11.Size = new System.Drawing.Size(22, 20); + this.txtMapping11.TabIndex = 12; + this.txtMapping11.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping11.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping12 + // + this.txtMapping12.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping12.Location = new System.Drawing.Point(314, 21); + this.txtMapping12.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping12.Name = "txtMapping12"; + this.txtMapping12.Size = new System.Drawing.Size(22, 20); + this.txtMapping12.TabIndex = 13; + this.txtMapping12.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping12.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping13 + // + this.txtMapping13.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping13.Location = new System.Drawing.Point(340, 21); + this.txtMapping13.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping13.Name = "txtMapping13"; + this.txtMapping13.Size = new System.Drawing.Size(22, 20); + this.txtMapping13.TabIndex = 14; + this.txtMapping13.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping13.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping14 + // + this.txtMapping14.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping14.Location = new System.Drawing.Point(366, 21); + this.txtMapping14.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping14.Name = "txtMapping14"; + this.txtMapping14.Size = new System.Drawing.Size(22, 20); + this.txtMapping14.TabIndex = 15; + this.txtMapping14.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping14.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping15 + // + this.txtMapping15.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping15.Location = new System.Drawing.Point(392, 21); + this.txtMapping15.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping15.Name = "txtMapping15"; + this.txtMapping15.Size = new System.Drawing.Size(22, 20); + this.txtMapping15.TabIndex = 16; + this.txtMapping15.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping15.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping2 + // + this.txtMapping2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping2.Location = new System.Drawing.Point(54, 21); + this.txtMapping2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping2.Name = "txtMapping2"; + this.txtMapping2.Size = new System.Drawing.Size(22, 20); + this.txtMapping2.TabIndex = 6; + this.txtMapping2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping2.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping3 + // + this.txtMapping3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping3.Location = new System.Drawing.Point(80, 21); + this.txtMapping3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping3.Name = "txtMapping3"; + this.txtMapping3.Size = new System.Drawing.Size(22, 20); + this.txtMapping3.TabIndex = 3; + this.txtMapping3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping3.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping5 + // + this.txtMapping5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping5.Location = new System.Drawing.Point(132, 21); + this.txtMapping5.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping5.Name = "txtMapping5"; + this.txtMapping5.Size = new System.Drawing.Size(22, 20); + this.txtMapping5.TabIndex = 5; + this.txtMapping5.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping5.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // txtMapping4 + // + this.txtMapping4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.txtMapping4.Location = new System.Drawing.Point(106, 21); + this.txtMapping4.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.txtMapping4.Name = "txtMapping4"; + this.txtMapping4.Size = new System.Drawing.Size(22, 20); + this.txtMapping4.TabIndex = 4; + this.txtMapping4.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.txtMapping4.TextChanged += new System.EventHandler(this.txtMapping_TextChanged); + // + // ctrlCharacterMapping + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tlpTiles); + this.Margin = new System.Windows.Forms.Padding(0); + this.Name = "ctrlCharacterMapping"; + this.Size = new System.Drawing.Size(416, 50); + this.tlpTiles.ResumeLayout(false); + this.tlpTiles.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picTiles)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tlpTiles; + private System.Windows.Forms.TextBox txtMapping0; + private System.Windows.Forms.TextBox txtMapping1; + private System.Windows.Forms.TextBox txtMapping3; + private System.Windows.Forms.TextBox txtMapping4; + private System.Windows.Forms.TextBox txtMapping5; + private System.Windows.Forms.TextBox txtMapping2; + private System.Windows.Forms.TextBox txtMapping6; + private System.Windows.Forms.TextBox txtMapping7; + private System.Windows.Forms.TextBox txtMapping8; + private System.Windows.Forms.TextBox txtMapping9; + private System.Windows.Forms.TextBox txtMapping10; + private System.Windows.Forms.TextBox txtMapping11; + private System.Windows.Forms.TextBox txtMapping12; + private System.Windows.Forms.TextBox txtMapping13; + private System.Windows.Forms.TextBox txtMapping14; + private System.Windows.Forms.TextBox txtMapping15; + public System.Windows.Forms.PictureBox picTiles; + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlCharacterMapping.cs b/GUI.NET/Debugger/Controls/ctrlCharacterMapping.cs new file mode 100644 index 00000000..d08c71f6 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCharacterMapping.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Collections.Concurrent; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlCharacterMapping : UserControl + { + private Color _activeBgColor = Color.FromArgb(180, 250, 200); + private TextBox[] _txtMappings; + private byte[][] _tileData = new byte[16][]; + private ConcurrentDictionary _charMappings; + private static readonly uint[] _hexLookup = InitializeHexLookup(); + + public ctrlCharacterMapping() + { + InitializeComponent(); + + for(int i = 0; i < 16; i++) { + _tileData[i] = new byte[16]; + } + + _txtMappings = new TextBox[16] { + txtMapping0, txtMapping1, txtMapping2, txtMapping3, txtMapping4, txtMapping5, txtMapping6, txtMapping7, + txtMapping8, txtMapping9, txtMapping10, txtMapping11, txtMapping12, txtMapping13, txtMapping14, txtMapping15 + }; + + if(Program.IsMono) { + this.SuspendLayout(); + tlpTiles.SuspendLayout(); + //this.picTiles.Margin = new Padding(0, 5, 0, 1); + for(int i = 0; i < 16; i++) { + _txtMappings[i].Width -= 4; + } + this.Width -= 72; + this.Height -= 4; + tlpTiles.ResumeLayout(); + this.ResumeLayout(); + } + } + + private static uint[] InitializeHexLookup() + { + var result = new uint[256]; + for(int i = 0; i < 256; i++) { + string s = i.ToString("X2"); + result[i] = ((uint)s[0]) + ((uint)s[1] << 16); + } + return result; + } + + private static string ToHexString(byte[] bytes) + { + char[] result = new char[bytes.Length * 2]; + for(int i = 0; i < bytes.Length; i++) { + var val = _hexLookup[bytes[i]]; + result[2 * i] = (char)val; + result[2 * i + 1] = (char)(val >> 16); + } + return new string(result); + } + + public static string GetColorIndependentKey(byte[] tileData) + { + sbyte nextColor = 0; + byte[] colorKey = new byte[16]; + sbyte[] lookupTable = new sbyte[4] { -1, -1, -1, -1 }; + for(int y = 0; y < 8; y++) { + byte lowByte = tileData[y]; + byte highByte = tileData[y + 8]; + + for(int x = 0; x < 8; x++) { + byte color = (byte)((lowByte & 0x01) | ((highByte << 1) & 0x02)); + lowByte >>= 1; + highByte >>= 1; + if(lookupTable[color] == -1) { + lookupTable[color] = nextColor; + nextColor++; + } + + colorKey[(y << 1) + x / 4] |= (byte)(lookupTable[color] << ((x & 0x03) << 1)); + } + } + + return ToHexString(colorKey); + } + + public void UpdateData(byte[] chrData, int rowIndex) + { + for(int i = 0; i < 16; i++) { + Array.Copy(chrData, rowIndex * 256 + i * 16, _tileData[i], 0, 16); + + string key = GetColorIndependentKey(_tileData[i]); + string mapping; + if(_charMappings.TryGetValue(key, out mapping)) { + _txtMappings[i].Text = mapping; + _txtMappings[i].BackColor = _activeBgColor; + } else { + _txtMappings[i].Text = ""; + _txtMappings[i].BackColor = Color.White; + } + } + } + + private void txtMapping_TextChanged(object sender, EventArgs e) + { + int i = Array.IndexOf(_txtMappings, sender); + string key = GetColorIndependentKey(_tileData[i]); + + string text = ((TextBox)sender).Text; + if(string.IsNullOrWhiteSpace(text)) { + _charMappings.TryRemove(key, out text); + ((TextBox)sender).BackColor = Color.White; + } else { + _charMappings[key] = text; + ((TextBox)sender).BackColor = _activeBgColor; + } + } + + public void SetCharacterMappings(ConcurrentDictionary charMappings) + { + _charMappings = charMappings; + } + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlCharacterMapping.resx b/GUI.NET/Debugger/Controls/ctrlCharacterMapping.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCharacterMapping.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlCharacterMappings.Designer.cs b/GUI.NET/Debugger/Controls/ctrlCharacterMappings.Designer.cs new file mode 100644 index 00000000..e9a0a6f5 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCharacterMappings.Designer.cs @@ -0,0 +1,211 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlCharacterMappings + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); + this.lblChrSelection = new System.Windows.Forms.Label(); + this.cboChrSelection = new System.Windows.Forms.ComboBox(); + this.grpTileInfo = new System.Windows.Forms.GroupBox(); + this.tlpTileMappings = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.lblHint = new System.Windows.Forms.Label(); + this.picHint = new System.Windows.Forms.PictureBox(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.tableLayoutPanel3.SuspendLayout(); + this.flowLayoutPanel2.SuspendLayout(); + this.grpTileInfo.SuspendLayout(); + this.tlpTileMappings.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picHint)).BeginInit(); + this.SuspendLayout(); + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 2; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.Controls.Add(this.flowLayoutPanel2, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.grpTileInfo, 1, 1); + this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 3; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(816, 492); + this.tableLayoutPanel3.TabIndex = 3; + // + // flowLayoutPanel2 + // + this.flowLayoutPanel2.Controls.Add(this.lblChrSelection); + this.flowLayoutPanel2.Controls.Add(this.cboChrSelection); + this.flowLayoutPanel2.Location = new System.Drawing.Point(0, 0); + this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel2.Name = "flowLayoutPanel2"; + this.flowLayoutPanel2.Size = new System.Drawing.Size(332, 27); + this.flowLayoutPanel2.TabIndex = 6; + // + // lblChrSelection + // + this.lblChrSelection.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblChrSelection.AutoSize = true; + this.lblChrSelection.Location = new System.Drawing.Point(3, 7); + this.lblChrSelection.Name = "lblChrSelection"; + this.lblChrSelection.Size = new System.Drawing.Size(80, 13); + this.lblChrSelection.TabIndex = 0; + this.lblChrSelection.Text = "CHR Selection:"; + // + // cboChrSelection + // + this.cboChrSelection.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboChrSelection.FormattingEnabled = true; + this.cboChrSelection.Location = new System.Drawing.Point(89, 3); + this.cboChrSelection.Name = "cboChrSelection"; + this.cboChrSelection.Size = new System.Drawing.Size(183, 21); + this.cboChrSelection.TabIndex = 1; + this.cboChrSelection.DropDown += new System.EventHandler(this.cboChrSelection_DropDown); + this.cboChrSelection.SelectedIndexChanged += new System.EventHandler(this.cboChrSelection_SelectedIndexChanged); + // + // grpTileInfo + // + this.grpTileInfo.Controls.Add(this.tlpTileMappings); + this.grpTileInfo.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpTileInfo.Location = new System.Drawing.Point(3, 30); + this.grpTileInfo.Name = "grpTileInfo"; + this.grpTileInfo.Size = new System.Drawing.Size(811, 455); + this.grpTileInfo.TabIndex = 4; + this.grpTileInfo.TabStop = false; + this.grpTileInfo.Text = "Tile Mappings"; + // + // tlpTileMappings + // + this.tlpTileMappings.ColumnCount = 3; + this.tlpTileMappings.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTileMappings.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tlpTileMappings.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpTileMappings.Controls.Add(this.tableLayoutPanel1, 0, 0); + this.tlpTileMappings.Dock = System.Windows.Forms.DockStyle.Fill; + this.tlpTileMappings.Location = new System.Drawing.Point(3, 16); + this.tlpTileMappings.Margin = new System.Windows.Forms.Padding(0); + this.tlpTileMappings.Name = "tlpTileMappings"; + this.tlpTileMappings.RowCount = 10; + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpTileMappings.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpTileMappings.Size = new System.Drawing.Size(805, 436); + this.tlpTileMappings.TabIndex = 0; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 2; + this.tlpTileMappings.SetColumnSpan(this.tableLayoutPanel1, 3); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.lblHint, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.picHint, 0, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 1; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(799, 26); + this.tableLayoutPanel1.TabIndex = 2; + // + // lblHint + // + this.lblHint.AutoSize = true; + this.lblHint.Dock = System.Windows.Forms.DockStyle.Fill; + this.lblHint.Location = new System.Drawing.Point(25, 0); + this.lblHint.Name = "lblHint"; + this.lblHint.Size = new System.Drawing.Size(771, 26); + this.lblHint.TabIndex = 1; + this.lblHint.Text = "Select a CHR page above and then enter the character matching each tile in the te" + + "xtbox below the tile itself.\r\nCharacter mappings are shared between all roms."; + // + // picHint + // + this.picHint.BackgroundImage = global::Mesen.GUI.Properties.Resources.Help; + this.picHint.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; + this.picHint.Location = new System.Drawing.Point(3, 5); + this.picHint.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3); + this.picHint.Name = "picHint"; + this.picHint.Size = new System.Drawing.Size(16, 16); + this.picHint.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.picHint.TabIndex = 0; + this.picHint.TabStop = false; + // + // toolTip + // + this.toolTip.AutoPopDelay = 32700; + this.toolTip.InitialDelay = 10; + this.toolTip.ReshowDelay = 10; + // + // ctrlCharacterMappings + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel3); + this.Name = "ctrlCharacterMappings"; + this.Size = new System.Drawing.Size(816, 492); + this.tableLayoutPanel3.ResumeLayout(false); + this.flowLayoutPanel2.ResumeLayout(false); + this.flowLayoutPanel2.PerformLayout(); + this.grpTileInfo.ResumeLayout(false); + this.tlpTileMappings.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picHint)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.GroupBox grpTileInfo; + private System.Windows.Forms.TableLayoutPanel tlpTileMappings; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2; + private System.Windows.Forms.Label lblChrSelection; + private System.Windows.Forms.ComboBox cboChrSelection; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label lblHint; + private System.Windows.Forms.PictureBox picHint; + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlCharacterMappings.cs b/GUI.NET/Debugger/Controls/ctrlCharacterMappings.cs new file mode 100644 index 00000000..e1d8d307 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCharacterMappings.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using Mesen.GUI.Controls; +using Mesen.GUI.Config; +using System.Collections.Concurrent; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlCharacterMappings : BaseControl + { + private UInt32 _chrSize; + private byte[] _chrPixelData; + private int _chrSelection = 0; + private ctrlCharacterMapping[] _mappings = new ctrlCharacterMapping[16]; + private byte[] _chrData = new byte[16*16*16]; + + public ctrlCharacterMappings() + { + InitializeComponent(); + + tlpTileMappings.SuspendLayout(); + for(int y = 0; y < 8; y++) { + for(int x = 0; x < 2; x++) { + ctrlCharacterMapping mapping = new ctrlCharacterMapping(); + tlpTileMappings.Controls.Add(mapping); + tlpTileMappings.SetColumn(mapping, x); + tlpTileMappings.SetRow(mapping, y + 1); + mapping.picTiles.Image = new Bitmap(416, 20); + _mappings[(y << 1) + x] = mapping; + } + } + tlpTileMappings.ResumeLayout(); + } + + public void GetData() + { + UInt32[] paletteData; + _chrPixelData = InteropEmu.DebugGetChrBank(_chrSelection, 9, false, CdlHighlightType.None, out paletteData); + + bool isChrRam = InteropEmu.DebugGetMemorySize(DebugMemoryType.ChrRom) == 0; + if(_chrSelection < 2) { + byte[] chrData = InteropEmu.DebugGetMemoryState(DebugMemoryType.PpuMemory); + Array.Copy(chrData, _chrSelection * 0x1000, _chrData, 0, 0x1000); + } else { + byte[] chrData = InteropEmu.DebugGetMemoryState(isChrRam ? DebugMemoryType.ChrRam : DebugMemoryType.ChrRom); + + int startIndex = (_chrSelection - 2) * 0x1000; + if(startIndex >= chrData.Length) { + //Can occur when switching games + startIndex = 0; + } + + Array.Copy(chrData, startIndex, _chrData, 0, 0x1000); + } + } + + public void RefreshViewer(bool refreshPreview = false) + { + UpdateChrBankDropdown(); + + GCHandle handle = GCHandle.Alloc(_chrPixelData, GCHandleType.Pinned); + try { + Bitmap source = new Bitmap(128, 128, 4*128, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()); + + for(int y = 0; y < 16; y++) { + using(Graphics g = Graphics.FromImage(_mappings[y].picTiles.Image)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + + g.TranslateTransform(1, 0); + for(int x = 0; x < 16; x++) { + g.FillRectangle(Brushes.DarkGreen, 3 + x * 26, 1, 18, 18); + } + + g.ScaleTransform(2, 2); + for(int x = 0; x < 16; x++) { + g.DrawImage(source, new Rectangle(2 + x * 13, 1, 8, 8), x * 8, y * 8, 8, 8, GraphicsUnit.Pixel); + } + } + _mappings[y].picTiles.Invalidate(); + _mappings[y].UpdateData(_chrData, y); + } + } finally { + handle.Free(); + } + } + + public void SetCharacterMappings(ConcurrentDictionary charMappings) + { + for(int i = 0; i < 16; i++) { + _mappings[i].SetCharacterMappings(charMappings); + } + } + + private void UpdateChrBankDropdown() + { + DebugState state = new DebugState(); + InteropEmu.DebugGetState(ref state); + + UInt32 chrSize = state.Cartridge.ChrRomSize == 0 ? state.Cartridge.ChrRamSize : state.Cartridge.ChrRomSize; + + if(chrSize != _chrSize) { + _chrSize = chrSize; + + int index = this.cboChrSelection.SelectedIndex; + this.cboChrSelection.Items.Clear(); + this.cboChrSelection.Items.Add("PPU: $0000"); + this.cboChrSelection.Items.Add("PPU: $1000"); + for(int i = 0; i < _chrSize / 0x1000; i++) { + this.cboChrSelection.Items.Add("CHR: $" + (i * 0x1000).ToString("X4")); + } + + this.cboChrSelection.SelectedIndex = this.cboChrSelection.Items.Count > index && index >= 0 ? index : 0; + this._chrSelection = this.cboChrSelection.SelectedIndex; + } + } + + private void cboChrSelection_DropDown(object sender, EventArgs e) + { + UpdateChrBankDropdown(); + } + + private void cboChrSelection_SelectedIndexChanged(object sender, EventArgs e) + { + this._chrSelection = this.cboChrSelection.SelectedIndex; + this.GetData(); + this.RefreshViewer(); + } + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlCharacterMappings.resx b/GUI.NET/Debugger/Controls/ctrlCharacterMappings.resx new file mode 100644 index 00000000..ed40e98e --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCharacterMappings.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 116, 17 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.Designer.cs b/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.Designer.cs new file mode 100644 index 00000000..f806ad45 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.Designer.cs @@ -0,0 +1,168 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlScanlineCycleSelect + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.flpRefreshTiming = new System.Windows.Forms.FlowLayoutPanel(); + this.lblShowFrameAt = new System.Windows.Forms.Label(); + this.lblCycle = new System.Windows.Forms.Label(); + this.btnReset = new System.Windows.Forms.Button(); + this.nudScanline = new Mesen.GUI.Controls.MesenNumericUpDown(); + this.nudCycle = new Mesen.GUI.Controls.MesenNumericUpDown(); + this.flpRefreshTiming.SuspendLayout(); + this.SuspendLayout(); + // + // flpRefreshTiming + // + this.flpRefreshTiming.Controls.Add(this.lblShowFrameAt); + this.flpRefreshTiming.Controls.Add(this.nudScanline); + this.flpRefreshTiming.Controls.Add(this.lblCycle); + this.flpRefreshTiming.Controls.Add(this.nudCycle); + this.flpRefreshTiming.Controls.Add(this.btnReset); + this.flpRefreshTiming.Dock = System.Windows.Forms.DockStyle.Fill; + this.flpRefreshTiming.Location = new System.Drawing.Point(0, 0); + this.flpRefreshTiming.Name = "flpRefreshTiming"; + this.flpRefreshTiming.Size = new System.Drawing.Size(530, 28); + this.flpRefreshTiming.TabIndex = 5; + // + // lblShowFrameAt + // + this.lblShowFrameAt.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblShowFrameAt.AutoSize = true; + this.lblShowFrameAt.Location = new System.Drawing.Point(3, 8); + this.lblShowFrameAt.Name = "lblShowFrameAt"; + this.lblShowFrameAt.Size = new System.Drawing.Size(266, 13); + this.lblShowFrameAt.TabIndex = 0; + this.lblShowFrameAt.Text = "When emulation is running, show PPU data at scanline"; + // + // lblCycle + // + this.lblCycle.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblCycle.AutoSize = true; + this.lblCycle.Location = new System.Drawing.Point(333, 8); + this.lblCycle.Name = "lblCycle"; + this.lblCycle.Size = new System.Drawing.Size(53, 13); + this.lblCycle.TabIndex = 5; + this.lblCycle.Text = "and cycle"; + // + // btnReset + // + this.btnReset.Location = new System.Drawing.Point(450, 3); + this.btnReset.Name = "btnReset"; + this.btnReset.Size = new System.Drawing.Size(75, 23); + this.btnReset.TabIndex = 7; + this.btnReset.Text = "Reset"; + this.btnReset.UseVisualStyleBackColor = true; + this.btnReset.Click += new System.EventHandler(this.btnReset_Click); + // + // nudScanline + // + this.nudScanline.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.nudScanline.DecimalPlaces = 0; + this.nudScanline.Increment = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudScanline.Location = new System.Drawing.Point(275, 4); + this.nudScanline.Maximum = new decimal(new int[] { + 260, + 0, + 0, + 0}); + this.nudScanline.MaximumSize = new System.Drawing.Size(10000, 20); + this.nudScanline.Minimum = new decimal(new int[] { + 1, + 0, + 0, + -2147483648}); + this.nudScanline.MinimumSize = new System.Drawing.Size(0, 21); + this.nudScanline.Name = "nudScanline"; + this.nudScanline.Size = new System.Drawing.Size(52, 21); + this.nudScanline.TabIndex = 5; + this.nudScanline.Value = new decimal(new int[] { + 241, + 0, + 0, + 0}); + this.nudScanline.ValueChanged += new System.EventHandler(this.nudScanlineCycle_ValueChanged); + // + // nudCycle + // + this.nudCycle.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.nudCycle.DecimalPlaces = 0; + this.nudCycle.Increment = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nudCycle.Location = new System.Drawing.Point(392, 4); + this.nudCycle.Maximum = new decimal(new int[] { + 340, + 0, + 0, + 0}); + this.nudCycle.MaximumSize = new System.Drawing.Size(10000, 20); + this.nudCycle.Minimum = new decimal(new int[] { + 0, + 0, + 0, + 0}); + this.nudCycle.MinimumSize = new System.Drawing.Size(0, 21); + this.nudCycle.Name = "nudCycle"; + this.nudCycle.Size = new System.Drawing.Size(52, 21); + this.nudCycle.TabIndex = 6; + this.nudCycle.Value = new decimal(new int[] { + 0, + 0, + 0, + 0}); + this.nudCycle.ValueChanged += new System.EventHandler(this.nudScanlineCycle_ValueChanged); + // + // ctrlScanlineCycleSelect + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.flpRefreshTiming); + this.Name = "ctrlScanlineCycleSelect"; + this.Size = new System.Drawing.Size(530, 28); + this.flpRefreshTiming.ResumeLayout(false); + this.flpRefreshTiming.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.FlowLayoutPanel flpRefreshTiming; + private System.Windows.Forms.Label lblShowFrameAt; + private GUI.Controls.MesenNumericUpDown nudScanline; + private System.Windows.Forms.Label lblCycle; + private GUI.Controls.MesenNumericUpDown nudCycle; + private System.Windows.Forms.Button btnReset; + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.cs b/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.cs new file mode 100644 index 00000000..3c4b0498 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Mesen.GUI.Config; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlScanlineCycleSelect : UserControl + { + private int _ppuViewerId = 0; + private int _scanline = 241; + private int _cycle = 0; + + public int Scanline { get { return _scanline; } } + public int Cycle { get { return _cycle; } } + + public ctrlScanlineCycleSelect() + { + InitializeComponent(); + } + + public void Initialize(int ppuViewerId, int scanline, int cycle) + { + _ppuViewerId = ppuViewerId; + _scanline = scanline; + _cycle = cycle; + + this.nudScanline.Value = _scanline; + this.nudCycle.Value = _cycle; + + InteropEmu.DebugSetPpuViewerScanlineCycle(_ppuViewerId, _scanline, _cycle); + } + + public void RefreshSettings() + { + InteropEmu.DebugSetPpuViewerScanlineCycle(_ppuViewerId, _scanline, _cycle); + } + + private void SetUpdateScanlineCycle(int scanline, int cycle) + { + _scanline = scanline; + _cycle = cycle; + RefreshSettings(); + } + + private void nudScanlineCycle_ValueChanged(object sender, EventArgs e) + { + SetUpdateScanlineCycle((int)this.nudScanline.Value, (int)this.nudCycle.Value); + } + + private void btnReset_Click(object sender, EventArgs e) + { + this.nudScanline.Value = 241; + this.nudCycle.Value = 0; + } + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.resx b/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlScanlineCycleSelect.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlTextHooker.Designer.cs b/GUI.NET/Debugger/Controls/ctrlTextHooker.Designer.cs new file mode 100644 index 00000000..ea94c386 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlTextHooker.Designer.cs @@ -0,0 +1,236 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlTextHooker + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.picNametable = new System.Windows.Forms.PictureBox(); + this.grpText = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.chkAutoCopyToClipboard = new System.Windows.Forms.CheckBox(); + this.chkIgnoreMirroredNametables = new System.Windows.Forms.CheckBox(); + this.btnClearSelection = new System.Windows.Forms.Button(); + this.txtSelectedText = new System.Windows.Forms.TextBox(); + this.chkUseScrollOffsets = new System.Windows.Forms.CheckBox(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.lblDakutenMode = new System.Windows.Forms.Label(); + this.cboDakutenMode = new System.Windows.Forms.ComboBox(); + this.tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable)).BeginInit(); + this.grpText.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + this.tableLayoutPanel3.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 2; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.picNametable, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.grpText, 1, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(923, 491); + this.tableLayoutPanel1.TabIndex = 2; + // + // picNametable + // + this.picNametable.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picNametable.Location = new System.Drawing.Point(4, 4); + this.picNametable.Margin = new System.Windows.Forms.Padding(4); + this.picNametable.Name = "picNametable"; + this.picNametable.Size = new System.Drawing.Size(514, 482); + this.picNametable.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.picNametable.TabIndex = 0; + this.picNametable.TabStop = false; + // + // grpText + // + this.grpText.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.grpText.Controls.Add(this.tableLayoutPanel2); + this.grpText.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpText.Location = new System.Drawing.Point(525, 3); + this.grpText.Name = "grpText"; + this.grpText.Size = new System.Drawing.Size(395, 484); + this.grpText.TabIndex = 4; + this.grpText.TabStop = false; + this.grpText.Text = "Text Hooker"; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 2; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Controls.Add(this.chkAutoCopyToClipboard, 0, 1); + this.tableLayoutPanel2.Controls.Add(this.chkIgnoreMirroredNametables, 0, 2); + this.tableLayoutPanel2.Controls.Add(this.btnClearSelection, 0, 5); + this.tableLayoutPanel2.Controls.Add(this.txtSelectedText, 0, 0); + this.tableLayoutPanel2.Controls.Add(this.chkUseScrollOffsets, 0, 3); + this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 0, 4); + this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 16); + this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 6; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(389, 465); + this.tableLayoutPanel2.TabIndex = 0; + // + // chkAutoCopyToClipboard + // + this.chkAutoCopyToClipboard.AutoSize = true; + this.chkAutoCopyToClipboard.Location = new System.Drawing.Point(3, 342); + this.chkAutoCopyToClipboard.Name = "chkAutoCopyToClipboard"; + this.chkAutoCopyToClipboard.Size = new System.Drawing.Size(132, 17); + this.chkAutoCopyToClipboard.TabIndex = 7; + this.chkAutoCopyToClipboard.Text = "Auto-copy to clipboard"; + this.chkAutoCopyToClipboard.UseVisualStyleBackColor = true; + // + // chkIgnoreMirroredNametables + // + this.chkIgnoreMirroredNametables.AutoSize = true; + this.chkIgnoreMirroredNametables.Location = new System.Drawing.Point(3, 365); + this.chkIgnoreMirroredNametables.Name = "chkIgnoreMirroredNametables"; + this.chkIgnoreMirroredNametables.Size = new System.Drawing.Size(153, 17); + this.chkIgnoreMirroredNametables.TabIndex = 6; + this.chkIgnoreMirroredNametables.Text = "Ignore mirrored nametables"; + this.chkIgnoreMirroredNametables.UseVisualStyleBackColor = true; + // + // btnClearSelection + // + this.btnClearSelection.Location = new System.Drawing.Point(3, 437); + this.btnClearSelection.Name = "btnClearSelection"; + this.btnClearSelection.Size = new System.Drawing.Size(92, 23); + this.btnClearSelection.TabIndex = 0; + this.btnClearSelection.Text = "Clear Selection"; + this.btnClearSelection.UseVisualStyleBackColor = true; + this.btnClearSelection.Visible = false; + // + // txtSelectedText + // + this.txtSelectedText.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.tableLayoutPanel2.SetColumnSpan(this.txtSelectedText, 2); + this.txtSelectedText.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtSelectedText.Location = new System.Drawing.Point(3, 3); + this.txtSelectedText.Multiline = true; + this.txtSelectedText.Name = "txtSelectedText"; + this.txtSelectedText.ReadOnly = true; + this.txtSelectedText.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtSelectedText.Size = new System.Drawing.Size(383, 333); + this.txtSelectedText.TabIndex = 1; + // + // chkUseScrollOffsets + // + this.chkUseScrollOffsets.AutoSize = true; + this.chkUseScrollOffsets.Location = new System.Drawing.Point(3, 388); + this.chkUseScrollOffsets.Name = "chkUseScrollOffsets"; + this.chkUseScrollOffsets.Size = new System.Drawing.Size(187, 17); + this.chkUseScrollOffsets.TabIndex = 2; + this.chkUseScrollOffsets.Text = "Adjust viewport by scrolling offsets"; + this.chkUseScrollOffsets.UseVisualStyleBackColor = true; + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 2; + this.tableLayoutPanel2.SetColumnSpan(this.tableLayoutPanel3, 2); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.Controls.Add(this.lblDakutenMode, 0, 0); + this.tableLayoutPanel3.Controls.Add(this.cboDakutenMode, 1, 0); + this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 408); + this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 1; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(219, 26); + this.tableLayoutPanel3.TabIndex = 5; + // + // lblDakutenMode + // + this.lblDakutenMode.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblDakutenMode.AutoSize = true; + this.lblDakutenMode.Location = new System.Drawing.Point(3, 6); + this.lblDakutenMode.Name = "lblDakutenMode"; + this.lblDakutenMode.Size = new System.Drawing.Size(81, 13); + this.lblDakutenMode.TabIndex = 4; + this.lblDakutenMode.Text = "Dakuten Mode:"; + // + // cboDakutenMode + // + this.cboDakutenMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboDakutenMode.FormattingEnabled = true; + this.cboDakutenMode.Location = new System.Drawing.Point(90, 3); + this.cboDakutenMode.Name = "cboDakutenMode"; + this.cboDakutenMode.Size = new System.Drawing.Size(121, 21); + this.cboDakutenMode.TabIndex = 5; + // + // ctrlTextHooker + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "ctrlTextHooker"; + this.Size = new System.Drawing.Size(923, 491); + this.tableLayoutPanel1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.picNametable)).EndInit(); + this.grpText.ResumeLayout(false); + this.tableLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel2.PerformLayout(); + this.tableLayoutPanel3.ResumeLayout(false); + this.tableLayoutPanel3.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.PictureBox picNametable; + private System.Windows.Forms.GroupBox grpText; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.Button btnClearSelection; + private System.Windows.Forms.TextBox txtSelectedText; + private System.Windows.Forms.CheckBox chkUseScrollOffsets; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.Label lblDakutenMode; + private System.Windows.Forms.ComboBox cboDakutenMode; + private System.Windows.Forms.CheckBox chkAutoCopyToClipboard; + private System.Windows.Forms.CheckBox chkIgnoreMirroredNametables; + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlTextHooker.cs b/GUI.NET/Debugger/Controls/ctrlTextHooker.cs new file mode 100644 index 00000000..82bad7ab --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlTextHooker.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using Mesen.GUI.Config; +using Mesen.GUI.Controls; +using Mesen.GUI.Forms; +using System.Collections.Concurrent; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlTextHooker : BaseControl + { + private byte[][] _nametablePixelData = new byte[4][]; + private byte[][] _tileData = new byte[4][]; + private byte[][] _attributeData = new byte[4][]; + private byte[] _tmpTileData = new byte[16]; + + private Bitmap _nametableImage = new Bitmap(512, 480); + private Bitmap _outputImage = new Bitmap(512, 480); + private int _xScroll = 0; + private int _yScroll = 0; + private DebugState _state = new DebugState(); + private ConcurrentDictionary _charMappings; + + public ctrlTextHooker() + { + InitializeComponent(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + if(!IsDesignMode) { + DebugInfo debugInfo = ConfigManager.Config.DebugInfo; + chkIgnoreMirroredNametables.Checked = debugInfo.TextHookerIgnoreMirroredNametables; + chkUseScrollOffsets.Checked = debugInfo.TextHookerAdjustViewportScrolling; + chkAutoCopyToClipboard.Checked = debugInfo.TextHookerAutoCopyToClipboard; + + BaseConfigForm.InitializeComboBox(cboDakutenMode, typeof(DakutenMode)); + cboDakutenMode.SetEnumValue(debugInfo.TextHookerDakutenMode); + } + } + + protected override void OnHandleDestroyed(EventArgs e) + { + base.OnHandleDestroyed(e); + + if(!IsDesignMode) { + DebugInfo debugInfo = ConfigManager.Config.DebugInfo; + debugInfo.TextHookerIgnoreMirroredNametables = chkIgnoreMirroredNametables.Checked; + debugInfo.TextHookerAdjustViewportScrolling = chkUseScrollOffsets.Checked; + debugInfo.TextHookerAutoCopyToClipboard = chkAutoCopyToClipboard.Checked; + debugInfo.TextHookerDakutenMode = cboDakutenMode.GetEnumValue(); + } + } + + public void GetData() + { + InteropEmu.DebugGetPpuScroll(out _xScroll, out _yScroll); + InteropEmu.DebugGetState(ref _state); + + for(int i = 0; i < 4; i++) { + InteropEmu.DebugGetNametable(i, ConfigManager.Config.DebugInfo.NtViewerUseGrayscalePalette, out _nametablePixelData[i], out _tileData[i], out _attributeData[i]); + } + + InteropEmu.DebugGetPpuScroll(out _xScroll, out _yScroll); + _xScroll &= 0xFFF8; + _yScroll &= 0xFFF8; + } + + public void RefreshViewer() + { + using(Graphics gNametable = Graphics.FromImage(_nametableImage)) { + for(int i = 0; i < 4; i++) { + GCHandle handle = GCHandle.Alloc(_nametablePixelData[i], GCHandleType.Pinned); + Bitmap source = new Bitmap(256, 240, 4*256, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()); + try { + gNametable.DrawImage(source, new Rectangle(i % 2 == 0 ? 0 : 256, i <= 1 ? 0 : 240, 256, 240), new Rectangle(0, 0, 256, 240), GraphicsUnit.Pixel); + } finally { + handle.Free(); + } + } + } + + using(Graphics g = Graphics.FromImage(_outputImage)) { + if(chkUseScrollOffsets.Checked) { + g.DrawImage(_nametableImage, -_xScroll, -_yScroll); + g.DrawImage(_nametableImage, -_xScroll + 512, -_yScroll + 480); + g.DrawImage(_nametableImage, -_xScroll + 512, -_yScroll); + g.DrawImage(_nametableImage, -_xScroll, -_yScroll + 480); + } else { + g.DrawImage(_nametableImage, 0, 0); + } + } + picNametable.Image = _outputImage; + + DakutenMode dakutenMode = cboDakutenMode.GetEnumValue(); + StringBuilder output = new StringBuilder(); + DakutenType[] previousLineDakutenType = new DakutenType[32]; + for(int nt = 0; nt < 4; nt++) { + for(int y = 0; y < 30; y++) { + StringBuilder lineOutput = new StringBuilder(); + for(int x = 0; x < 32; x++) { + int outNt, outY, outX; + GetIndexes(nt, y, x, out outNt, out outY, out outX); + if(IgnoreTile(outNt)) { + continue; + } + + string key = GetTileKey(outNt, (outY << 5) + outX); + string value = GetMappedCharacter(key); + + DakutenType dakutenType = GetDakutenType(value); + if(dakutenType != DakutenType.None) { + previousLineDakutenType[x] = dakutenType; + } else { + DakutenType effectiveDakuten = dakutenMode == DakutenMode.OnTop ? previousLineDakutenType[x] : DakutenType.None; + previousLineDakutenType[x] = DakutenType.None; + + if(effectiveDakuten == DakutenType.None && dakutenMode == DakutenMode.OnTheRight) { + GetIndexes(nt, y, x + 1, out outNt, out outY, out outX); + string nextTileKey = GetTileKey(outNt, (outY << 5) + outX); + string nextTileValue = GetMappedCharacter(nextTileKey); + effectiveDakuten = GetDakutenType(nextTileValue); + } + + bool isKana = ( + (value[0] >= '\x3041' && value[0] <= '\x3096') || //hiragana + (value[0] >= '\x30A1' && value[0] <= '\x30FA') //katakana + ); + + if(isKana && effectiveDakuten == DakutenType.Dakuten) { + lineOutput.Append((char)(value[0] + 1)); + } else if(isKana && effectiveDakuten == DakutenType.Handakuten) { + lineOutput.Append((char)(value[0] + 2)); + } else { + lineOutput.Append(value); + } + } + } + + string rowString = lineOutput.ToString().Trim(); + if(rowString.Length > 0) { + output.AppendLine(rowString); + } + } + } + + txtSelectedText.Text = output.ToString(); + if(chkAutoCopyToClipboard.Checked) { + Clipboard.SetText(txtSelectedText.Text); + } + } + + private string GetMappedCharacter(string key) + { + string value; + if(this._charMappings.TryGetValue(key, out value)) { + return value; + } else { + return " "; + } + } + + private DakutenType GetDakutenType(string value) + { + if(value == "daku" || value == "゙") { + return DakutenType.Dakuten; + } else if(value == "han" || value == "゚") { + return DakutenType.Handakuten; + } else { + return DakutenType.None; + } + } + + private string GetTileKey(int nametableIndex, int index) + { + byte tileIndex = _tileData[nametableIndex][index]; + + for(int i = 0; i < 16; i++) { + _tmpTileData[i] = InteropEmu.DebugGetMemoryValue(DebugMemoryType.PpuMemory, (UInt32)(_state.PPU.ControlFlags.BackgroundPatternAddr + tileIndex * 16 + i)); + } + + return ctrlCharacterMapping.GetColorIndependentKey(_tmpTileData); + } + + private bool IgnoreTile(int nametableIndex) + { + if(chkIgnoreMirroredNametables.Checked) { + switch(_state.Cartridge.Mirroring) { + case MirroringType.ScreenAOnly: + case MirroringType.ScreenBOnly: + if(nametableIndex > 0) { + return true; + } + break; + + case MirroringType.Horizontal: + if((nametableIndex & 0x01) == 0x01) { + return true; + } + break; + + case MirroringType.Vertical: + if((nametableIndex & 0x02) == 0x02) { + return true; + } + break; + } + } + return false; + } + + public void SetCharacterMappings(ConcurrentDictionary charMappings) + { + _charMappings = charMappings; + } + + private void GetIndexes(int inNt, int inY, int inX, out int outNt, out int outY, out int outX) + { + outX = inX; + outY = inY; + outNt = inNt & 0x03; + + if(chkUseScrollOffsets.Checked) { + outY += _yScroll / 8; + outX += _xScroll / 8; + } + + while(outX < 0) { + outX += 32; + outNt ^= 1; + } + + while(outX >= 32) { + outX -= 32; + outNt ^= 1; + } + + while(outY >= 30) { + outY -= 30; + outNt ^= 2; + } + + while(outY < 0) { + outY += 30; + outNt ^= 2; + } + + outNt &= 0x03; + } + } + + enum DakutenType { + None = 0, + Dakuten = 1, + Handakuten = 2 + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlTextHooker.resx b/GUI.NET/Debugger/Controls/ctrlTextHooker.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlTextHooker.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/DebugWindowManager.cs b/GUI.NET/Debugger/DebugWindowManager.cs index 2a78e9b7..1d03d8aa 100644 --- a/GUI.NET/Debugger/DebugWindowManager.cs +++ b/GUI.NET/Debugger/DebugWindowManager.cs @@ -30,6 +30,7 @@ namespace Mesen.GUI.Debugger case DebugWindow.ScriptWindow: frm = new frmScript(); break; case DebugWindow.ApuViewer: frm = new frmApuViewer(); break; case DebugWindow.EventViewer: frm = new frmEventViewer(); break; + case DebugWindow.TextHooker: frm = new frmTextHooker(); break; } _openedWindows.Add(frm); frm.FormClosed += Debugger_FormClosed; @@ -92,6 +93,7 @@ namespace Mesen.GUI.Debugger case DebugWindow.Assembler: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmAssembler)); case DebugWindow.Debugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger)); case DebugWindow.ApuViewer: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmApuViewer)); + case DebugWindow.TextHooker: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmTextHooker)); } return null; @@ -126,6 +128,7 @@ namespace Mesen.GUI.Debugger Debugger, ScriptWindow, ApuViewer, - EventViewer + EventViewer, + TextHooker, } } diff --git a/GUI.NET/Debugger/frmDbgPreferences.cs b/GUI.NET/Debugger/frmDbgPreferences.cs index c4fc808f..32dbc25c 100644 --- a/GUI.NET/Debugger/frmDbgPreferences.cs +++ b/GUI.NET/Debugger/frmDbgPreferences.cs @@ -44,6 +44,7 @@ namespace Mesen.GUI.Debugger GetMember(nameof(DebuggerShortcutsConfig.OpenMemoryTools)), GetMember(nameof(DebuggerShortcutsConfig.OpenPpuViewer)), GetMember(nameof(DebuggerShortcutsConfig.OpenScriptWindow)), + GetMember(nameof(DebuggerShortcutsConfig.OpenTextHooker)), GetMember(nameof(DebuggerShortcutsConfig.OpenTraceLogger)) }; diff --git a/GUI.NET/Debugger/frmDebugger.Designer.cs b/GUI.NET/Debugger/frmDebugger.Designer.cs index f96105f8..be51fa32 100644 --- a/GUI.NET/Debugger/frmDebugger.Designer.cs +++ b/GUI.NET/Debugger/frmDebugger.Designer.cs @@ -178,6 +178,7 @@ namespace Mesen.GUI.Debugger this.mnuMemoryViewer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuPpuViewer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuScriptWindow = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuTextHooker = new System.Windows.Forms.ToolStripMenuItem(); this.mnuTraceLogger = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem13 = new System.Windows.Forms.ToolStripSeparator(); this.mnuEditHeader = new System.Windows.Forms.ToolStripMenuItem(); @@ -251,8 +252,8 @@ namespace Mesen.GUI.Debugger this.splitContainer.Panel2.Controls.Add(this.picWatchHelp); this.splitContainer.Panel2.Controls.Add(this.tableLayoutPanel10); this.splitContainer.Panel2MinSize = 100; - this.splitContainer.Size = new System.Drawing.Size(1075, 765); - this.splitContainer.SplitterDistance = 576; + this.splitContainer.Size = new System.Drawing.Size(1075, 570); + this.splitContainer.SplitterDistance = 438; this.splitContainer.SplitterWidth = 7; this.splitContainer.TabIndex = 1; this.splitContainer.TabStop = false; @@ -276,7 +277,7 @@ namespace Mesen.GUI.Debugger // this.ctrlSplitContainerTop.Panel2.Controls.Add(this.tlpFunctionLabelLists); this.ctrlSplitContainerTop.Panel2MinSize = 150; - this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1075, 576); + this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1075, 438); this.ctrlSplitContainerTop.SplitterDistance = 750; this.ctrlSplitContainerTop.SplitterWidth = 7; this.ctrlSplitContainerTop.TabIndex = 3; @@ -297,8 +298,8 @@ namespace Mesen.GUI.Debugger this.tlpTop.Name = "tlpTop"; this.tlpTop.RowCount = 1; this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 576F)); - this.tlpTop.Size = new System.Drawing.Size(750, 576); + this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 570F)); + this.tlpTop.Size = new System.Drawing.Size(750, 438); this.tlpTop.TabIndex = 2; // // panel1 @@ -309,7 +310,7 @@ namespace Mesen.GUI.Debugger this.panel1.Location = new System.Drawing.Point(3, 0); this.panel1.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(286, 576); + this.panel1.Size = new System.Drawing.Size(286, 438); this.panel1.TabIndex = 5; // // ctrlSourceViewer @@ -318,7 +319,7 @@ namespace Mesen.GUI.Debugger this.ctrlSourceViewer.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlSourceViewer.Location = new System.Drawing.Point(0, 0); this.ctrlSourceViewer.Name = "ctrlSourceViewer"; - this.ctrlSourceViewer.Size = new System.Drawing.Size(286, 576); + this.ctrlSourceViewer.Size = new System.Drawing.Size(286, 438); this.ctrlSourceViewer.SymbolProvider = null; this.ctrlSourceViewer.TabIndex = 7; this.ctrlSourceViewer.Visible = false; @@ -332,7 +333,7 @@ namespace Mesen.GUI.Debugger this.ctrlDebuggerCode.Location = new System.Drawing.Point(0, 0); this.ctrlDebuggerCode.Name = "ctrlDebuggerCode"; this.ctrlDebuggerCode.ShowMemoryValues = false; - this.ctrlDebuggerCode.Size = new System.Drawing.Size(286, 576); + this.ctrlDebuggerCode.Size = new System.Drawing.Size(286, 438); this.ctrlDebuggerCode.SymbolProvider = null; this.ctrlDebuggerCode.TabIndex = 2; this.ctrlDebuggerCode.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode); @@ -346,7 +347,7 @@ namespace Mesen.GUI.Debugger this.panel2.Location = new System.Drawing.Point(292, 0); this.panel2.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); this.panel2.Name = "panel2"; - this.panel2.Size = new System.Drawing.Size(1, 576); + this.panel2.Size = new System.Drawing.Size(1, 438); this.panel2.TabIndex = 6; // // ctrlSourceViewerSplit @@ -355,7 +356,7 @@ namespace Mesen.GUI.Debugger this.ctrlSourceViewerSplit.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlSourceViewerSplit.Location = new System.Drawing.Point(0, 0); this.ctrlSourceViewerSplit.Name = "ctrlSourceViewerSplit"; - this.ctrlSourceViewerSplit.Size = new System.Drawing.Size(1, 576); + this.ctrlSourceViewerSplit.Size = new System.Drawing.Size(1, 438); this.ctrlSourceViewerSplit.SymbolProvider = null; this.ctrlSourceViewerSplit.TabIndex = 8; this.ctrlSourceViewerSplit.Visible = false; @@ -369,7 +370,7 @@ namespace Mesen.GUI.Debugger this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(0, 0); this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit"; this.ctrlDebuggerCodeSplit.ShowMemoryValues = false; - this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 576); + this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 438); this.ctrlDebuggerCodeSplit.SymbolProvider = null; this.ctrlDebuggerCodeSplit.TabIndex = 4; this.ctrlDebuggerCodeSplit.Visible = false; @@ -389,7 +390,7 @@ namespace Mesen.GUI.Debugger this.tableLayoutPanel1.RowCount = 2; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(458, 576); + this.tableLayoutPanel1.Size = new System.Drawing.Size(458, 438); this.tableLayoutPanel1.TabIndex = 7; // // ctrlConsoleStatus @@ -413,7 +414,7 @@ namespace Mesen.GUI.Debugger this.tlpVerticalLayout.Name = "tlpVerticalLayout"; this.tlpVerticalLayout.RowCount = 1; this.tlpVerticalLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tlpVerticalLayout.Size = new System.Drawing.Size(458, 176); + this.tlpVerticalLayout.Size = new System.Drawing.Size(458, 38); this.tlpVerticalLayout.TabIndex = 4; // // tlpFunctionLabelLists @@ -429,16 +430,16 @@ namespace Mesen.GUI.Debugger this.tlpFunctionLabelLists.RowCount = 2; this.tlpFunctionLabelLists.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.tlpFunctionLabelLists.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tlpFunctionLabelLists.Size = new System.Drawing.Size(318, 576); + this.tlpFunctionLabelLists.Size = new System.Drawing.Size(318, 438); this.tlpFunctionLabelLists.TabIndex = 5; // // grpLabels // this.grpLabels.Controls.Add(this.ctrlLabelList); this.grpLabels.Dock = System.Windows.Forms.DockStyle.Fill; - this.grpLabels.Location = new System.Drawing.Point(3, 291); + this.grpLabels.Location = new System.Drawing.Point(3, 222); this.grpLabels.Name = "grpLabels"; - this.grpLabels.Size = new System.Drawing.Size(312, 282); + this.grpLabels.Size = new System.Drawing.Size(312, 213); this.grpLabels.TabIndex = 6; this.grpLabels.TabStop = false; this.grpLabels.Text = "Labels"; @@ -448,7 +449,7 @@ namespace Mesen.GUI.Debugger this.ctrlLabelList.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlLabelList.Location = new System.Drawing.Point(3, 16); this.ctrlLabelList.Name = "ctrlLabelList"; - this.ctrlLabelList.Size = new System.Drawing.Size(306, 263); + this.ctrlLabelList.Size = new System.Drawing.Size(306, 194); this.ctrlLabelList.TabIndex = 0; this.ctrlLabelList.OnFindOccurrence += new System.EventHandler(this.ctrlLabelList_OnFindOccurrence); this.ctrlLabelList.OnLabelSelected += new System.EventHandler(this.ctrlLabelList_OnLabelSelected); @@ -459,7 +460,7 @@ namespace Mesen.GUI.Debugger this.grpFunctions.Dock = System.Windows.Forms.DockStyle.Fill; this.grpFunctions.Location = new System.Drawing.Point(3, 3); this.grpFunctions.Name = "grpFunctions"; - this.grpFunctions.Size = new System.Drawing.Size(312, 282); + this.grpFunctions.Size = new System.Drawing.Size(312, 213); this.grpFunctions.TabIndex = 5; this.grpFunctions.TabStop = false; this.grpFunctions.Text = "Functions"; @@ -469,7 +470,7 @@ namespace Mesen.GUI.Debugger this.ctrlFunctionList.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlFunctionList.Location = new System.Drawing.Point(3, 16); this.ctrlFunctionList.Name = "ctrlFunctionList"; - this.ctrlFunctionList.Size = new System.Drawing.Size(306, 263); + this.ctrlFunctionList.Size = new System.Drawing.Size(306, 194); this.ctrlFunctionList.TabIndex = 0; this.ctrlFunctionList.OnFindOccurrence += new System.EventHandler(this.ctrlFunctionList_OnFindOccurrence); this.ctrlFunctionList.OnFunctionSelected += new System.EventHandler(this.ctrlFunctionList_OnFunctionSelected); @@ -500,7 +501,7 @@ namespace Mesen.GUI.Debugger this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel10.Size = new System.Drawing.Size(1075, 182); + this.tableLayoutPanel10.Size = new System.Drawing.Size(1075, 125); this.tableLayoutPanel10.TabIndex = 0; // // grpWatch @@ -509,7 +510,7 @@ namespace Mesen.GUI.Debugger this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill; this.grpWatch.Location = new System.Drawing.Point(3, 3); this.grpWatch.Name = "grpWatch"; - this.grpWatch.Size = new System.Drawing.Size(352, 176); + this.grpWatch.Size = new System.Drawing.Size(352, 119); this.grpWatch.TabIndex = 2; this.grpWatch.TabStop = false; this.grpWatch.Text = "Watch"; @@ -519,7 +520,7 @@ namespace Mesen.GUI.Debugger this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlWatch.Location = new System.Drawing.Point(3, 16); this.ctrlWatch.Name = "ctrlWatch"; - this.ctrlWatch.Size = new System.Drawing.Size(346, 157); + this.ctrlWatch.Size = new System.Drawing.Size(346, 100); this.ctrlWatch.TabIndex = 0; // // grpBreakpoints @@ -528,7 +529,7 @@ namespace Mesen.GUI.Debugger this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill; this.grpBreakpoints.Location = new System.Drawing.Point(361, 3); this.grpBreakpoints.Name = "grpBreakpoints"; - this.grpBreakpoints.Size = new System.Drawing.Size(352, 176); + this.grpBreakpoints.Size = new System.Drawing.Size(352, 119); this.grpBreakpoints.TabIndex = 3; this.grpBreakpoints.TabStop = false; this.grpBreakpoints.Text = "Breakpoints"; @@ -538,7 +539,7 @@ namespace Mesen.GUI.Debugger this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16); this.ctrlBreakpoints.Name = "ctrlBreakpoints"; - this.ctrlBreakpoints.Size = new System.Drawing.Size(346, 157); + this.ctrlBreakpoints.Size = new System.Drawing.Size(346, 100); this.ctrlBreakpoints.TabIndex = 0; this.ctrlBreakpoints.BreakpointNavigation += new System.EventHandler(this.ctrlBreakpoints_BreakpointNavigation); // @@ -548,7 +549,7 @@ namespace Mesen.GUI.Debugger this.grpCallstack.Dock = System.Windows.Forms.DockStyle.Fill; this.grpCallstack.Location = new System.Drawing.Point(719, 3); this.grpCallstack.Name = "grpCallstack"; - this.grpCallstack.Size = new System.Drawing.Size(353, 176); + this.grpCallstack.Size = new System.Drawing.Size(353, 119); this.grpCallstack.TabIndex = 4; this.grpCallstack.TabStop = false; this.grpCallstack.Text = "Call Stack"; @@ -558,7 +559,7 @@ namespace Mesen.GUI.Debugger this.ctrlCallstack.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlCallstack.Location = new System.Drawing.Point(3, 16); this.ctrlCallstack.Name = "ctrlCallstack"; - this.ctrlCallstack.Size = new System.Drawing.Size(347, 157); + this.ctrlCallstack.Size = new System.Drawing.Size(347, 100); this.ctrlCallstack.TabIndex = 0; this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected); // @@ -1533,6 +1534,7 @@ namespace Mesen.GUI.Debugger this.mnuMemoryViewer, this.mnuPpuViewer, this.mnuScriptWindow, + this.mnuTextHooker, this.mnuTraceLogger, this.toolStripMenuItem13, this.mnuEditHeader, @@ -1590,6 +1592,14 @@ namespace Mesen.GUI.Debugger this.mnuScriptWindow.Text = "Script Window"; this.mnuScriptWindow.Click += new System.EventHandler(this.mnuScriptWindow_Click); // + // mnuTextHooker + // + this.mnuTextHooker.Image = global::Mesen.GUI.Properties.Resources.Font; + this.mnuTextHooker.Name = "mnuTextHooker"; + this.mnuTextHooker.Size = new System.Drawing.Size(171, 22); + this.mnuTextHooker.Text = "Text Hooker"; + this.mnuTextHooker.Click += new System.EventHandler(this.mnuTextHooker_Click); + // // mnuTraceLogger // this.mnuTraceLogger.Image = global::Mesen.GUI.Properties.Resources.LogWindow; @@ -1707,7 +1717,7 @@ namespace Mesen.GUI.Debugger this.toolStripStatusLabel1, this.lblCyclesElapsedCount, this.lblCyclesElapsed}); - this.statusStrip.Location = new System.Drawing.Point(0, 855); + this.statusStrip.Location = new System.Drawing.Point(0, 660); this.statusStrip.Name = "statusStrip"; this.statusStrip.Size = new System.Drawing.Size(1075, 24); this.statusStrip.TabIndex = 3; @@ -1762,7 +1772,7 @@ namespace Mesen.GUI.Debugger // ctrlPpuMemoryMapping // this.ctrlPpuMemoryMapping.Dock = System.Windows.Forms.DockStyle.Bottom; - this.ctrlPpuMemoryMapping.Location = new System.Drawing.Point(0, 822); + this.ctrlPpuMemoryMapping.Location = new System.Drawing.Point(0, 627); this.ctrlPpuMemoryMapping.Name = "ctrlPpuMemoryMapping"; this.ctrlPpuMemoryMapping.Size = new System.Drawing.Size(1075, 33); this.ctrlPpuMemoryMapping.TabIndex = 5; @@ -1772,7 +1782,7 @@ namespace Mesen.GUI.Debugger // ctrlCpuMemoryMapping // this.ctrlCpuMemoryMapping.Dock = System.Windows.Forms.DockStyle.Bottom; - this.ctrlCpuMemoryMapping.Location = new System.Drawing.Point(0, 789); + this.ctrlCpuMemoryMapping.Location = new System.Drawing.Point(0, 594); this.ctrlCpuMemoryMapping.Name = "ctrlCpuMemoryMapping"; this.ctrlCpuMemoryMapping.Size = new System.Drawing.Size(1075, 33); this.ctrlCpuMemoryMapping.TabIndex = 4; @@ -1792,7 +1802,7 @@ namespace Mesen.GUI.Debugger // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1075, 879); + this.ClientSize = new System.Drawing.Size(1075, 684); this.Controls.Add(this.splitContainer); this.Controls.Add(this.ctrlCpuMemoryMapping); this.Controls.Add(this.ctrlPpuMemoryMapping); @@ -2007,5 +2017,6 @@ namespace Mesen.GUI.Debugger private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; private System.Windows.Forms.ToolStripMenuItem mnuUseVerticalLayout; private System.Windows.Forms.ToolStripMenuItem mnuBreakOnUninitMemoryRead; + private System.Windows.Forms.ToolStripMenuItem mnuTextHooker; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmDebugger.cs b/GUI.NET/Debugger/frmDebugger.cs index 4dc6fcbf..b000147c 100644 --- a/GUI.NET/Debugger/frmDebugger.cs +++ b/GUI.NET/Debugger/frmDebugger.cs @@ -265,6 +265,7 @@ namespace Mesen.GUI.Debugger mnuPpuViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenPpuViewer)); mnuScriptWindow.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenScriptWindow)); mnuTraceLogger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTraceLogger)); + mnuTextHooker.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTextHooker)); } private void InitToolbar() @@ -277,7 +278,7 @@ namespace Mesen.GUI.Debugger mnuRunPpuCycle, mnuRunScanline, mnuRunOneFrame, null, mnuToggleBreakpoint, mnuDisableEnableBreakpoint, null, mnuFind, mnuFindPrev, mnuFindNext, null, - mnuApuViewer, mnuAssembler, mnuEventViewer, mnuMemoryViewer, mnuPpuViewer, mnuScriptWindow, mnuTraceLogger, null, + mnuApuViewer, mnuAssembler, mnuEventViewer, mnuMemoryViewer, mnuPpuViewer, mnuScriptWindow, mnuTextHooker, mnuTraceLogger, null, mnuEditHeader, null, mnuSplitView, mnuUseVerticalLayout, null ); @@ -963,6 +964,11 @@ namespace Mesen.GUI.Debugger } } + private void mnuTextHooker_Click(object sender, EventArgs e) + { + DebugWindowManager.OpenDebugWindow(DebugWindow.TextHooker); + } + private void mnuTraceLogger_Click(object sender, EventArgs e) { DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger); diff --git a/GUI.NET/Debugger/frmPpuViewer.Designer.cs b/GUI.NET/Debugger/frmPpuViewer.Designer.cs index b67b4277..9232a196 100644 --- a/GUI.NET/Debugger/frmPpuViewer.Designer.cs +++ b/GUI.NET/Debugger/frmPpuViewer.Designer.cs @@ -40,6 +40,7 @@ namespace Mesen.GUI.Debugger this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRefreshOnBreak = new System.Windows.Forms.ToolStripMenuItem(); this.tabMain = new System.Windows.Forms.TabControl(); this.tpgNametableViewer = new System.Windows.Forms.TabPage(); this.ctrlNametableViewer = new Mesen.GUI.Debugger.Controls.ctrlNametableViewer(); @@ -49,20 +50,13 @@ namespace Mesen.GUI.Debugger this.ctrlSpriteViewer = new Mesen.GUI.Debugger.Controls.ctrlSpriteViewer(); this.tpgPaletteViewer = new System.Windows.Forms.TabPage(); this.ctrlPaletteViewer = new Mesen.GUI.Debugger.Controls.ctrlPaletteViewer(); - this.flpRefreshTiming = new System.Windows.Forms.FlowLayoutPanel(); - this.lblShowFrameAt = new System.Windows.Forms.Label(); - this.nudScanline = new Mesen.GUI.Controls.MesenNumericUpDown(); - this.lblCycle = new System.Windows.Forms.Label(); - this.nudCycle = new Mesen.GUI.Controls.MesenNumericUpDown(); - this.btnReset = new System.Windows.Forms.Button(); - this.mnuRefreshOnBreak = new System.Windows.Forms.ToolStripMenuItem(); + this.ctrlScanlineCycle = new Mesen.GUI.Debugger.Controls.ctrlScanlineCycleSelect(); this.menuStrip1.SuspendLayout(); this.tabMain.SuspendLayout(); this.tpgNametableViewer.SuspendLayout(); this.tpgChrViewer.SuspendLayout(); this.tpgSpriteViewer.SuspendLayout(); this.tpgPaletteViewer.SuspendLayout(); - this.flpRefreshTiming.SuspendLayout(); this.SuspendLayout(); // // menuStrip1 @@ -126,6 +120,14 @@ namespace Mesen.GUI.Debugger this.mnuAutoRefresh.Text = "Auto-refresh"; this.mnuAutoRefresh.Click += new System.EventHandler(this.mnuAutoRefresh_Click); // + // mnuRefreshOnBreak + // + this.mnuRefreshOnBreak.CheckOnClick = true; + this.mnuRefreshOnBreak.Name = "mnuRefreshOnBreak"; + this.mnuRefreshOnBreak.Size = new System.Drawing.Size(198, 22); + this.mnuRefreshOnBreak.Text = "Refresh on pause/break"; + this.mnuRefreshOnBreak.Click += new System.EventHandler(this.mnuRefreshOnBreak_Click); + // // tabMain // this.tabMain.Controls.Add(this.tpgNametableViewer); @@ -136,7 +138,7 @@ namespace Mesen.GUI.Debugger this.tabMain.Location = new System.Drawing.Point(0, 24); this.tabMain.Name = "tabMain"; this.tabMain.SelectedIndex = 0; - this.tabMain.Size = new System.Drawing.Size(709, 551); + this.tabMain.Size = new System.Drawing.Size(709, 553); this.tabMain.TabIndex = 3; this.tabMain.SelectedIndexChanged += new System.EventHandler(this.tabMain_SelectedIndexChanged); // @@ -145,7 +147,7 @@ namespace Mesen.GUI.Debugger this.tpgNametableViewer.Controls.Add(this.ctrlNametableViewer); this.tpgNametableViewer.Location = new System.Drawing.Point(4, 22); this.tpgNametableViewer.Name = "tpgNametableViewer"; - this.tpgNametableViewer.Size = new System.Drawing.Size(701, 525); + this.tpgNametableViewer.Size = new System.Drawing.Size(701, 527); this.tpgNametableViewer.TabIndex = 0; this.tpgNametableViewer.Text = "Nametable Viewer"; this.tpgNametableViewer.UseVisualStyleBackColor = true; @@ -155,7 +157,7 @@ namespace Mesen.GUI.Debugger this.ctrlNametableViewer.Dock = System.Windows.Forms.DockStyle.Fill; this.ctrlNametableViewer.Location = new System.Drawing.Point(0, 0); this.ctrlNametableViewer.Name = "ctrlNametableViewer"; - this.ctrlNametableViewer.Size = new System.Drawing.Size(701, 525); + this.ctrlNametableViewer.Size = new System.Drawing.Size(701, 527); this.ctrlNametableViewer.TabIndex = 0; this.ctrlNametableViewer.OnSelectChrTile += new System.EventHandler(this.ctrlNametableViewer_OnSelectChrTile); // @@ -215,118 +217,13 @@ namespace Mesen.GUI.Debugger this.ctrlPaletteViewer.Size = new System.Drawing.Size(701, 525); this.ctrlPaletteViewer.TabIndex = 0; // - // flpRefreshTiming + // ctrlScanlineCycle // - this.flpRefreshTiming.Controls.Add(this.lblShowFrameAt); - this.flpRefreshTiming.Controls.Add(this.nudScanline); - this.flpRefreshTiming.Controls.Add(this.lblCycle); - this.flpRefreshTiming.Controls.Add(this.nudCycle); - this.flpRefreshTiming.Controls.Add(this.btnReset); - this.flpRefreshTiming.Dock = System.Windows.Forms.DockStyle.Bottom; - this.flpRefreshTiming.Location = new System.Drawing.Point(0, 575); - this.flpRefreshTiming.Name = "flpRefreshTiming"; - this.flpRefreshTiming.Size = new System.Drawing.Size(709, 30); - this.flpRefreshTiming.TabIndex = 4; - // - // lblShowFrameAt - // - this.lblShowFrameAt.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.lblShowFrameAt.AutoSize = true; - this.lblShowFrameAt.Location = new System.Drawing.Point(3, 8); - this.lblShowFrameAt.Name = "lblShowFrameAt"; - this.lblShowFrameAt.Size = new System.Drawing.Size(266, 13); - this.lblShowFrameAt.TabIndex = 0; - this.lblShowFrameAt.Text = "When emulation is running, show PPU data at scanline"; - // - // nudScanline - // - this.nudScanline.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.nudScanline.DecimalPlaces = 0; - this.nudScanline.Increment = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.nudScanline.Location = new System.Drawing.Point(275, 4); - this.nudScanline.Maximum = new decimal(new int[] { - 260, - 0, - 0, - 0}); - this.nudScanline.MaximumSize = new System.Drawing.Size(10000, 20); - this.nudScanline.Minimum = new decimal(new int[] { - 1, - 0, - 0, - -2147483648}); - this.nudScanline.Name = "nudScanline"; - this.nudScanline.Size = new System.Drawing.Size(52, 20); - this.nudScanline.TabIndex = 5; - this.nudScanline.Value = new decimal(new int[] { - 241, - 0, - 0, - 0}); - this.nudScanline.ValueChanged += new System.EventHandler(this.nudScanlineCycle_ValueChanged); - // - // lblCycle - // - this.lblCycle.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.lblCycle.AutoSize = true; - this.lblCycle.Location = new System.Drawing.Point(333, 8); - this.lblCycle.Name = "lblCycle"; - this.lblCycle.Size = new System.Drawing.Size(53, 13); - this.lblCycle.TabIndex = 5; - this.lblCycle.Text = "and cycle"; - // - // nudCycle - // - this.nudCycle.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.nudCycle.DecimalPlaces = 0; - this.nudCycle.Increment = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.nudCycle.Location = new System.Drawing.Point(392, 4); - this.nudCycle.Maximum = new decimal(new int[] { - 340, - 0, - 0, - 0}); - this.nudCycle.MaximumSize = new System.Drawing.Size(10000, 20); - this.nudCycle.Minimum = new decimal(new int[] { - 0, - 0, - 0, - 0}); - this.nudCycle.Name = "nudCycle"; - this.nudCycle.Size = new System.Drawing.Size(52, 20); - this.nudCycle.TabIndex = 6; - this.nudCycle.Value = new decimal(new int[] { - 0, - 0, - 0, - 0}); - this.nudCycle.ValueChanged += new System.EventHandler(this.nudScanlineCycle_ValueChanged); - // - // btnReset - // - this.btnReset.Location = new System.Drawing.Point(450, 3); - this.btnReset.Name = "btnReset"; - this.btnReset.Size = new System.Drawing.Size(75, 23); - this.btnReset.TabIndex = 7; - this.btnReset.Text = "Reset"; - this.btnReset.UseVisualStyleBackColor = true; - this.btnReset.Click += new System.EventHandler(this.btnReset_Click); - // - // mnuRefreshOnBreak - // - this.mnuRefreshOnBreak.CheckOnClick = true; - this.mnuRefreshOnBreak.Name = "mnuRefreshOnBreak"; - this.mnuRefreshOnBreak.Size = new System.Drawing.Size(198, 22); - this.mnuRefreshOnBreak.Text = "Refresh on pause/break"; - this.mnuRefreshOnBreak.Click += new System.EventHandler(this.mnuRefreshOnBreak_Click); + this.ctrlScanlineCycle.Dock = System.Windows.Forms.DockStyle.Bottom; + this.ctrlScanlineCycle.Location = new System.Drawing.Point(0, 577); + this.ctrlScanlineCycle.Name = "ctrlScanlineCycle"; + this.ctrlScanlineCycle.Size = new System.Drawing.Size(709, 28); + this.ctrlScanlineCycle.TabIndex = 4; // // frmPpuViewer // @@ -335,7 +232,7 @@ namespace Mesen.GUI.Debugger this.ClientSize = new System.Drawing.Size(709, 605); this.Controls.Add(this.tabMain); this.Controls.Add(this.menuStrip1); - this.Controls.Add(this.flpRefreshTiming); + this.Controls.Add(this.ctrlScanlineCycle); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.MainMenuStrip = this.menuStrip1; this.MaximizeBox = false; @@ -350,8 +247,6 @@ namespace Mesen.GUI.Debugger this.tpgChrViewer.ResumeLayout(false); this.tpgSpriteViewer.ResumeLayout(false); this.tpgPaletteViewer.ResumeLayout(false); - this.flpRefreshTiming.ResumeLayout(false); - this.flpRefreshTiming.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -375,12 +270,7 @@ namespace Mesen.GUI.Debugger private System.Windows.Forms.TabPage tpgPaletteViewer; private Controls.ctrlPaletteViewer ctrlPaletteViewer; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; - private System.Windows.Forms.FlowLayoutPanel flpRefreshTiming; - private System.Windows.Forms.Label lblShowFrameAt; - private MesenNumericUpDown nudScanline; - private System.Windows.Forms.Label lblCycle; - private MesenNumericUpDown nudCycle; - private System.Windows.Forms.Button btnReset; private System.Windows.Forms.ToolStripMenuItem mnuRefreshOnBreak; + private Controls.ctrlScanlineCycleSelect ctrlScanlineCycle; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmPpuViewer.cs b/GUI.NET/Debugger/frmPpuViewer.cs index d6c0ef44..44055137 100644 --- a/GUI.NET/Debugger/frmPpuViewer.cs +++ b/GUI.NET/Debugger/frmPpuViewer.cs @@ -28,8 +28,7 @@ namespace Mesen.GUI.Debugger { InitializeComponent(); - _ppuViewerId = _nextPpuViewerId; - _nextPpuViewerId++; + _ppuViewerId = GetNextPpuViewerId(); this._selectedTab = this.tpgNametableViewer; this.mnuAutoRefresh.Checked = ConfigManager.Config.DebugInfo.PpuAutoRefresh; @@ -42,6 +41,11 @@ namespace Mesen.GUI.Debugger } } + public static int GetNextPpuViewerId() + { + return _nextPpuViewerId++; + } + private void InitShortcuts() { mnuRefresh.InitShortcut(this, nameof(DebuggerShortcutsConfig.Refresh)); @@ -55,10 +59,7 @@ namespace Mesen.GUI.Debugger this._notifListener = new InteropEmu.NotificationListener(); this._notifListener.OnNotification += this._notifListener_OnNotification; - this.nudScanline.Value = ConfigManager.Config.DebugInfo.PpuDisplayScanline; - this.nudCycle.Value = ConfigManager.Config.DebugInfo.PpuDisplayCycle; - - InteropEmu.DebugSetPpuViewerScanlineCycle(_ppuViewerId, (int)this.nudScanline.Value, (int)this.nudCycle.Value); + this.ctrlScanlineCycle.Initialize(_ppuViewerId, ConfigManager.Config.DebugInfo.PpuDisplayScanline, ConfigManager.Config.DebugInfo.PpuDisplayCycle); this.ctrlNametableViewer.GetData(); this.ctrlChrViewer.GetData(); @@ -79,6 +80,8 @@ namespace Mesen.GUI.Debugger base.OnFormClosing(e); this._notifListener.OnNotification -= this._notifListener_OnNotification; ConfigManager.Config.DebugInfo.PpuWindowLocation = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Location : this.Location; + ConfigManager.Config.DebugInfo.PpuDisplayScanline = ctrlScanlineCycle.Scanline; + ConfigManager.Config.DebugInfo.PpuDisplayCycle = ctrlScanlineCycle.Cycle; ConfigManager.ApplyChanges(); InteropEmu.DebugClearPpuViewerSettings(_ppuViewerId); } @@ -107,7 +110,7 @@ namespace Mesen.GUI.Debugger case InteropEmu.ConsoleNotificationType.GameLoaded: //Configuration is lost when debugger is restarted (when switching game or power cycling) - InteropEmu.DebugSetPpuViewerScanlineCycle(_ppuViewerId, ConfigManager.Config.DebugInfo.PpuDisplayScanline, ConfigManager.Config.DebugInfo.PpuDisplayCycle); + ctrlScanlineCycle.RefreshSettings(); break; } } @@ -162,23 +165,7 @@ namespace Mesen.GUI.Debugger ConfigManager.Config.DebugInfo.PpuRefreshOnBreak = this.mnuRefreshOnBreak.Checked; ConfigManager.ApplyChanges(); } - - private void SetUpdateScanlineCycle(int scanline, int cycle) - { - scanline = Math.Min(260, Math.Max(-1, scanline)); - cycle = Math.Min(340, Math.Max(0, cycle)); - - InteropEmu.DebugSetPpuViewerScanlineCycle(_ppuViewerId, scanline, cycle); - ConfigManager.Config.DebugInfo.PpuDisplayScanline = scanline; - ConfigManager.Config.DebugInfo.PpuDisplayCycle = cycle; - ConfigManager.ApplyChanges(); - } - - private void nudScanlineCycle_ValueChanged(object sender, EventArgs e) - { - SetUpdateScanlineCycle((int)this.nudScanline.Value, (int)this.nudCycle.Value); - } - + private void tabMain_SelectedIndexChanged(object sender, EventArgs e) { this._selectedTab = this.tabMain.SelectedTab; @@ -189,15 +176,9 @@ namespace Mesen.GUI.Debugger } } - private void btnReset_Click(object sender, EventArgs e) - { - this.nudScanline.Value = 241; - this.nudCycle.Value = 0; - } - protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { - if(!this.nudScanline.ContainsFocus && !this.nudCycle.ContainsFocus) { + if(!this.ctrlScanlineCycle.ContainsFocus) { if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.Copy) { if(this.tabMain.SelectedTab == tpgNametableViewer) { ctrlNametableViewer.CopyToClipboard(); diff --git a/GUI.NET/Debugger/frmTextHooker.Designer.cs b/GUI.NET/Debugger/frmTextHooker.Designer.cs new file mode 100644 index 00000000..68b36d2a --- /dev/null +++ b/GUI.NET/Debugger/frmTextHooker.Designer.cs @@ -0,0 +1,222 @@ +using Mesen.GUI.Controls; + +namespace Mesen.GUI.Debugger +{ + partial class frmTextHooker + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + if(this._notifListener != null) { + this._notifListener.Dispose(); + this._notifListener = null; + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.menuStrip1 = new Mesen.GUI.Controls.ctrlMesenMenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuClose = new System.Windows.Forms.ToolStripMenuItem(); + this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRefreshOnBreak = new System.Windows.Forms.ToolStripMenuItem(); + this.tabMain = new System.Windows.Forms.TabControl(); + this.tpgTextHooker = new System.Windows.Forms.TabPage(); + this.ctrlTextHooker = new Mesen.GUI.Debugger.Controls.ctrlTextHooker(); + this.tpgCharacterMappings = new System.Windows.Forms.TabPage(); + this.ctrlCharacterMappings = new Mesen.GUI.Debugger.Controls.ctrlCharacterMappings(); + this.ctrlScanlineCycle = new Mesen.GUI.Debugger.Controls.ctrlScanlineCycleSelect(); + this.menuStrip1.SuspendLayout(); + this.tabMain.SuspendLayout(); + this.tpgTextHooker.SuspendLayout(); + this.tpgCharacterMappings.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.viewToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(857, 24); + this.menuStrip1.TabIndex = 2; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuClose}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Text = "File"; + // + // mnuClose + // + this.mnuClose.Image = global::Mesen.GUI.Properties.Resources.Exit; + this.mnuClose.Name = "mnuClose"; + this.mnuClose.Size = new System.Drawing.Size(103, 22); + this.mnuClose.Text = "Close"; + this.mnuClose.Click += new System.EventHandler(this.mnuClose_Click); + // + // viewToolStripMenuItem + // + this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuRefresh, + this.toolStripMenuItem1, + this.mnuAutoRefresh, + this.mnuRefreshOnBreak}); + this.viewToolStripMenuItem.Name = "viewToolStripMenuItem"; + this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20); + this.viewToolStripMenuItem.Text = "View"; + // + // mnuRefresh + // + this.mnuRefresh.Image = global::Mesen.GUI.Properties.Resources.Reset; + this.mnuRefresh.Name = "mnuRefresh"; + this.mnuRefresh.Size = new System.Drawing.Size(198, 22); + this.mnuRefresh.Text = "Refresh"; + this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(195, 6); + // + // mnuAutoRefresh + // + this.mnuAutoRefresh.Checked = true; + this.mnuAutoRefresh.CheckOnClick = true; + this.mnuAutoRefresh.CheckState = System.Windows.Forms.CheckState.Checked; + this.mnuAutoRefresh.Name = "mnuAutoRefresh"; + this.mnuAutoRefresh.Size = new System.Drawing.Size(198, 22); + this.mnuAutoRefresh.Text = "Auto-refresh"; + this.mnuAutoRefresh.Click += new System.EventHandler(this.mnuAutoRefresh_Click); + // + // mnuRefreshOnBreak + // + this.mnuRefreshOnBreak.CheckOnClick = true; + this.mnuRefreshOnBreak.Name = "mnuRefreshOnBreak"; + this.mnuRefreshOnBreak.Size = new System.Drawing.Size(198, 22); + this.mnuRefreshOnBreak.Text = "Refresh on pause/break"; + this.mnuRefreshOnBreak.Click += new System.EventHandler(this.mnuRefreshOnBreak_Click); + // + // tabMain + // + this.tabMain.Controls.Add(this.tpgTextHooker); + this.tabMain.Controls.Add(this.tpgCharacterMappings); + this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabMain.Location = new System.Drawing.Point(0, 24); + this.tabMain.Name = "tabMain"; + this.tabMain.SelectedIndex = 0; + this.tabMain.Size = new System.Drawing.Size(857, 515); + this.tabMain.TabIndex = 3; + this.tabMain.SelectedIndexChanged += new System.EventHandler(this.tabMain_SelectedIndexChanged); + // + // tpgTextHooker + // + this.tpgTextHooker.Controls.Add(this.ctrlTextHooker); + this.tpgTextHooker.Location = new System.Drawing.Point(4, 22); + this.tpgTextHooker.Name = "tpgTextHooker"; + this.tpgTextHooker.Size = new System.Drawing.Size(849, 489); + this.tpgTextHooker.TabIndex = 0; + this.tpgTextHooker.Text = "Text Hooker"; + this.tpgTextHooker.UseVisualStyleBackColor = true; + // + // ctrlTextHooker + // + this.ctrlTextHooker.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlTextHooker.Location = new System.Drawing.Point(0, 0); + this.ctrlTextHooker.Name = "ctrlTextHooker"; + this.ctrlTextHooker.Size = new System.Drawing.Size(849, 489); + this.ctrlTextHooker.TabIndex = 0; + // + // tpgCharacterMappings + // + this.tpgCharacterMappings.Controls.Add(this.ctrlCharacterMappings); + this.tpgCharacterMappings.Location = new System.Drawing.Point(4, 22); + this.tpgCharacterMappings.Name = "tpgCharacterMappings"; + this.tpgCharacterMappings.Size = new System.Drawing.Size(849, 489); + this.tpgCharacterMappings.TabIndex = 1; + this.tpgCharacterMappings.Text = "Character Mappings"; + this.tpgCharacterMappings.UseVisualStyleBackColor = true; + // + // ctrlCharacterMappings + // + this.ctrlCharacterMappings.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlCharacterMappings.Location = new System.Drawing.Point(0, 0); + this.ctrlCharacterMappings.Name = "ctrlCharacterMappings"; + this.ctrlCharacterMappings.Size = new System.Drawing.Size(849, 489); + this.ctrlCharacterMappings.TabIndex = 0; + // + // ctrlScanlineCycle + // + this.ctrlScanlineCycle.Dock = System.Windows.Forms.DockStyle.Bottom; + this.ctrlScanlineCycle.Location = new System.Drawing.Point(0, 539); + this.ctrlScanlineCycle.Name = "ctrlScanlineCycle"; + this.ctrlScanlineCycle.Size = new System.Drawing.Size(857, 28); + this.ctrlScanlineCycle.TabIndex = 4; + // + // frmTextHooker + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(857, 567); + this.Controls.Add(this.tabMain); + this.Controls.Add(this.ctrlScanlineCycle); + this.Controls.Add(this.menuStrip1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MainMenuStrip = this.menuStrip1; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "frmTextHooker"; + this.Text = "Text Hooker"; + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.tabMain.ResumeLayout(false); + this.tpgTextHooker.ResumeLayout(false); + this.tpgCharacterMappings.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private Mesen.GUI.Controls.ctrlMesenMenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem mnuClose; + private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem mnuRefresh; + private System.Windows.Forms.ToolStripMenuItem mnuAutoRefresh; + private System.Windows.Forms.TabControl tabMain; + private System.Windows.Forms.TabPage tpgTextHooker; + private System.Windows.Forms.TabPage tpgCharacterMappings; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem mnuRefreshOnBreak; + private Controls.ctrlTextHooker ctrlTextHooker; + private Controls.ctrlCharacterMappings ctrlCharacterMappings; + private Controls.ctrlScanlineCycleSelect ctrlScanlineCycle; + } +} \ No newline at end of file diff --git a/GUI.NET/Debugger/frmTextHooker.cs b/GUI.NET/Debugger/frmTextHooker.cs new file mode 100644 index 00000000..7b694bab --- /dev/null +++ b/GUI.NET/Debugger/frmTextHooker.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Mesen.GUI.Config; +using Mesen.GUI.Forms; + +namespace Mesen.GUI.Debugger +{ + public partial class frmTextHooker : BaseForm + { + private static Dictionary _defaultCharMappings = new Dictionary(); + private ConcurrentDictionary _charMappings = new ConcurrentDictionary(); + + private DateTime _lastUpdate = DateTime.MinValue; + private InteropEmu.NotificationListener _notifListener; + private TabPage _selectedTab; + private bool _refreshing = false; + private int _ppuViewerId = 0; + + public frmTextHooker() + { + InitializeComponent(); + + _ppuViewerId = frmPpuViewer.GetNextPpuViewerId(); + + this._selectedTab = this.tpgTextHooker; + this.mnuAutoRefresh.Checked = ConfigManager.Config.DebugInfo.TextHookerAutoRefresh; + this.mnuRefreshOnBreak.Checked = ConfigManager.Config.DebugInfo.TextHookerRefreshOnBreak; + + if(ConfigManager.Config.DebugInfo.TextHookerWindowLocation.HasValue) { + this.StartPosition = FormStartPosition.Manual; + this.Location = ConfigManager.Config.DebugInfo.TextHookerWindowLocation.Value; + } + } + + static frmTextHooker() + { + char[] separator = new char[] { ',' }; + foreach(string mappingRow in ResourceManager.ReadZippedResource("CharacterMappings.txt").Replace("\r", "").Split('\n')) { + string[] parts = mappingRow.Split(separator, 2); + if(parts.Length == 2) { + _defaultCharMappings[parts[0]] = parts[1]; + } + } + } + + private void InitShortcuts() + { + mnuRefresh.InitShortcut(this, nameof(DebuggerShortcutsConfig.Refresh)); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + if(!this.DesignMode) { + this._charMappings = new ConcurrentDictionary(); + + foreach(KeyValuePair kvp in _defaultCharMappings) { + this._charMappings[kvp.Key] = kvp.Value; + } + + foreach(CharMap mapping in ConfigManager.Config.DebugInfo.TextHookerCharMappings) { + this._charMappings[mapping.Key] = mapping.Value; + } + + this.ctrlScanlineCycle.Initialize(_ppuViewerId, ConfigManager.Config.DebugInfo.TextHookerDisplayScanline, ConfigManager.Config.DebugInfo.TextHookerDisplayCycle); + this.ctrlTextHooker.SetCharacterMappings(_charMappings); + this.ctrlCharacterMappings.SetCharacterMappings(_charMappings); + + this._notifListener = new InteropEmu.NotificationListener(); + this._notifListener.OnNotification += this._notifListener_OnNotification; + + this.ctrlTextHooker.GetData(); + this.ctrlCharacterMappings.GetData(); + + this.ctrlTextHooker.RefreshViewer(); + this.ctrlCharacterMappings.RefreshViewer(); + + this.InitShortcuts(); + } + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + base.OnFormClosing(e); + this._notifListener.OnNotification -= this._notifListener_OnNotification; + InteropEmu.DebugClearPpuViewerSettings(_ppuViewerId); + + List mappings = new List(); + foreach(KeyValuePair kvp in _charMappings) { + if(!string.IsNullOrWhiteSpace(kvp.Value)) { + string defaultMapping; + if(_defaultCharMappings.TryGetValue(kvp.Key, out defaultMapping)) { + if(defaultMapping == kvp.Value) { + //Don't save mapping in user's profile if it matches the built-in mappings + continue; + } + } + + mappings.Add(new CharMap() { Key = kvp.Key, Value = kvp.Value }); + } + } + ConfigManager.Config.DebugInfo.TextHookerCharMappings = mappings; + ConfigManager.Config.DebugInfo.TextHookerWindowLocation = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Location : this.Location; + ConfigManager.Config.DebugInfo.TextHookerDisplayScanline = ctrlScanlineCycle.Scanline; + ConfigManager.Config.DebugInfo.TextHookerDisplayCycle = ctrlScanlineCycle.Cycle; + ConfigManager.ApplyChanges(); + } + + private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e) + { + switch(e.NotificationType) { + case InteropEmu.ConsoleNotificationType.CodeBreak: + case InteropEmu.ConsoleNotificationType.GamePaused: + if(ConfigManager.Config.DebugInfo.TextHookerRefreshOnBreak) { + this.GetData(); + this.BeginInvoke((MethodInvoker)(() => this.RefreshViewers())); + } + break; + + case InteropEmu.ConsoleNotificationType.PpuViewerDisplayFrame: + if(e.Parameter.ToInt32() == _ppuViewerId) { + if(ConfigManager.Config.DebugInfo.TextHookerAutoRefresh && !_refreshing && (DateTime.Now - _lastUpdate).Milliseconds > 66) { + //Update at 15 fps at most + this.GetData(); + this.BeginInvoke((MethodInvoker)(() => this.RefreshViewers())); + _lastUpdate = DateTime.Now; + } + } + break; + + case InteropEmu.ConsoleNotificationType.GameLoaded: + //Configuration is lost when debugger is restarted (when switching game or power cycling) + ctrlScanlineCycle.RefreshSettings(); + break; + } + } + + private void GetData() + { + if(_selectedTab == this.tpgTextHooker) { + this.ctrlTextHooker.GetData(); + } else if(_selectedTab == this.tpgCharacterMappings) { + this.ctrlCharacterMappings.GetData(); + } + } + + private void RefreshViewers() + { + _refreshing = true; + if(_selectedTab == this.tpgTextHooker) { + this.ctrlTextHooker.RefreshViewer(); + } else if(_selectedTab == this.tpgCharacterMappings) { + this.ctrlCharacterMappings.RefreshViewer(); + } + _refreshing = false; + } + + private void mnuRefresh_Click(object sender, EventArgs e) + { + this.GetData(); + this.RefreshViewers(); + } + + private void mnuClose_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void mnuAutoRefresh_Click(object sender, EventArgs e) + { + ConfigManager.Config.DebugInfo.TextHookerAutoRefresh = this.mnuAutoRefresh.Checked; + ConfigManager.ApplyChanges(); + } + + private void mnuRefreshOnBreak_Click(object sender, EventArgs e) + { + ConfigManager.Config.DebugInfo.TextHookerRefreshOnBreak = this.mnuRefreshOnBreak.Checked; + ConfigManager.ApplyChanges(); + } + + private void tabMain_SelectedIndexChanged(object sender, EventArgs e) + { + this._selectedTab = this.tabMain.SelectedTab; + if(InteropEmu.DebugIsExecutionStopped()) { + //Refresh data when changing tabs when not running + this.GetData(); + this.RefreshViewers(); + } + } + } +} diff --git a/GUI.NET/Debugger/frmTextHooker.resx b/GUI.NET/Debugger/frmTextHooker.resx new file mode 100644 index 00000000..e83821e0 --- /dev/null +++ b/GUI.NET/Debugger/frmTextHooker.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 107, 17 + + \ No newline at end of file diff --git a/GUI.NET/Dependencies/CharacterMappings.txt b/GUI.NET/Dependencies/CharacterMappings.txt new file mode 100644 index 00000000..d02d6608 --- /dev/null +++ b/GUI.NET/Dependencies/CharacterMappings.txt @@ -0,0 +1,1289 @@ +00005405051405145400051405145405,3 +50551454145414545055005400540000,P +00005515001454150500050005145405,5 +9452945294529451545554549452800A,W +00005005141414141414500500000000,o +54555000400100050014005054550000,Z +00000000101040040001400410100000,x +00000001550104010404040010004000,ケ +00000400550514001400440004010404,オ +00004000540504001000540141144000,ネ +00005055145014505055145014505055,B +A4AA545A400A400A400A400A400A4005,T +A400A400A400A400A429A429901A4005,J +00001450545450154005501554541450,X +00005405051405141400400100055515,2 +00000000000040551000100040010000,っ +945294525094529442A54AA50AA92AAA,V +00005055141414141414501500140055,P +50551450145050554051505014500000,R +50051414141450004001400100004001,? +9452945294525454509542A50AA92AA8,V +04054100040001014010444044400001,ぶ +00001450145014501450145014505015,U +50050410041004105405040010004001,9 +50051414001454141414540500000000,G +00005015145014505015145014505015,8 +14141414500540014001400100000000,Y +40055014145014505051141445050000,Q +40005045445044504440500540000000,ゆ +00005005140040000000000000105405,こ +50155450540050050015005454550000,2 +40AA40290029002900290929A9AA5515,L +A40A692915A500A400A42969A51A5405,C +00000000540100000000000000005505,ニ +54550050005050550050005054550000,E +50151450545050014005041554550000,2 +00000450445144514451445144551015,W +00054000001050110414040010004001,ら +54551450500040010005000500050000,7 +A42A29A4A502942A50A9A9AA55550000,2 +00005455041400145015001400140055,F +94529454145554555451545014528002,N +00005415400140014001400140010000,T +54551400100150010001000100050000,ア +50011404051405140514040550010000,0 +00005455005050551400140014505015,5 +54551400140054551400140054550000,ヨ +A42A29A4A92A6915A500942A50150000,9 +54501014401400155014141404500000,K +A42A69A5999AA99A999A69A5A56A5415,© +14501454145554555451545014500000,N +50151450145014505451505044150000,Q +50005001500050005000500055050000,1 +54555400500140050015005454550000,Z +00005015041004105015001000100010,P +00010001141541010101150511110501,ね +00005455004050550400040004405015,5 +00005015040504050405040504055015,D +50010005000550550005000500040000,f +00041004045544044010401040440041,か +50004001000500140005400150000000,く +40150401050404100410041010104005,ひ +40150001040104015415044410444010,み +00000000000014141414000000000000,‥ +A4AA69A529A4A5AA54A500A400A40014,P +00001450505040510055405150501450,K +50151454145414541454145450150000,O +00000000500114050014040550010000,c +00000000500514150054145450150000,c +00015455140050004005101104410000,ネ +54154001400140014001400140010000,T +9452945294525455145094529452A082,H +00000000000040014001000000000000,・ +50155450545054155400544050150000,9 +A4AA69A529A4A5AA69A529A4A5AA5455,B +00500014001400140014041454510000,L +54055000500050005000505040150000,J +54550050005050555400544050150000,5 +00000000000054550000000000000000,ー +04000400100010004000000100040050,ノ +00004015000500050005010501055515,L +00005455A46A5469A56A6955A56A5455,5 +00045055140414041414141050400000,カ +00000000541504100400040010004001,ワ +902AA4A554A4A02A690529A0A52A5405,S +00005415040010001001400010010414,ヌ +00000000400140010000000040014001,: +00005415010501055405000500054015,P +A42A69A515A400A400A429A4A46A5015,C +50050410041050050410041004105005,8 +00050001541550001000001450050000,さ +00551004141010401040404040400015,ひ +54505051405500554055505154500000,K +40101004400054150001000450010000,そ +54050514001454050500051454050000,S +40014001000500000000000000000000,' +54154001400140014001400100000000,T +00000015040004150400100040000015,シ +902AA4A554A4A42A691529A4A52A5415,S +50050414005000500050005004145005,C +00005015041404145015001400140014,P +00004414441444145415100500000000,W +54150410041010004000000100010001,7 +00005400540114051404141455151400,4 +54154141400140014001400100050000,T +00001015400550015404141000000000,X +00000000001040554010001100100000,ャ +00540044005400000000000000000000,゚ +00050005000500050005000555050000,L +00000000000040444000000100140000,ッ +50151450140050050014005054550000,2 +50151450145050151450145050150000,8 +00000000440550145014500514005405,g +00150000401510501000400000050000,う +00004000100110011001400014010000,l +14501454145554555454145414540000,N +50050410041050000001000100000001,? +54150014541505000500051454050000,5 +A4AA69A529A4A4AA69A529A4A5AA5455,B +54050514051405140514051454050000,O +50155450544050010005001454550000,2 +00004000000100040010044054550400,ム +14505454545454551451145114500000,M +00005515001400145415001400145515,E +00004000550541004100410001010404,カ +00005515100040000001000100015000,て +04100450045404540451445014500410,N +50050014005050551450145050150000,6 +A4AA69A529A4A9A495AAA0A6A9A45554,R +00005455005000505055005000500050,F +00000000000000050005400000010000,, +50551454145414541454145450550000,D +00404055015505541550554000405555,Z +50151450005050151400145050150000,S +10001040544110401040544110445041,は +14505454545554551451145014500000,M +00000005000500050005000500050005,I +00000000000004000400040004005405,」 +54055141514011414141514145055555,N +54550050005050550050005000500000,F +00004001000150050001000100010000,f +00140014401550151054105010500000,h +00005515010041005400400040000001,ア +00005055141414141414141414145055,D +40004000000100014005400440101410,ん +40005415000100045005041004005001,ち +00545550554140415041505000545555,G +50150001501500014015104100140000,ま +14051405040100000000000000000000," +50050414041550051510051054050000,8 +50415041504150415041504101505555,U +50551454145450555054145414540000,R +50151450140050051400145050150000,3 +00000000101010111011101140040000,w +9452505242510A554A5152529452A082,K +00000000501154151454145014500000,n +00015015000115040004001040101510,た +50005001400540154051400140010000,イ +54550050005050551400140050550000,5 +00015455000100015455000100010000,キ +00005415000100015415000100015401,モ +50550150414101404155414105505555,g +00001555041404140414041404145005,U +54551440144014001000500040050000,ワ +00001450145014501451545554541450,W +00000000000000005405000000000000,ー +00005015141414145015001400140000,p +00005400440144010405540504140455,A +A42A69A52950A40A502900A4A9AA5555,2 +A42A69A52950A40A690529A0A56A5415,3 +00000000505454151411141105110000,m +00005015145000505451145014505015,G +00001554041544155414141404140455,N +50150050505554505450545050150000,6 +00001414141414141414540500000000,u +00000000141014501450545044150000,u +00045055000454140010005154410000,た +00145014401440155015501400000000,k +50414040015005540150404050415555,X +00001414141410045005400100000000,v +10101010101010101004400000010000,り +00005411001000100010001154110000,に +50155450545050155450545050150000,8 +A402A40AA429A4A4A9AAA515A4001400,4 +14581656965556595658165816580A28,N +00005415A45A5469A56A6969A55A5415,6 +00004001400140000001000000000000,' +00151001100454151044104440100000,み +00000000041504000400040010004015,ン +00100050005000500050005004505015,L +00000000000000005555000000000000,ー +14505014400540055014145004400000,X +14500414041404151005400540010000,V +50150450045004505055405010500410,R +50415041504140400150055415555555,V +A4AA69A529A429A4A5AA54A500A40054,P +14505454501540055015545414500000,X +50154000000150050410040004005005,ろ +00005015500050155050541500000000,a +00005405011400145405050005105405,S +5015965A16A05A05A81600585655AAAA,2 +00000000540514141450545044150400,q +00000000400454050414100100014000,ゃ +00005455005000505055005000505455,E +00005005001450055400500500000000,s +00000000500514141450145050150000,o +00000000000050550000000000000000,- +00500050005000500050005054550000,L +00005015145014501450145014505015,O +54150514051415145015541415140000,R +00005415041004100400040010004001,ワ +10100411401000140011001000100010,ド +00005415041004100410041054150000,ロ +94529456945554515450145294528002,N +50011405051405140514140550010000,0 +945A5456545514519450945294528002,M +40005405100055010400140000045401,き +A4A4A4A4906A401A902AA4A5A4A45454,X +50505050505040150005000500050000,Y +00005000500050014001000100000005,! +00000000401040104010401010050000,u +00000000100054141405000500140000,r +00005405040004001001500044000405,ヌ +40051010444504444445101040050000,© +00000004400500040015404400140000,ょ +50551454145450544055505414540000,R +00000410041004041000100040000005,ソ +04100450045010501014401440050001,V +40004001400140014001400140014001,I +00000000000000000000400140010000,. +00005455544050014005001504545455,Z +00101010041140100010101010104005,じ +00054000000144104440444000050000,ふ +0000000000000000000580058016002A,, +54005401140514145515140014000000,4 +00005005141454150014500500000000,e +50151454145400541454145450150000,C +50010404001454141414140450010000,G +40014001400140014001400100000000,l +50415040104000400041404150415555,N +40004000545540004000000100010014,ナ +54551400140014005004400550000000,マ +00000000041504000400100040000015,ン +54550401040110014004000400040010,ア +50051414141454151014540500000000,Q +40150001500504100440040050050000,ろ +50151450145014505455145014500000,A +94949494949450A542A94AA94AA90AA8,Y +00000000000000000000000500050000,. +00000000000000045015100100010001,ャ +00005015000100010001000100015455,エ +54550054005454550054005454550000,E +00000000501540000001000450150000,z +00015415400010001000001000105005,さ +00000000000040550004000440550000,ェ +54015000500050005014400500000000,J +50414040004000401041504150415555,M +00500555055505550555055505555555,T +50015005501450505455500050000000,4 +00005015145014501450545514501450,A +04100450045004500450045004545015,U +50005001500450145415500054000000,4 +00050005501500051005400100000000,t +50054001400140014001400150050000,I +00004005101104410441044104411014,の +10004000000100050051000100010001,イ +00005455100040000001400410100440,ス +00000014001400140014001454150000,L +A42A69A529A4A92A6905A500942A5005,9 +54550094AA9452950294AA94AA552A80,F +00150000405500010004001450450000,え +A4AA69A529A429A429A429A4A4AA5055,D +00004000101010100410044004000000,ハ +00010001545510004001101504410001,ネ +94529454145554555451545294528002,N +94529452945294529452945250150280,U +00050000541510004000400140045410,え +40105055441004101010001000040000,や +50151450545014511454145050150000,0 +00000000000000050005000100040000,, +40150001500504100441440450010000,る +00004005100410044005000400040000,p +00000004000440051004100410040000,h +549540814AA94AA94AA94AA94AA90AA8,T +50511414141440141014141450510000,B +50151450140054014001000040010000,? +00000000000000004001400100000000,. +40050000500504100400040010004001,う +00000000400510104015001050050000,e +00004005501414505455145014501450,A +04100450045004505455045004500410,H +00514014101414141414101440510000,D +50051414005400540054141450050000,C +14501450145154555455545414500000,W +A402A40AA429A4A5A9AAA55554000000,4 +00000000000140041010040001000000,ヘ +54050014005054511450141454150000,G +00000005401044055000100140000000,g +00005415040004001000100040000005,フ +04501014400400010001400450101440,X +945294529452945294529452509502A0,U +50151450045050551450145050150000,6 +00000000500414141414500440010000,v +50511414145450150014001400500000,P +00005015145000500050005014505015,C +00000114011401145515011401140114,H +00000000000054054000400040005405,ェ +A42A69A529A4A46A69A529A4A46A5015,8 +00000000000000000000000500050014,, +40045004101414500440044000000000,ハ +00005015141414145015101414140000,R +50414141054115400540014140415555,K +00005455000054550001000100550000,テ +10000000140054001400140014045011,j +50054001014005501554155415545555,Y +04040404040404040401040010004000,り +00000000000010111011000000000000,… +9452505242510A556A555A5154520002,K +04100450045010144005000100010001,Y +A40A542900A4A4AA69A529A4A52A5405,6 +50510414001440150014041454510000,E +00000000500150044014001550050000,e +40004000545540014004400440104001,オ +54050404040444111400100040000005,タ +00000100410441040400040010004001,ツ +94529452945294529452945250950280,U +00140014401550141414001400140000,ト +04140415441554141414041400000000,N +00000000400050114414441050014000,ゅ +40514051405144514451545150510000,ル +00105050041104140414045050100000,わ +00000000000010005405500010011004,ォ +14051405100400000000000000000000," +10005441104010405440104150100000,は +00005015041004105015041004105015,B +00005415A55A696969696969A55A5415,0 +00000004001140401000040000000000,へ +00000005000500000000000500050000,: +00004005101044450444444510104005,© +00005005141400141414500500000000,c +5455140052AA4AA94AA54AA54AA50AA0,7 +545500505255140094AA945250150280,5 +00005000100110041010104054551000,4 +50151450145054151400145050150000,9 +00040014001450555454545050550000,b +00000011501510511010400500040004,ゃ +00001450145014501450145054545015,U +00004000400000010001040455150110,ム +00000004000440051004100440050000,b +949494949494508542A14AA94AA90AA8,Y +50151414501514141414501500000000,B +50155450545054155400540050150000,9 +00005415040004000400040004005415,コ +00005055504040010005001410505055,Z +00140014001414145014401500150000,レ +00014005400500010001000000010000,! +40004010501144140451544444445110,ぬ +50000000500050005000501440050000,j +00445145004451450145504451440545,ほ +00005015145014505415140014505015,9 +50151450145054151400500040150000,9 +900AA42929A529A4A9AA69A529A40514,A +00001414141414141414141450050000,U +14501450145014505014400500010000,V +00000004551501041404000401045401,セ +9002A40AA40A940A500A400500290015,! +40055014145014505455145014500000,A +00000000141050044005501414500000,x +50155450545054505450545550150000,O +40051014045004500450045010144005,O +00000000101014141414541445050000,u +00005405500050005000505050514015,J +00005005041004105405040004105005,9 +00005015044004005015004000405455,2 +900AA42929A529A4A9AA69A529A41554,A +50105455501050105000500040010000,サ +50150450045004505055045004505015,B +A42A69A529A4A52A69A529A4A52A5405,8 +00005015044004405015044004405015,8 +00005415A56A6955A41A5569A96A5555,2 +00000000501554101450505500500040,p +54555400500140050015545554550000,Z +40051011044104410441041110050000,の +00005455000554550005000554050000,モ +00010001545500015455000100010001,キ +00005000400100050051000100010001,イ +00000000000000000000000011001100,゙ +00545004141010401040401000050000,ひ +00005455500000010004000400015000,て +00000000541501000100010004005001,つ +00000001505500050005000540010000,t +50151450005050551450145050150000,6 +50555055005000500050005000000000,「 +00015455144014401400500040050000,ウ +00005505000055051000100010004000,テ +50415041504110410040404050415555,W +54151410544114001400500040050000,タ +10101010545510104010001450050000,せ +00005015145014005005001400505455,2 +94529454145554515450145294528002,N +00004001100404100410541504100410,A +14545454505540555055545414540000,K +00000000400550141410050001000000,へ +54551400140014005000400100050000,フ +00040004000400040004000404045001,し +50004001400140014001400100050000,I +00005055040004001000400000010004,7 +40151050105450155441144050150000,8 +A4A4A4A4A4A4942A500A400A400A4001,Y +00005005041000100010001004105005,C +00000000000540104010401040100000,n +00005015145014505001145014505015,3 +40055010145014501450101440050000,0 +14501450145014501450145050150000,U +40051014140050011400141450050000,3 +00000000000044044404040010004000,ッ +00000000400054004000400150040401,ょ +00000440145044440441044004400440,M +00004001400100000000400140010000,: +00005515010001001405400140001000,マ +00045055000450154444044110140000,あ +40010000000100050005000500040000,i +40010000000100050005000500040050,j +00000000400500104005100040150000,s +00005050505040150005401550505050,X +00014010001050110414040050010000,ら +00005455646964696569A96A65555400,4 +00500014501414151414141550050000,b +94525454545554551451145094528002,M +54055001500150015041504140150000,J +00005015145000505055145014505015,6 +00000000141014505014401500050000,v +00000000000000015405040100014000,ャ +00154040001100041011404014150000,& +54150014501500140014001400000000,F +A4AA54A5A0AA695529A4A52A54150000,5 +00001050405000510054005140501050,K +00005055140004005400400500000000,つ +A402A40AA406A402A402A402A4025401,1 +00005001040404004000000040000000,? +00005455400100050004000550010000,て +40005015000144055010100400045401,を +10041004100400000000000000000000," +40051014140050004001000454150000,2 +54411040544110405440104150100000,ほ +04000410551004100410541005115010,は +00000000145114511451541550140000,w +50001001100410101010541510001000,4 +00000000000050050400040010004001,っ +00500555055505550555055500505555,I +54550054005450550054005400540000,F +00005050505050505050545550005000,4 +54010505001400140014050554010000,C +9452945294521451145154549090A2A2,W +40051010444104440444444110104005,© +40014005400140014001400154150000,1 +50150000000054554000400000010004,テ +A42A69A52914A502542A40A5A9AA5515,2 +04100450045004500451445154541010,W +00000455101440155015501414141455,K +00140014501514141414501500000000,b +00040405041004141400500040150000,シ +14141414141414141414500500000000,U +40004000400040004000400000004000,! +10005515100050011004500110004000,す +00050001000400000000000000000000,' +50151414141450150014001400000000,P +00010001141541010101040504110101,れ +00005405141414145405140014000000,q +54050404041014001000400040000005,ク +14505454545514511450145014500000,M +00005515051405141400500040014001,7 +40051014045004500450445010144405,Q +50151450540050054015005454550000,2 +00041004045500104040400550104005,な +00000400040010041001400010010414,メ +14541454145414545014400500010000,V +50155454145014501450545450150000,0 +5455A85A00585055A05A00585455A8AA,E +00005015141414141414141400000000,n +00000000000000004001400100050000,, +00140014501414151414141414145000,h +00000010400550005005501414050000,a +50050005541500050005000500000000,f +10005411111411101110111154004001,ゆ +14541454145454551454145414540000,H +00005005041000405440044004105005,G +50511414101440155014141404500000,R +902AA4A554A4A46A691529A4A56A5415,S +00000005401550501440040000000000,ヘ +945294529452945252144A852AA1AAA8,V +5015945A28580058005814585895A02A,C +50151454005000500050145450150000,C +00001004100450011000100440010000,y +14505454545544450441044004400000,M +500596160A5A0058005816145A05A802,C +14405450501450054001400500150000,Y +50150010401550001400101040050000,5 +00000000505014151414141405140000,n +00000001000100014001140100010001,ト +54011400140014001450145050150000,J +50051414001400141414500500000000,C +40055015145414545455145414540000,A +A4A4A4A4A4A4906A401A400A400A4005,Y +00100010001000100010101010104005,し +00010001545500011011041104410001,ホ +00005015145000505015140014505015,S +10001000150010001000500514104105,よ +00000000000000005055000000000000,- +00005005041400140014041404145005,C +00001000400500155001541450410000,s +10001040544110401040104010404000,け +40011000000454040105010404005000,ら +00000000001450010001000100010000,r +54150514051405140514051454150000,D +50155455140050051400545540150000,3 +00005455A56A6955A41A6955A56A5455,3 +50550050505514001400145050150000,5 +40010000541510004000400140041410,え +14001400540514141414540500000000,d +00000110051415155111411001100110,M +A42A69A529A4A96A691529A0A46A5015,9 +54550054005454550054005400540000,F +40004010401150144450044504411014,め +14001400540514151454545454150000,d +A4AA69A529A4A9A495AAA4A6A9A55554,R +00005405051405145505050005145405,9 +00001000551510001000100040000005,ナ +50555055505550555055504101505555,J +00140014001400140014001455150000,L +14005400540050014001000000140014,! +00000000101014511451545550140000,w +50055011504150415455545550010000,4 +40051010100040000001000000010000,? +00000000000000000000150011001500,゚ +00005405011401140114111414144505,Q +50011404001450151414040550010000,6 +10101010545510101010401000105005,せ +04001410500440014005101404500000,メ +00015515000154010505111141100405,あ +00005015044004005005040004405015,3 +5455540050A942A50A952A5454550000,Z +00005055100010004000400000010014,フ +00005455041400145015001404145455,E +90AAA4A529A429A429A4A5A494AA5015,D +00005455040004001000400400014000,マ +50551454145450551454145450550000,B +50050014500514001414500500000000,S +90AAA4A529A429A429A4A5A494AA5055,D +50150450045004505055005000500010,P +A42A69A529A429A4A9A6A4A5996A4515,Q +549542A95AA514A0945250950280AAAA,3 +00000000501550505050501550404015,g +00004001500550054001000040010000,! +A42A69A529A429A429A429A4A56A5415,0 +00000000141410054001500414140000,x +00001450145014501450501440050001,V +00005015044004405415040004405015,9 +00000000140550105050505150145000,q +00005455145054505000500140014001,7 +00005005141414005005001454150000,2 +00045055000150554000400100404015,き +00001555041404145415041404141555,H +40011004141404145014140445010000,Q +94AA94AA94AA94AA945A9452509502A0,J +00000000000000000000000400110004,。 +00140014001400140014541500000000,L +54154001400140014001400140014001,T +50151414141450155014141400000000,R +14541454145450154005400540050000,Y +00000000000000000000001400140050,, +00005005041400145514041404145005,G +00005015140050051400140050150000,3 +00000000401110141414141550140050,p +00004000550540001000550510000400,キ +00000000000000000000001400140000,. +40015004141004100414100540010000,0 +00000055001400140014001404145455,L +54050514150054015005001555150000,2 +94529452945294529452945252150A80,U +54055000000154050110410111045401,る +54150514051454150514051454150000,B +54004001501540014001400150000000,f +50050410001550055400141050050000,S +501454555A165816581654555A16280A,# +54551450140050005000400140010000,7 +00005005141414141414141450050000,O +A42A69A529A429A4A9A6A5A5992A4515,Q +00045055000450150410040050010000,ち +00001000100050011004100450010000,d +00005055000400045455000400045405,モ +00001450145414555451545014501450,N +00500050505500500050005050550000,ヒ +00005055000500050005000500050005,T +54150410541100110011001100150000,『 +00000000000000550001000140550000,ュ +00001555041410054001400140015005,Y +54550094AA9452950294AA9454550080,E +00005015145014005005140014505015,3 +10405045141044440441044410100000,め +14141414141410045005400100000000,V +54555450500040010005000500050000,7 +00000004551501010401000140004000,ヤ +A40A692914A4A9A429A42929A50A5401,G +00040004505404050404101410440404,れ +50150450005000505015040004505015,S +40005405400054054000500544104005,ま +00000001044110114005101104410001,* +40011004141454151414141400000000,A +00004015101004100410041010104015,D +A4A4A4A4A4A4A4A4A9AAA555A4005400,4 +00501414500500050014001454050000,と +40014001400000010000000000000000,' +A42A29A4A42A69A529A4A52A54150000,8 +5455A85A00585055A05A0058005800A8,F +A4AAA4959052400A002924A4A4AA5455,Z +00005455140050004001400540054005,7 +10004000000100040004000140001000,く +00005515010510055005100501055515,E +00000000000540104010401000050000,o +00000000000100000001000100010000,i +00005001500550145050504054555000,4 +00000554141544140414041404141555,M +00014415010100010005011101155401,む +50051414141414141414500500000000,O +00000000541510004001000554550000,z +9452945294521451545554541452800A,W +00054000000000014010444044400005,ふ +00005415040004000400100040000005,フ +50054000000154154000000100015000,そ +00014055000450154050005050150000,を +40104010505504100411501000100004,や +545500505255140094AA945A52150A80,5 +00005001500550015001500150015001,1 +00000500140050001005100010001000,イ +00000000000000000014004100410014,。 +00000000000005050505000000000000,.. +50050000000050050000000050150400,ミ +04000404540405051111111141100405,め +50155450545054505450545050150000,0 +00005005041404140414041404145005,O +00000000000050011000100010005401,ュ +94525454509542A55A95545494508002,X +A42A69A515A4A46A691529A0A46A5015,S +54150400100040011000040004105005,3 +A42A69A500A4A4AA69A529A4A56A5415,6 +54055141114111411140414045515555,W +10001001540111054110151111111404,ぬ +00000000400500100010001040050000,c +00009002900250010000900290025001,: +A42A69A529A429A4A9AA69A529A41554,A +50151450145014555451505044150000,Q +54505450545554505450545054500000,H +00000001404510511041104140050001,ゅ +40151050105440151440144050150000,8 +10101010101010101004100040000001,り +00005415001450150014001454150000,E +00000000101010104004400500010000,v +545514505042428904A5149454550080,Z +50151450140050011400145050150000,3 +50151450145014501450145050150000,O +00000440044010101010400440040001,V +44144414441444145415100100000000,W +04400440044144455455545414500000,W +00000000141014505014400500050014,y +945252524A512A554A51525014528002,K +54550050AA5252550250AA52AA52AA02,F +00005455005000505055540054005055,5 +00000000000440050004001400454014,ょ +00005501010101015104040010004000,タ +40014005001410501450545504000000,ム +54554005400540054005400540050000,T +00015401000100015015044100140000,よ +14505054401540055005541414500000,X +00005050505050504015000500050005,Y +00414010100400000000000000000000,゙ +50550050505554005400545050150000,5 +40005410010501141401000140004000,や +50050410414101440144414104105005,© +40004000545540004000400100150000,ナ +00000000400410111011101110110000,m +00045015000450150004040450010000,も +00005415541500140014001400140000,「 +00005005041004105005041004105005,8 +50054141414101414141414150055555,H +40014005400140014001400150000000,l +A4AA69A529A4A4AA69A529A4A4AA5055,B +00000000000000000005401040100005,。 +00000005401040104005440010000000,q +00005000100010001000100010005400,1 +9452945414555451545294529452A082,N +14505050405100554051505014500000,K +00001415541544140414041404140414,M +54551400545514001400500040050000,ヲ +00001040144004400444005400100000,い +00005015145400500050005014545015,C +50050410514101440144514104105005,© +00100010541040150010001000105405,ヒ +00000005400040054010401010050000,a +40155000000000000414145050150000,こ +00005415441140014001400140014001,T +00050005140510054005110514050000,k +00005005141400145414141450050000,G +00005015044004400440044004405015,0 +00055001101000155001005050150000,ミ +00005015000054550400100040000005,ラ +00000001000100014001100100010001,ト +54015000500050005014501040050000,J +00005055100040004000400110040450,ス +00000000500510001000100010005415,ユ +00010005000100010001000100014005,1 +04101050405000510055405150501410,K +54150450100040000005001414505055,Z +00001400140014001400541554150000,」 +00000000000000000000040041001000,゙ +50051414140050004001000000050005,? +00000104041110044000040111040410,% +50151454005054501450145450150000,G +00000004000454050004000400045405,ヒ +50505050505001540555055505555555,Y +00005405001450151400541550150000,S +A42A00A5A4AA69A529A4A52A54150000,6 +40151050045004500450045010504015,D +A4AA69A529A4A5AA68A529A4A5AA5415,B +00001554155415541554155415545555,T +00005015541514111411141100000000,m +14545054405500554055505414540000,K +40005415400040054004400540000000,す +50551450145014501450145050550000,D +50010404040410004000400000004000,? +00000004004540544044001500040000,ゅ +54555440500140050015001500150000,7 +00000000010501000105040010004005,シ +00150015001500150015001554150000,L +40054015400540054005400540050000,1 +00040004500400050004001000105405,と +14501450145014501400140050010000,リ +900A6425A9A469A629A92524940A5001,0 +14141404140450054001400100050000,Y +10041004545510041004500040000005,サ +40005045445044404440444450010005,ゆ +54050514001400140014051454050000,C +50010004001050150410041004105005,6 +50050014005454541454141454050000,G +90029002500100000000900290025001,: +40054005400000010000000000000000,' +00000004000400040404040450040005,レ +00000414041454150414041404140414,H +40010000400140054001400150010000,i +50041455441144104040404000050000,か +00001450145414555455545154501450,N +54550054005450550054005454550000,E +00000000000054155415000000000000,- +50051414005000500050141450050000,C +14501450145054551450145014500000,H +14505050405100554055505154500000,K +A42A69A52950A40A690529A0A46A5015,3 +00010001545504010401040444101040,カ +50551450145014505055005000500000,P +54010001000100010001000100000000,「 +00005515010510055005100500054015,F +00001450545450154005400540054005,Y +40055010141454051400101440050000,9 +50050414041550055510051054050000,8 +50501414141414141414141450050000,U +50551450145014504055505014500000,R +00040455040400040014044404545005,む +00505550555001505550555000505555,E +40045415404450554404444450154004,$ +00000000000054050400500040004000,ァ +900A642529A429A429A42524940A5001,O +50001400540014011404541514140000,A +00405041415505551554155415545555,7 +00000000000000000005000540000001,, +04141415541544140414041400000000,M +14501450145114515455545414500000,W +00005515511150015001500150015405,T +54050514051455050500140050050000,9 +00000410041004105415041004100410,H +40155050005050151400145050150000,S +00004005400140014001400150050000,1 +54154001400140014001400154150000,I +00054015401500050005000000000005,! +00000010001000100410101040110014,レ +00005015545054505001400504155455,2 +54550050505514001400145050150000,5 +40051014045004500450545504500410,A +94525454545594519450945294528082,M +00000000000000000005000100040000,, +40011004141414141414100440010000,O +00040004405500044055000404045001,も +00005005141400140014141450050000,C +50551450145054504055505154500000,R +00000000000000000000000580058002,. +00005015145400545015540054505015,S +00000104010101010400040010004001,ソ +00040015100404140044041450050000,む +00005015145400505450145014545015,G +50551450145050551450145050550000,B +A42A69A529A4A96A691529A4A56A5415,9 +00005555A96A6955A5019406501A4015,7 +40051010101550055410141450050000,8 +00000000500514145055005450150000,e +40005455400040154010400540000001,す +04000400040004000410045004505015,J +54150514051405145415001400140000,P +00005000500050005000505050504015,J +50011405051405145515051405140000,A +00010401411511011004100410114000,か +00405541554101405541554155415555,F +54050014005054501450141454050000,G +54550050AA5252550250AA5254550000,E +54150514051405145415141405140000,R +00010001000100010001000100000001,! +A42A69A529A4A46A69A529A4A56A5415,8 +54150050005000505055005000500010,F +14145014401540155014141400000000,K +00000440101040040001400410100440,X +00001040044004400440044000410014,い +00000400500110005515100010004000,チ +54555000400140055014145004400000,ス +00010001141541010101010501111401,わ +00140014501514141414141400000000,h +00000400100040000001000400100000,/ +00000000000000290029001900240010,, +14501450145054545015400500010000,V +54150014501500140014541500000000,E +54A50094AA5254521452949454A500A0,G +50415041104100400040404050415555,W +00005055145014501450505500500050,P +00040004401500044015000404045001,も +54545454501450144005400500010000,V +04000410551104100410041004101004,け +00000000540504000400040004005405,コ +00005015145014501450545150504415,Q +00000000500500545015540040550000,s +A400A400A402900240020001400A4005,! +54011400140014001454145450150000,J +04101454545144500450045004500410,M +94525454545514519450945294528002,M +00000404010401040104010410044001,い +54555400400550155400544050150000,3 +00140404040014005000401500050000,ン +00050005000500050005000000050000,! +00005015044000405055044004405015,6 +50050004000400040000000000000000,「 +54150010001050150400040004105005,5 +00005411001000100010001000115410,に +54555155455515555554555155455515,/ +00004001400440104000400040004000,1 +54550094AA9452950294AA942A552A80,F +00000000000000004001400140000001,, +40011000000040001004111011104001,ふ +00005415A55A6969A55A6969A55A5415,8 +00041055041040104041500444010000,な +00001450545454551451145114501450,M +14541454145414541454145450150000,U +00005015000000000000000000005455,ニ +A4AA541A400A400A400A400A400A4001,T +00004000541540004000440441104110,ホ +00041055040450050414044410140000,お +50414040004010415041504150415555,M +40151014141414141014401500000000,D +00000000501510004001500050000001,z +50050414005000505451045004145005,G +50151454145414545455505444150000,Q +00050005000100040000000000000000,' +00000000000050150000000000000000,- +00005005101010404000400000010014,ク +00004001400540014001400140015005,1 +00005501010101010104040004005000,ク +44051410500040010005041454110000,Z +40054015400540054005400550150000,1 +00000000000000000000002900290015,. +00000011405510114010000400010000,ゃ +A42A69A529A429A4A9A6A9A5A46A5015,Q +00140014000400100000000000000000,' +00004000550501040100040004005000,ウ +900A642529A429A469A6A524A91A5501,Q +00005005400140014001400140015005,I +10001000100040044001100100040050,メ +44041104405500045410001000415440,だ +00000015400150155454545050150000,a +50551450145014505055505014500000,R +00000000541440150054005400540000,r +54151410500040014001000500050000,7 +00015015400054051000000440050000,き +00004055004000400040004000000000,「 +00040004000400040004140550010000,し +00000014501514150014001400000000,r +549540814AA94AA94AA94AA954950080,I +50405150455015540551054501055555,X +40004004500544140441544444445110,ぬ +54150050005000505055005000505415,E +00005001440441104110411041100405,の +14005000500150045014501414050000,d +00000000000000000000000044001100,゙ +9452545454551451945094529452A082,M +50551450145050550050005000500000,P +902AA4A5A4A4A456900A402AA4AA5455,2 +54010005001454150514051454050000,6 +00005405051405140514051405145405,0 +54551450500242A90AA52AA52AA0AAAA,7 +00005405040004005405040004005405,ヨ +00005415A55A6969A95A6915A51A5415,9 +14141414141450054001400140010000,Y +00005405051400145415051405145405,6 +00005005000054150400040010004001,ラ +50150000545514001400500040050000,ラ +54551440144014401440545554550000,ロ +50050410040010004001000400105415,2 +04040404551504040404100400045501,せ +00105054041104141410445010100000,ね +00015455000110111011145104410000,ホ +50151450145014501451505044150000,Q +00010001000140011001000100010001,ト +40004000000100014005110411100410,ん +00000000000004001000500010011000,ィ +00000004001540515040140000000000,へ +14501450501450144005400500010000,V +00005055145014501450505550501450,R +00000010001040100011001550100000,k +00000004000400054005100400040004,ト +00000550141450054001500514140550,X +50150454005450155400545050150000,S +00000000141514051405500100050010,y +54050514051405145514141451050000,Q +900A642529A429A469A6A524A91A5505,Q +14501451145114511451545550140000,W +00000010001000100010001000105415,L +54A914A894AA94AA9452945250950280,J +00000000000000000000000040014001,. +00010401411510041010500114044001,な +00005441004000400040004000445441,に +00000000005500010055000100550000,ョ +00005405040004001000500004010104,ス +00000000000000000005000500010004,, +54155400500140050015541500000000,Z +40555054145414541454505440550000,D +94529452945254551450945294528002,H +00005015045404500450445010544415,Q +00004000000040004000401000050000,j +00000401551504010401040010004000,サ +040605061A406A902A8006050606565A,X +54551400500040014005400540050000,7 +54055000400114040110010004005001,ろ +40014015401540054005400550150000,1 +00004005401540054005400540054005,1 +40055010140050000001000000010000,? +A4AA69A529A429A4A4AAA4A569A41554,R +00000000000000554000400000010014,っ +00140014501440150055505010500000,k +A42A69A515A4A4AA69A529A4A46A5015,6 +04141015400550015404141000000000,X +50505050505050505455500050000000,4 +00045055000450051414444404411014,あ +945A545450954AA5529554549450A082,X +A42A69A529A4A96A6915A500942A5015,9 +40150001000454550001000400045001,そ +00000000000054000400540004005400,ョ +00000555141450144015501414140555,K +00001450545454551451145014501450,M +00004015501414141414141450150000,D +50151450145014511450145050150000,O +00005055145014501450145014505055,D +00005415001000105015001000100010,F +94529452145154555455545494508002,W +00000000400040005405040410004000,ゥ +00015001000100010001001540411015,よ +40014005400140014001400150050000,1 +40155054005450151400145450150000,S +50054001400140014001500500000000,I +50154005400540054005400550150000,I +40055010545014501454101440050000,0 +A42A69A529A429A429A4A42A50050000,0 +50015005500150015001500150010000,1 +00000054000004540400100040000055,シ +00001414141454154001400140010000,Y +54150014001454150014001400140000,F +A40A692905A500A400A42928A50A5401,C +00140014001400140014001454150000,L +A4AA540A400A400A400A400A400A4001,T +00005415500040010005541500000000,Z +00005015040504055005040504055015,B +00000000000000000015001500010004,, +A42A69A529A429A429A429A4A46A5015,0 +14141414541514141414141400000000,H +00005055141414145015501414141455,R +00545550554100415041505000545555,G +00040004505500045005041004005005,ち +50151454005454541454545444150000,G +A42A69A52914A50A680129A0A52A5405,3 +500596162A5A0058005816165A05A80A,C +00005015000000000000545500000000,ニ +90029002900140020001000000000000,' +900A902A901A900A900A900A900A5005,1 +00001450145014505455145014501450,H +00504155055501545055504101505555,3 +50510414001440150014001400500000,F +A4AA549590AAA4152900A5A4942A5005,5 +40010000400140014001400100000000,i +50150454005450551454145450150000,6 +00005415140014001400140054150000,コ +00001450145014505014501450144005,V +002900290029002900290029A92A5515,L +545514509452508242A94AA94AA90AAA,7 +902A500A400A400A400A400A902A5005,I +00005005141414145415141414140000,A +00000014001400140014001400145415,L +44041104000450050010004000405415,ど +00405541554101405541554100405555,E +00000000000000000000040011000400,゚ +00005401500050005000501050104005,J +54411040544110405041144410445041,ほ +54150514051414145015541415140000,R +A4AA69A529A4A5AA94A6A4A429A40514,R +00001414141450054001400500050000,Y +00040004500400050010004000405415,と +00010001000440054010041150410000,ん +54155000400150051400145050150000,3 +54050514051405145515051405140000,A +00000011001100110011001104115041,ル +900AA42969A429A4A9AA69A529A41554,A +00000000400550141414140550010000,o +04015115000154010105011101110404,お +5015965A2A585659965A16585895A02A,G +4055809600160016001600160016002A,T +00000000540540004000400040005515,エ +00005015145014501450545154505015,Q +40154005400540054005400550150000,1 +A42A69A529A429A429A429A4A42A5015,O +50151450145050010001000000010000,? +50054141014041404141414105055555,M +00001000100004040404011001100100,ハ +00000000505504000400040050000005,つ +00004015100000000000001000405015,こ +A4AA69A529A429A4A4AA50A500A40054,P +00000001545500011011101104410001,ホ +00040004505500045410001000415440,た +40055014145054551450145014500000,A +40555050145014501450505040550000,D +00005055141414145015141414145055,B +14541455545154501450145014500000,N +00000000000000000014001400040010,, +00050005505500050005140540010000,t +00005015901A901690069416A41A5415,1 +00000000000040444044400040010014,ッ +00005015545414501450145054545015,O +00000000000000000000000000140014,. +5015945A56585A29A801800000058002,? +50054000400044005405051104111004,み +10001000500040004001000500540000,ノ +00000000400150041410050001000000,へ +00014015000410054011400400045001,を +00040001545540005000004000105005,さ +04044455000450050414044404441014,お +00005415001000105015001000105415,E +14501450145154555455501410100000,W +5000540156015A016801A00000058002,! +54015000500050005050505040150000,J +00000000000054050000000000000000,- +54545454545454545454545450150000,U +9002900A900290029002A92A55150000,1 +00004001150040011500000040011500,ミ +00005405051405145405051405145405,8 +00540054005400540054005454550000,L +00004000400440044104410444045014,ル +54155000400550005400545050150000,3 +50151414051405140514141450150000,D +50014404401040110015040450010000,C +50154000000550150440040504115005,る +10005441104010401040105050100000,け +50051414001454050500051454050000,S +9002900A9006900290029002A92A5515,1 +400A400A400A400A400A400A400A4005,I +00000404040404040404040010004000,リ +00000000541504100410041004105415,ロ +40014001400140014001000040010000,! +00005000500050005000501450144005,J +50155455544054405455544054400000,A +00000004001500040004000440010000,t +00040004505404050404041404441004,わ +00000400100040000001000400000000,/ +4001600560016001600160015805A802,1 +40101051101110141014105004100000,れ +50415041504100405041504150415555,H +00000400040004001000100040000001,ノ +10005505100055051000540111044001,ま +54051414141014005000400100050000,ク +00005055041404145015101404141555,R +00040004505404050404141444445404,ね +50050410041004100410041004105005,0 +10101010505544100410100400040004,や +50151010101050154004400444105440,兄 +00000000000040151001100140010004,ァ +54550001400110010001000100010001,下 +00041004045544044410401040400005,か +10001000101110111010101444100441,似 +00105015404550151000101110040451,気 +00000000000000001010000000000000,‥ +50150400040010044001400110040050,ヌ +50150000545510004000400540101440,え +10101015101114411011100410041050,外 +00105011045404100450045004105010,わ +00000001540104041010400140001000,々 +00010001501510115455000140041450,央 +00000000000400114040100004000000,ヘ +00015455000150150000444400445001,志 +44104010545540104050101110110404,伏 +00014004101044450000501510105015,合 +40044004541540505011441440104010,休 +40105415401040505011401040105415,住 +00005055040004001010400400014000,マ +10154404101044454004501540045410,発 +00105011105510111055105110511414,机 +00015455100040001005045100010001,ネ +00040010545504404445444444451440,向 +40005045445044404440444050000001,ゆ +00000000000000000000440011001100,゙ +00000000000000005455000000000000,ー +00100010005500104055041004105005,も +40054000000140004000400040000001,了 +00015455000140051011444500010001,本 +10111011000154554004400444105440,光 +50150000501504400400040010004005,う +00000444044404441000100040000005,ツ +40000005000150150001545500010005,手 +00014004101044450001400500015015,全 +00000000000010004001001500010001,ィ +54150010501510101014401140411454,反 +54550010101514111045100110041410,死 +40005051400054454000041154450444,法 +00055000000000044001004000145401,ミ +00050005000500050005000000050005,! +50150000545504000400040010004015,ラ +00011011041104111041400000050050,少 +50550400100040000001400410100440,ス +54014454004454544444545400004444,照 +00000000000040005000400550100005,ょ +00015455444440101440501500015455,空 +00014004101004405015100410045010,分 +00000000000010044005101440040004,ゃ +00000000000000001400410041001400,゚ +00015455044050150001545500010005,宇 +00010011001104110411041110114041,ル +50154000000500015455400040000005,子 +00000000000000004005400040005015,ュ +00150001000100014001400410100440,入 +00045055000154554000004000405015,き +40051000001000105055040004005015,ら +40150010001000100010000000000000,「 +00005415041004105415041004105415,日 +00045405041004401000100040000001,ク +00105011045454100451045104115010,ね +40004000545540004000400000010004,ナ +00115015001154554004400444105440,先 +10044455040450150444044404441014,お +40004000545540004001400440104040,オ +00005455100010151011101510005000,可 +50154000000154554000000100015000,そ +00045005101040440005545504045405,名 +00015455000150051004101010404001,方 +00005055040004000400040004005055,コ +10001000100440014000100100040010,メ +00005455040054150400100040010014,ヲ +50151011501510115015101110115040,用 +50554001000550550400040004405015,ろ +40005455400054554000401550400415,ま +10405445104050411044144410444011,は +00004004440404440044004404015400,心 +00010011501504110451044504451014,め +10041004541510041004545510041010,井 +00400040545500400040004000405415,ヒ +00045411004454111050101010105010,行 +40044004541140545410401054104010,作 +40044004541540505011441450114010,体 +00000040104004400440044000410014,い +10101010545510101010400040000001,サ +00000000000040051010100040000001,っ +00000015400040004000400040005455,ユ +00100015544444044455440444115440,知 +00000000000000004005000100015015,ェ +00010001101104110411044100010005,小 +00045405005410111011401410410404,攻 +50054010545500105011101100115440,危 +00005041044010400040004404415010,に +00055415041054150410541504105415,自 +00014004501504405015100040000001,今 +00000001000150010001000100015455,上 +00040004505504040404100400040004,ヤ +00040004400440041010101004100440,ハ +00044004101044404004000140041450,父 +00010001545504414444145004401440,内 +54150410541504105415041054150410,目 +10005455100050051010101050054000,す +00010001000400041010101050410454,ム +00100010001000100010001004045001,し +10041050101040544010445454510411,私 +10101010545510101010001000105405,せ +00000054040004000400100040000055,ン +04100410041004100410040010004001,リ +00040004505504040404041004101040,カ +00045405040404115040100040000001,タ +40010014501540104010545510100440,兵 +00400040004000400440104040410014,レ +00011011101150150001044104415455,出 +00005455044004400440044004405455,ロ +50550004000454550004000400045401,モ +54451040544510405041144410444011,ほ +54415114451415414154145114454115,% +00015455000100015015000100015455,主 +00000000000040151000500510004015,ョ +00040004000400040015041104415040,ん +00010001545540005015004000405415,さ +00000000000040005015400140044010,ォ +00100010505504100410101000105405,セ +50151450145050000001000100000001,? +54550001000154550001400410100440,天 +00000000000000045015100440040004,ャ +40005415401054154010501144444000,床 +00105415401040404000400000010004,ケ +00040004000450050004000400040004,ト +40104040545404450454444404545000,的 +54155415401054154010544504045405,居 +00005015040004005405040004005015,ヨ +00015455400454100451501450100411,夜 +04545000405454445054104110411044,所 +04001000400040054050400040004000,イ +00151001101550411441104110444010,み +00010001545500045015040004005015,ち +54554001100504110441000100010001,不 +50505050505050505050000050505050,!! +40000001000400100010000400014000,く +00045455100450054414444404411014,あ +00000000000010001000100010005005,」 +00000400040010001000400000010014,ノ +54010451040154515000101110411404,沢 +44044000545104015451040154110441,消 +00550004141010401040104040100005,ひ +54550440444504404445444444451440,同 +10001040544510401040104010404010,け +40004000540040004015504044400015,よ +00054000000540004410444044400441,ふ +00005455100040000001000140001000,て +50150400100000000040004004105005,こ +50550400040110014001000100040010,ア +00014055000450054010004000405415,を +00005055040004001000100040000005,フ +04011004140500000000000000000000,” +00000054000004540400040010004055,シ +00000000505504000400040010004005,つ +00000000000000114011101540110001,ゅ +00045455000440105415405040105415,在 +00000440041010041000400000010004,ソ +00105010105110141010105010500410,れ +00000004001100114040404010000400,へ +40105411405410114454105144100411,核 +00040004000450050010004000405415,と +40004000545540005000400540504001,才 +10004015400054554000400000010004,チ +44144000545540004004104510444455,武 +00105415101050555014501510105010,何 +50554001001450550415444044405015,る +54550444104140401041044400405415,区 +40514010004100000000000000000000,” +00005455044004400400100040000005,ワ +00010001545504415455000100010001,中 +00040004505500010001545540004000,キ +00000000000010111011100040000001,ッ +00041404005510101040500514104005,な +40004000400000010001400410100440,人 +00015455044154550001444400445441,忠 +00011011400554550400545504005455,当 +40044004401054104050401040101410,化 +00000400100040000005001400500040,/ +00000440044004400444101010004000,り +54550440444544444445044054550440,回 +00110011501500414005000100015455,生 +00105415401050454004541540004000,年 +50411444144410404040404000004040,!? +00115015041104515444044104455010,ぬ +10101010105454011004504410105044,対 +54004454544444545444445444000401,明 +50150000545540004000400000010004,テ +00010001545504400440040010004005,ウ +00015455044150151011501510115015,宙 +00041004045500040014044404445011,む +00041004401140505415401040105415,任 +54150410541504105415041004101440,月 \ No newline at end of file diff --git a/GUI.NET/Dependencies/resources.en.xml b/GUI.NET/Dependencies/resources.en.xml index 53057541..ed0734e0 100644 --- a/GUI.NET/Dependencies/resources.en.xml +++ b/GUI.NET/Dependencies/resources.en.xml @@ -1145,5 +1145,10 @@ Undefined (2) Undefined (3) + + Ignore + On the right + On top + \ No newline at end of file diff --git a/GUI.NET/Forms/frmMain.Designer.cs b/GUI.NET/Forms/frmMain.Designer.cs index edc181cc..3624d6e4 100644 --- a/GUI.NET/Forms/frmMain.Designer.cs +++ b/GUI.NET/Forms/frmMain.Designer.cs @@ -181,6 +181,8 @@ namespace Mesen.GUI.Forms this.mnuRunAutomaticTest = new System.Windows.Forms.ToolStripMenuItem(); this.mnuDebugger = new System.Windows.Forms.ToolStripMenuItem(); this.mnuLogWindow = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem27 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuInstallHdPack = new System.Windows.Forms.ToolStripMenuItem(); this.mnuHdPackEditor = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); this.mnuRandomGame = new System.Windows.Forms.ToolStripMenuItem(); @@ -193,6 +195,7 @@ namespace Mesen.GUI.Forms this.mnuMemoryViewer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuPpuViewer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuScriptWindow = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuTextHooker = new System.Windows.Forms.ToolStripMenuItem(); this.mnuTraceLogger = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem25 = new System.Windows.Forms.ToolStripSeparator(); this.mnuEditHeader = new System.Windows.Forms.ToolStripMenuItem(); @@ -205,8 +208,6 @@ namespace Mesen.GUI.Forms this.mnuReportBug = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem27 = new System.Windows.Forms.ToolStripSeparator(); - this.mnuInstallHdPack = new System.Windows.Forms.ToolStripMenuItem(); this.panelRenderer.SuspendLayout(); this.panelInfo.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.picIcon)).BeginInit(); @@ -1443,6 +1444,19 @@ namespace Mesen.GUI.Forms this.mnuLogWindow.Text = "Log Window"; this.mnuLogWindow.Click += new System.EventHandler(this.mnuLogWindow_Click); // + // toolStripMenuItem27 + // + this.toolStripMenuItem27.Name = "toolStripMenuItem27"; + this.toolStripMenuItem27.Size = new System.Drawing.Size(179, 6); + // + // mnuInstallHdPack + // + this.mnuInstallHdPack.Image = global::Mesen.GUI.Properties.Resources.Import; + this.mnuInstallHdPack.Name = "mnuInstallHdPack"; + this.mnuInstallHdPack.Size = new System.Drawing.Size(182, 22); + this.mnuInstallHdPack.Text = "Install HD Pack"; + this.mnuInstallHdPack.Click += new System.EventHandler(this.mnuInstallHdPack_Click); + // // mnuHdPackEditor // this.mnuHdPackEditor.Image = global::Mesen.GUI.Properties.Resources.HdPack; @@ -1480,6 +1494,7 @@ namespace Mesen.GUI.Forms this.mnuMemoryViewer, this.mnuPpuViewer, this.mnuScriptWindow, + this.mnuTextHooker, this.mnuTraceLogger, this.toolStripMenuItem25, this.mnuEditHeader}); @@ -1546,6 +1561,14 @@ namespace Mesen.GUI.Forms this.mnuScriptWindow.Text = "Script Window"; this.mnuScriptWindow.Click += new System.EventHandler(this.mnuScriptWindow_Click); // + // mnuTextHooker + // + this.mnuTextHooker.Image = global::Mesen.GUI.Properties.Resources.Font; + this.mnuTextHooker.Name = "mnuTextHooker"; + this.mnuTextHooker.Size = new System.Drawing.Size(162, 22); + this.mnuTextHooker.Text = "Text Hooker"; + this.mnuTextHooker.Click += new System.EventHandler(this.mnuTextHooker_Click); + // // mnuTraceLogger // this.mnuTraceLogger.Image = global::Mesen.GUI.Properties.Resources.LogWindow; @@ -1639,19 +1662,6 @@ namespace Mesen.GUI.Forms this.mnuAbout.Text = "About"; this.mnuAbout.Click += new System.EventHandler(this.mnuAbout_Click); // - // toolStripMenuItem27 - // - this.toolStripMenuItem27.Name = "toolStripMenuItem27"; - this.toolStripMenuItem27.Size = new System.Drawing.Size(179, 6); - // - // mnuInstallHdPack - // - this.mnuInstallHdPack.Image = global::Mesen.GUI.Properties.Resources.Import; - this.mnuInstallHdPack.Name = "mnuInstallHdPack"; - this.mnuInstallHdPack.Size = new System.Drawing.Size(182, 22); - this.mnuInstallHdPack.Text = "Install HD Pack"; - this.mnuInstallHdPack.Click += new System.EventHandler(this.mnuInstallHdPack_Click); - // // frmMain // this.AllowDrop = true; @@ -1857,6 +1867,7 @@ namespace Mesen.GUI.Forms private System.Windows.Forms.ToolStripMenuItem mnuLoadLastSession; private System.Windows.Forms.ToolStripSeparator toolStripMenuItem27; private System.Windows.Forms.ToolStripMenuItem mnuInstallHdPack; + private System.Windows.Forms.ToolStripMenuItem mnuTextHooker; } } diff --git a/GUI.NET/Forms/frmMain.Tools.cs b/GUI.NET/Forms/frmMain.Tools.cs index c3866a17..16269e18 100644 --- a/GUI.NET/Forms/frmMain.Tools.cs +++ b/GUI.NET/Forms/frmMain.Tools.cs @@ -341,5 +341,10 @@ namespace Mesen.GUI.Forms { DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger); } + + private void mnuTextHooker_Click(object sender, EventArgs e) + { + DebugWindowManager.OpenDebugWindow(DebugWindow.TextHooker); + } } } diff --git a/GUI.NET/Forms/frmMain.cs b/GUI.NET/Forms/frmMain.cs index 90417a31..64ff295e 100644 --- a/GUI.NET/Forms/frmMain.cs +++ b/GUI.NET/Forms/frmMain.cs @@ -710,6 +710,7 @@ namespace Mesen.GUI.Forms mnuPpuViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenPpuViewer)); mnuScriptWindow.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenScriptWindow)); mnuTraceLogger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTraceLogger)); + mnuTextHooker.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTextHooker)); } private void BindShortcut(ToolStripMenuItem item, EmulatorShortcut shortcut, Func isActionEnabled = null) @@ -1041,6 +1042,7 @@ namespace Mesen.GUI.Forms mnuEventViewer.Enabled = running; mnuPpuViewer.Enabled = running; mnuScriptWindow.Enabled = running; + mnuTextHooker.Enabled = running; mnuTraceLogger.Enabled = running; mnuInstallHdPack.Enabled = running; diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index 3cf69ef3..381f81a6 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -392,6 +392,18 @@ ctrlAddressList.cs + + UserControl + + + ctrlCharacterMapping.cs + + + UserControl + + + ctrlCharacterMappings.cs + Component @@ -440,6 +452,18 @@ ctrlEventViewerPpuView.cs + + UserControl + + + ctrlScanlineCycleSelect.cs + + + UserControl + + + ctrlTextHooker.cs + UserControl @@ -747,6 +771,12 @@ frmMemoryViewer.cs + + Form + + + frmTextHooker.cs + Form @@ -1252,6 +1282,12 @@ CodeViewerActions.cs + + ctrlCharacterMapping.cs + + + ctrlCharacterMappings.cs + ctrlDbgShortcuts.cs @@ -1267,9 +1303,18 @@ ctrlEventViewerPpuView.cs + + ctrlScanlineCycleSelect.cs + + + ctrlTextHooker.cs + ctrlSourceViewer.cs + + frmTextHooker.cs + Always @@ -1663,6 +1708,9 @@ Always + + Always + Always @@ -1808,7 +1856,6 @@ Dependencies\Dependencies.zip -