diff --git a/Contralto/AltoSystem.cs b/Contralto/AltoSystem.cs index fb0222f..5380cc7 100644 --- a/Contralto/AltoSystem.cs +++ b/Contralto/AltoSystem.cs @@ -28,6 +28,8 @@ namespace Contralto _mouse = new Mouse(); _ethernetController = new EthernetController(this); + + _cpu = new AltoCPU(this); // Attach memory-mapped devices to the bus @@ -177,7 +179,7 @@ namespace Contralto private AltoCPU _cpu; private MemoryBus _memBus; - private Contralto.Memory.Memory _mem; + private Memory.Memory _mem; private Keyboard _keyboard; private Mouse _mouse; private DiskController _diskController; diff --git a/Contralto/AltoWindow.Designer.cs b/Contralto/AltoWindow.Designer.cs index 52688db..556d7f3 100644 --- a/Contralto/AltoWindow.Designer.cs +++ b/Contralto/AltoWindow.Designer.cs @@ -39,17 +39,17 @@ this.drive0ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.loadToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.unloadToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.Drive0ImageName = new System.Windows.Forms.ToolStripMenuItem(); this.drive1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.loadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.unloadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Drive1ImageName = new System.Windows.Forms.ToolStripMenuItem(); this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.SystemShowDebuggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.StatusLine = new System.Windows.Forms.StatusStrip(); this.CaptureStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this.Drive0ImageName = new System.Windows.Forms.ToolStripMenuItem(); - this.Drive1ImageName = new System.Windows.Forms.ToolStripMenuItem(); this.SystemStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); this.DiskStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); ((System.ComponentModel.ISupportInitialize)(this.DisplayBox)).BeginInit(); @@ -92,7 +92,7 @@ // exitToolStripMenuItem // this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; - this.exitToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.exitToolStripMenuItem.Size = new System.Drawing.Size(92, 22); this.exitToolStripMenuItem.Text = "Exit"; this.exitToolStripMenuItem.Click += new System.EventHandler(this.OnFileExitClick); // @@ -154,6 +154,13 @@ this.unloadToolStripMenuItem1.Text = "Unload..."; this.unloadToolStripMenuItem1.Click += new System.EventHandler(this.OnSystemDrive0UnloadClick); // + // Drive0ImageName + // + this.Drive0ImageName.Enabled = false; + this.Drive0ImageName.Name = "Drive0ImageName"; + this.Drive0ImageName.Size = new System.Drawing.Size(167, 22); + this.Drive0ImageName.Text = "Image Name"; + // // drive1ToolStripMenuItem // this.drive1ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -167,17 +174,24 @@ // loadToolStripMenuItem // this.loadToolStripMenuItem.Name = "loadToolStripMenuItem"; - this.loadToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.loadToolStripMenuItem.Size = new System.Drawing.Size(134, 22); this.loadToolStripMenuItem.Text = "Load..."; this.loadToolStripMenuItem.Click += new System.EventHandler(this.OnSystemDrive1LoadClick); // // unloadToolStripMenuItem // this.unloadToolStripMenuItem.Name = "unloadToolStripMenuItem"; - this.unloadToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.unloadToolStripMenuItem.Size = new System.Drawing.Size(134, 22); this.unloadToolStripMenuItem.Text = "Unload..."; this.unloadToolStripMenuItem.Click += new System.EventHandler(this.OnSystemDrive1UnloadClick); // + // Drive1ImageName + // + this.Drive1ImageName.Enabled = false; + this.Drive1ImageName.Name = "Drive1ImageName"; + this.Drive1ImageName.Size = new System.Drawing.Size(134, 22); + this.Drive1ImageName.Text = "Image Name"; + // // optionsToolStripMenuItem // this.optionsToolStripMenuItem.Enabled = false; @@ -228,20 +242,6 @@ this.CaptureStatusLabel.Size = new System.Drawing.Size(102, 17); this.CaptureStatusLabel.Text = "CaptureStatusLabel"; // - // Drive0ImageName - // - this.Drive0ImageName.Enabled = false; - this.Drive0ImageName.Name = "Drive0ImageName"; - this.Drive0ImageName.Size = new System.Drawing.Size(167, 22); - this.Drive0ImageName.Text = "Image Name"; - // - // Drive1ImageName - // - this.Drive1ImageName.Enabled = false; - this.Drive1ImageName.Name = "Drive1ImageName"; - this.Drive1ImageName.Size = new System.Drawing.Size(152, 22); - this.Drive1ImageName.Text = "Image Name"; - // // SystemStatusLabel // this.SystemStatusLabel.Name = "SystemStatusLabel"; @@ -271,6 +271,7 @@ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.Text = "ContrAlto"; this.Deactivate += new System.EventHandler(this.OnWindowDeactivate); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.OnAltoWindowClosed); this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnKeyDown); this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.OnKeyUp); this.Leave += new System.EventHandler(this.OnWindowLeave); diff --git a/Contralto/CPU/CPU.cs b/Contralto/CPU/CPU.cs index fd763fc..a9c1f1a 100644 --- a/Contralto/CPU/CPU.cs +++ b/Contralto/CPU/CPU.cs @@ -97,8 +97,7 @@ namespace Contralto.CPU _l = 0; _m = 0; _ir = 0; - _aluC0 = 0; - _rb = 0; + _aluC0 = 0; _rmr = 0xffff; // Start all tasks in ROM0 // Reset tasks. @@ -233,8 +232,7 @@ namespace Contralto.CPU // R and S register files and bank select private ushort[] _r; - private ushort[][] _s; - private ushort _rb; // S register bank select + private ushort[][] _s; // Stores the last carry from the ALU on a Load L private ushort _aluC0; diff --git a/Contralto/CPU/Tasks/DiskTask.cs b/Contralto/CPU/Tasks/DiskTask.cs index 01073d3..4188b70 100644 --- a/Contralto/CPU/Tasks/DiskTask.cs +++ b/Contralto/CPU/Tasks/DiskTask.cs @@ -167,10 +167,17 @@ namespace Contralto.CPU break; case DiskF2.NFER: - // "NEXT <- NEXT OR (IF fatal error in latches THEN 0 ELSE 1)" - // We assume success for now... + // "NEXT <- NEXT OR (IF fatal error in latches THEN 0 ELSE 1)" _nextModifier |= GetInitModifier(instruction); - _nextModifier |= 0x1; + + if (true) //!_diskController.FatalError) + { + _nextModifier |= 0x1; + } + else + { + Console.WriteLine("fatal disk error"); + } break; case DiskF2.STROBON: diff --git a/Contralto/CPU/Tasks/EmulatorTask.cs b/Contralto/CPU/Tasks/EmulatorTask.cs index f7bc740..96fdb00 100644 --- a/Contralto/CPU/Tasks/EmulatorTask.cs +++ b/Contralto/CPU/Tasks/EmulatorTask.cs @@ -34,9 +34,9 @@ namespace Contralto.CPU switch (ebs) { case EmulatorBusSource.ReadSLocation: - if (_rSelect != 0) + if (_srSelect != 0) { - return _cpu._s[_cpu._rb][_rSelect]; + return _cpu._s[_rb][_srSelect]; } else { @@ -47,8 +47,10 @@ namespace Contralto.CPU } case EmulatorBusSource.LoadSLocation: + // "When an S register is being loaded from M, the processor bus receives an + // undefined value rather than being set to zero." _loadS = true; - return 0; // TODO: technically this is an "undefined value," not zero. + return 0xffff; // TODO: technically this is an "undefined value.". default: throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs)); @@ -136,6 +138,14 @@ namespace Contralto.CPU _wrtRam = true; break; + case EmulatorF1.LoadESRB: + // For now, this is always 0; we do not yet support the 3K RAM system with 8 banks of S registers. + _rb = 0; + Logging.Log.Write(Logging.LogType.Warning, Logging.LogComponent.EmulatorTask, "ESRB<- ({0}) not fully implemented.", + Conversion.ToOctal((_busData & 0xe) >> 1)); + //_rb = (ushort)((_busData & 0xe) >> 1); + break; + default: throw new InvalidOperationException(String.Format("Unhandled emulator F1 {0}.", ef1)); } @@ -165,6 +175,9 @@ namespace Contralto.CPU // // "...DNS also addresses R from (3-IR[3 - 4])..." // + + // TODO: is S reg select impacted by this? + //_srSelect = _rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x1800) >> 11) ^ 3); break; diff --git a/Contralto/CPU/Tasks/Task.cs b/Contralto/CPU/Tasks/Task.cs index d9a916f..8bae25c 100644 --- a/Contralto/CPU/Tasks/Task.cs +++ b/Contralto/CPU/Tasks/Task.cs @@ -53,6 +53,7 @@ namespace Contralto.CPU // _mpc = (ushort)_taskType; _rdRam = false; + _rb = 0; } public virtual void BlockTask() @@ -95,6 +96,7 @@ namespace Contralto.CPU _loadR = false; _loadS = false; _rSelect = 0; + _srSelect = 0; _busData = 0; @@ -118,7 +120,7 @@ namespace Contralto.CPU nextModifier = _nextModifier; _nextModifier = 0; - _rSelect = instruction.RSELECT; + _srSelect = _rSelect = instruction.RSELECT; // Give tasks the chance to modify parameters early on (like RSELECT) ExecuteSpecialFunction2Early(instruction); @@ -220,7 +222,8 @@ namespace Contralto.CPU // // If there was a WRTRAM operation last cycle, we write the uCode RAM here - // using the results of this instruction's ALU operation. + // using the results of this instruction's ALU operation and the M register + // from the last instruction. // if (_wrtRam) { @@ -371,10 +374,10 @@ namespace Contralto.CPU _cpu._r[_rSelect] = Shifter.Output; } - // Do writeback to selected R register from M + // Do writeback to selected S register from M if (_loadS) { - _cpu._s[_cpu._rb][_rSelect] = _cpu._m; + _cpu._s[_rb][_srSelect] = _cpu._m; } // Load T @@ -485,6 +488,7 @@ namespace Contralto.CPU protected ushort _busData; // Data placed onto the bus (ANDed from multiple sources) protected ushort _nextModifier; // Bits ORed onto the NEXT field of the current instruction protected uint _rSelect; // RSELECT field from current instruction, potentially modified by task + protected uint _srSelect; // RSELECT field as used by S register access (not modified in the same way as normal _rSelect). protected bool _loadS; // Whether to load S from M at and of cycle protected bool _loadR; // Whether to load R from shifter at end of cycle. protected bool _rdRam; // Whether to load uCode RAM onto the bus during the next cycle. @@ -497,6 +501,7 @@ namespace Contralto.CPU // protected AltoCPU _cpu; protected ushort _mpc; + protected ushort _rb; // S register bank select protected TaskType _taskType; protected bool _wakeup; diff --git a/Contralto/CPU/UCodeMemory.cs b/Contralto/CPU/UCodeMemory.cs index 7e6d8c2..6bdccd1 100644 --- a/Contralto/CPU/UCodeMemory.cs +++ b/Contralto/CPU/UCodeMemory.cs @@ -104,7 +104,13 @@ namespace Contralto.CPU _ramBank = (address & 0x3000) >> 12; _ramSelect = (address & 0x0800) == 0; _lowHalfsel = (address & 0x0400) == 0; - _ramAddr = (address & 0x3ff); + _ramAddr = (address & 0x3ff); + + if (_ramBank != 0) + { + //throw new NotImplementedException(String.Format("Unexpected RAM BANK select of {0}", _ramBank)); + _ramBank = 0; + } } /// @@ -117,7 +123,8 @@ namespace Contralto.CPU { Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: Current Bank {0}", _microcodeBank[(int)task]); - // 2K ROM + // 2K ROM + /* switch(_microcodeBank[(int)task]) { case MicrocodeBank.ROM0: @@ -131,10 +138,10 @@ namespace Contralto.CPU case MicrocodeBank.RAM0: _microcodeBank[(int)task] = (nextAddress & 0x100) == 0 ? MicrocodeBank.ROM0 : MicrocodeBank.ROM1; break; - } + }*/ // for 1K ROM - //_microcodeBank[(int)task] = _microcodeBank[(int)task] == MicrocodeBank.ROM0 ? MicrocodeBank.RAM0 : MicrocodeBank.ROM0; + _microcodeBank[(int)task] = _microcodeBank[(int)task] == MicrocodeBank.ROM0 ? MicrocodeBank.RAM0 : MicrocodeBank.ROM0; Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: New Bank {0} for Task {1}", _microcodeBank[(int)task], task); } @@ -144,13 +151,7 @@ namespace Contralto.CPU if (!_ramSelect) { throw new NotImplementedException("Read from microcode ROM not implemented."); - } - - if (_ramBank > 0) - { - //throw new InvalidOperationException("RAM bank > 0, unexpected."); - _ramBank = 0; - } + } // pretend no ram for the moment Logging.Log.Write(Logging.LogComponent.Microcode, "CRAM address for read: Bank {0}, RAM {1}, lowhalf {2} addr {3}", @@ -178,13 +179,7 @@ namespace Contralto.CPU { // No-op, can't write to ROM. return; - } - - if (_ramBank > 0) - { - //throw new InvalidOperationException("RAM bank > 0, unexpected."); - _ramBank = 0; - } + } Logging.Log.Write(Logging.LogComponent.Microcode, "CRAM address for write: Bank {0}, addr {1}", _ramBank, diff --git a/Contralto/Debugger.Designer.cs b/Contralto/Debugger.Designer.cs index 714be87..d9f283f 100644 --- a/Contralto/Debugger.Designer.cs +++ b/Contralto/Debugger.Designer.cs @@ -53,6 +53,8 @@ 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.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Debugger)); this.Microcode = new System.Windows.Forms.GroupBox(); this.SourceTabs = new System.Windows.Forms.TabControl(); @@ -109,6 +111,13 @@ this.ResetButton = new System.Windows.Forms.Button(); this.RunToNextTaskButton = new System.Windows.Forms.Button(); this.NovaStep = new System.Windows.Forms.Button(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this._reservedMemory = new System.Windows.Forms.DataGridView(); + this.dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.dataGridViewTextBoxColumn10 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.dataGridViewTextBoxColumn11 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.label3 = new System.Windows.Forms.Label(); + this.MemoryJumpToAddress = new System.Windows.Forms.TextBox(); this.Microcode.SuspendLayout(); this.SourceTabs.SuspendLayout(); this.Rom0Page.SuspendLayout(); @@ -127,6 +136,8 @@ ((System.ComponentModel.ISupportInitialize)(this._memoryData)).BeginInit(); this.groupBox5.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this._diskData)).BeginInit(); + this.groupBox6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this._reservedMemory)).BeginInit(); this.SuspendLayout(); // // Microcode @@ -149,7 +160,7 @@ this.SourceTabs.Location = new System.Drawing.Point(6, 19); this.SourceTabs.Name = "SourceTabs"; this.SourceTabs.SelectedIndex = 0; - this.SourceTabs.Size = new System.Drawing.Size(590, 571); + this.SourceTabs.Size = new System.Drawing.Size(590, 580); this.SourceTabs.TabIndex = 14; this.SourceTabs.SelectedIndexChanged += new System.EventHandler(this.OnTabChanged); // @@ -159,7 +170,7 @@ this.Rom0Page.Location = new System.Drawing.Point(4, 22); this.Rom0Page.Name = "Rom0Page"; this.Rom0Page.Padding = new System.Windows.Forms.Padding(3); - this.Rom0Page.Size = new System.Drawing.Size(582, 545); + this.Rom0Page.Size = new System.Drawing.Size(582, 554); this.Rom0Page.TabIndex = 0; this.Rom0Page.Text = "ROM0"; this.Rom0Page.UseVisualStyleBackColor = true; @@ -199,7 +210,7 @@ this._rom0SourceViewer.ShowCellErrors = false; this._rom0SourceViewer.ShowEditingIcon = false; this._rom0SourceViewer.ShowRowErrors = false; - this._rom0SourceViewer.Size = new System.Drawing.Size(582, 545); + this._rom0SourceViewer.Size = new System.Drawing.Size(582, 554); this._rom0SourceViewer.TabIndex = 1; this._rom0SourceViewer.TabStop = false; this._rom0SourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.SourceViewCellClick); @@ -454,7 +465,7 @@ // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(11, 599); + this.label2.Location = new System.Drawing.Point(11, 602); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(47, 13); this.label2.TabIndex = 13; @@ -462,7 +473,7 @@ // // JumpToAddress // - this.JumpToAddress.Location = new System.Drawing.Point(59, 596); + this.JumpToAddress.Location = new System.Drawing.Point(64, 599); this.JumpToAddress.Name = "JumpToAddress"; this.JumpToAddress.Size = new System.Drawing.Size(48, 20); this.JumpToAddress.TabIndex = 12; @@ -670,7 +681,7 @@ this.groupBox3.Size = new System.Drawing.Size(137, 344); this.groupBox3.TabIndex = 8; this.groupBox3.TabStop = false; - this.groupBox3.Text = "Other Registers"; + this.groupBox3.Text = "CPU Registers"; // // _otherRegs // @@ -729,6 +740,8 @@ // // groupBox4 // + this.groupBox4.Controls.Add(this.MemoryJumpToAddress); + this.groupBox4.Controls.Add(this.label3); this.groupBox4.Controls.Add(this._memoryData); this.groupBox4.Location = new System.Drawing.Point(172, 634); this.groupBox4.Name = "groupBox4"; @@ -773,7 +786,7 @@ this._memoryData.ShowCellToolTips = false; this._memoryData.ShowEditingIcon = false; this._memoryData.ShowRowErrors = false; - this._memoryData.Size = new System.Drawing.Size(279, 273); + this._memoryData.Size = new System.Drawing.Size(279, 257); this._memoryData.TabIndex = 0; this._memoryData.TabStop = false; this._memoryData.VirtualMode = true; @@ -936,11 +949,107 @@ this.NovaStep.UseVisualStyleBackColor = true; this.NovaStep.Click += new System.EventHandler(this.NovaStep_Click); // + // groupBox6 + // + this.groupBox6.Controls.Add(this._reservedMemory); + this.groupBox6.Location = new System.Drawing.Point(757, 3); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Size = new System.Drawing.Size(180, 975); + this.groupBox6.TabIndex = 3; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "Reserved Memory"; + // + // _reservedMemory + // + this._reservedMemory.AllowUserToAddRows = false; + this._reservedMemory.AllowUserToDeleteRows = false; + this._reservedMemory.AllowUserToResizeColumns = false; + this._reservedMemory.AllowUserToResizeRows = false; + dataGridViewCellStyle26.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this._reservedMemory.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle26; + this._reservedMemory.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this._reservedMemory.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.dataGridViewTextBoxColumn9, + this.dataGridViewTextBoxColumn10, + this.dataGridViewTextBoxColumn11}); + dataGridViewCellStyle27.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle27.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle27.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle27.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle27.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle27.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle27.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this._reservedMemory.DefaultCellStyle = dataGridViewCellStyle27; + this._reservedMemory.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; + this._reservedMemory.Location = new System.Drawing.Point(7, 19); + this._reservedMemory.MultiSelect = false; + this._reservedMemory.Name = "_reservedMemory"; + this._reservedMemory.ReadOnly = true; + this._reservedMemory.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single; + this._reservedMemory.RowHeadersVisible = false; + this._reservedMemory.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing; + this._reservedMemory.RowTemplate.Height = 18; + this._reservedMemory.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.CellSelect; + this._reservedMemory.ShowCellErrors = false; + this._reservedMemory.ShowCellToolTips = false; + this._reservedMemory.ShowEditingIcon = false; + this._reservedMemory.ShowRowErrors = false; + this._reservedMemory.Size = new System.Drawing.Size(167, 950); + this._reservedMemory.TabIndex = 0; + this._reservedMemory.TabStop = false; + // + // dataGridViewTextBoxColumn9 + // + this.dataGridViewTextBoxColumn9.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells; + this.dataGridViewTextBoxColumn9.HeaderText = "Addr"; + this.dataGridViewTextBoxColumn9.Name = "dataGridViewTextBoxColumn9"; + this.dataGridViewTextBoxColumn9.ReadOnly = true; + this.dataGridViewTextBoxColumn9.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; + this.dataGridViewTextBoxColumn9.Width = 35; + // + // dataGridViewTextBoxColumn10 + // + this.dataGridViewTextBoxColumn10.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells; + this.dataGridViewTextBoxColumn10.HeaderText = "Name"; + this.dataGridViewTextBoxColumn10.Name = "dataGridViewTextBoxColumn10"; + this.dataGridViewTextBoxColumn10.ReadOnly = true; + this.dataGridViewTextBoxColumn10.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.dataGridViewTextBoxColumn10.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; + this.dataGridViewTextBoxColumn10.Width = 41; + // + // dataGridViewTextBoxColumn11 + // + this.dataGridViewTextBoxColumn11.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.dataGridViewTextBoxColumn11.HeaderText = "Value"; + this.dataGridViewTextBoxColumn11.Name = "dataGridViewTextBoxColumn11"; + this.dataGridViewTextBoxColumn11.ReadOnly = true; + this.dataGridViewTextBoxColumn11.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.dataGridViewTextBoxColumn11.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(6, 279); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(47, 13); + this.label3.TabIndex = 14; + this.label3.Text = "Jump to:"; + // + // MemoryJumpToAddress + // + this.MemoryJumpToAddress.Location = new System.Drawing.Point(53, 276); + this.MemoryJumpToAddress.Name = "MemoryJumpToAddress"; + this.MemoryJumpToAddress.Size = new System.Drawing.Size(48, 20); + this.MemoryJumpToAddress.TabIndex = 15; + this.MemoryJumpToAddress.TabStop = false; + this.MemoryJumpToAddress.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnMemoryJumpAddressKeyDown); + // // Debugger // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(750, 997); + this.ClientSize = new System.Drawing.Size(949, 997); + this.Controls.Add(this.groupBox6); this.Controls.Add(this.NovaStep); this.Controls.Add(this.RunToNextTaskButton); this.Controls.Add(this.ResetButton); @@ -981,9 +1090,12 @@ this.groupBox3.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this._otherRegs)).EndInit(); this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this._memoryData)).EndInit(); this.groupBox5.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this._diskData)).EndInit(); + this.groupBox6.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this._reservedMemory)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -1046,5 +1158,12 @@ private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn4; private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3; private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn5; + private System.Windows.Forms.GroupBox groupBox6; + private System.Windows.Forms.DataGridView _reservedMemory; + private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn9; + private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn10; + private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11; + private System.Windows.Forms.TextBox MemoryJumpToAddress; + private System.Windows.Forms.Label label3; } } \ No newline at end of file diff --git a/Contralto/Debugger.cs b/Contralto/Debugger.cs index 0f9f6f9..8b9e341 100644 --- a/Contralto/Debugger.cs +++ b/Contralto/Debugger.cs @@ -134,6 +134,13 @@ namespace Contralto _diskData.Rows[8].Cells[1].Value = Conversion.ToOctal(_system.DiskController.KSTAT, 6); _diskData.Rows[9].Cells[1].Value = _system.DiskController.RECNO.ToString(); + // Reserved memory locations + for (int i = 0; i < _reservedMemoryEntries.Length; i++) + { + _reservedMemory.Rows[i].Cells[2].Value = + Conversion.ToOctal(_system.MemoryBus.DebugReadWord(_reservedMemoryEntries[i].Address), 6); + } + // // Select active tab based on current UCode bank switch (UCodeMemory.Bank) @@ -248,7 +255,15 @@ 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"); + + for(int i=0;i< _reservedMemoryEntries.Length;i++) + { + _reservedMemory.Rows.Add( + Conversion.ToOctal(_reservedMemoryEntries[i].Address, 3), + _reservedMemoryEntries[i].Name, + Conversion.ToOctal(0, 6)); + } } @@ -641,6 +656,25 @@ namespace Contralto } } + private void OnMemoryJumpAddressKeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Return || + e.KeyCode == Keys.Enter) + { + try + { + UInt16 address = Convert.ToUInt16(MemoryJumpToAddress.Text, 8); + + // find the source address that matches this, if any. + HighlightNovaSourceLine(address); + } + catch + { + // eh, just do nothing for now + } + } + } + private void OnStepButtonClicked(object sender, EventArgs e) { _execType = ExecutionType.Step; @@ -790,6 +824,80 @@ namespace Contralto InternalError, } + private struct ReservedMemoryEntry + { + public ReservedMemoryEntry(ushort address, string name) + { + Address = address; + Name = name; + } + + public ushort Address; + public string Name; + } + + private ReservedMemoryEntry[] _reservedMemoryEntries = + { + new ReservedMemoryEntry(0x110, "DASTART"), + new ReservedMemoryEntry(0x111, "V.INT"), + new ReservedMemoryEntry(0x112, "ITQUAN"), + new ReservedMemoryEntry(0x113, "ITBITS"), + new ReservedMemoryEntry(0x114, "MOUSEX"), + new ReservedMemoryEntry(0x115, "MOUSEY"), + new ReservedMemoryEntry(0x116, "CURSORX"), + new ReservedMemoryEntry(0x117, "CURSORY"), + new ReservedMemoryEntry(0x118, "RTC"), + new ReservedMemoryEntry(0x119, "CURMAP0"), + new ReservedMemoryEntry(0x11a, "CURMAP1"), + new ReservedMemoryEntry(0x11b, "CURMAP2"), + new ReservedMemoryEntry(0x11c, "CURMAP3"), + new ReservedMemoryEntry(0x11d, "CURMAP4"), + new ReservedMemoryEntry(0x11e, "CURMAP5"), + new ReservedMemoryEntry(0x11f, "CURMAP6"), + new ReservedMemoryEntry(0x120, "CURMAP7"), + new ReservedMemoryEntry(0x121, "CURMAP8"), + new ReservedMemoryEntry(0x122, "CURMAP9"), + new ReservedMemoryEntry(0x123, "CURMAP10"), + new ReservedMemoryEntry(0x124, "CURMAP11"), + new ReservedMemoryEntry(0x125, "CURMAP12"), + new ReservedMemoryEntry(0x126, "CURMAP13"), + new ReservedMemoryEntry(0x127, "CURMAP14"), + new ReservedMemoryEntry(0x128, "CURMAP15"), + new ReservedMemoryEntry(0x12a, "WW"), + new ReservedMemoryEntry(0x12b, "ACTIVE"), + new ReservedMemoryEntry(0x140, "PCLOC"), + new ReservedMemoryEntry(0x141, "INTVEC0"), + new ReservedMemoryEntry(0x142, "INTVEC1"), + new ReservedMemoryEntry(0x143, "INTVEC2"), + new ReservedMemoryEntry(0x144, "INTVEC3"), + new ReservedMemoryEntry(0x145, "INTVEC4"), + new ReservedMemoryEntry(0x146, "INTVEC5"), + new ReservedMemoryEntry(0x147, "INTVEC6"), + new ReservedMemoryEntry(0x148, "INTVEC7"), + new ReservedMemoryEntry(0x149, "INTVEC8"), + new ReservedMemoryEntry(0x14a, "INTVEC9"), + new ReservedMemoryEntry(0x14b, "INTVEC10"), + new ReservedMemoryEntry(0x14c, "INTVEC11"), + new ReservedMemoryEntry(0x14d, "INTVEC12"), + new ReservedMemoryEntry(0x14e, "INTVEC13"), + new ReservedMemoryEntry(0x14f, "INTVEC14"), + new ReservedMemoryEntry(0x151, "KBLK"), + new ReservedMemoryEntry(0x152, "KSTAT"), + new ReservedMemoryEntry(0x153, "KADDR"), + new ReservedMemoryEntry(0x154, "S.INTBM"), + new ReservedMemoryEntry(0x155, "ITTIM"), + new ReservedMemoryEntry(0x156, "TRAPPC"), + new ReservedMemoryEntry(0x180, "EPLOC"), + new ReservedMemoryEntry(0x181, "EBLOC"), + new ReservedMemoryEntry(0x182, "EELOC"), + new ReservedMemoryEntry(0x183, "ELLOC"), + new ReservedMemoryEntry(0x184, "EICLOC"), + new ReservedMemoryEntry(0x185, "EIPLOC"), + new ReservedMemoryEntry(0x186, "EOCLOC"), + new ReservedMemoryEntry(0x187, "EOPLOC"), + new ReservedMemoryEntry(0x188, "EHLOC"), + }; + private AltoSystem _system; private ExecutionController _controller; @@ -811,5 +919,6 @@ namespace Contralto // Nova Debugger breakpoints; same as above private bool[] _novaBreakpointEnabled; + } } diff --git a/Contralto/Debugger.resx b/Contralto/Debugger.resx index 032e0c7..2f44b9e 100644 --- a/Contralto/Debugger.resx +++ b/Contralto/Debugger.resx @@ -195,6 +195,15 @@ True + + True + + + True + + + True + diff --git a/Contralto/Disk/bravox.dsk b/Contralto/Disk/bravox.dsk index 1b2a22e..b527dad 100644 Binary files a/Contralto/Disk/bravox.dsk and b/Contralto/Disk/bravox.dsk differ diff --git a/Contralto/Disk/games.dsk b/Contralto/Disk/games.dsk index 946f0e7..45d96a8 100644 Binary files a/Contralto/Disk/games.dsk and b/Contralto/Disk/games.dsk differ diff --git a/Contralto/Disk/gamesb.dsk b/Contralto/Disk/gamesb.dsk index dbd478c..22c41bb 100644 Binary files a/Contralto/Disk/gamesb.dsk and b/Contralto/Disk/gamesb.dsk differ diff --git a/Contralto/Disk/gsl.dsk b/Contralto/Disk/gsl.dsk index 370d44c..7e1dadc 100644 Binary files a/Contralto/Disk/gsl.dsk and b/Contralto/Disk/gsl.dsk differ diff --git a/Contralto/Disk/mazeWar.dsk b/Contralto/Disk/mazeWar.dsk index 2b01346..a6bfe83 100644 Binary files a/Contralto/Disk/mazeWar.dsk and b/Contralto/Disk/mazeWar.dsk differ diff --git a/Contralto/Disk/mazeWarTry2.dsk b/Contralto/Disk/mazeWarTry2.dsk index 1a17797..bf4f3ed 100644 Binary files a/Contralto/Disk/mazeWarTry2.dsk and b/Contralto/Disk/mazeWarTry2.dsk differ diff --git a/Contralto/Disk/nonprog.dsk b/Contralto/Disk/nonprog.dsk index 9d7bc9d..a4fde57 100644 Binary files a/Contralto/Disk/nonprog.dsk and b/Contralto/Disk/nonprog.dsk differ diff --git a/Contralto/Disk/st76boot.dsk b/Contralto/Disk/st76boot.dsk index 2add0c3..bf12ce9 100644 Binary files a/Contralto/Disk/st76boot.dsk and b/Contralto/Disk/st76boot.dsk differ diff --git a/Contralto/Disk/tdisk4.dsk b/Contralto/Disk/tdisk4.dsk index 81321bf..8a1eb59 100644 Binary files a/Contralto/Disk/tdisk4.dsk and b/Contralto/Disk/tdisk4.dsk differ diff --git a/Contralto/Display/DisplayController.cs b/Contralto/Display/DisplayController.cs index 3a37ae8..803bffa 100644 --- a/Contralto/Display/DisplayController.cs +++ b/Contralto/Display/DisplayController.cs @@ -167,45 +167,25 @@ namespace Contralto.Display displayWord = _whiteOnBlack ? _dataBuffer.Dequeue() : (ushort)~_dataBuffer.Dequeue(); } + _display.DrawDisplayWord(_scanline, _word, displayWord, _lowRes); + // Merge in cursor word: // Calculate X offset of current word int xOffset = _word * (_lowRes ? 32 : 16); - // Is cursor within this range? (Note cursor is always 16 bits wide regardless of - // display mode, but may span two 16-bit display words.) - if ((_cursorXLatched >= xOffset && _cursorXLatched < xOffset + 16) || - (_cursorXLatched + 16 >= xOffset & _cursorXLatched + 16 < xOffset + 16)) - { - // Yes. Merge bits in the appropriate place. - int shift = (_cursorXLatched - xOffset); - - // Which half of the 32-bit word the cursor will appear in are we in? - if (shift > 0) - { - // Take the cursor word shifted by the current offset - displayWord ^= (ushort)((_cursorRegLatched) >> shift); - } - else - { - // Take the cursor word shifted left - displayWord ^= (ushort)((_cursorRegLatched) << (-shift)); - } - } - - _display.DrawDisplayWord(_scanline, _word, displayWord, _lowRes); - _word++; - if (_word == (_lowRes ? _scanlineWords / 4 : _scanlineWords / 2)) - { - // Run MRT - //_system.CPU.WakeupTask(TaskType.MemoryRefresh); - } - if (_word >= (_lowRes ? _scanlineWords / 2 : _scanlineWords)) { // End of scanline. - // Move to next. + // Move to next. + + // Draw cursor for this scanline first + if (_cursorXLatched < 606) + { + _display.DrawCursorWord(_scanline, _cursorXLatched, _cursorRegLatched); + } + _scanline += 2; if (_scanline > 807) @@ -274,21 +254,17 @@ namespace Contralto.Display } public void LoadDDR(ushort word) - { - - if (_dataBuffer.Count < 20) - { - _dataBuffer.Enqueue(word); - } - - /* + { + _dataBuffer.Enqueue(word); + + // Sanity check: data length should never exceed 16 words. - if (_dataBuffer.Count >= 16) - { - - //_dataBuffer.Dequeue(); - //_system.CPU.BlockTask(TaskType.DisplayWord); - } */ + // TODO: we're allowing up to 18 before we start discarding things. + // This indicates that our timing is messed up somewhere... + if (_dataBuffer.Count > 18) + { + _dataBuffer.Dequeue(); + } } public void LoadXPREG(ushort word) @@ -296,32 +272,17 @@ namespace Contralto.Display if (!_cursorXLatch) { _cursorXLatch = true; - _cursorX = (ushort)(~word); - - //System.Console.WriteLine("XPREG {0}, scanline {1} word {2}", word, _scanline, _word); + _cursorX = (ushort)(~word); } } public void LoadCSR(ushort word) - { - /* - if (_cursorReg != 0 && word == 0) - { - System.Console.WriteLine("csr disabled, scanline {0}", _scanline); - } */ - + { if (!_cursorRegLatch) { _cursorRegLatch = true; - _cursorReg = (ushort)word; - - if (word != 0) - { - //System.Console.WriteLine("csr {0} scanline {1}, word {2}", Conversion.ToOctal(word), _scanline, _word); - } - } - - + _cursorReg = (ushort)word; + } } public void SETMODE(ushort word) diff --git a/Contralto/Display/FakeDisplayController.cs b/Contralto/Display/FakeDisplayController.cs index 097a7b5..258defb 100644 --- a/Contralto/Display/FakeDisplayController.cs +++ b/Contralto/Display/FakeDisplayController.cs @@ -89,7 +89,7 @@ _display.DrawDisplayWord(scanline, wordOffset, (ushort)(dcb.whiteOnBlack ? 0x0 : 0xffff), false); } - _display.Render(); + //_display.Render(); // decrement scan line counter for this DCB, if < 0, grab next DCB. dcb.scanlineCount--; diff --git a/Contralto/Display/IAltoDisplay.cs b/Contralto/Display/IAltoDisplay.cs index d2d5cd2..45ffe1e 100644 --- a/Contralto/Display/IAltoDisplay.cs +++ b/Contralto/Display/IAltoDisplay.cs @@ -17,6 +17,15 @@ namespace Contralto.Display /// void DrawDisplayWord(int scanline, int wordOffset, ushort dataWord, bool lowRes); + /// + /// Renders the cursor word for the specified scanline + /// + /// + /// + /// + /// + void DrawCursorWord(int scanline, int xOffset, ushort cursorWord); + /// /// Causes the display to be rendered /// diff --git a/Contralto/ExecutionController.cs b/Contralto/ExecutionController.cs index 6e5a5a4..3f53b16 100644 --- a/Contralto/ExecutionController.cs +++ b/Contralto/ExecutionController.cs @@ -18,7 +18,8 @@ namespace Contralto { _system = system; - _execAbort = false; + _execAbort = false; + _userAbort = false; } @@ -29,7 +30,7 @@ namespace Contralto public void StopExecution() { - _execAbort = true; + _userAbort = true; if (_execThread != null) { @@ -80,6 +81,7 @@ namespace Contralto } _execAbort = false; + _userAbort = false; _execThread = new Thread(new System.Threading.ThreadStart(ExecuteProc)); _execThread.Start(); @@ -108,7 +110,7 @@ namespace Contralto _execAbort = _stepCallback(); } - if (_execAbort) + if (_execAbort || _userAbort) { // Halt execution break; @@ -119,6 +121,7 @@ namespace Contralto // Execution thread and state private Thread _execThread; private bool _execAbort; + private bool _userAbort; private StepCallbackDelegate _stepCallback; private ErrorCallbackDelegate _errorCallback; diff --git a/Contralto/IO/DiabloPack.cs b/Contralto/IO/DiabloPack.cs index 743d076..df1ad2f 100644 --- a/Contralto/IO/DiabloPack.cs +++ b/Contralto/IO/DiabloPack.cs @@ -142,11 +142,51 @@ namespace Contralto.IO } } + public void Save(Stream imageStream) + { + for (int cylinder = 0; cylinder < _geometry.Cylinders; cylinder++) + { + for (int track = 0; track < _geometry.Tracks; track++) + { + for (int sector = 0; sector < _geometry.Sectors; sector++) + { + byte[] header = new byte[4]; // 2 words + byte[] label = new byte[16]; // 8 words + byte[] data = new byte[512]; // 256 words + + // + // Bitsavers images have an extra word in the header for some reason. + // We will follow this 'standard' when writing out. + // TODO: should support different formats ("correct" raw, Alto CopyDisk format, etc.) + // + byte[] dummy = new byte[2]; + imageStream.Write(dummy, 0, 2); + + DiabloDiskSector s = _sectors[cylinder, track, sector]; + + WriteWordBuffer(imageStream, s.Header); + WriteWordBuffer(imageStream, s.Label); + WriteWordBuffer(imageStream, s.Data); + } + } + } + } + public DiabloDiskSector GetSector(int cylinder, int track, int sector) { return _sectors[cylinder, track, sector]; } + private void WriteWordBuffer(Stream imageStream, ushort[] buffer) + { + // TODO: this is beyond inefficient + for(int i=0;i> 8)); + } + } + private void SwapBytes(byte[] data) { for(int i=0;i> 12, (_kDataWrite & 0x2) >> 1, (_kDataWrite & 0x1)); - - //if ((_kAdr & 0x1) != 0) - { - //_disk = ((_kDataWrite & 0x2) >> 1); - } - + Log.Write(LogComponent.DiskController, " -Selected disk is {0}", _disk); if ((_kDataWrite & 0x1) != 0) @@ -113,7 +108,20 @@ namespace Contralto.IO if (_sendAdr & (_kDataWrite & 0x2) != 0) { // Select disk if _sendAdr is true - _disk = (_kAdr & 0x1); + _disk = (_kAdr & 0x1); + _seeking = false; + + /* + + // Clear the NOTREADY flag depending on whether the drive is loaded or not + if (_drives[_disk].IsLoaded) + { + _kStat &= (ushort)~NOTREADY; + } + else + { + _kStat |= NOTREADY; + } */ } } @@ -186,8 +194,30 @@ namespace Contralto.IO { get { - // TODO: verify what generates this signal - return true; + // This is the SRWREADY signal, generated by the drive itself. + // This is true if the drive is: + // - powered on, loaded with a disk, spun up + // - not actively seeking + return _drives[0].IsLoaded; + } + } + + public bool FatalError + { + get + { + // + // A fatal error is signaled when any of: + // - SECLATE + // - A seek error + // - Drive not ready + // Is true. + // (In reality the logic is a bit more complicated, + // but this is sufficient.) + // + return (_kStat & SECLATE) != 0 || + (_kStat & SEEKFAIL) != 0 || + (_kStat & NOTREADY) != 0; } } @@ -207,6 +237,7 @@ namespace Contralto.IO _kDataWrite = 0; _kDataWriteLatch = false; _sendAdr = false; + _seeking = false; _wdInhib = true; _xferOff = true; @@ -261,7 +292,7 @@ namespace Contralto.IO SelectedDrive.Sector = _sector; // Only wake up if not actively seeking. - if ((_kStat & 0x0040) == 0) + if ((_kStat & STROBE) == 0) { Log.Write(LogType.Verbose, LogComponent.DiskController, "Waking up sector task for C/H/S {0}/{1}/{2}", SelectedDrive.Cylinder, SelectedDrive.Head, _sector); _system.CPU.WakeupTask(CPU.TaskType.DiskSector); @@ -269,7 +300,7 @@ namespace Contralto.IO // Reset SECLATE _seclate = false; _seclateEnable = true; - _kStat &= 0xffef; + _kStat &= (ushort)~SECLATE; // Schedule a disk word wakeup to spin the disk _wordEvent.TimestampNsec = _wordDuration; @@ -306,11 +337,11 @@ namespace Contralto.IO } private void SeclateCallback(ulong timeNsec, ulong skewNsec, object context) - { + { if (_seclateEnable) { - _seclate = true; - _kStat |= 0x0010; // TODO: move to constant field! + _seclate = true; + _kStat |= SECLATE; // TODO: move to constant field! Log.Write(LogComponent.DiskSectorTask, "SECLATE for sector {0}.", _sector); } } @@ -318,7 +349,7 @@ namespace Contralto.IO public void ClearStatus() { // "...clears KSTAT[13]." (chksum error flag) - _kStat &= 0xfffb; + _kStat &= 0xff4b; } public void IncrementRecord() @@ -367,9 +398,10 @@ namespace Contralto.IO // TODO: handle Model-44 cylinder count (and packs, for that matter) if (destCylinder > 202) { - _kStat |= 0x0080; + _kStat |= SEEKFAIL; Log.Write(LogComponent.DiskController, "Seek failed, specified cylinder {0} is out of range.", destCylinder); + _seeking = false; } else { @@ -377,10 +409,11 @@ namespace Contralto.IO _destCylinder = destCylinder; // Clear the fail bit. - _kStat &= 0xff7f; + _kStat &= (ushort)~SEEKFAIL; // Set seek bit - _kStat |= 0x0040; + _kStat |= STROBE; + _seeking = true; // And figure out how long this will take. _seekDuration = (ulong)(CalculateSeekTime() / (ulong)(Math.Abs(_destCylinder - SelectedDrive.Cylinder) + 1)); @@ -518,7 +551,7 @@ namespace Contralto.IO if (bWakeup) { Log.Write(LogType.Verbose, LogComponent.DiskWordTask, "Word task awoken for word {0}.", _sectorWordIndex); - _system.CPU.WakeupTask(TaskType.DiskWord); + _system.CPU.WakeupTask(TaskType.DiskWord); } // Last, move to the next word. @@ -548,7 +581,8 @@ namespace Contralto.IO if (SelectedDrive.Cylinder == _destCylinder) { // clear Seek bit - _kStat &= 0xffbf; + _kStat &= (ushort)~STROBE; + _seeking = false; Log.Write(LogComponent.DiskController, "Seek to {0} completed.", SelectedDrive.Cylinder); } @@ -612,6 +646,7 @@ namespace Contralto.IO private int _destCylinder; private ulong _seekDuration; private Event _seekEvent; + private bool _seeking; // Selected disk private int _disk; @@ -652,7 +687,7 @@ namespace Contralto.IO // 8.5uS for seclate delay (approx. 50 clocks) private static ulong _seclateDuration = (ulong)(85.0 * Conversion.UsecToNsec * _scale); private bool _seclateEnable; - private bool _seclate; + private bool _seclate; private Event _seclateEvent; // Attached drives @@ -661,5 +696,12 @@ namespace Contralto.IO private AltoSystem _system; private bool _debugRead; + + // KSTAT bitfields + private readonly ushort SECLATE = 0x10; + private readonly ushort NOTREADY = 0x20; + private readonly ushort STROBE = 0x40; + private readonly ushort SEEKFAIL = 0x80; + } } diff --git a/Contralto/Notes.txt b/Contralto/Notes.txt index f2047f7..00e6c36 100644 --- a/Contralto/Notes.txt +++ b/Contralto/Notes.txt @@ -80,3 +80,12 @@ Project is on backburner while working on SUPDUP; notes for myself on current st unsure if this is intentional... (i.e. marks a non-bootable pack) + Never mind -- pack was corrupted + + + 12/18/2015: + + Remaining disk controller signals: + + NFER -- look at -KFER signal to determine what a "fatal error" is + SWRNRDY -- llok at -SRWRDY signal to see what "ready" means