1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-22 10:31:01 +00:00

Fixed S register addressing (many things now working!), tweaked display (mouse displays correctly in lowres mode). Added support for committing disk changes back to disk images (done automatically when switching disks or exiting). Repaired BravoX image.

This commit is contained in:
Josh Dersch 2015-12-22 15:45:56 -08:00
parent 3c8a64bac8
commit 0cce77c842
26 changed files with 471 additions and 149 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}
/// <summary>
@ -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,

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -195,6 +195,15 @@
<metadata name="dataGridViewTextBoxColumn2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn9.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn10.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dataGridViewTextBoxColumn11.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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)

View File

@ -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--;

View File

@ -17,6 +17,15 @@ namespace Contralto.Display
/// <param name="lowRes"></param>
void DrawDisplayWord(int scanline, int wordOffset, ushort dataWord, bool lowRes);
/// <summary>
/// Renders the cursor word for the specified scanline
/// </summary>
/// <param name="scanline"></param>
/// <param name="wordOffset"></param>
/// <param name="dataWord"></param>
/// <param name="lowRes"></param>
void DrawCursorWord(int scanline, int xOffset, ushort cursorWord);
/// <summary>
/// Causes the display to be rendered
/// </summary>

View File

@ -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;

View File

@ -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<buffer.Length;i++)
{
imageStream.WriteByte((byte)buffer[i]);
imageStream.WriteByte((byte)(buffer[i] >> 8));
}
}
private void SwapBytes(byte[] data)
{
for(int i=0;i<data.Length;i+=2)

View File

@ -71,12 +71,7 @@ namespace Contralto.IO
(_kDataWrite & 0xf000) >> 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;
}
}

View File

@ -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