diff --git a/Contralto/CPU/CPU.cs b/Contralto/CPU/CPU.cs
index 528b3b4..13fdeb7 100644
--- a/Contralto/CPU/CPU.cs
+++ b/Contralto/CPU/CPU.cs
@@ -1,5 +1,7 @@
using System.Timers;
+using Contralto.Logging;
+
namespace Contralto.CPU
{
public enum TaskType
@@ -145,22 +147,30 @@ namespace Contralto.CPU
///
public void SoftReset()
{
- // Reset tasks.
+ // Soft-Reset tasks.
for (int i = 0; i < _tasks.Length; i++)
{
if (_tasks[i] != null)
{
- _tasks[i].Reset();
+ _tasks[i].SoftReset();
}
}
UCodeMemory.LoadBanksFromRMR(_rmr);
+ _rmr = 0xffff; // Reset RMR (all tasks start in ROM0)
+
+ // Start in Emulator
+ _currentTask = _tasks[0];
- // Execute the initial task switch.
- TaskSwitch();
-
- _currentTask = _nextTask;
- _nextTask = null;
+ //
+ // TODO:
+ // This is a hack of sorts, it ensures that the sector task initializes
+ // itself as soon as the Emulator task yields after the reset. (CopyDisk is broken otherwise due to the
+ // sector task stomping over the KBLK CopyDisk sets up after the reset. This is a race of sorts.)
+ // Unsure if there is a deeper issue here or if there are other reset semantics
+ // in play here.
+ //
+ WakeupTask(CPU.TaskType.DiskSector);
Logging.Log.Write(Logging.LogComponent.CPU, "Silent Boot; microcode banks initialized to {0}", Conversion.ToOctal(_rmr));
}
@@ -173,7 +183,8 @@ namespace Contralto.CPU
public void WakeupTask(TaskType task)
{
if (_tasks[(int)task] != null)
- {
+ {
+ Log.Write(LogComponent.TaskSwitch, "Wakeup enabled for Task {0}", task);
_tasks[(int)task].WakeupTask();
}
}
@@ -186,7 +197,8 @@ namespace Contralto.CPU
public void BlockTask(TaskType task)
{
if (_tasks[(int)task] != null)
- {
+ {
+ Log.Write(LogComponent.TaskSwitch, "Removed wakeup for Task {0}", task);
_tasks[(int)task].BlockTask();
}
}
@@ -218,8 +230,15 @@ namespace Contralto.CPU
for (int i = _tasks.Length - 1; i >= 0; i--)
{
if (_tasks[i] != null && _tasks[i].Wakeup)
- {
+ {
_nextTask = _tasks[i];
+
+ if (_nextTask != _currentTask && _currentTask != null)
+ {
+ Log.Write(LogComponent.TaskSwitch, "TASK: Next task will be {0} (pri {1}); current task {2} (pri {3})",
+ (TaskType)_nextTask.Priority, _nextTask.Priority,
+ (TaskType)_currentTask.Priority, _currentTask.Priority);
+ }
break;
}
}
diff --git a/Contralto/CPU/Tasks/DiskTask.cs b/Contralto/CPU/Tasks/DiskTask.cs
index 4188b70..9b1eb8b 100644
--- a/Contralto/CPU/Tasks/DiskTask.cs
+++ b/Contralto/CPU/Tasks/DiskTask.cs
@@ -1,4 +1,5 @@
using Contralto.IO;
+using Contralto.Logging;
using System;
namespace Contralto.CPU
@@ -22,6 +23,8 @@ namespace Contralto.CPU
protected override bool ExecuteInstruction(MicroInstruction instruction)
{
+ // Log.Write(LogComponent.Debug, "{0}: {1}", Conversion.ToOctal(_mpc), UCodeDisassembler.DisassembleInstruction(instruction, _taskType));
+
bool task = base.ExecuteInstruction(instruction);
// Deal with SECLATE semantics: If the Disk Sector task wakes up and runs before
@@ -32,13 +35,7 @@ namespace Contralto.CPU
{
// Sector task is running; clear enable for seclate signal
_diskController.DisableSeclate();
- }
-
- /*
- if (_taskType == TaskType.DiskWord)
- {
- _wakeup = false;
- } */
+ }
return task;
}
@@ -170,32 +167,32 @@ namespace Contralto.CPU
// "NEXT <- NEXT OR (IF fatal error in latches THEN 0 ELSE 1)"
_nextModifier |= GetInitModifier(instruction);
- if (true) //!_diskController.FatalError)
+ if (!_diskController.FatalError)
{
_nextModifier |= 0x1;
}
else
{
- Console.WriteLine("fatal disk error");
+ Console.WriteLine("fatal disk error on disk {0}", _diskController.Drive);
}
break;
case DiskF2.STROBON:
// "NEXT <- NEXT OR (IF seek strobe still on THEN 1 ELSE 0)"
_nextModifier |= GetInitModifier(instruction);
- if ((_diskController.KSTAT & 0x0040) == 0x0040)
+ if ((_diskController.KSTAT & DiskController.STROBE) != 0)
{
_nextModifier |= 0x1;
}
break;
case DiskF2.SWRNRDY:
- // "NEXT <- NEXT OR (IF disk not ready to accept command THEN 1 ELSE 0)
- // for now, always zero (not sure when this would be 1 yet)
+ // "NEXT <- NEXT OR (IF disk not ready to accept command THEN 1 ELSE 0)
_nextModifier |= GetInitModifier(instruction);
if (!_diskController.Ready)
{
- _nextModifier |= 1;
+ Console.WriteLine("disk {0} not ready", _diskController.Drive);
+ _nextModifier |= 0x1;
}
break;
diff --git a/Contralto/CPU/Tasks/EmulatorTask.cs b/Contralto/CPU/Tasks/EmulatorTask.cs
index 96fdb00..44c33e6 100644
--- a/Contralto/CPU/Tasks/EmulatorTask.cs
+++ b/Contralto/CPU/Tasks/EmulatorTask.cs
@@ -105,6 +105,11 @@ namespace Contralto.CPU
// BOOT (soft-reset) operation.
// Reset the CPU using the current RMR (start tasks in RAM or ROM as specified.)
_cpu.SoftReset();
+
+ // Since this is a soft reset, we don't want MPC to be taken from the NEXT
+ // field at the end of the cycle, setting this flag causes the main Task
+ // implementation to skip updating _mpc at the end of this instruction.
+ _softReset = true;
}
else if(_busData != 0)
{
@@ -139,11 +144,17 @@ namespace Contralto.CPU
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);
+ // For now, this is always 0; we do not yet support the 3K RAM system with 8 banks of S registers.
+ _rb = (ushort)((_busData & 0xe) >> 1);
+
+ if (_rb != 0)
+ {
+ _rb = 0;
+ Logging.Log.Write(Logging.LogType.Warning, Logging.LogComponent.EmulatorTask, "ESRB<- ({0}) not fully implemented.",
+ Conversion.ToOctal((_busData & 0xe) >> 1));
+
+ throw new NotImplementedException("ESRB<-");
+ }
break;
default:
diff --git a/Contralto/CPU/Tasks/Task.cs b/Contralto/CPU/Tasks/Task.cs
index 2f0f232..3fa1ada 100644
--- a/Contralto/CPU/Tasks/Task.cs
+++ b/Contralto/CPU/Tasks/Task.cs
@@ -56,6 +56,14 @@ namespace Contralto.CPU
_rb = 0;
}
+ public virtual void SoftReset()
+ {
+ //
+ // As above but we leave all other state alone.
+ //
+ _mpc = (ushort)_taskType;
+ }
+
public virtual void BlockTask()
{
_wakeup = false;
@@ -98,6 +106,7 @@ namespace Contralto.CPU
_rSelect = 0;
_srSelect = 0;
_busData = 0;
+ _softReset = false;
Shifter.SetMagic(false);
@@ -414,9 +423,8 @@ namespace Contralto.CPU
// this depends on the value of the NEXT field in this instruction
//
if (swMode)
- {
- //Console.WriteLine("SWMODE NEXT {0} Modifier {1}", Conversion.ToOctal(instruction.NEXT), Conversion.ToOctal(nextModifier));
- UCodeMemory.SwitchMode((ushort)(instruction.NEXT), _taskType);
+ {
+ UCodeMemory.SwitchMode(instruction.NEXT, _taskType);
Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1}", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier));
}
@@ -430,8 +438,12 @@ namespace Contralto.CPU
//
// Select next address, using the address modifier from the last instruction.
+ // (Unless a soft reset occurred during this instruction)
//
- _mpc = (ushort)(instruction.NEXT | nextModifier);
+ if (!_softReset)
+ {
+ _mpc = (ushort)(instruction.NEXT | nextModifier);
+ }
return nextTask;
}
@@ -486,15 +498,16 @@ namespace Contralto.CPU
//
// TODO: maybe instead of these being shared (which feels kinda bad)
// these could be encapsulated in an object and passed to subclass implementations?
- 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.
- protected bool _wrtRam; // Whether to write uCode RAM from M and ALU outputs during the next cycle.
- protected bool _swMode; // Whether to switch uCode banks during the next cycle.
+ 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.
+ protected bool _wrtRam; // Whether to write uCode RAM from M and ALU outputs during the next cycle.
+ protected bool _swMode; // Whether to switch uCode banks during the next cycle.
+ protected bool _softReset; // Whether this instruction caused a soft reset (so MPC should not come from instruction's NEXT field)
//
diff --git a/Contralto/CPU/UCodeMemory.cs b/Contralto/CPU/UCodeMemory.cs
index 61be085..c8ff2ac 100644
--- a/Contralto/CPU/UCodeMemory.cs
+++ b/Contralto/CPU/UCodeMemory.cs
@@ -72,7 +72,7 @@ namespace Contralto.CPU
public static void LoadBanksFromRMR(ushort rmr)
{
for(int i=0;i<16;i++)
- {
+ {
_microcodeBank[i] = (rmr & (1 << i)) == 0 ? MicrocodeBank.RAM0 : MicrocodeBank.ROM0;
}
}
diff --git a/Contralto/Contralto.csproj b/Contralto/Contralto.csproj
index 986efde..24dac31 100644
--- a/Contralto/Contralto.csproj
+++ b/Contralto/Contralto.csproj
@@ -160,7 +160,7 @@
PreserveNewest
- PreserveNewest
+ Always
PreserveNewest
diff --git a/Contralto/Debugger.Designer.cs b/Contralto/Debugger.Designer.cs
index d9f283f..b18af4a 100644
--- a/Contralto/Debugger.Designer.cs
+++ b/Contralto/Debugger.Designer.cs
@@ -97,6 +97,8 @@
this.Reg = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.RegValue = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.groupBox4 = new System.Windows.Forms.GroupBox();
+ this.MemoryJumpToAddress = new System.Windows.Forms.TextBox();
+ this.label3 = new System.Windows.Forms.Label();
this._memoryData = new System.Windows.Forms.DataGridView();
this.Bkpt = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.Address = new System.Windows.Forms.DataGridViewTextBoxColumn();
@@ -116,8 +118,7 @@
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.HackButton = new System.Windows.Forms.Button();
this.Microcode.SuspendLayout();
this.SourceTabs.SuspendLayout();
this.Rom0Page.SuspendLayout();
@@ -270,7 +271,7 @@
this.Rom1Page.Location = new System.Drawing.Point(4, 22);
this.Rom1Page.Name = "Rom1Page";
this.Rom1Page.Padding = new System.Windows.Forms.Padding(3);
- this.Rom1Page.Size = new System.Drawing.Size(582, 545);
+ this.Rom1Page.Size = new System.Drawing.Size(582, 554);
this.Rom1Page.TabIndex = 1;
this.Rom1Page.Text = "ROM1";
this.Rom1Page.UseVisualStyleBackColor = true;
@@ -369,7 +370,7 @@
this.Rom2Page.Location = new System.Drawing.Point(4, 22);
this.Rom2Page.Name = "Rom2Page";
this.Rom2Page.Padding = new System.Windows.Forms.Padding(3);
- this.Rom2Page.Size = new System.Drawing.Size(582, 545);
+ this.Rom2Page.Size = new System.Drawing.Size(582, 554);
this.Rom2Page.TabIndex = 2;
this.Rom2Page.Text = "RAM0";
this.Rom2Page.UseVisualStyleBackColor = true;
@@ -750,6 +751,24 @@
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Memory";
//
+ // 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);
+ //
+ // 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:";
+ //
// _memoryData
//
this._memoryData.AllowUserToAddRows = false;
@@ -1026,29 +1045,22 @@
this.dataGridViewTextBoxColumn11.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.dataGridViewTextBoxColumn11.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
//
- // label3
+ // HackButton
//
- 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);
+ this.HackButton.Location = new System.Drawing.Point(295, 955);
+ this.HackButton.Name = "HackButton";
+ this.HackButton.Size = new System.Drawing.Size(36, 23);
+ this.HackButton.TabIndex = 15;
+ this.HackButton.Text = "hack";
+ this.HackButton.UseVisualStyleBackColor = true;
+ this.HackButton.Click += new System.EventHandler(this.HackButton_Click);
//
// Debugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(949, 997);
+ this.Controls.Add(this.HackButton);
this.Controls.Add(this.groupBox6);
this.Controls.Add(this.NovaStep);
this.Controls.Add(this.RunToNextTaskButton);
@@ -1165,5 +1177,6 @@
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11;
private System.Windows.Forms.TextBox MemoryJumpToAddress;
private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Button HackButton;
}
}
\ No newline at end of file
diff --git a/Contralto/Debugger.cs b/Contralto/Debugger.cs
index 8b9e341..046d996 100644
--- a/Contralto/Debugger.cs
+++ b/Contralto/Debugger.cs
@@ -919,6 +919,10 @@ namespace Contralto
// Nova Debugger breakpoints; same as above
private bool[] _novaBreakpointEnabled;
-
+ private void HackButton_Click(object sender, EventArgs e)
+ {
+ Logging.Log.LogComponents |= Logging.LogComponent.TaskSwitch;
+ Logging.Log.Write(Logging.LogComponent.Debug, "***** HACK HIT ******");
+ }
}
}
diff --git a/Contralto/Disk/Clark-Games.dsk b/Contralto/Disk/Clark-Games.dsk
index f029879..9cd6130 100644
Binary files a/Contralto/Disk/Clark-Games.dsk and b/Contralto/Disk/Clark-Games.dsk differ
diff --git a/Contralto/Disk/bravox.dsk b/Contralto/Disk/bravox.dsk
index f4349ca..cdee65b 100644
Binary files a/Contralto/Disk/bravox.dsk and b/Contralto/Disk/bravox.dsk differ
diff --git a/Contralto/Disk/diag.dsk b/Contralto/Disk/diag.dsk
index 79ce944..9a5ba19 100644
Binary files a/Contralto/Disk/diag.dsk and b/Contralto/Disk/diag.dsk differ
diff --git a/Contralto/Disk/games.dsk b/Contralto/Disk/games.dsk
index c901c5e..a2b05df 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 e4d8068..e3f86b3 100644
Binary files a/Contralto/Disk/gamesb.dsk and b/Contralto/Disk/gamesb.dsk differ
diff --git a/Contralto/Disk/nonprog.dsk b/Contralto/Disk/nonprog.dsk
index ed40c82..7724991 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 eb44786..30c5abf 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 2f4e05d..385d482 100644
Binary files a/Contralto/Disk/tdisk4.dsk and b/Contralto/Disk/tdisk4.dsk differ
diff --git a/Contralto/Disk/xmsmall.dsk b/Contralto/Disk/xmsmall.dsk
index a56b9d6..b8a7c3b 100644
Binary files a/Contralto/Disk/xmsmall.dsk and b/Contralto/Disk/xmsmall.dsk differ
diff --git a/Contralto/IO/DiskController.cs b/Contralto/IO/DiskController.cs
index b221b2b..b5a5bcd 100644
--- a/Contralto/IO/DiskController.cs
+++ b/Contralto/IO/DiskController.cs
@@ -110,9 +110,7 @@ namespace Contralto.IO
// Select disk if _sendAdr is true
_disk = (_kAdr & 0x1);
_seeking = false;
-
- /*
-
+
// Clear the NOTREADY flag depending on whether the drive is loaded or not
if (_drives[_disk].IsLoaded)
{
@@ -121,7 +119,7 @@ namespace Contralto.IO
else
{
_kStat |= NOTREADY;
- } */
+ }
}
}
@@ -182,7 +180,7 @@ namespace Contralto.IO
public int Drive
{
- get { return 0; }
+ get { return _disk; }
}
public double ClocksUntilNextSector
@@ -198,7 +196,7 @@ namespace Contralto.IO
// This is true if the drive is:
// - powered on, loaded with a disk, spun up
// - not actively seeking
- return _drives[0].IsLoaded;
+ return _drives[_disk].IsLoaded && !_seeking;
}
}
@@ -253,7 +251,7 @@ namespace Contralto.IO
_drives[0].Reset();
_drives[1].Reset();
- // Create events to be reused during execution
+ // Create events to be reused during execution
// Schedule the first sector immediately.
_sectorEvent = new Event(0, null, SectorCallback);
@@ -278,7 +276,7 @@ namespace Contralto.IO
//
// Next sector; move to next sector and wake up Disk Sector task.
//
- _sector = (_sector + 1) % 12;
+ _sector = (_sector + 1) % 12;
_kStat = (ushort)((_kStat & 0x0fff) | (_sector << 12));
@@ -295,6 +293,8 @@ namespace Contralto.IO
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);
+ Log.Write(LogType.Verbose, LogComponent.DiskController, "KADR is {0}", Conversion.ToOctal(_kAdr));
+ Log.Write(LogType.Verbose, LogComponent.DiskController, "KDATA is {0}", Conversion.ToOctal(_kDataWrite));
_system.CPU.WakeupTask(CPU.TaskType.DiskSector);
// Reset SECLATE
@@ -403,7 +403,7 @@ namespace Contralto.IO
Log.Write(LogComponent.DiskController, "Seek failed, specified cylinder {0} is out of range.", destCylinder);
_seeking = false;
}
- else
+ else if (destCylinder != SelectedDrive.Cylinder)
{
// Otherwise, start a seek.
_destCylinder = destCylinder;
@@ -423,6 +423,12 @@ namespace Contralto.IO
Log.Write(LogComponent.DiskController, "Seek to {0} from {1} commencing. Will take {2} nsec.", _destCylinder, SelectedDrive.Cylinder, _seekDuration);
}
+ else
+ {
+ // Clear the fail bit.
+ _kStat &= (ushort)~SEEKFAIL;
+ Log.Write(LogComponent.DiskController, "Seek is a no op ({0} to {1}).", destCylinder, SelectedDrive.Cylinder);
+ }
}
///
@@ -685,7 +691,7 @@ namespace Contralto.IO
// SECLATE data.
// 8.5uS for seclate delay (approx. 50 clocks)
- private static ulong _seclateDuration = (ulong)(85.0 * Conversion.UsecToNsec * _scale);
+ private static ulong _seclateDuration = (ulong)(20.0 * Conversion.UsecToNsec * _scale);
private bool _seclateEnable;
private bool _seclate;
private Event _seclateEvent;
@@ -698,10 +704,10 @@ namespace Contralto.IO
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;
+ public static readonly ushort SECLATE = 0x10;
+ public static readonly ushort NOTREADY = 0x20;
+ public static readonly ushort STROBE = 0x40;
+ public static readonly ushort SEEKFAIL = 0x80;
}
}
diff --git a/Contralto/Logging/Log.cs b/Contralto/Logging/Log.cs
index 31c7263..4357653 100644
--- a/Contralto/Logging/Log.cs
+++ b/Contralto/Logging/Log.cs
@@ -1,4 +1,7 @@
-using System;
+#define LOGGING_ENABLED
+
+using System;
+using System.IO;
namespace Contralto.Logging
{
@@ -21,8 +24,10 @@ namespace Contralto.Logging
CPU = 0x200,
EthernetController = 0x400,
EthernetTask = 0x800,
+ TaskSwitch = 0x1000,
- All = 0x7fffffff
+ Debug = 0x40000000,
+ All = 0x7fffffff
}
///
@@ -47,10 +52,19 @@ namespace Contralto.Logging
static Log()
{
// TODO: make configurable
- _components = LogComponent.None; // LogComponent.EthernetController; // | LogComponent.Microcode | LogComponent.Memory | LogComponent.CPU;
- _type = LogType.Normal | LogType.Warning | LogType.Error;
+ _components = LogComponent.CPU; // LogComponent.DiskController | LogComponent.DiskSectorTask | LogComponent.Debug | LogComponent.CPU; // LogComponent.EthernetController; // | LogComponent.Microcode | LogComponent.Memory | LogComponent.CPU;
+ _type = LogType.Normal | LogType.Warning | LogType.Error | LogType.Verbose;
+
+ _logStream = new StreamWriter("log.txt");
}
+ public static LogComponent LogComponents
+ {
+ get { return _components; }
+ set { _components = value; }
+ }
+
+#if LOGGING_ENABLED
///
/// Logs a message without specifying type/severity for terseness;
/// will not log if Type has been set to None.
@@ -72,10 +86,28 @@ namespace Contralto.Logging
// My log has something to tell you...
// TODO: color based on type, etc.
Console.WriteLine(component.ToString() + ": " + message, args);
+
+ if (_logStream != null)
+ {
+ _logStream.WriteLine(component.ToString() + ": " + message, args);
+ }
}
}
+#else
+ public static void Write(LogComponent component, string message, params object[] args)
+ {
+
+ }
+
+ public static void Write(LogType type, LogComponent component, string message, params object[] args)
+ {
+
+ }
+
+#endif
private static LogComponent _components;
private static LogType _type;
+ private static StreamWriter _logStream;
}
}
diff --git a/Contralto/Memory/MemoryBus.cs b/Contralto/Memory/MemoryBus.cs
index db17e90..39e1c6f 100644
--- a/Contralto/Memory/MemoryBus.cs
+++ b/Contralto/Memory/MemoryBus.cs
@@ -168,7 +168,7 @@ namespace Contralto.Memory
_memoryAddress = address;
_extendedMemoryReference = extendedMemoryReference;
_task = task;
- _memoryCycle = 1;
+ _memoryCycle = 1;
}
}
@@ -190,6 +190,13 @@ namespace Contralto.Memory
case 5:
// Single word read
//Log.Write(LogType.Verbose, LogComponent.Memory, "Single-word read of {0} from {1} (cycle 5)", Conversion.ToOctal(_memoryData), Conversion.ToOctal(_memoryAddress ^ 1));
+
+ // debug
+ /*
+ if (_memoryAddress == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk
+ {
+ Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData);
+ } */
return _memoryData;
// ***
@@ -212,11 +219,23 @@ namespace Contralto.Memory
//Log.Write(LogType.Verbose, LogComponent.Memory, "Double-word read of {0} from {1} (cycle 6)", Conversion.ToOctal(_memoryData2), Conversion.ToOctal(_memoryAddress ^ 1));
_doubleWordMixed = false;
+ // debug
+ /*
+ if ((_memoryAddress ^ 1) == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk
+ {
+ Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData2);
+ } */
return _memoryData2;
}
else
{
_doubleWordMixed = false;
+ // debug
+ /*
+ if (_memoryAddress == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk
+ {
+ Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData);
+ } */
//Log.Write(LogType.Verbose, LogComponent.Memory, "Single-word read of {0} from {1} (post cycle 6)", Conversion.ToOctal(_memoryData), Conversion.ToOctal(_memoryAddress));
return _memoryData;
}
@@ -236,12 +255,21 @@ namespace Contralto.Memory
throw new InvalidOperationException("Unexpected microcode behavior -- LoadMD during incorrect memory cycle.");
case 3:
+
+ // debug
+ if (_memoryAddress == 0xfc90 || _memoryAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk
+ {
+ Logging.Log.Write(Logging.LogComponent.Debug, "++> Task {0} wrote {1} to {3} (was {2}).", _task, Conversion.ToOctal(data), Conversion.ToOctal(DebugReadWord(_task, _memoryAddress)), Conversion.ToOctal(_memoryAddress));
+ }
+
_memoryData = data; // Only really necessary to show in debugger
// Start of doubleword write:
WriteToBus(_memoryAddress, data, _task, _extendedMemoryReference);
_doubleWordStore = true;
_doubleWordMixed = true;
+
+
/*
Log.Write(
LogType.Verbose,
@@ -262,7 +290,22 @@ namespace Contralto.Memory
Conversion.ToOctal(data),
_doubleWordStore ? Conversion.ToOctal(_memoryAddress ^ 1) : Conversion.ToOctal(_memoryAddress));
*/
- WriteToBus(_doubleWordStore ? (ushort)(_memoryAddress ^ 1) : _memoryAddress, data, _task, _extendedMemoryReference);
+ // debug
+ ushort actualAddress = _doubleWordStore ? (ushort)(_memoryAddress ^ 1) : _memoryAddress;
+
+ /*
+ if (actualAddress == 0xfc90 || actualAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk
+ {
+ Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} wrote {1} to {4} (was {2}). Extd {3}", _task, Conversion.ToOctal(data), Conversion.ToOctal(DebugReadWord(_task, actualAddress)), _extendedMemoryReference, Conversion.ToOctal(actualAddress));
+ } */
+
+ WriteToBus(actualAddress, data, _task, _extendedMemoryReference);
+
+ /*
+ if (actualAddress == 0xfc90 || actualAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk
+ {
+ Logging.Log.Write(Logging.LogComponent.Debug, "--> Now {0}.", Conversion.ToOctal(DebugReadWord(_task, actualAddress)));
+ } */
break;
}