From ca638f1d6e59e5efab60f0d2cb3b45e2eb8306dc Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Tue, 10 Nov 2015 17:04:05 -0800 Subject: [PATCH] Initial rough implementation of Display hardware and associated tasks. Not really working. --- Contralto/AltoSystem.cs | 16 ++ Contralto/CPU/CPU.cs | 31 ++- Contralto/CPU/Tasks/CursorTask.cs | 42 ++++ Contralto/CPU/Tasks/DisplayHorizontalTask.cs | 14 +- Contralto/CPU/Tasks/DisplayVerticalTask.cs | 48 ++++ Contralto/CPU/Tasks/DisplayWordTask.cs | 8 +- Contralto/CPU/Tasks/MemoryRefreshTask.cs | 26 +++ Contralto/CPU/Tasks/Task.cs | 4 +- Contralto/CPU/UCodeMemory.cs | 21 +- Contralto/Contralto.csproj | 3 + Contralto/Debugger.Designer.cs | 207 ++++++++++------- Contralto/Debugger.cs | 65 +++++- Contralto/Display/DisplayController.cs | 224 ++++++++++++++++++- Contralto/IO/DiskController.cs | 4 +- Contralto/Logging/Log.cs | 83 +++++++ Contralto/Memory/Memory.cs | 5 + Contralto/Program.cs | 24 +- 17 files changed, 697 insertions(+), 128 deletions(-) create mode 100644 Contralto/CPU/Tasks/CursorTask.cs create mode 100644 Contralto/CPU/Tasks/DisplayVerticalTask.cs create mode 100644 Contralto/CPU/Tasks/MemoryRefreshTask.cs create mode 100644 Contralto/Logging/Log.cs diff --git a/Contralto/AltoSystem.cs b/Contralto/AltoSystem.cs index 89a8779..1226e06 100644 --- a/Contralto/AltoSystem.cs +++ b/Contralto/AltoSystem.cs @@ -51,6 +51,17 @@ namespace Contralto _displayController.Reset(); } + /// + /// Attaches an emulated display device to the system. + /// TODO: This is currently tightly-coupled with the Debugger, make + /// more general. + /// + /// + public void AttachDisplay(Debugger d) + { + _displayController.AttachDisplay(d); + } + public void SingleStep() { // Run every device that needs attention for a single clock cycle. @@ -75,6 +86,11 @@ namespace Contralto get { return _diskController; } } + public DisplayController DisplayController + { + get { return _displayController; } + } + /// /// Time (in msec) for one system clock /// diff --git a/Contralto/CPU/CPU.cs b/Contralto/CPU/CPU.cs index c85efb6..70b1da1 100644 --- a/Contralto/CPU/CPU.cs +++ b/Contralto/CPU/CPU.cs @@ -31,11 +31,28 @@ namespace Contralto.CPU _tasks[(int)TaskType.Emulator] = new EmulatorTask(this); _tasks[(int)TaskType.DiskSector] = new DiskTask(this, true); _tasks[(int)TaskType.DiskWord] = new DiskTask(this, false); - _tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this); + //_tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this); + //_tasks[(int)TaskType.DisplayHorizontal] = new DisplayHorizontalTask(this); + //_tasks[(int)TaskType.DisplayVertical] = new DisplayVerticalTask(this); + //_tasks[(int)TaskType.Cursor] = new CursorTask(this); + _tasks[(int)TaskType.MemoryRefresh] = new MemoryRefreshTask(this); Reset(); } + public void Hack() + { + _tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this); + _tasks[(int)TaskType.DisplayHorizontal] = new DisplayHorizontalTask(this); + _tasks[(int)TaskType.DisplayVertical] = new DisplayVerticalTask(this); + _tasks[(int)TaskType.Cursor] = new CursorTask(this); + + _tasks[(int)TaskType.DisplayWord].Reset(); + _tasks[(int)TaskType.DisplayHorizontal].Reset(); + _tasks[(int)TaskType.DisplayVertical].Reset(); + _tasks[(int)TaskType.Cursor].Reset(); + } + public Task[] Tasks { get { return _tasks; } @@ -148,6 +165,18 @@ namespace Contralto.CPU } } + public bool IsBlocked(TaskType task) + { + if (_tasks[(int)task] != null) + { + return _tasks[(int)task].Wakeup; + } + else + { + return false; + } + } + /// /// Used by the debugger to determine if a task switch is taking /// place. diff --git a/Contralto/CPU/Tasks/CursorTask.cs b/Contralto/CPU/Tasks/CursorTask.cs new file mode 100644 index 0000000..b5bcae7 --- /dev/null +++ b/Contralto/CPU/Tasks/CursorTask.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Contralto.Memory; + +namespace Contralto.CPU +{ + public partial class AltoCPU + { + /// + /// DisplayWordTask provides functionality for the DWT task + /// + private class CursorTask : Task + { + public CursorTask(AltoCPU cpu) : base(cpu) + { + _taskType = TaskType.DisplayWord; + + // The Wakeup signal is always true for the Emulator task. + _wakeup = false; + } + + protected override void ExecuteSpecialFunction2(MicroInstruction instruction) + { + DisplayWordF2 ef2 = (DisplayWordF2)instruction.F2; + switch (ef2) + { + case DisplayWordF2.LoadDDR: + + break; + + default: + throw new InvalidOperationException(String.Format("Unhandled display word F2 {0}.", ef2)); + break; + } + } + } + } +} diff --git a/Contralto/CPU/Tasks/DisplayHorizontalTask.cs b/Contralto/CPU/Tasks/DisplayHorizontalTask.cs index 543d77a..4905a32 100644 --- a/Contralto/CPU/Tasks/DisplayHorizontalTask.cs +++ b/Contralto/CPU/Tasks/DisplayHorizontalTask.cs @@ -11,25 +11,27 @@ namespace Contralto.CPU public partial class AltoCPU { /// - /// DisplayWordTask provides functionality for the DWT task + /// DisplayWordTask provides functionality for the DHT task /// private class DisplayHorizontalTask : Task { public DisplayHorizontalTask(AltoCPU cpu) : base(cpu) { - _taskType = TaskType.DisplayHorizontal; - - // The Wakeup signal is always true for the Emulator task. + _taskType = TaskType.DisplayHorizontal; _wakeup = false; } protected override void ExecuteSpecialFunction2(MicroInstruction instruction) { - DisplayWordF2 ef2 = (DisplayWordF2)instruction.F2; + DisplayHorizontalF2 ef2 = (DisplayHorizontalF2)instruction.F2; switch (ef2) { - case DisplayWordF2.LoadDDR: + case DisplayHorizontalF2.EVENFIELD: + _nextModifier |= (ushort)(_cpu._system.DisplayController.EVENFIELD ? 1 : 0); + break; + case DisplayHorizontalF2.SETMODE: + // NO-op for now break; default: diff --git a/Contralto/CPU/Tasks/DisplayVerticalTask.cs b/Contralto/CPU/Tasks/DisplayVerticalTask.cs new file mode 100644 index 0000000..5c48279 --- /dev/null +++ b/Contralto/CPU/Tasks/DisplayVerticalTask.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Contralto.Memory; + +namespace Contralto.CPU +{ + public partial class AltoCPU + { + /// + /// DisplayVerticalTask provides functionality for the DVT task + /// + private class DisplayVerticalTask : Task + { + public DisplayVerticalTask(AltoCPU cpu) : base(cpu) + { + _taskType = TaskType.DisplayVertical; + _wakeup = false; + } + + protected override bool ExecuteInstruction(MicroInstruction instruction) + { + // We put ourselves back to sleep immediately once we've started running + _wakeup = false; + + return base.ExecuteInstruction(instruction); + } + + protected override void ExecuteSpecialFunction2(MicroInstruction instruction) + { + DisplayVerticalF2 ef2 = (DisplayVerticalF2)instruction.F2; + switch (ef2) + { + case DisplayVerticalF2.EVENFIELD: + _nextModifier |= (ushort)(_cpu._system.DisplayController.EVENFIELD ? 1 : 0); + break; + + default: + throw new InvalidOperationException(String.Format("Unhandled display vertical F2 {0}.", ef2)); + break; + } + } + } + } +} diff --git a/Contralto/CPU/Tasks/DisplayWordTask.cs b/Contralto/CPU/Tasks/DisplayWordTask.cs index 8f1768d..d2bf2b0 100644 --- a/Contralto/CPU/Tasks/DisplayWordTask.cs +++ b/Contralto/CPU/Tasks/DisplayWordTask.cs @@ -17,19 +17,17 @@ namespace Contralto.CPU { public DisplayWordTask(AltoCPU cpu) : base(cpu) { - _taskType = TaskType.DisplayWord; - - // The Wakeup signal is always true for the Emulator task. + _taskType = TaskType.DisplayWord; _wakeup = false; } - + protected override void ExecuteSpecialFunction2(MicroInstruction instruction) { DisplayWordF2 ef2 = (DisplayWordF2)instruction.F2; switch (ef2) { case DisplayWordF2.LoadDDR: - + _cpu._system.DisplayController.LoadDDR(_busData); break; default: diff --git a/Contralto/CPU/Tasks/MemoryRefreshTask.cs b/Contralto/CPU/Tasks/MemoryRefreshTask.cs new file mode 100644 index 0000000..1342c35 --- /dev/null +++ b/Contralto/CPU/Tasks/MemoryRefreshTask.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Contralto.Memory; + +namespace Contralto.CPU +{ + public partial class AltoCPU + { + /// + /// DisplayWordTask provides functionality for the Memory Refresh task + /// + private class MemoryRefreshTask : Task + { + public MemoryRefreshTask(AltoCPU cpu) : base(cpu) + { + _taskType = TaskType.MemoryRefresh; + + _wakeup = false; + } + } + } +} diff --git a/Contralto/CPU/Tasks/Task.cs b/Contralto/CPU/Tasks/Task.cs index 35d3145..d185751 100644 --- a/Contralto/CPU/Tasks/Task.cs +++ b/Contralto/CPU/Tasks/Task.cs @@ -71,9 +71,9 @@ namespace Contralto.CPU public bool ExecuteNext() { // TODO: cache microinstructions (or pre-decode them) to save consing all these up every time. - MicroInstruction instruction = new MicroInstruction(UCodeMemory.UCodeROM[_mpc]); + MicroInstruction instruction = UCodeMemory.DecodeCache[_mpc]; - // Grab BLOCK bit so that other tasks can look at it + // Grab BLOCK bit so that other tasks / hardware can look at it _block = instruction.F1 == SpecialFunction1.Block; //Console.WriteLine("R5:{0},R6:{1},IR:{2} - {3}:{4}", OctalHelpers.ToOctal(_cpu._r[5]), OctalHelpers.ToOctal(_cpu._r[6]), OctalHelpers.ToOctal(_cpu._ir), OctalHelpers.ToOctal(_mpc), UCodeDisassembler.DisassembleInstruction(instruction, _taskType)); diff --git a/Contralto/CPU/UCodeMemory.cs b/Contralto/CPU/UCodeMemory.cs index 279bb94..640f48a 100644 --- a/Contralto/CPU/UCodeMemory.cs +++ b/Contralto/CPU/UCodeMemory.cs @@ -32,6 +32,9 @@ namespace Contralto.CPU { _uCodeRam = new UInt32[1024]; LoadMicrocode(_uCodeRoms); + + _decodeCache = new MicroInstruction[2048]; + CacheMicrocodeDecode(); } public static UInt32[] UCodeROM @@ -44,6 +47,11 @@ namespace Contralto.CPU get { return _uCodeRam; } } + public static MicroInstruction[] DecodeCache + { + get { return _decodeCache; } + } + private static void LoadMicrocode(RomFile[] romInfo) { _uCodeRom = new UInt32[2048]; @@ -90,6 +98,14 @@ namespace Contralto.CPU return mappedAddress; } + private static void CacheMicrocodeDecode() + { + for(int i=0;i<_uCodeRom.Length;i++) + { + _decodeCache[i] = new MicroInstruction(_uCodeRom[i]); + } + } + private static RomFile[] _uCodeRoms = { // first K @@ -114,7 +130,10 @@ namespace Contralto.CPU }; private static UInt32[] _uCodeRom; - private static UInt32[] _uCodeRam; + private static UInt32[] _uCodeRam; + + + private static MicroInstruction[] _decodeCache; } diff --git a/Contralto/Contralto.csproj b/Contralto/Contralto.csproj index 99f9a4c..7e61926 100644 --- a/Contralto/Contralto.csproj +++ b/Contralto/Contralto.csproj @@ -48,7 +48,10 @@ + + + diff --git a/Contralto/Debugger.Designer.cs b/Contralto/Debugger.Designer.cs index 554b743..ba51e8c 100644 --- a/Contralto/Debugger.Designer.cs +++ b/Contralto/Debugger.Designer.cs @@ -28,21 +28,21 @@ /// private void InitializeComponent() { - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle9 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle11 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle12 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle13 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle14 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle15 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle16 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle20 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle17 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle18 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle19 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle21 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle22 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle23 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle24 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle25 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle26 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle27 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle28 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle29 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle30 = new System.Windows.Forms.DataGridViewCellStyle(); this.Microcode = new System.Windows.Forms.GroupBox(); this.label2 = new System.Windows.Forms.Label(); this.JumpToAddress = new System.Windows.Forms.TextBox(); @@ -84,6 +84,9 @@ this.Address = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.Data = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.Disassembly = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.DisplayBox = new System.Windows.Forms.PictureBox(); + this.button1 = new System.Windows.Forms.Button(); this.Microcode.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this._sourceViewer)).BeginInit(); this.groupBox1.SuspendLayout(); @@ -96,6 +99,8 @@ ((System.ComponentModel.ISupportInitialize)(this._memoryData)).BeginInit(); this.groupBox5.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this._diskData)).BeginInit(); + this.groupBox6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.DisplayBox)).BeginInit(); this.SuspendLayout(); // // Microcode @@ -133,8 +138,8 @@ this._sourceViewer.AllowUserToDeleteRows = false; this._sourceViewer.AllowUserToResizeColumns = false; this._sourceViewer.AllowUserToResizeRows = false; - dataGridViewCellStyle1.BackColor = System.Drawing.Color.Silver; - this._sourceViewer.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1; + dataGridViewCellStyle16.BackColor = System.Drawing.Color.Silver; + this._sourceViewer.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle16; this._sourceViewer.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleVertical; this._sourceViewer.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this._sourceViewer.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { @@ -147,14 +152,14 @@ this._sourceViewer.Name = "_sourceViewer"; this._sourceViewer.ReadOnly = true; this._sourceViewer.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single; - dataGridViewCellStyle5.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle5.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle5.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - dataGridViewCellStyle5.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle5.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle5.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle5.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this._sourceViewer.RowHeadersDefaultCellStyle = dataGridViewCellStyle5; + dataGridViewCellStyle20.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle20.BackColor = System.Drawing.SystemColors.Control; + dataGridViewCellStyle20.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle20.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridViewCellStyle20.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle20.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle20.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + this._sourceViewer.RowHeadersDefaultCellStyle = dataGridViewCellStyle20; this._sourceViewer.RowHeadersVisible = false; this._sourceViewer.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing; this._sourceViewer.RowTemplate.Height = 18; @@ -182,9 +187,9 @@ // T // this.T.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader; - dataGridViewCellStyle2.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this.T.DefaultCellStyle = dataGridViewCellStyle2; + dataGridViewCellStyle17.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle17.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this.T.DefaultCellStyle = dataGridViewCellStyle17; this.T.HeaderText = "T"; this.T.Name = "T"; this.T.ReadOnly = true; @@ -195,8 +200,8 @@ // Addr // this.Addr.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader; - dataGridViewCellStyle3.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.Addr.DefaultCellStyle = dataGridViewCellStyle3; + dataGridViewCellStyle18.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.Addr.DefaultCellStyle = dataGridViewCellStyle18; this.Addr.HeaderText = "Addr"; this.Addr.Name = "Addr"; this.Addr.ReadOnly = true; @@ -207,8 +212,8 @@ // Source // this.Source.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; - dataGridViewCellStyle4.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.Source.DefaultCellStyle = dataGridViewCellStyle4; + dataGridViewCellStyle19.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.Source.DefaultCellStyle = dataGridViewCellStyle19; this.Source.HeaderText = "Source Code"; this.Source.Name = "Source"; this.Source.ReadOnly = true; @@ -231,21 +236,21 @@ this._registerData.AllowUserToDeleteRows = false; this._registerData.AllowUserToResizeColumns = false; this._registerData.AllowUserToResizeRows = false; - dataGridViewCellStyle6.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); - this._registerData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle6; + dataGridViewCellStyle21.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this._registerData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle21; this._registerData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this._registerData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.RegNum, this.R, this.S}); - dataGridViewCellStyle7.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle7.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle7.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - dataGridViewCellStyle7.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle7.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle7.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle7.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this._registerData.DefaultCellStyle = dataGridViewCellStyle7; + dataGridViewCellStyle22.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle22.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle22.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle22.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle22.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle22.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle22.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this._registerData.DefaultCellStyle = dataGridViewCellStyle22; this._registerData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; this._registerData.Location = new System.Drawing.Point(7, 19); this._registerData.MultiSelect = false; @@ -346,21 +351,21 @@ // this._taskData.AllowUserToAddRows = false; this._taskData.AllowUserToDeleteRows = false; - dataGridViewCellStyle8.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); - this._taskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle8; + dataGridViewCellStyle23.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this._taskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle23; this._taskData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this._taskData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.TaskName, this.TaskState, this.TaskPC}); - dataGridViewCellStyle9.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle9.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle9.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - dataGridViewCellStyle9.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle9.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle9.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle9.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this._taskData.DefaultCellStyle = dataGridViewCellStyle9; + dataGridViewCellStyle24.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle24.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle24.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle24.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle24.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle24.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle24.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this._taskData.DefaultCellStyle = dataGridViewCellStyle24; this._taskData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; this._taskData.Location = new System.Drawing.Point(7, 19); this._taskData.MultiSelect = false; @@ -416,20 +421,20 @@ // this._otherRegs.AllowUserToAddRows = false; this._otherRegs.AllowUserToDeleteRows = false; - dataGridViewCellStyle10.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); - this._otherRegs.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle10; + dataGridViewCellStyle25.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this._otherRegs.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle25; this._otherRegs.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this._otherRegs.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.Reg, this.RegValue}); - dataGridViewCellStyle11.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle11.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle11.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - dataGridViewCellStyle11.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle11.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle11.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle11.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this._otherRegs.DefaultCellStyle = dataGridViewCellStyle11; + dataGridViewCellStyle26.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle26.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle26.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle26.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle26.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle26.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle26.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this._otherRegs.DefaultCellStyle = dataGridViewCellStyle26; this._otherRegs.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; this._otherRegs.Location = new System.Drawing.Point(7, 19); this._otherRegs.MultiSelect = false; @@ -482,8 +487,8 @@ this._memoryData.AllowUserToAddRows = false; this._memoryData.AllowUserToDeleteRows = false; this._memoryData.AllowUserToResizeRows = false; - dataGridViewCellStyle12.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); - this._memoryData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle12; + dataGridViewCellStyle27.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this._memoryData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle27; this._memoryData.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithoutHeaderText; this._memoryData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this._memoryData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { @@ -491,14 +496,14 @@ this.Address, this.Data, this.Disassembly}); - dataGridViewCellStyle13.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle13.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle13.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - dataGridViewCellStyle13.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle13.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle13.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle13.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this._memoryData.DefaultCellStyle = dataGridViewCellStyle13; + dataGridViewCellStyle28.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle28.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle28.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle28.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle28.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle28.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle28.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this._memoryData.DefaultCellStyle = dataGridViewCellStyle28; this._memoryData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; this._memoryData.Location = new System.Drawing.Point(6, 19); this._memoryData.MultiSelect = false; @@ -551,20 +556,20 @@ // this._diskData.AllowUserToAddRows = false; this._diskData.AllowUserToDeleteRows = false; - dataGridViewCellStyle14.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); - this._diskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle14; + dataGridViewCellStyle29.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this._diskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle29; this._diskData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this._diskData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.dataGridViewTextBoxColumn1, this.dataGridViewTextBoxColumn2}); - dataGridViewCellStyle15.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle15.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle15.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - dataGridViewCellStyle15.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle15.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle15.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle15.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - this._diskData.DefaultCellStyle = dataGridViewCellStyle15; + dataGridViewCellStyle30.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle30.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle30.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle30.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle30.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle30.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle30.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this._diskData.DefaultCellStyle = dataGridViewCellStyle30; this._diskData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; this._diskData.Location = new System.Drawing.Point(6, 19); this._diskData.MultiSelect = false; @@ -671,11 +676,42 @@ this.Disassembly.Resizable = System.Windows.Forms.DataGridViewTriState.False; this.Disassembly.ToolTipText = "Disassembly"; // + // groupBox6 + // + this.groupBox6.Controls.Add(this.DisplayBox); + this.groupBox6.Location = new System.Drawing.Point(758, 3); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Size = new System.Drawing.Size(617, 834); + this.groupBox6.TabIndex = 15; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "Display"; + // + // DisplayBox + // + this.DisplayBox.BackColor = System.Drawing.SystemColors.Window; + this.DisplayBox.Location = new System.Drawing.Point(6, 19); + this.DisplayBox.Name = "DisplayBox"; + this.DisplayBox.Size = new System.Drawing.Size(606, 808); + this.DisplayBox.TabIndex = 0; + this.DisplayBox.TabStop = false; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(799, 873); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 1; + this.button1.Text = "HACK"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // // Debugger // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(753, 997); + this.ClientSize = new System.Drawing.Size(1376, 997); + this.Controls.Add(this.button1); + this.Controls.Add(this.groupBox6); this.Controls.Add(this.NovaStep); this.Controls.Add(this.RunToNextTaskButton); this.Controls.Add(this.ResetButton); @@ -707,6 +743,8 @@ ((System.ComponentModel.ISupportInitialize)(this._memoryData)).EndInit(); this.groupBox5.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this._diskData)).EndInit(); + this.groupBox6.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.DisplayBox)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -755,5 +793,8 @@ 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.PictureBox DisplayBox; + private System.Windows.Forms.Button button1; } } \ No newline at end of file diff --git a/Contralto/Debugger.cs b/Contralto/Debugger.cs index e4125e2..e8bf5a2 100644 --- a/Contralto/Debugger.cs +++ b/Contralto/Debugger.cs @@ -10,6 +10,7 @@ using System.Windows.Forms; using Contralto.CPU; using System.Threading; +using System.Drawing.Imaging; namespace Contralto { @@ -69,6 +70,43 @@ namespace Contralto base.Refresh(); RefreshUI(); + } + + public void RefreshAltoDisplay() + { + BeginInvoke(new StepDelegate(RefreshDisplayBox)); + } + + private void RefreshDisplayBox() + { + // Update the display + BitmapData data = _displayBuffer.LockBits(_displayRect, ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); + + IntPtr ptr = data.Scan0; + System.Runtime.InteropServices.Marshal.Copy(_displayData, 0, ptr, _displayData.Length); + + _displayBuffer.UnlockBits(data); + DisplayBox.Refresh(); + } + + /// + /// Invoked by the DisplayController to put a word on the emulated screen. + /// + /// + /// + /// + public void DrawDisplayWord(int scanline, int wordOffset, ushort word) + { + // TODO: move magic numbers to constants + int address = scanline * 76 + wordOffset * 2; + + if (address > _displayData.Length) + { + throw new InvalidOperationException("Display word address is out of bounds."); + } + + _displayData[address] = (byte)(word >> 8); + _displayData[address + 1] = (byte)(word); } private void RefreshUI() @@ -150,6 +188,15 @@ namespace Contralto ExecutionStateLabel.Text = String.Format("Stopped (error {0})", _lastExceptionText); break; } + + // Update the display + BitmapData data = _displayBuffer.LockBits(_displayRect, ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); + + IntPtr ptr = data.Scan0; + System.Runtime.InteropServices.Marshal.Copy(_displayData, 0, ptr, _displayData.Length); + + _displayBuffer.UnlockBits(data); + } private void InitControls() @@ -187,7 +234,11 @@ namespace Contralto _diskData.Rows.Add("KADR", "0"); _diskData.Rows.Add("KCOM", "0"); _diskData.Rows.Add("KSTAT", "0"); - _diskData.Rows.Add("RECNO", "0"); + _diskData.Rows.Add("RECNO", "0"); + + _displayBuffer = new Bitmap(608, 808, PixelFormat.Format1bppIndexed); + + DisplayBox.Image = _displayBuffer; } @@ -375,7 +426,7 @@ namespace Contralto Color.LightSeaGreen,// 8 - memory refresh Color.LightYellow, // 9 - display word Color.LightPink, // 10 - cursor - Color.LightGoldenrodYellow, // 11 - display horizontal + Color.Chartreuse, // 11 - display horizontal Color.LightCoral, // 12 - display vertical Color.LightSteelBlue, // 13 - parity Color.Gray, // 14 - disk word @@ -763,6 +814,16 @@ namespace Contralto // Nova Debugger breakpoints; same as above private bool[] _novaBreakpointEnabled; + // Display related data. + // At some point this should move elsewhere. + // Note: display is actually 606 pixels wide, but that's not an even multiple of 8, so we round up. + private byte[] _displayData = new byte[808 * 76]; + private Bitmap _displayBuffer; + private Rectangle _displayRect = new Rectangle(0, 0, 608, 808); + private void button1_Click(object sender, EventArgs e) + { + _system.CPU.Hack(); + } } } diff --git a/Contralto/Display/DisplayController.cs b/Contralto/Display/DisplayController.cs index 12d9df9..cd3d671 100644 --- a/Contralto/Display/DisplayController.cs +++ b/Contralto/Display/DisplayController.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Contralto.Logging; +using Contralto.CPU; namespace Contralto.Display { @@ -17,25 +18,240 @@ namespace Contralto.Display { public DisplayController(AltoSystem system) { - _system = system; + _system = system; Reset(); } + public void AttachDisplay(Debugger display) + { + _display = display; + } + public void Reset() { _evenField = true; + _clocks = 0; + _totalClocks = 0; + _state = DisplayState.VerticalBlank; + _scanline = 0; + _word = 0; + _dwtBlocked = false; + _dhtBlocked = false; } public void Clock() { - // TODO: Move the electron beam appropriately and wake up the display tasks - // as necessary. + + // + // Move the electron beam appropriately and wake up the display tasks + // as necessary. Render the display at the end of the field. + // + + // + // "The display control hardware also generates wakeup requests to the microprocessor + // tasking hardware. The vertical task DVT is awakened once per field, at the beginning + // of vertical retrace. The display horizontal task is awakened once at the beginning of + // each field, and thereafter whenever the display word task blocks. DHT can block itself, + // in which case neither it nor the word task can be awakened until the start of the next + // field. The wakeup request for the display word task (DWT) is controlled by the state + // of the 16 word buffer. If DWT has not executed a BLOCK, if DHT is not blocked, and if + // the buffer is not full, DWT wakeups are generated. The hardware sets the buffer empty + // and clears the DWT block flip-flop at the beginning of horizontal retrace for every + // scan line." + // + + // + // Check the BLOCK status of the DWT and DHT tasks for the last executed uInstruction. + // + _dhtBlocked = _system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DisplayHorizontal && + _system.CPU.CurrentTask.BLOCK; + + if (_system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DisplayWord && + _system.CPU.CurrentTask.BLOCK) + { + //Console.WriteLine("DWT BLOCK"); + _dwtBlocked = true; + + // + // Wake up DHT if it has not blocked itself. + // + if (!_dhtBlocked) + { + _system.CPU.WakeupTask(TaskType.DisplayHorizontal); + } + } + + _clocks++; + _totalClocks++; + + switch (_state) + { + case DisplayState.VerticalBlank: + // Just killing time + if (_clocks > _verticalBlankClocks) + { + // End of VBlank + _clocks -= _verticalBlankClocks; + _scanline = _evenField ? 0 : 1; + _word = 0; + _dataBuffer.Clear(); + + // Wake up DVT, DHT + _dwtBlocked = false; + _dhtBlocked = false; + _system.CPU.WakeupTask(TaskType.DisplayVertical); + _system.CPU.WakeupTask(TaskType.DisplayHorizontal); + _system.CPU.BlockTask(TaskType.DisplayWord); + + // Run MRT + _system.CPU.WakeupTask(TaskType.MemoryRefresh); + + // TODO: clear DWT, DHT block flip-flop + _state = DisplayState.VisibleScanline; + + //Console.WriteLine("Frame"); + } + break; + + case DisplayState.VisibleScanline: + // + // "If the DWT has not executed a BLOCK, if DHT is not blocked, and if the + // buffer is not full, DWT wakeups are generated." + // + if (_dataBuffer.Count < 16 && + !_system.CPU.IsBlocked(TaskType.DisplayHorizontal) && + !_dwtBlocked) + { + //Console.WriteLine("DWT wakeup, {0}", _dataBuffer.Count); + _system.CPU.WakeupTask(TaskType.DisplayWord); + } + else + { + // We can't take any words right now, remove Wakeup from + // the DWT. + if (_dataBuffer.Count >= 16) + { + //Log.Write(LogComponent.Display, "buffer full, blocking DWT."); + } + _system.CPU.BlockTask(TaskType.DisplayWord); + } + + // + // A scanline is 38 words wide; we clock in each word + // from the buffer (if present). + // + if (_clocks > _wordClocks) + { + _clocks -= _wordClocks; + + ushort displayWord = 0xaaaa; + if (_dataBuffer.Count > 0) + { + // Dequeue a word and draw it to the screen + displayWord = _dataBuffer.Dequeue(); + } + + _display.DrawDisplayWord(_scanline, _word, displayWord); + + _word++; + if (_word > 37) + { + // Done with this line + _dwtBlocked = false; + _dataBuffer.Clear(); + _state = DisplayState.HorizontalBlank; + } + } + break; + + case DisplayState.HorizontalBlank: + // Kill time until end of HBlank + if (_clocks > _horizontalBlankClocks) + { + _clocks -= _horizontalBlankClocks; + + // Move to next scanline + _scanline += 2; + _word = 0; + + if (_scanline > 807) + { + // Done with field, move to vblank, tell display to render + _state = DisplayState.VerticalBlank; + _evenField = !_evenField; + + _system.CPU.BlockTask(TaskType.DisplayVertical); + _system.CPU.BlockTask(TaskType.DisplayHorizontal); + _system.CPU.BlockTask(TaskType.DisplayWord); + + _display.RefreshAltoDisplay(); + + _frames++; + //Log.Write(LogComponent.Display, "Display field completed. {0} total clocks elapsed.", _totalClocks); + _totalClocks = 0; + } + else + { + _state = DisplayState.VisibleScanline; + } + } + break; + } } + public void LoadDDR(ushort word) + { + _dataBuffer.Enqueue(word); - bool _evenField; + //Console.WriteLine("Enqueue {0}", _dataBuffer.Count); + // Sanity check: data length should never exceed 16 words. + if (_dataBuffer.Count > 16) + { + _dataBuffer.Dequeue(); + _system.CPU.BlockTask(TaskType.DisplayWord); + } + } + + public bool EVENFIELD + { + get { return _evenField; } + } + + private enum DisplayState + { + Invalid = 0, + VerticalBlank, + VisibleScanline, + HorizontalBlank, + } + + private bool _evenField; + private double _clocks; + private double _totalClocks; + private int _frames; + private DisplayState _state; + + // Indicates whether the DWT or DHT blocked itself + // in which case they cannot be reawakened until the next field. + private bool _dwtBlocked; + private bool _dhtBlocked; + + private int _scanline; + private int _word; + + private Queue _dataBuffer = new Queue(16); private AltoSystem _system; + private Debugger _display; + + // Timing constants + // 38uS per scanline; 4uS for hblank. + // ~35 scanlines for vblank (1330uS) + private const double _wordClocks = (34.0 / 38.0) / 0.17; // uSec to clocks + private const double _horizontalBlankClocks = 4.0 / 0.17; + private const double _verticalBlankClocks = 1333.0 / 0.17; + + } } diff --git a/Contralto/IO/DiskController.cs b/Contralto/IO/DiskController.cs index 804d851..a760426 100644 --- a/Contralto/IO/DiskController.cs +++ b/Contralto/IO/DiskController.cs @@ -297,7 +297,7 @@ namespace Contralto.IO // Update the WDINIT signal; this is based on WDALLOW (!_wdInhib) which sets WDINIT (this is done // in KCOM way above). // WDINIT is reset when BLOCK (a BLOCK F1 is being executed) and WDTSKACT (the disk word task is running) are 1. - // + // if (_system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DiskWord && _system.CPU.CurrentTask.BLOCK) { @@ -639,7 +639,7 @@ namespace Contralto.IO // Sector timing. Based on table on pg. 43 of the Alto Hardware Manual private double _elapsedSectorTime; // elapsed time in this sector (in clocks) private const double _sectorDuration = (40.0 / 12.0); // time in msec for one sector - private const double _sectorClocks = _sectorDuration / 0.00017; // number of clock cycles per sector time. + private const double _sectorClocks = _sectorDuration / (0.00017); // number of clock cycles per sector time. private int _sectorWordIndex; diff --git a/Contralto/Logging/Log.cs b/Contralto/Logging/Log.cs new file mode 100644 index 0000000..679891c --- /dev/null +++ b/Contralto/Logging/Log.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Contralto.Logging +{ + /// + /// Specifies a component to specify logging for + /// + [Flags] + public enum LogComponent + { + None = 0, + EmulatorTask = 0x1, + DiskSectorTask = 0x2, + DiskWordTask = 0x4, + DiskController = 0x8, + Alu = 0x10, + Memory = 0x20, + Keyboard = 0x40, + Display = 0x80, + + All = 0x7fffffff + } + + /// + /// Specifies the type (or severity) of a given log message + /// + [Flags] + public enum LogType + { + None = 0, + Normal = 0x1, + Warning = 0x2, + Error = 0x4, + Verbose = 0x8, + All = 0x7fffffff + } + + /// + /// Provides basic functionality for logging messages of all types. + /// + public static class Log + { + static Log() + { + // TODO: make configurable + _components = LogComponent.All; + _type = LogType.Normal | LogType.Warning | LogType.Error; + } + + /// + /// Logs a message without specifying type/severity for terseness; + /// will not log if Type has been set to None. + /// + /// + /// + /// + public static void Write(LogComponent component, string message, params object[] args) + { + Write(LogType.Normal, component, message, args); + } + + public static void Write(LogType type, LogComponent component, string message, params object[] args) + { + if ((_type & type) != 0 && + (_components & component) != 0) + { + // + // My log has something to tell you... + // TODO: color based on type, etc. + Console.WriteLine(component.ToString() + ": " + message, args); + } + } + + + + private static LogComponent _components; + private static LogType _type; + } +} diff --git a/Contralto/Memory/Memory.cs b/Contralto/Memory/Memory.cs index 6434663..ae6a595 100644 --- a/Contralto/Memory/Memory.cs +++ b/Contralto/Memory/Memory.cs @@ -60,6 +60,11 @@ namespace Contralto.Memory address += 0x10000 * GetBankNumber(task, extendedMemory); _mem[address] = data; + if (address == 0x110 && data != 0) + { + Console.WriteLine("DASTART WRITE!"); + } + /* if (extendedMemory) { diff --git a/Contralto/Program.cs b/Contralto/Program.cs index dc09fff..d712372 100644 --- a/Contralto/Program.cs +++ b/Contralto/Program.cs @@ -14,31 +14,11 @@ namespace Contralto static void Main(string[] args) { - AltoSystem system = new AltoSystem(); - - - /* - for(int address=0; address < 1024; address++) - { - - MicroInstruction inst = new MicroInstruction(UCodeMemory.UCodeROM[address]); - - Console.WriteLine("{0}: {1} - RSEL:{2} ALUF:{3} BS:{4} F1:{5} F2:{6} T:{7} L:{8} NEXT:{9}", - OctalHelpers.ToOctal(address, 4), - OctalHelpers.ToOctal((int)UCodeMemory.UCodeROM[address], 11), - OctalHelpers.ToOctal((int)inst.RSELECT, 2), - OctalHelpers.ToOctal((int)inst.ALUF, 2), - OctalHelpers.ToOctal((int)inst.BS), - OctalHelpers.ToOctal((int)inst.F1, 2), - OctalHelpers.ToOctal((int)inst.F2, 2), - inst.LoadT ? 1 : 0, - inst.LoadL ? 1 : 0, - OctalHelpers.ToOctal((int)inst.NEXT, 4)); - } */ - + AltoSystem system = new AltoSystem(); // for now everything is driven through the debugger Debugger d = new Debugger(system); + system.AttachDisplay(d); d.LoadSourceCode("Disassembly\\altoIIcode3.mu"); d.ShowDialog();