diff --git a/Contralto/AltoSystem.cs b/Contralto/AltoSystem.cs
index a87b36f..4d77140 100644
--- a/Contralto/AltoSystem.cs
+++ b/Contralto/AltoSystem.cs
@@ -25,7 +25,7 @@ namespace Contralto
_keyboard = new Keyboard();
_diskController = new DiskController(this);
_displayController = new DisplayController(this);
- _fakeDisplayController = new FakeDisplayController(this);
+ //_fakeDisplayController = new FakeDisplayController(this);
// Attach memory-mapped devices to the bus
_memBus.AddDevice(_mem);
@@ -36,7 +36,7 @@ namespace Contralto
_clockableDevices.Add(_memBus);
_clockableDevices.Add(_diskController);
_clockableDevices.Add(_displayController);
- _clockableDevices.Add(_fakeDisplayController);
+ //_clockableDevices.Add(_fakeDisplayController);
_clockableDevices.Add(_cpu);
Reset();
@@ -62,13 +62,14 @@ namespace Contralto
public void AttachDisplay(Debugger d)
{
_displayController.AttachDisplay(d);
- _fakeDisplayController.AttachDisplay(d);
+ // _fakeDisplayController.AttachDisplay(d);
}
public void SingleStep()
{
// Run every device that needs attention for a single clock cycle.
- for (int i = 0; i < _clockableDevices.Count; i++)
+ int count = _clockableDevices.Count;
+ for (int i = 0; i < count; i++)
{
_clockableDevices[i].Clock();
}
diff --git a/Contralto/CPU/CPU.cs b/Contralto/CPU/CPU.cs
index 51705bd..66cd539 100644
--- a/Contralto/CPU/CPU.cs
+++ b/Contralto/CPU/CPU.cs
@@ -31,27 +31,14 @@ namespace Contralto.CPU
_tasks[(int)TaskType.Emulator] = new EmulatorTask(this);
_tasks[(int)TaskType.DiskSector] = new DiskTask(this, true);
_tasks[(int)TaskType.DiskWord] = new DiskTask(this, false);
- //_tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this);
- //_tasks[(int)TaskType.DisplayHorizontal] = new DisplayHorizontalTask(this);
+ _tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this);
+ _tasks[(int)TaskType.DisplayHorizontal] = new DisplayHorizontalTask(this);
_tasks[(int)TaskType.DisplayVertical] = new DisplayVerticalTask(this);
_tasks[(int)TaskType.Cursor] = new CursorTask(this);
_tasks[(int)TaskType.MemoryRefresh] = new MemoryRefreshTask(this);
Reset();
- }
-
- public void Hack()
- {
- _tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this);
- //_tasks[(int)TaskType.DisplayHorizontal] = new DisplayHorizontalTask(this);
- //_tasks[(int)TaskType.DisplayVertical] = new DisplayVerticalTask(this);
- //_tasks[(int)TaskType.Cursor] = new CursorTask(this);
-
- _tasks[(int)TaskType.DisplayWord].Reset();
- //_tasks[(int)TaskType.DisplayHorizontal].Reset();
- //_tasks[(int)TaskType.DisplayVertical].Reset();
- //_tasks[(int)TaskType.Cursor].Reset();
- }
+ }
public Task[] Tasks
{
diff --git a/Contralto/CPU/Tasks/DisplayHorizontalTask.cs b/Contralto/CPU/Tasks/DisplayHorizontalTask.cs
index 0ff1e7e..231e19c 100644
--- a/Contralto/CPU/Tasks/DisplayHorizontalTask.cs
+++ b/Contralto/CPU/Tasks/DisplayHorizontalTask.cs
@@ -17,8 +17,16 @@ namespace Contralto.CPU
{
_taskType = TaskType.DisplayHorizontal;
_wakeup = false;
- }
-
+ }
+
+ protected override bool ExecuteInstruction(MicroInstruction instruction)
+ {
+ // We put ourselves back to sleep immediately once we've started running
+ _wakeup = false;
+
+ return base.ExecuteInstruction(instruction);
+ }
+
protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
{
DisplayHorizontalF2 dh2 = (DisplayHorizontalF2)instruction.F2;
diff --git a/Contralto/CPU/Tasks/DisplayWordTask.cs b/Contralto/CPU/Tasks/DisplayWordTask.cs
index 88bc108..6727f62 100644
--- a/Contralto/CPU/Tasks/DisplayWordTask.cs
+++ b/Contralto/CPU/Tasks/DisplayWordTask.cs
@@ -18,7 +18,15 @@ namespace Contralto.CPU
{
_taskType = TaskType.DisplayWord;
_wakeup = false;
- }
+ }
+
+ protected override bool ExecuteInstruction(MicroInstruction instruction)
+ {
+ // We put ourselves back to sleep immediately once we've started running
+ _wakeup = false;
+
+ return base.ExecuteInstruction(instruction);
+ }
protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
{
diff --git a/Contralto/Debugger.Designer.cs b/Contralto/Debugger.Designer.cs
index 58e4a88..b7076b7 100644
--- a/Contralto/Debugger.Designer.cs
+++ b/Contralto/Debugger.Designer.cs
@@ -110,7 +110,6 @@
this.NovaStep = new System.Windows.Forms.Button();
this.groupBox6 = new System.Windows.Forms.GroupBox();
this.DisplayBox = new System.Windows.Forms.PictureBox();
- this.button1 = new System.Windows.Forms.Button();
this.Microcode.SuspendLayout();
this.SourceTabs.SuspendLayout();
this.Rom0Page.SuspendLayout();
@@ -960,23 +959,11 @@
this.DisplayBox.TabStop = false;
this.DisplayBox.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.DisplayBox_PreviewKeyDown);
//
- // button1
- //
- this.button1.Location = new System.Drawing.Point(799, 873);
- this.button1.Name = "button1";
- this.button1.Size = new System.Drawing.Size(75, 23);
- this.button1.TabIndex = 1;
- this.button1.TabStop = false;
- this.button1.Text = "HACK";
- this.button1.UseVisualStyleBackColor = true;
- this.button1.Click += new System.EventHandler(this.button1_Click);
- //
// Debugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1376, 997);
- this.Controls.Add(this.button1);
this.Controls.Add(this.groupBox6);
this.Controls.Add(this.NovaStep);
this.Controls.Add(this.RunToNextTaskButton);
@@ -1071,7 +1058,6 @@
private System.Windows.Forms.DataGridViewTextBoxColumn Disassembly;
private System.Windows.Forms.GroupBox groupBox6;
private System.Windows.Forms.PictureBox DisplayBox;
- private System.Windows.Forms.Button button1;
private System.Windows.Forms.TabControl SourceTabs;
private System.Windows.Forms.TabPage Rom0Page;
private System.Windows.Forms.TabPage Rom1Page;
diff --git a/Contralto/Debugger.cs b/Contralto/Debugger.cs
index b168f85..5ca4306 100644
--- a/Contralto/Debugger.cs
+++ b/Contralto/Debugger.cs
@@ -89,6 +89,8 @@ namespace Contralto
_displayBuffer.UnlockBits(data);
DisplayBox.Refresh();
+
+ Array.Clear(_displayData, 0, _displayData.Length);
}
///
@@ -833,7 +835,7 @@ namespace Contralto
break;
}
-
+
if (_execAbort || // The Stop button was hit
_microcodeBreakpointEnabled[_system.CPU.CurrentTask.MPC] || // A microcode breakpoint was hit
(execType == ExecutionType.NextTask &&
@@ -855,7 +857,7 @@ namespace Contralto
_execAbort = false;
break;
- }
+ }
}
}
@@ -1031,12 +1033,6 @@ namespace Contralto
private Rectangle _displayRect = new Rectangle(0, 0, 608, 808);
// Keyboard mapping from windows vkeys to Alto keys
- private Dictionary _keyMap;
-
- private void button1_Click(object sender, EventArgs e)
- {
- _system.CPU.Hack();
- }
-
+ private Dictionary _keyMap;
}
}
diff --git a/Contralto/Display/DisplayController.cs b/Contralto/Display/DisplayController.cs
index c7340cb..450dd83 100644
--- a/Contralto/Display/DisplayController.cs
+++ b/Contralto/Display/DisplayController.cs
@@ -35,8 +35,16 @@ namespace Contralto.Display
_state = DisplayState.VerticalBlank;
_scanline = 0;
_word = 0;
- _dwtBlocked = false;
+ _dwtBlocked = true;
_dhtBlocked = false;
+
+ _whiteOnBlack = false;
+ _lowRes = false;
+
+ // Wakeup DVT
+ _system.CPU.WakeupTask(TaskType.DisplayVertical);
+ _system.CPU.BlockTask(TaskType.DisplayHorizontal);
+ _system.CPU.BlockTask(TaskType.DisplayWord);
}
public void Clock()
@@ -63,13 +71,16 @@ namespace Contralto.Display
//
// Check the BLOCK status of the DWT and DHT tasks for the last executed uInstruction.
//
- _dhtBlocked = _system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DisplayHorizontal &&
- _system.CPU.CurrentTask.BLOCK;
+
+ if (_system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DisplayHorizontal &&
+ _system.CPU.CurrentTask.BLOCK)
+ {
+ _dhtBlocked = true;
+ }
if (_system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DisplayWord &&
_system.CPU.CurrentTask.BLOCK)
- {
- //Console.WriteLine("DWT BLOCK");
+ {
_dwtBlocked = true;
//
@@ -88,23 +99,12 @@ namespace Contralto.Display
// "If the DWT has not executed a BLOCK, if DHT is not blocked, and if the
// buffer is not full, DWT wakeups are generated."
//
- if (_dataBuffer.Count < 16 &&
- !_system.CPU.IsBlocked(TaskType.DisplayHorizontal) &&
+ if (_dataBuffer.Count < 16 &&
+ !_dhtBlocked &&
!_dwtBlocked)
- {
- //Console.WriteLine("DWT wakeup, {0}", _dataBuffer.Count);
+ {
_system.CPU.WakeupTask(TaskType.DisplayWord);
- }
- else
- {
- // We can't take any words right now, remove Wakeup from
- // the DWT.
- if (_dataBuffer.Count >= 16)
- {
- //Log.Write(LogComponent.Display, "buffer full, blocking DWT.");
- }
- _system.CPU.BlockTask(TaskType.DisplayWord);
- }
+ }
switch (_state)
{
@@ -112,7 +112,7 @@ namespace Contralto.Display
// Just killing time
if (_clocks > _verticalBlankClocks)
{
- // End of VBlank
+ // End of VBlank, start new visible frame
_clocks -= _verticalBlankClocks;
_scanline = _evenField ? 0 : 1;
_word = 0;
@@ -121,12 +121,9 @@ namespace Contralto.Display
// Wake up DVT, DHT
_dwtBlocked = false;
_dhtBlocked = false;
- _system.CPU.WakeupTask(TaskType.DisplayHorizontal);
- _system.CPU.BlockTask(TaskType.DisplayWord);
+ _system.CPU.WakeupTask(TaskType.DisplayHorizontal);
- _state = DisplayState.HorizontalBlank;
-
- //Console.WriteLine("Frame");
+ _state = DisplayState.HorizontalBlank;
}
break;
@@ -139,14 +136,14 @@ namespace Contralto.Display
{
_clocks -= _wordClocks;
- ushort displayWord = 0xaaaa;
+ ushort displayWord = (ushort)(_whiteOnBlack ? 0 : 0xffff);
if (_dataBuffer.Count > 0)
{
// Dequeue a word and draw it to the screen
- displayWord = _dataBuffer.Dequeue();
+ displayWord = _whiteOnBlack ? _dataBuffer.Dequeue() : (ushort)~_dataBuffer.Dequeue();
}
- //_display.DrawDisplayWord(_scanline, _word, displayWord);
+ _display.DrawDisplayWord(_scanline, _word, displayWord);
_word++;
if (_word > 37)
@@ -154,7 +151,7 @@ namespace Contralto.Display
// Done with this line
_dwtBlocked = false;
_dataBuffer.Clear();
- _state = DisplayState.HorizontalBlank;
+ _state = DisplayState.HorizontalBlank;
}
}
break;
@@ -170,7 +167,7 @@ namespace Contralto.Display
_word = 0;
if (_scanline > 807)
- {
+ {
// Done with field, move to vblank, tell display to render
_state = DisplayState.VerticalBlank;
_evenField = !_evenField;
@@ -178,13 +175,13 @@ namespace Contralto.Display
// Wakeup DVT
_system.CPU.WakeupTask(TaskType.DisplayVertical);
- // Block DHT
+ // Block DHT, DWT
_system.CPU.BlockTask(TaskType.DisplayHorizontal);
_system.CPU.BlockTask(TaskType.DisplayWord);
- //_display.RefreshAltoDisplay();
+ _display.RefreshAltoDisplay();
- _frames++;
+ _fields++;
//Log.Write(LogComponent.Display, "Display field completed. {0} total clocks elapsed.", _totalClocks);
_totalClocks = 0;
}
@@ -204,16 +201,22 @@ namespace Contralto.Display
{
_dataBuffer.Enqueue(word);
- //Console.WriteLine("Enqueue {0}", _dataBuffer.Count);
+ //Console.WriteLine("Enqueue {0}, scanline {1}", word, _scanline);
// Sanity check: data length should never exceed 16 words.
if (_dataBuffer.Count > 16)
- {
- _dataBuffer.Dequeue();
- _system.CPU.BlockTask(TaskType.DisplayWord);
+ {
+ //_dataBuffer.Dequeue();
+ //_system.CPU.BlockTask(TaskType.DisplayWord);
}
}
+ public void SETMODE(ushort word)
+ {
+ _lowRes = (word & 0x8000) != 0;
+ _whiteOnBlack = (word & 0x4000) != 0;
+ }
+
public bool EVENFIELD
{
get { return _evenField; }
@@ -228,15 +231,17 @@ namespace Contralto.Display
}
private bool _evenField;
+ private bool _lowRes;
+ private bool _whiteOnBlack;
private double _clocks;
private double _totalClocks;
- private int _frames;
+ private int _fields;
private DisplayState _state;
// Indicates whether the DWT or DHT blocked itself
// in which case they cannot be reawakened until the next field.
private bool _dwtBlocked;
- private bool _dhtBlocked;
+ private bool _dhtBlocked;
private int _scanline;
private int _word;
diff --git a/Contralto/Display/FakeDisplayController.cs b/Contralto/Display/FakeDisplayController.cs
index bebc790..4dcbb23 100644
--- a/Contralto/Display/FakeDisplayController.cs
+++ b/Contralto/Display/FakeDisplayController.cs
@@ -98,7 +98,7 @@ namespace Contralto.Display
_display.DrawDisplayWord(scanline, wordOffset, (ushort)(dcb.whiteOnBlack ? 0x0 : 0xffff));
}
- //_display.RefreshAltoDisplay();
+ _display.RefreshAltoDisplay();
// decrement scan line counter for this DCB, if < 0, grab next DCB.
dcb.scanlineCount--;
diff --git a/Contralto/Logging/Log.cs b/Contralto/Logging/Log.cs
index cc5af43..0a4066c 100644
--- a/Contralto/Logging/Log.cs
+++ b/Contralto/Logging/Log.cs
@@ -48,7 +48,7 @@ namespace Contralto.Logging
static Log()
{
// TODO: make configurable
- _components = LogComponent.All;
+ _components = LogComponent.None;
_type = LogType.Normal | LogType.Warning | LogType.Error;
}
diff --git a/Contralto/Memory/Memory.cs b/Contralto/Memory/Memory.cs
index ae6a595..6706f49 100644
--- a/Contralto/Memory/Memory.cs
+++ b/Contralto/Memory/Memory.cs
@@ -15,6 +15,14 @@ namespace Contralto.Memory
Reset();
}
+ ///
+ /// The top address of main memory (above which lies the I/O space)
+ ///
+ public static ushort MemTop
+ {
+ get { return _memTop; }
+ }
+
public void Reset()
{
// 4 64K banks
@@ -33,13 +41,6 @@ namespace Contralto.Memory
{
address += 0x10000 * GetBankNumber(task, extendedMemory);
ushort data = _mem[address];
-
- /*
- if (extendedMemory)
- {
- Log.Write(LogComponent.Memory, "extended memory read from {0} - {1}", Conversion.ToOctal(address), Conversion.ToOctal(data));
- } */
-
return data;
}
}
@@ -58,18 +59,7 @@ namespace Contralto.Memory
else
{
address += 0x10000 * GetBankNumber(task, extendedMemory);
- _mem[address] = data;
-
- if (address == 0x110 && data != 0)
- {
- Console.WriteLine("DASTART WRITE!");
- }
-
- /*
- if (extendedMemory)
- {
- Log.Write(LogComponent.Memory, "extended memory write to {0} of {1}", Conversion.ToOctal(address), Conversion.ToOctal(data));
- } */
+ _mem[address] = data;
}
}
@@ -85,12 +75,12 @@ namespace Contralto.Memory
private readonly MemoryRange[] _addresses =
{
- new MemoryRange(0, _memTop), // Main bank of RAM to 176777; IO page above this.
- new MemoryRange(_xmBanksStart, _xmBanksStart + 16), // Memory bank registers
+ new MemoryRange(0, _memTop), // Main bank of RAM to 176777; IO page above this.
+ new MemoryRange(_xmBanksStart, (ushort)(_xmBanksStart + 16)), // Memory bank registers
};
- private const int _memTop = 0xfdff; // 176777
- private const int _xmBanksStart = 0xffe0; // 177740
+ private static readonly ushort _memTop = 0xfdff; // 176777
+ private static readonly ushort _xmBanksStart = 0xffe0; // 177740
private ushort[] _mem;
diff --git a/Contralto/Memory/MemoryBus.cs b/Contralto/Memory/MemoryBus.cs
index 653b801..dfa833e 100644
--- a/Contralto/Memory/MemoryBus.cs
+++ b/Contralto/Memory/MemoryBus.cs
@@ -42,6 +42,11 @@ namespace Contralto.Memory
else
{
_bus.Add(addr, dev);
+
+ if (dev is Memory)
+ {
+ _mainMemory = (Memory)dev;
+ }
}
}
}
@@ -269,17 +274,27 @@ namespace Contralto.Memory
///
private ushort ReadFromBus(ushort address, TaskType task, bool extendedMemoryReference)
{
- // Look up address in hash; if populated ask the device
- // to return a value otherwise throw.
- if (_bus.ContainsKey(address))
+ if (address <= Memory.MemTop)
{
- return _bus[address].Read(address, task, extendedMemoryReference);
+ // Main memory access; shortcut hashtable lookup for performance reasons.
+ return _mainMemory.Read(address, task, extendedMemoryReference);
}
else
{
- //throw new NotImplementedException(String.Format("Read from unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address)));
- //Console.WriteLine("Read from unimplemented memory-mapped I/O device at {0}.", Conversion.ToOctal(address));
- return 0;
+ // Memory-mapped device access:
+ // Look up address in hash; if populated ask the device
+ // to return a value otherwise throw.
+ IMemoryMappedDevice memoryMappedDevice = null;
+ if (_bus.TryGetValue(address, out memoryMappedDevice))
+ {
+ return memoryMappedDevice.Read(address, task, extendedMemoryReference);
+ }
+ else
+ {
+ //throw new NotImplementedException(String.Format("Read from unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address)));
+ //Console.WriteLine("Read from unimplemented memory-mapped I/O device at {0}.", Conversion.ToOctal(address));
+ return 0;
+ }
}
}
@@ -291,16 +306,26 @@ namespace Contralto.Memory
///
private void WriteToBus(ushort address, ushort data, TaskType task, bool extendedMemoryReference)
{
- // Look up address in hash; if populated ask the device
- // to store a value otherwise throw.
- if (_bus.ContainsKey(address))
- {
- _bus[address].Load(address, data, task, extendedMemoryReference);
+ if (address <= Memory.MemTop)
+ {
+ // Main memory access; shortcut hashtable lookup for performance reasons.
+ _mainMemory.Load(address, data, task, extendedMemoryReference);
}
else
{
- // throw new NotImplementedException(String.Format("Write to unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address)));
- //Console.WriteLine("Write to unimplemented memory-mapped I/O device at {0}.", Conversion.ToOctal(address));
+ // Memory-mapped device access:
+ // Look up address in hash; if populated ask the device
+ // to store a value otherwise throw.
+ IMemoryMappedDevice memoryMappedDevice = null;
+ if (_bus.TryGetValue(address, out memoryMappedDevice))
+ {
+ memoryMappedDevice.Load(address, data, task, extendedMemoryReference);
+ }
+ else
+ {
+ // throw new NotImplementedException(String.Format("Write to unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address)));
+ //Console.WriteLine("Write to unimplemented memory-mapped I/O device at {0}.", Conversion.ToOctal(address));
+ }
}
}
@@ -308,7 +333,13 @@ namespace Contralto.Memory
/// Hashtable used for address-based dispatch to devices on the memory bus.
///
private Dictionary _bus;
-
+
+ //
+ // Optimzation: keep reference to main memory; since 99.9999% of accesses go directly there,
+ // we can avoid the hashtable overhead using a simple address check.
+ //
+ private Memory _mainMemory;
+
private bool _memoryOperationActive;
private int _memoryCycle;
private ushort _memoryAddress;