From 46d625586fa00c41ed0372e731b15497071e6874 Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Thu, 12 May 2016 18:31:22 -0700 Subject: [PATCH] Initial pass at implementing Alto Music (Organ/DAC interfaces). Not currently functional. Fixed Nova diassembly to properly handle alto-specific instructions; fixed some annoyances with microcode disassembler. --- Contralto/AltoSystem.cs | 4 + Contralto/CPU/NovaDisassembler.cs | 106 ++++++++------------ Contralto/CPU/Tasks/Task.cs | 2 +- Contralto/CPU/UCodeDisassembler.cs | 49 ++++++--- Contralto/Contralto.csproj | 1 + Contralto/IO/Music.cs | 121 +++++++++++++++++++++++ Contralto/Logging/Log.cs | 1 + Contralto/Memory/IMemoryMappedDevice.cs | 4 +- Contralto/Memory/Memory.cs | 23 +++-- Contralto/Memory/MemoryBus.cs | 16 +-- Contralto/UI/Debugger.Designer.cs | 126 ++++++++++++++---------- Contralto/UI/Debugger.cs | 44 ++++++++- 12 files changed, 345 insertions(+), 152 deletions(-) create mode 100644 Contralto/IO/Music.cs diff --git a/Contralto/AltoSystem.cs b/Contralto/AltoSystem.cs index 6fb8c9d..0c182e1 100644 --- a/Contralto/AltoSystem.cs +++ b/Contralto/AltoSystem.cs @@ -27,6 +27,7 @@ namespace Contralto _displayController = new DisplayController(this); _mouse = new Mouse(); _ethernetController = new EthernetController(this); + _musicInterface = new Music(this); _cpu = new AltoCPU(this); @@ -35,6 +36,7 @@ namespace Contralto _memBus.AddDevice(_mem); _memBus.AddDevice(_keyboard); _memBus.AddDevice(_mouse); + _memBus.AddDevice(_musicInterface); // Register devices that need clocks _clockableDevices = new List(); @@ -58,6 +60,7 @@ namespace Contralto _mouse.Reset(); _cpu.Reset(); _ethernetController.Reset(); + _musicInterface.Reset(); UCodeMemory.Reset(); } @@ -230,6 +233,7 @@ namespace Contralto private DiskController _diskController; private DisplayController _displayController; private EthernetController _ethernetController; + private Music _musicInterface; private Scheduler _scheduler; private ulong _clocks; diff --git a/Contralto/CPU/NovaDisassembler.cs b/Contralto/CPU/NovaDisassembler.cs index 2a56492..9335424 100644 --- a/Contralto/CPU/NovaDisassembler.cs +++ b/Contralto/CPU/NovaDisassembler.cs @@ -16,11 +16,7 @@ namespace Contralto.CPU.Nova _altoIOTable = new Dictionary(); _altoIOTable.Add(0x6210, "MUL"); - _altoIOTable.Add(0x6211, "DIV"); - _altoIOTable.Add(0x6000, "CYCLE"); - _altoIOTable.Add(0x6900, "JSRII"); - _altoIOTable.Add(0x6a00, "JSRIS"); - _altoIOTable.Add(0x6e00, "CONVERT"); + _altoIOTable.Add(0x6211, "DIV"); _altoIOTable.Add(0x6203, "RCLK"); _altoIOTable.Add(0x6204, "SIO"); _altoIOTable.Add(0x6205, "BLT"); @@ -61,8 +57,9 @@ namespace Contralto.CPU.Nova disassembly = DisassembleLoadStore(address, instructionWord); break; - case InstructionClass.IO: - disassembly = DisassembleIO(instructionWord); + case InstructionClass.AltoSpecific1: + case InstructionClass.AltoSpecific2: + disassembly = DisassembleAltoSpecific(address, instructionWord); break; default: @@ -189,46 +186,50 @@ namespace Contralto.CPU.Nova return d.ToString(); } - private static string DisassembleIO(ushort instructionWord) + private static string DisassembleAltoSpecific(ushort address, ushort instructionWord) { StringBuilder d = new StringBuilder(); // - // First see if this is an Alto-specific instruction; if so - // use those mnemonics. Otherwise decode as a Nova I/O instruction. + // Check for Alto-specific instructions that do not use the DISP field // if (_altoIOTable.ContainsKey(instructionWord)) { - return _altoIOTable[instructionWord]; - } - - // Accumulator - int ac = (instructionWord & 0x1800) >> 11; - - // Transfer - IOTransfer trans = (IOTransfer)(instructionWord & 0x700); - - // Control - IOControl cont = (IOControl)(instructionWord & 0xc0); - - // Device code - int deviceCode = (instructionWord & 0x3f); - - if (trans != IOTransfer.SKP) - { - d.AppendFormat("{0}{1} {2},{3}", - trans, - cont == IOControl.None ? String.Empty : cont.ToString(), - ac, - Conversion.ToOctal(deviceCode)); + d.Append(_altoIOTable[instructionWord]); } else { - d.AppendFormat("{0} {1}", - (IOSkip)cont, - Conversion.ToOctal(deviceCode)); - } + // + // Check for Alto-specific instructions using the DISP field + int topBits = (instructionWord & 0xff00); + switch (topBits) + { + case 0x6000: + d.AppendFormat("CYCLE {0}", Conversion.ToOctal(instructionWord & 0xf)); + break; + + case 0x6900: + d.AppendFormat("JSRII {0} ;({1})", + Conversion.ToOctal((sbyte)(instructionWord & 0xff)), + Conversion.ToOctal(address + (sbyte)((instructionWord & 0xff)))); + break; + + case 0x6a00: + d.AppendFormat("JSRIS {0}", Conversion.ToOctal((sbyte)(instructionWord & 0xff))); + break; + + case 0x6e00: + d.AppendFormat("CONVERT {0}", Conversion.ToOctal((sbyte)(instructionWord & 0xff))); + break; + + default: + // Unimplemented, treated as a TRAP to either ROM or RAM. + d.Append("TRAP"); + break; + } + } + return d.ToString(); } @@ -286,7 +287,8 @@ namespace Contralto.CPU.Nova MEM = 0x0000, LDA = 0x2000, STA = 0x4000, - IO = 0x6000, + AltoSpecific1 = 0x6000, + AltoSpecific2 = 0x7000, } private enum ALCFunctions @@ -327,35 +329,7 @@ namespace Contralto.CPU.Nova SNR = 0x5, SEZ = 0x6, SBN = 0x7, - } - - private enum IOTransfer - { - NIO = 0x000, - DIA = 0x100, - DOA = 0x200, - DIB = 0x300, - DOB = 0x400, - DIC = 0x500, - DOC = 0x600, - SKP = 0x700, - } - - private enum IOControl - { - None = 0x00, - S = 0x40, - C = 0x80, - P = 0xc0, - } - - private enum IOSkip - { - SKPBN = 0x00, - SKPBZ = 0x40, - SKPDN = 0x80, - SKPDZ = 0xc0, - } + } private enum MemFunction { diff --git a/Contralto/CPU/Tasks/Task.cs b/Contralto/CPU/Tasks/Task.cs index 884d3e4..1983c8d 100644 --- a/Contralto/CPU/Tasks/Task.cs +++ b/Contralto/CPU/Tasks/Task.cs @@ -501,7 +501,7 @@ namespace Contralto.CPU // if (swMode) { - // Log.Write(Logging.LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1} (NEXT is {2})", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier), Conversion.ToOctal(instruction.NEXT)); + //Log.Write(LogType.Verbose, LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1} (NEXT is {2})", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier), Conversion.ToOctal(instruction.NEXT)); UCodeMemory.SwitchMode((ushort)(instruction.NEXT | nextModifier), _taskType); } diff --git a/Contralto/CPU/UCodeDisassembler.cs b/Contralto/CPU/UCodeDisassembler.cs index a78083f..e20a546 100644 --- a/Contralto/CPU/UCodeDisassembler.cs +++ b/Contralto/CPU/UCodeDisassembler.cs @@ -24,9 +24,8 @@ namespace Contralto.CPU string source = string.Empty; string operation = string.Empty; string f1 = string.Empty; - string f2 = string.Empty; - string loadT = string.Empty; - string loadL = string.Empty; + string f2 = string.Empty; + string load = string.Empty; // Select BUS data. if (instruction.F1 != SpecialFunction1.Constant && @@ -36,7 +35,7 @@ namespace Contralto.CPU switch (instruction.BS) { case BusSource.ReadR: - source = String.Format("R[{0}] ", Conversion.ToOctal((int)rSelect)); + source = String.Format("$R{0} ", Conversion.ToOctal((int)rSelect)); break; case BusSource.LoadR: @@ -45,7 +44,7 @@ namespace Contralto.CPU break; case BusSource.None: - source = "177777(no source) "; + // nothing break; case BusSource.TaskSpecific1: @@ -240,41 +239,61 @@ namespace Contralto.CPU break; } - loadT = String.Format("T<- {0}", loadTFromALU ? operation : source); + load = String.Format("T<- {0}", loadTFromALU ? operation : source); } // Load L (and M) from ALU if (instruction.LoadL) { - if (string.IsNullOrEmpty(loadT)) + if (string.IsNullOrEmpty(load)) { - loadL = String.Format("L<- {0}", operation); + load = String.Format("L<- {0}", operation); } else { - loadL = String.Format("L<- {0}", loadT); + load = String.Format("L<- {0}", load); } } // Do writeback to selected R register from shifter output if (loadR) { - loadL = String.Format("R[{0}]<- {1}", Conversion.ToOctal((int)rSelect), loadL != String.Empty ? loadL : operation); + load = String.Format("$R{0}<- {1}", + Conversion.ToOctal((int)rSelect), + load != String.Empty ? load : operation); } // Do writeback to selected S register from M if (loadS) { - loadL = String.Format("S[{0}]<- {1}", Conversion.ToOctal((int)rSelect), loadL); + if (string.IsNullOrEmpty(load)) + { + load = String.Format("$S{0}<- M", + Conversion.ToOctal((int)rSelect)); + } + else + { + load = String.Format("$S{0}<- M, {1}", + Conversion.ToOctal((int)rSelect), + load); + } } - if (!string.IsNullOrEmpty(loadL) || !string.IsNullOrEmpty(loadT)) + if (!string.IsNullOrEmpty(load)) { - disassembly.AppendFormat("{0}{1}{2}{3} :{4}", f1, f2, loadT, loadL, Conversion.ToOctal(instruction.NEXT)); + disassembly.AppendFormat("{0}{1}{2} :{3}", + f1, + f2, + load, + Conversion.ToOctal(instruction.NEXT)); } else { - disassembly.AppendFormat("{0}{1}{2} :{3}", f1, f2, operation, Conversion.ToOctal(instruction.NEXT)); + disassembly.AppendFormat("{0}{1}{2} :{3}", + f1, + f2, + operation, + Conversion.ToOctal(instruction.NEXT)); } @@ -326,7 +345,7 @@ namespace Contralto.CPU { case EmulatorBusSource.ReadSLocation: loadS = false; - return String.Format("<-S[{0}]", Conversion.ToOctal((int)instruction.RSELECT)); + return String.Format("$S{0}", Conversion.ToOctal((int)instruction.RSELECT)); case EmulatorBusSource.LoadSLocation: loadS = true; diff --git a/Contralto/Contralto.csproj b/Contralto/Contralto.csproj index c8398df..ce773a1 100644 --- a/Contralto/Contralto.csproj +++ b/Contralto/Contralto.csproj @@ -118,6 +118,7 @@ + diff --git a/Contralto/IO/Music.cs b/Contralto/IO/Music.cs new file mode 100644 index 0000000..88abfff --- /dev/null +++ b/Contralto/IO/Music.cs @@ -0,0 +1,121 @@ +using Contralto.CPU; +using Contralto.Logging; +using Contralto.Memory; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Contralto.IO +{ + /// + /// Implements the hardware for Ted Kaehler's organ keyboard and DAC + /// + public class Music : IMemoryMappedDevice + { + public Music(AltoSystem system) + { + //_musicIo = new FileStream("c:\\alto\\mus.snd", FileMode.Create, FileAccess.ReadWrite); + _system = system; + Reset(); + } + + ~Music() + { + //_musicIo.Close(); + } + + public void Reset() + { + _foo = true; + } + + /// + /// Reads a word from the specified address. + /// + /// + /// + /// + public ushort Read(int address, TaskType task, bool extendedMemory) + { + // debug for kaehler's music st + Log.Write(LogType.Verbose, LogComponent.Music, "MUSIC (I/O) read from {0} by task {1} (bank {2}), Nova PC {3}", + Conversion.ToOctal(address), + task, + UCodeMemory.GetBank(task), + Conversion.ToOctal(_system.CPU.R[6])); + + if (address == 0xfffe) + { + return _lastDac; + } + else + { + _foo = !_foo; + + if (!_foo) + { + return 0x800; + } + else + { + return 0; + } + + + + } + } + + /// + /// Writes a word to the specified address. + /// + /// + /// + public void Load(int address, ushort data, TaskType task, bool extendedMemory) + { + Log.Write(LogType.Verbose, LogComponent.Music, "MUSIC (I/O) write to {0} ({1}) by task {2} (bank {3})", + Conversion.ToOctal(address), + Conversion.ToOctal(data), + task, + UCodeMemory.GetBank(task)); + + if (address == 0xfffe) + { + //_musicIo.WriteByte((byte)(data >> 8)); + //_musicIo.WriteByte((byte)data); + _lastDac = data; + } + } + + /// + /// Specifies the range (or ranges) of addresses decoded by this device. + /// + public MemoryRange[] Addresses + { + get { return _addresses; } + } + + + /// + /// From: http://bitsavers.org/pdf/xerox/alto/memos_1975/Reserved_Alto_Memory_Locations_Jan75.pdf + /// + /// #177140 - #177157: Organ Keyboard (Organ Hardware - Kaehler) + /// #177776: Digital-Analog Converter (DAC Hardware - Kaehler) + /// + private readonly MemoryRange[] _addresses = + { + new MemoryRange(0xfe60, 0xfe6f), // Organ + new MemoryRange(0xfffe, 0xfffe) // DAC + }; + + private ushort _lastDac; + + private AltoSystem _system; + + private FileStream _musicIo; + private bool _foo; + } +} diff --git a/Contralto/Logging/Log.cs b/Contralto/Logging/Log.cs index c27c7e6..a117878 100644 --- a/Contralto/Logging/Log.cs +++ b/Contralto/Logging/Log.cs @@ -28,6 +28,7 @@ namespace Contralto.Logging HostNetworkInterface = 0x2000, EthernetPacket = 0x4000, Configuration = 0x8000, + Music = 0x10000, Debug = 0x40000000, All = 0x7fffffff diff --git a/Contralto/Memory/IMemoryMappedDevice.cs b/Contralto/Memory/IMemoryMappedDevice.cs index c66c79c..970a2e1 100644 --- a/Contralto/Memory/IMemoryMappedDevice.cs +++ b/Contralto/Memory/IMemoryMappedDevice.cs @@ -11,9 +11,9 @@ namespace Contralto.Memory { public MemoryRange(ushort start, ushort end) { - if (!(end > start)) + if (!(end >= start)) { - throw new ArgumentOutOfRangeException("end must be greater than start."); + throw new ArgumentOutOfRangeException("end must be greater than or equal to start."); } Start = start; diff --git a/Contralto/Memory/Memory.cs b/Contralto/Memory/Memory.cs index 913f5a5..cb85558 100644 --- a/Contralto/Memory/Memory.cs +++ b/Contralto/Memory/Memory.cs @@ -55,11 +55,17 @@ namespace Contralto.Memory } else { + /* - if (extendedMemory) + // debug for kaehler's music st + if (address == 0x1fe || address == 0x1ff) // music microcode + // || (address >= 0x7f00 && address <= 0x80ff)) // DAC buffer { - Log.Write(LogComponent.Memory, "Extended memory read, bank {0} address {1}, read {2}", GetBankNumber(task, extendedMemory), Conversion.ToOctal(address), Conversion.ToOctal(_mem[address + 0x10000 * GetBankNumber(task, extendedMemory)])); - } */ + System.Console.WriteLine("MUSIC read from {0} by task {1} in bank {2}.", + Conversion.ToOctal(address), task, UCodeMemory.GetBank(task)); + } + */ + address += 0x10000 * GetBankNumber(task, extendedMemory); return _mem[address]; } @@ -79,12 +85,15 @@ namespace Contralto.Memory else { /* - if (extendedMemory) + if (address == 0x1fe || address == 0x1ff || // music microcode + (address >= 0x7f00 && address <= 0x80ff)) // DAC buffer { - Log.Write(LogComponent.Memory, "Extended memory write, bank {0} address {1}, data {2}", GetBankNumber(task, extendedMemory), Conversion.ToOctal(address), Conversion.ToOctal(data)); - } */ - address += 0x10000 * GetBankNumber(task, extendedMemory); + System.Console.WriteLine("MUSIC write to {0} ({1}) by task {2} in bank {3}.", + Conversion.ToOctal(address), Conversion.ToOctal(data), task, UCodeMemory.GetBank(task)); + } + */ + address += 0x10000 * GetBankNumber(task, extendedMemory); _mem[address] = data; } } diff --git a/Contralto/Memory/MemoryBus.cs b/Contralto/Memory/MemoryBus.cs index 27d892e..7e5512a 100644 --- a/Contralto/Memory/MemoryBus.cs +++ b/Contralto/Memory/MemoryBus.cs @@ -1,6 +1,7 @@ using Contralto.CPU; using System; using System.Collections.Generic; +using System.IO; namespace Contralto.Memory { @@ -21,9 +22,10 @@ namespace Contralto.Memory public MemoryBus() { _bus = new Dictionary(65536); - _systemType = Configuration.SystemType; + _systemType = Configuration.SystemType; + Reset(); - } + } public void AddDevice(IMemoryMappedDevice dev) { @@ -62,7 +64,7 @@ namespace Contralto.Memory _doubleWordStore = false; _doubleWordMixed = false; _memoryOperationActive = false; - _extendedMemoryReference = false; + _extendedMemoryReference = false; } public ushort MAR @@ -415,11 +417,11 @@ namespace Contralto.Memory if (_bus.TryGetValue(address, out memoryMappedDevice)) { return memoryMappedDevice.Read(address, task, extendedMemoryReference); - } + } else - { + { return 0; - } + } } } @@ -445,7 +447,7 @@ namespace Contralto.Memory if (_bus.TryGetValue(address, out memoryMappedDevice)) { memoryMappedDevice.Load(address, data, task, extendedMemoryReference); - } + } } } diff --git a/Contralto/UI/Debugger.Designer.cs b/Contralto/UI/Debugger.Designer.cs index 1da89f9..bf6a47d 100644 --- a/Contralto/UI/Debugger.Designer.cs +++ b/Contralto/UI/Debugger.Designer.cs @@ -89,10 +89,6 @@ this.MemoryJumpToAddress = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); this._memoryData = new System.Windows.Forms.DataGridView(); - this.Bkpt = new System.Windows.Forms.DataGridViewCheckBoxColumn(); - this.Address = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.Data = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.Disassembly = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.label1 = new System.Windows.Forms.Label(); this.ExecutionStateLabel = new System.Windows.Forms.Label(); this.ResetButton = new System.Windows.Forms.Button(); @@ -134,6 +130,12 @@ this.dataGridViewTextBoxColumn13 = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.dataGridViewTextBoxColumn14 = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.dataGridViewTextBoxColumn15 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.MemoryFindTextBox = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.Bkpt = new System.Windows.Forms.DataGridViewCheckBoxColumn(); + this.Address = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.Data = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.Disassembly = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.Microcode.SuspendLayout(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this._registerData)).BeginInit(); @@ -448,6 +450,8 @@ // // groupBox4 // + this.groupBox4.Controls.Add(this.MemoryFindTextBox); + this.groupBox4.Controls.Add(this.label4); this.groupBox4.Controls.Add(this.MemoryJumpToAddress); this.groupBox4.Controls.Add(this.label3); this.groupBox4.Controls.Add(this._memoryData); @@ -519,49 +523,6 @@ this._memoryData.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.MemoryViewCellClick); this._memoryData.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.OnMemoryCellValueNeeded); // - // Bkpt - // - this.Bkpt.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells; - this.Bkpt.FalseValue = "false"; - this.Bkpt.HeaderText = "B"; - this.Bkpt.Name = "Bkpt"; - this.Bkpt.ReadOnly = true; - this.Bkpt.Resizable = System.Windows.Forms.DataGridViewTriState.False; - this.Bkpt.ToolTipText = "Breakpoint"; - this.Bkpt.TrueValue = "true"; - this.Bkpt.Width = 20; - // - // Address - // - this.Address.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells; - this.Address.HeaderText = "Addr"; - this.Address.MinimumWidth = 16; - this.Address.Name = "Address"; - this.Address.ReadOnly = true; - this.Address.Resizable = System.Windows.Forms.DataGridViewTriState.False; - this.Address.ToolTipText = "Address"; - this.Address.Width = 54; - // - // Data - // - this.Data.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells; - this.Data.HeaderText = "Data"; - this.Data.MinimumWidth = 16; - this.Data.Name = "Data"; - this.Data.ReadOnly = true; - this.Data.Resizable = System.Windows.Forms.DataGridViewTriState.False; - this.Data.ToolTipText = "Data"; - this.Data.Width = 55; - // - // Disassembly - // - this.Disassembly.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; - this.Disassembly.HeaderText = "Disassembly"; - this.Disassembly.Name = "Disassembly"; - this.Disassembly.ReadOnly = true; - this.Disassembly.Resizable = System.Windows.Forms.DataGridViewTriState.False; - this.Disassembly.ToolTipText = "Disassembly"; - // // label1 // this.label1.AutoSize = true; @@ -1213,6 +1174,67 @@ this.dataGridViewTextBoxColumn15.Resizable = System.Windows.Forms.DataGridViewTriState.False; this.dataGridViewTextBoxColumn15.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; // + // MemoryFindTextBox + // + this.MemoryFindTextBox.Location = new System.Drawing.Point(159, 294); + this.MemoryFindTextBox.Name = "MemoryFindTextBox"; + this.MemoryFindTextBox.Size = new System.Drawing.Size(48, 20); + this.MemoryFindTextBox.TabIndex = 17; + this.MemoryFindTextBox.TabStop = false; + this.MemoryFindTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnMemoryFindKeyDown); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(123, 297); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(30, 13); + this.label4.TabIndex = 16; + this.label4.Text = "Find:"; + // + // Bkpt + // + this.Bkpt.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells; + this.Bkpt.FalseValue = "false"; + this.Bkpt.HeaderText = "B"; + this.Bkpt.Name = "Bkpt"; + this.Bkpt.ReadOnly = true; + this.Bkpt.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.Bkpt.ToolTipText = "Breakpoint"; + this.Bkpt.TrueValue = "true"; + this.Bkpt.Width = 20; + // + // Address + // + this.Address.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader; + this.Address.HeaderText = "Addr"; + this.Address.MinimumWidth = 16; + this.Address.Name = "Address"; + this.Address.ReadOnly = true; + this.Address.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.Address.ToolTipText = "Address"; + this.Address.Width = 16; + // + // Data + // + this.Data.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader; + this.Data.HeaderText = "Data"; + this.Data.MinimumWidth = 16; + this.Data.Name = "Data"; + this.Data.ReadOnly = true; + this.Data.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.Data.ToolTipText = "Data"; + this.Data.Width = 16; + // + // Disassembly + // + this.Disassembly.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.Disassembly.HeaderText = "Disassembly"; + this.Disassembly.Name = "Disassembly"; + this.Disassembly.ReadOnly = true; + this.Disassembly.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.Disassembly.ToolTipText = "Disassembly"; + // // Debugger // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -1301,10 +1323,6 @@ private System.Windows.Forms.Button ResetButton; private System.Windows.Forms.Button RunToNextTaskButton; private System.Windows.Forms.Button NovaStep; - private System.Windows.Forms.DataGridViewCheckBoxColumn Bkpt; - private System.Windows.Forms.DataGridViewTextBoxColumn Address; - private System.Windows.Forms.DataGridViewTextBoxColumn Data; - private System.Windows.Forms.DataGridViewTextBoxColumn Disassembly; private System.Windows.Forms.GroupBox groupBox6; private System.Windows.Forms.DataGridView _reservedMemory; private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn9; @@ -1343,5 +1361,11 @@ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn13; private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn14; private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn15; + private System.Windows.Forms.TextBox MemoryFindTextBox; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.DataGridViewCheckBoxColumn Bkpt; + private System.Windows.Forms.DataGridViewTextBoxColumn Address; + private System.Windows.Forms.DataGridViewTextBoxColumn Data; + private System.Windows.Forms.DataGridViewTextBoxColumn Disassembly; } } \ No newline at end of file diff --git a/Contralto/UI/Debugger.cs b/Contralto/UI/Debugger.cs index d085b94..92bc249 100644 --- a/Contralto/UI/Debugger.cs +++ b/Contralto/UI/Debugger.cs @@ -772,6 +772,39 @@ namespace Contralto } } + private void OnMemoryFindKeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Return || + e.KeyCode == Keys.Enter) + { + try + { + UInt16 value = Convert.ToUInt16(MemoryFindTextBox.Text, 8); + + // find the first address that contains this value + ushort address = 0; + if (_memoryData.SelectedRows.Count > 0) + { + // start at entry after selected line + address = (ushort)(_memoryData.SelectedRows[0].Index + 1); + } + + for(int i=address;i<65536;i++) + { + if (_system.MemoryBus.DebugReadWord((ushort)i) == value) + { + HighlightNovaSourceLine((ushort)i); + break; + } + } + } + catch + { + // eh, just do nothing for now + } + } + } + private void OnStepButtonClicked(object sender, EventArgs e) { _execType = ExecutionType.Step; @@ -891,13 +924,16 @@ namespace Contralto // See if we need to stop here if (_execAbort || // The Stop button was hit - _microcodeBreakpointEnabled[(int)UCodeMemory.GetBank(_system.CPU.CurrentTask.TaskType), _system.CPU.CurrentTask.MPC] || // A microcode breakpoint was hit + _microcodeBreakpointEnabled[ + (int)UCodeMemory.GetBank( + _system.CPU.CurrentTask.TaskType), + _system.CPU.CurrentTask.MPC] || // A microcode breakpoint was hit (_execType == ExecutionType.NextTask && _system.CPU.NextTask != null && _system.CPU.NextTask != _system.CPU.CurrentTask) || // The next task was switched to (_system.CPU.CurrentTask.MPC == 0x10 && // MPC is 20(octal) meaning a new Nova instruction and... (_novaBreakpointEnabled[_system.CPU.R[6]] || // A breakpoint is set here - _execType == ExecutionType.NextNovaInstruction))) // or we're running only a single Nova instruction. + _execType == ExecutionType.NextNovaInstruction))) // or we're running only a single Nova instruction. { // Stop here as we've hit a breakpoint or have been stopped // Update UI to indicate where we stopped. @@ -1411,6 +1447,8 @@ namespace Contralto private bool[,] _microcodeBreakpointEnabled; // Nova Debugger breakpoints; same as above - private bool[] _novaBreakpointEnabled; + private bool[] _novaBreakpointEnabled; + + } }