diff --git a/Contralto/CPU/Tasks/DiskTask.cs b/Contralto/CPU/Tasks/DiskTask.cs
index 7d695b2..2490f8d 100644
--- a/Contralto/CPU/Tasks/DiskTask.cs
+++ b/Contralto/CPU/Tasks/DiskTask.cs
@@ -46,8 +46,7 @@ namespace Contralto.CPU
return _cpu._system.DiskController.KSTAT;
case DiskBusSource.ReadKDATA:
- ushort kdata = _cpu._system.DiskController.KDATA;
- return kdata;
+ return _cpu._system.DiskController.KDATA;
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
@@ -61,8 +60,7 @@ namespace Contralto.CPU
switch (df1)
{
case DiskF1.LoadKDATA:
- // "The KDATA register is loaded from BUS[0-15]."
- Log.Write(LogComponent.DiskController, "KDATA loaded with {0}", OctalHelpers.ToOctal(_busData));
+ // "The KDATA register is loaded from BUS[0-15]."
_cpu._system.DiskController.KDATA = _busData;
break;
@@ -70,8 +68,7 @@ namespace Contralto.CPU
// "This causes the KADR register to be loaded from BUS[8-14].
// in addition, it causes the head address bit to be loaded from KDATA[13]."
// (the latter is done by DiskController)
- _cpu._system.DiskController.KADR = (ushort)((_busData & 0xfe) >> 1);
- Log.Write(LogComponent.DiskController, "KADR bus data is {0}", OctalHelpers.ToOctal(_busData));
+ _cpu._system.DiskController.KADR = (ushort)((_busData & 0xff));
break;
case DiskF1.LoadKCOMM:
@@ -89,9 +86,15 @@ namespace Contralto.CPU
case DiskF1.LoadKSTAT:
// "KSTAT[12-15] are loaded from BUS[12-15]. (Actually BUS[13] is ORed onto
// KSTAT[13].)"
+
+ // From the schematic (and ucode source, based on the values it actually uses for BUS[13]), BUS[13]
+ // is also inverted. So there's that, too.
- // OR in BUS[12-15] after masking in KSTAT[13] so it is ORed in properly.
- _cpu._system.DiskController.KSTAT = (ushort)(((_cpu._system.DiskController.KSTAT & 0xfff4)) | (_busData & 0xf));
+ // build BUS[12-15] with bit 13 flipped.
+ int modifiedBusData = (_busData & 0xb) | ((~_busData) & 0x4);
+
+ // OR in BUS[12-15] after masking in KSTAT[13] so it is ORed in properly.
+ _cpu._system.DiskController.KSTAT = (ushort)(((_cpu._system.DiskController.KSTAT & 0xfff4)) | modifiedBusData);
break;
case DiskF1.STROBE:
diff --git a/Contralto/CPU/Tasks/EmulatorTask.cs b/Contralto/CPU/Tasks/EmulatorTask.cs
index 65c310d..4bf1232 100644
--- a/Contralto/CPU/Tasks/EmulatorTask.cs
+++ b/Contralto/CPU/Tasks/EmulatorTask.cs
@@ -282,7 +282,7 @@ namespace Contralto.CPU
case 0x400:
case 0x500:
case 0x600:
- // NEG, INC, ADC, SUB, ADD, AND - invert the carry bit
+ // NEG, INC, ADC, SUB, ADD - invert the carry bit
if (_cpu._aluC0 != 0)
{
carry = (~carry) & 0x1;
diff --git a/Contralto/Debugger.Designer.cs b/Contralto/Debugger.Designer.cs
index da2809d..554b743 100644
--- a/Contralto/Debugger.Designer.cs
+++ b/Contralto/Debugger.Designer.cs
@@ -79,11 +79,11 @@
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.ResetButton = new System.Windows.Forms.Button();
this.RunToNextTaskButton = new System.Windows.Forms.Button();
- this.B = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this.NovaStep = new System.Windows.Forms.Button();
+ this.Bkpt = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.Address = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Data = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Disassembly = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.NovaStep = new System.Windows.Forms.Button();
this.Microcode.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this._sourceViewer)).BeginInit();
this.groupBox1.SuspendLayout();
@@ -481,11 +481,13 @@
//
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;
+ 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[] {
- this.B,
+ this.Bkpt,
this.Address,
this.Data,
this.Disassembly});
@@ -503,6 +505,7 @@
this._memoryData.Name = "_memoryData";
this._memoryData.ReadOnly = true;
this._memoryData.RowHeadersVisible = false;
+ this._memoryData.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing;
this._memoryData.RowTemplate.DefaultCellStyle.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this._memoryData.RowTemplate.Height = 18;
this._memoryData.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
@@ -512,7 +515,9 @@
this._memoryData.ShowRowErrors = false;
this._memoryData.Size = new System.Drawing.Size(279, 273);
this._memoryData.TabIndex = 0;
+ this._memoryData.VirtualMode = true;
this._memoryData.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.MemoryViewCellClick);
+ this._memoryData.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.OnMemoryCellValueNeeded);
//
// label1
//
@@ -613,21 +618,31 @@
this.RunToNextTaskButton.UseVisualStyleBackColor = true;
this.RunToNextTaskButton.Click += new System.EventHandler(this.RunToNextTaskButton_Click);
//
- // B
+ // NovaStep
//
- this.B.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells;
- this.B.FalseValue = "false";
- this.B.HeaderText = "B";
- this.B.Name = "B";
- this.B.ReadOnly = true;
- this.B.Resizable = System.Windows.Forms.DataGridViewTriState.False;
- this.B.ToolTipText = "Breakpoint";
- this.B.TrueValue = "true";
- this.B.Width = 20;
+ this.NovaStep.Location = new System.Drawing.Point(207, 954);
+ this.NovaStep.Name = "NovaStep";
+ this.NovaStep.Size = new System.Drawing.Size(66, 23);
+ this.NovaStep.TabIndex = 14;
+ this.NovaStep.Text = "Nova Step";
+ this.NovaStep.UseVisualStyleBackColor = true;
+ this.NovaStep.Click += new System.EventHandler(this.NovaStep_Click);
+ //
+ // Bkpt
+ //
+ this.Bkpt.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
+ this.Bkpt.FalseValue = "false";
+ this.Bkpt.HeaderText = "B";
+ this.Bkpt.Name = "Bkpt";
+ this.Bkpt.ReadOnly = true;
+ this.Bkpt.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+ this.Bkpt.ToolTipText = "Breakpoint";
+ this.Bkpt.TrueValue = "true";
+ this.Bkpt.Width = 20;
//
// Address
//
- this.Address.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells;
+ this.Address.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
this.Address.HeaderText = "Addr";
this.Address.MinimumWidth = 16;
this.Address.Name = "Address";
@@ -638,7 +653,7 @@
//
// Data
//
- this.Data.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells;
+ this.Data.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
this.Data.HeaderText = "Data";
this.Data.MinimumWidth = 16;
this.Data.Name = "Data";
@@ -656,16 +671,6 @@
this.Disassembly.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.Disassembly.ToolTipText = "Disassembly";
//
- // NovaStep
- //
- this.NovaStep.Location = new System.Drawing.Point(207, 954);
- this.NovaStep.Name = "NovaStep";
- this.NovaStep.Size = new System.Drawing.Size(66, 23);
- this.NovaStep.TabIndex = 14;
- this.NovaStep.Text = "Nova Step";
- this.NovaStep.UseVisualStyleBackColor = true;
- this.NovaStep.Click += new System.EventHandler(this.NovaStep_Click);
- //
// Debugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -745,10 +750,10 @@
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
private System.Windows.Forms.Button ResetButton;
private System.Windows.Forms.Button RunToNextTaskButton;
- private System.Windows.Forms.DataGridViewCheckBoxColumn B;
+ private System.Windows.Forms.Button NovaStep;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn Bkpt;
private System.Windows.Forms.DataGridViewTextBoxColumn Address;
private System.Windows.Forms.DataGridViewTextBoxColumn Data;
private System.Windows.Forms.DataGridViewTextBoxColumn Disassembly;
- private System.Windows.Forms.Button NovaStep;
}
}
\ No newline at end of file
diff --git a/Contralto/Debugger.cs b/Contralto/Debugger.cs
index ca50a93..fafc3f3 100644
--- a/Contralto/Debugger.cs
+++ b/Contralto/Debugger.cs
@@ -112,13 +112,7 @@ namespace Contralto
_diskData.Rows[6].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KADR, 6);
_diskData.Rows[7].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KCOM, 6);
_diskData.Rows[8].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KSTAT, 6);
- _diskData.Rows[9].Cells[1].Value = _system.DiskController.RECNO.ToString();
-
- for (ushort i = 0; i < 1024; i++)
- {
- _memoryData.Rows[i].Cells[2].Value = OctalHelpers.ToOctal(_system.MemoryBus.DebugReadWord(i), 6);
- _memoryData.Rows[i].Cells[3].Value = Contralto.CPU.Nova.NovaDisassembler.DisassembleInstruction(i, _system.MemoryBus.DebugReadWord(i));
- }
+ _diskData.Rows[9].Cells[1].Value = _system.DiskController.RECNO.ToString();
// Find the right source line.
HighlightMicrocodeSourceLine(_system.CPU.CurrentTask.MPC);
@@ -170,15 +164,8 @@ namespace Contralto
_taskData.Rows.Add("0", "0", "0");
}
-
- for (ushort i=0;i<1024;i++)
- {
- _memoryData.Rows.Add(
- false,
- OctalHelpers.ToOctal(i, 6),
- OctalHelpers.ToOctal(_system.MemoryBus.DebugReadWord(i), 6),
- Contralto.CPU.Nova.NovaDisassembler.DisassembleInstruction(i, _system.MemoryBus.DebugReadWord(i)));
- }
+ // TODO: handle extended memory
+ _memoryData.RowCount = 65536;
_otherRegs.Rows.Add("L", "0");
_otherRegs.Rows.Add("T", "0");
@@ -266,11 +253,55 @@ namespace Contralto
}
}
+
+ ///
+ /// Fill in memory view on demand.
+ ///
+ ///
+ ///
+ private void OnMemoryCellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
+ {
+ // TODO: handle extended memory
+ if (e.RowIndex > 65535)
+ {
+ // Top of memory, nothing to do
+ return;
+ }
+
+ switch(_memoryData.Columns[e.ColumnIndex].Name)
+ {
+ case "Bkpt":
+ e.Value = GetNovaBreakpoint((UInt16)e.RowIndex);
+ break;
+
+ case "Address":
+ e.Value = OctalHelpers.ToOctal(e.RowIndex, 6);
+ break;
+
+ case "Data":
+ e.Value = OctalHelpers.ToOctal(_system.MemoryBus.DebugReadWord((ushort)e.RowIndex), 6);
+
+ break;
+
+ case "Disassembly":
+ e.Value = CPU.Nova.NovaDisassembler.DisassembleInstruction(
+ (ushort)e.RowIndex,
+ _system.MemoryBus.DebugReadWord((ushort)e.RowIndex));
+ break;
+ }
+
+ }
+
private void ModifyMicrocodeBreakpoint(UInt16 address, bool set)
{
_microcodeBreakpointEnabled[address] = set;
}
+ private bool GetNovaBreakpoint(UInt16 address)
+ {
+ return _novaBreakpointEnabled[address];
+ }
+
private void ModifyNovaBreakpoint(UInt16 address, bool set)
{
_novaBreakpointEnabled[address] = set;
diff --git a/Contralto/Debugger.resx b/Contralto/Debugger.resx
index f85eb74..be4a8f3 100644
--- a/Contralto/Debugger.resx
+++ b/Contralto/Debugger.resx
@@ -153,7 +153,7 @@
True
-
+
True
diff --git a/Contralto/Disassembly/boot block disassembly.txt b/Contralto/Disassembly/boot block disassembly.txt
index 7890cd4..3ca0b00 100644
--- a/Contralto/Disassembly/boot block disassembly.txt
+++ b/Contralto/Disassembly/boot block disassembly.txt
@@ -196,12 +196,12 @@
213:035000 - LDA 3,AC2+0 ; AC3 gets current DCB address
214:025412 - LDA 1,AC3+12 ; AC1 gets label data (previous disk address)
215:022732 - LDA@ 0,.+-46 ;(147) ; Load AC0 with contents KBLK (check controller status)
-216:101014 - MOV# 0,0,SZR ; if zero (error or idle) then go to 199
+216:101014 - MOV# 0,0,SZR ; if zero (idle) then go to 220
217:000406 - JMP .+6 ;(225) ; not idle, go to 225
-220:021401 - LDA 0,AC3+1
-221:101014 - MOV# 0,0,SZR
-222:000406 - JMP .+6 ;(230)
-223:056724 - STA@ 3,.+-54 ;(147)
+220:021401 - LDA 0,AC3+1 ; Load AC3 with next DCB address
+221:101014 - MOV# 0,0,SZR ; is this zero?
+222:000406 - JMP .+6 ;(230) ; no -- goto 230
+223:056724 - STA@ 3,.+-54 ;(147) ; yes - write DCB to KBLK (tell disk controller to execute DCB)
224:000767 - JMP .+-11 ;(213)
225:125014 - MOV# 1,1,SZR ; we get here when the disk controller is not idle; see if prev. addr is zero
@@ -238,7 +238,7 @@
257:161000 - MOV 3,0
260:024765 - LDA 1,.+-13 ;(245)
261:034411 - LDA 3,.+11 ;(272)
-262:061005 - BLT
+262:061005 - BLT`
263:020757 - LDA 0,.+-21 ;(242)
264:024457 - LDA 1,.+57 ;(343)
265:034663 - LDA 3,.+-115 ;(150)
diff --git a/Contralto/IO/DiskController.cs b/Contralto/IO/DiskController.cs
index 3f8f436..64fd44d 100644
--- a/Contralto/IO/DiskController.cs
+++ b/Contralto/IO/DiskController.cs
@@ -28,15 +28,20 @@ namespace Contralto.IO
fs.Close();
}
+ ///
+ /// TODO: this is messy; the read and write sides of KDATA are distinct hardware.
+ /// According to docs, on a Write, eventually it appears on the Read side during an actual write to the disk
+ /// but not right away. For now, this never happens (since we don't yet support writing).
+ ///
public ushort KDATA
{
get
{
- return _kData;
+ return _kDataRead;
}
set
{
- _kData = value;
+ _kDataWrite = value;
}
}
@@ -49,29 +54,28 @@ namespace Contralto.IO
_recNo = 0;
// "In addition, it causes the head address bit to be loaded from KDATA[13]."
- _head = (_kData & 0x4) >> 2;
+ _head = (_kDataWrite & 0x4) >> 2;
// "0 normally, 1 if the command is to terminate immediately after the correct cylinder
// position is reached (before any data is transferred)."
_dataXfer = (_kAdr & 0x2) != 0x2;
- Log.Write(LogComponent.DiskController, "KADR set to {0} (Seal {1}, Header {2}, Label {3}, Data {4}, Xfer {5}, Drive {6})",
+ Log.Write(LogComponent.DiskController, "KADR set to {0} (Header {1}, Label {2}, Data {3}, Xfer {4}, Drive {5})",
OctalHelpers.ToOctal(_kAdr),
- OctalHelpers.ToOctal((_kAdr & 0xff00) >> 8),
OctalHelpers.ToOctal((_kAdr & 0xc0) >> 6),
OctalHelpers.ToOctal((_kAdr & 0x30) >> 4),
OctalHelpers.ToOctal((_kAdr & 0xc) >> 2),
_dataXfer,
_kAdr & 0x1);
- Log.Write(LogComponent.DiskController, " Disk Address is C/H/S {0}/{1}/{2}, Drive {3} Restore {4}",
- (_kData & 0x0ff8) >> 3,
- (_kData & 0x4) >> 2,
- (_kData & 0xf000) >> 12,
- ((_kData & 0x2) >> 1),
- (_kData & 0x1));
+ Log.Write(LogComponent.DiskController, " -Disk Address is C/H/S {0}/{1}/{2}, Drive {3} Restore {4}",
+ (_kDataWrite & 0x0ff8) >> 3,
+ _head,
+ (_kDataWrite & 0xf000) >> 12,
+ (_kDataWrite & 0x2) >> 1,
+ (_kDataWrite & 0x1));
- Log.Write(LogComponent.DiskController, " Selected disk is {0}", ((_kData & 0x2) >> 1) ^ (_kAdr & 0x1));
+ Log.Write(LogComponent.DiskController, " -Selected disk is {0}", ((_kDataWrite & 0x2) >> 1) ^ (_kAdr & 0x1));
}
}
@@ -187,7 +191,8 @@ namespace Contralto.IO
_sector = 0;
_head = 0;
_kStat = 0;
- _kData = 0;
+ _kDataRead = 0;
+ _kDataWrite = 0;
_sendAdr = false;
_wdInhib = true;
@@ -229,7 +234,7 @@ namespace Contralto.IO
_sectorWordIndex = 0;
_sectorWordTime = 0.0;
- _kData = 13;
+ _kDataRead = 0;
// Load new sector in
LoadSector();
@@ -326,7 +331,7 @@ namespace Contralto.IO
Log.Write(LogComponent.DiskController, "STROBE: Seek initialized.");
- _destCylinder = (_kData & 0x0ff8) >> 3;
+ _destCylinder = (_kDataWrite & 0x0ff8) >> 3;
// set "seek fail" bit based on selected cylinder (if out of bounds) and do not
// commence a seek if so.
@@ -428,8 +433,8 @@ namespace Contralto.IO
{
if (!_xferOff)
{
- Log.Write(LogComponent.DiskWordTask, "Word {0} read into KDATA", OctalHelpers.ToOctal(diskWord));
- _kData = diskWord;
+ Log.Write(LogType.Verbose, LogComponent.DiskWordTask, "Sector {0} Word {1} read into KDATA", _sector, OctalHelpers.ToOctal(diskWord));
+ _kDataRead = diskWord;
}
if (!_wdInhib)
@@ -451,7 +456,7 @@ namespace Contralto.IO
if (bWakeup)
{
- Log.Write(LogComponent.DiskWordTask, "Sector task awoken.");
+ Log.Write(LogType.Verbose, LogComponent.DiskWordTask, "Word task awoken.");
_system.CPU.WakeupTask(CPU.TaskType.DiskWord);
}
@@ -477,7 +482,9 @@ namespace Contralto.IO
_sectorData[i] = new DataCell(sector.Header[j], CellType.Data);
}
- _sectorData[_headerOffset + 3].Data = CalculateChecksum(_sectorData, _headerOffset + 1, 2);
+ ushort checksum = CalculateChecksum(_sectorData, _headerOffset + 1, 2);
+ _sectorData[_headerOffset + 3].Data = checksum;
+ Log.Write(LogType.Verbose, LogComponent.DiskController, "Header checksum for C/H/S {0}/{1}/{2} is {3}", _cylinder, _head, _sector, OctalHelpers.ToOctal(checksum));
// Label (8 words data, 1 word cksum)
for (int i = _labelOffset + 1, j = 7; i < _labelOffset + 9; i++, j--)
@@ -486,7 +493,9 @@ namespace Contralto.IO
_sectorData[i] = new DataCell(sector.Label[j], CellType.Data);
}
- _sectorData[_labelOffset + 9].Data = CalculateChecksum(_sectorData, _labelOffset + 1, 8);
+ checksum = CalculateChecksum(_sectorData, _labelOffset + 1, 8);
+ _sectorData[_labelOffset + 9].Data = checksum;
+ Log.Write(LogType.Verbose, LogComponent.DiskController, "Label checksum for C/H/S {0}/{1}/{2} is {3}", _cylinder, _head, _sector, OctalHelpers.ToOctal(checksum));
// sector data (256 words data, 1 word cksum)
for (int i = _dataOffset + 1, j = 255; i < _dataOffset + 257; i++, j--)
@@ -495,7 +504,9 @@ namespace Contralto.IO
_sectorData[i] = new DataCell(sector.Data[j], CellType.Data);
}
- _sectorData[_dataOffset + 257].Data = CalculateChecksum(_sectorData, _dataOffset + 1, 256);
+ checksum = CalculateChecksum(_sectorData, _dataOffset + 1, 256);
+ _sectorData[_dataOffset + 257].Data = checksum;
+ Log.Write(LogType.Verbose, LogComponent.DiskController, "Data checksum for C/H/S {0}/{1}/{2} is {3}", _cylinder, _head, _sector, OctalHelpers.ToOctal(checksum));
}
@@ -542,7 +553,7 @@ namespace Contralto.IO
//
ushort checksum = 0x151;
- for(int i = offset; i < length;i++)
+ for(int i = offset; i < offset + length;i++)
{
// Sanity check that we're checksumming actual data
if (sectorData[i].Type != CellType.Data)
@@ -556,7 +567,8 @@ namespace Contralto.IO
return checksum;
}
- private ushort _kData;
+ private ushort _kDataRead;
+ private ushort _kDataWrite;
private ushort _kAdr;
private ushort _kCom;
private ushort _kStat;
diff --git a/Contralto/Memory/Memory.cs b/Contralto/Memory/Memory.cs
index 86c5d70..8c81d64 100644
--- a/Contralto/Memory/Memory.cs
+++ b/Contralto/Memory/Memory.cs
@@ -25,8 +25,7 @@ namespace Contralto.Memory
}
public void Load(int address, ushort data)
- {
- //Log.Write(LogComponent.DiskWordTask, "Word {0} written to {1}", OctalHelpers.ToOctal(data), OctalHelpers.ToOctal(address));
+ {
_mem[address] = data;
}