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

Minor performance improvements. General cleanup. Fixed major (but subtle) issue with memory state machine (BravoX now works!). Updated readme and installer for 1.1 release.

This commit is contained in:
Josh Dersch 2016-10-17 14:32:22 -07:00
parent 39277a17a2
commit ae0896b362
14 changed files with 240 additions and 143 deletions

View File

@ -220,14 +220,14 @@ namespace Contralto.CPU
F1 == SpecialFunction1.Constant ||
F2 == SpecialFunction2.Constant;
BS4 = ((int)BS > 4);
BS4 = ((int)BS >= 4);
// Constant ROM access:
// "The constant memory is gated to the bus by F1=7, F2=7, or BS>4. The constant memory is addressed by the
// (8 bit) concatenation of RSELECT and BS. The intent in enabling constants with BS>4 is to provide a masking
// facility, particularly for the <-MOUSE and <-DISP bus sources. This works because the processor bus ANDs if
// more than one source is gated to it. Up to 32 such mask contans can be provided for each of the four bus sources
// > 4."
// >= 4."
// NOTE also:
// "Note that the [emulator task F2] functions which replace the low bits of RSELECT with IR affect only the
// selection of R; they do not affect the address supplied to the constant ROM."

View File

@ -51,6 +51,10 @@ namespace Contralto.CPU.Nova
_altoIOTable.Add(0x6214, "BITBLT");
_altoIOTable.Add(0x6215, "XMLDA");
_altoIOTable.Add(0x6216, "XMSTA");
_altoIOTable.Add(0x6200, "DIR");
_altoIOTable.Add(0x6201, "EIR");
_altoIOTable.Add(0x6202, "BRI");
_altoIOTable.Add(0x620b, "DIRS");
}
/// <summary>

View File

@ -51,9 +51,9 @@ namespace Contralto.CPU
}
}
protected override ushort GetBusSource(int bs)
protected override ushort GetBusSource(MicroInstruction instruction)
{
DiskBusSource dbs = (DiskBusSource)bs;
DiskBusSource dbs = (DiskBusSource)instruction.BS;
switch (dbs)
{
@ -64,7 +64,7 @@ namespace Contralto.CPU
return _diskController.KDATA;
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", instruction.BS));
}
}

View File

@ -51,16 +51,16 @@ namespace Contralto.CPU
throw new InvalidOperationException("The emulator task is always in wakeup state.");
}
protected override ushort GetBusSource(int bs)
protected override ushort GetBusSource(MicroInstruction instruction)
{
EmulatorBusSource ebs = (EmulatorBusSource)bs;
EmulatorBusSource ebs = (EmulatorBusSource)instruction.BS;
switch (ebs)
{
case EmulatorBusSource.ReadSLocation:
if (_srSelect != 0)
if (instruction.RSELECT != 0)
{
return _cpu._s[_rb][_srSelect];
return _cpu._s[_rb][instruction.RSELECT];
}
else
{
@ -77,7 +77,7 @@ namespace Contralto.CPU
return 0xffff; // Technically this is an "undefined value," we're defining it as -1.
default:
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", instruction.BS));
}
}
@ -220,7 +220,7 @@ namespace Contralto.CPU
// "IR<- also merges bus bits 0, 5, 6 and 7 into NEXT[6-9] which does a first level
// instruction dispatch."
_nextModifier = (ushort)(((_busData & 0x8000) >> 12) | ((_busData & 0x0700) >> 8));
_nextModifier |= (ushort)(((_busData & 0x8000) >> 12) | ((_busData & 0x0700) >> 8));
// "IR<- clears SKIP"
_skip = 0;
@ -247,11 +247,11 @@ namespace Contralto.CPU
//
if ((_cpu._ir & 0x8000) != 0)
{
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
_nextModifier |= (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
}
else
{
_nextModifier = ControlROM.ACSourceROM[((_cpu._ir & 0x7f00) >> 8) + 0x80];
_nextModifier |= ControlROM.ACSourceROM[((_cpu._ir & 0x7f00) >> 8) + 0x80];
}
break;
@ -279,12 +279,12 @@ namespace Contralto.CPU
if ((_cpu._ir & 0x8000) != 0)
{
// 3-IR[8-9] (shift field of arithmetic instruction)
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
_nextModifier |= (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
}
else
{
// Use the PROM.
_nextModifier = ControlROM.ACSourceROM[((_cpu._ir & 0x7f00) >> 8)];
_nextModifier |= ControlROM.ACSourceROM[((_cpu._ir & 0x7f00) >> 8)];
}
break;

View File

@ -50,9 +50,9 @@ namespace Contralto.CPU
return base.ExecuteInstruction(instruction);
}
protected override ushort GetBusSource(int bs)
protected override ushort GetBusSource(MicroInstruction instruction)
{
EthernetBusSource ebs = (EthernetBusSource)bs;
EthernetBusSource ebs = (EthernetBusSource)instruction.BS;
switch(ebs)
{

View File

@ -19,6 +19,7 @@ using System;
using Contralto.Memory;
using Contralto.Logging;
using System.IO;
namespace Contralto.CPU
{
@ -143,8 +144,7 @@ namespace Contralto.CPU
ushort nextModifier;
_loadR = false;
_loadS = false;
_rSelect = 0;
_srSelect = 0;
_rSelect = 0;
_busData = 0;
_softReset = false;
@ -158,16 +158,16 @@ namespace Contralto.CPU
{
if (!_cpu._system.MemoryBus.Ready(instruction.MemoryOperation))
{
// Suspend operation for this cycle.
// Suspend operation for this cycle.
return InstructionCompletion.MemoryWait;
}
}
// If we have a modified next field from the last instruction, make sure it gets applied to this one.
nextModifier = _nextModifier;
_nextModifier = 0;
_srSelect = _rSelect = instruction.RSELECT;
_rSelect = instruction.RSELECT;
// Give tasks the chance to modify parameters early on (like RSELECT)
ExecuteSpecialFunction2Early(instruction);
@ -193,11 +193,11 @@ namespace Contralto.CPU
case BusSource.TaskSpecific1:
case BusSource.TaskSpecific2:
_busData = GetBusSource((int)instruction.BS); // task specific -- call into specific implementation
_busData = GetBusSource(instruction); // task specific -- call into specific implementation
break;
case BusSource.ReadMD:
_busData = _cpu._system.MemoryBus.ReadMD();
_busData = _cpu._system.MemoryBus.ReadMD();
break;
case BusSource.ReadMouse:
@ -218,7 +218,7 @@ namespace Contralto.CPU
if ((_cpu._ir & 0x300) != 0)
{
// sign extend if necessary
if ((_cpu._ir & 0x80) == 0x80)
if ((_cpu._ir & 0x80) != 0)
{
_busData |= (0xff00);
}
@ -311,7 +311,7 @@ namespace Contralto.CPU
_cpu._system.MemoryBus.LoadMAR(
aluData,
_taskType,
_systemType == SystemType.AltoI ? false : instruction.F2 == SpecialFunction2.StoreMD);
_systemType == SystemType.AltoI ? false : instruction.F2 == SpecialFunction2.StoreMD);
break;
case SpecialFunction1.Task:
@ -366,7 +366,7 @@ namespace Contralto.CPU
case SpecialFunction2.BusEq0:
if (_busData == 0)
{
_nextModifier = 1;
_nextModifier |= 1;
}
break;
@ -380,14 +380,14 @@ namespace Contralto.CPU
case SpecialFunction2.Bus:
// Select bits 6-15 (bits 0-9 in modern parlance) of the bus
_nextModifier = (ushort)(_busData & 0x3ff);
_nextModifier |= (ushort)(_busData & 0x3ff);
break;
case SpecialFunction2.ALUCY:
// ALUC0 is the carry produced by the ALU during the most recent microinstruction
// that loaded L. It is *not* the carry produced during the execution of the microinstruction
// that contains the ALUCY function.
_nextModifier = _cpu._aluC0;
_nextModifier |= _cpu._aluC0;
break;
case SpecialFunction2.StoreMD:
@ -446,7 +446,7 @@ namespace Contralto.CPU
//
if ((short)Shifter.Output < 0)
{
_nextModifier = 1;
_nextModifier |= 1;
}
break;
@ -454,7 +454,7 @@ namespace Contralto.CPU
// See note above.
if (Shifter.Output == 0)
{
_nextModifier = 1;
_nextModifier |= 1;
}
break;
}
@ -472,7 +472,7 @@ namespace Contralto.CPU
// Do writeback to selected S register from M
if (_loadS)
{
_cpu._s[_rb][_srSelect] = _cpu._m;
_cpu._s[_rb][instruction.RSELECT] = _cpu._m;
}
// Load T
@ -546,7 +546,7 @@ namespace Contralto.CPU
/// </summary>
/// <param name="bs"></param>
/// <returns></returns>
protected virtual ushort GetBusSource(int bs)
protected virtual ushort GetBusSource(MicroInstruction instruction)
{
// Nothing by default.
return 0;
@ -631,8 +631,7 @@ namespace Contralto.CPU
// 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 uint _rSelect; // RSELECT field from current instruction, potentially modified by task
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.

View File

@ -16,6 +16,7 @@
*/
using Contralto.CPU;
using Contralto.Logging;
using System;
using System.Collections.Generic;
@ -23,7 +24,7 @@ namespace Contralto.Memory
{
public enum MemoryOperation
{
None,
None,
LoadAddress,
Read,
Store
@ -76,9 +77,10 @@ namespace Contralto.Memory
{
_memoryCycle = 0;
_memoryAddress = 0;
_memoryData = 0;
_doubleWordStore = false;
_doubleWordMixed = false;
_memoryDataLow = 0;
_memoryDataHigh = 0;
_firstWordStored = false;
_firstWordRead = false;
_memoryOperationActive = false;
_extendedMemoryReference = false;
}
@ -88,9 +90,19 @@ namespace Contralto.Memory
get { return _memoryAddress; }
}
public ushort MD
public ushort MDLow
{
get { return _memoryData; }
get { return _memoryDataLow; }
}
public ushort MDHigh
{
get { return _memoryDataHigh; }
}
public ushort MDWrite
{
get { return _memoryDataWrite; }
}
public int Cycle
@ -134,27 +146,26 @@ namespace Contralto.Memory
{
ClockAltoII();
}
}
}
}
private void ClockAltoI()
{
switch (_memoryCycle)
{
case 4:
// Buffered read of single word
_memoryData = ReadFromBus(_memoryAddress, _task, _extendedMemoryReference);
_memoryDataLow = ReadFromBus(_memoryAddress, _task, _extendedMemoryReference);
break;
case 5:
// Buffered read of double-word
_memoryData2 = ReadFromBus((ushort)(_memoryAddress | 1), _task, _extendedMemoryReference);
_memoryDataHigh = ReadFromBus((ushort)(_memoryAddress | 1), _task, _extendedMemoryReference);
break;
case 7:
// End of memory operation
_memoryOperationActive = false;
_doubleWordStore = false;
_memoryOperationActive = false;
break;
}
}
@ -165,18 +176,17 @@ namespace Contralto.Memory
{
case 3:
// Buffered read of single word
_memoryData = ReadFromBus(_memoryAddress, _task, _extendedMemoryReference);
_memoryDataLow = ReadFromBus(_memoryAddress, _task, _extendedMemoryReference);
break;
case 4:
// Buffered read of double-word
_memoryData2 = ReadFromBus((ushort)(_memoryAddress ^ 1), _task, _extendedMemoryReference);
_memoryDataHigh = ReadFromBus((ushort)(_memoryAddress ^ 1), _task, _extendedMemoryReference);
break;
case 5:
case 6:
// End of memory operation
_memoryOperationActive = false;
_doubleWordStore = false;
_memoryOperationActive = false;
break;
}
}
@ -198,7 +208,7 @@ namespace Contralto.Memory
case MemoryOperation.Store:
if (_systemType == SystemType.AltoI)
{
// // Store operations take place on cycles 5 and 6
// Store operations take place on cycles 5 and 6
return _memoryCycle > 4;
}
else
@ -220,6 +230,13 @@ namespace Contralto.Memory
public void LoadMAR(ushort address, TaskType task, bool extendedMemoryReference)
{
//
// This seems like as good a place as any to point out an oddity --
// The Hardware Reference (Section 2, page 7) notes:
// "MAR<- cannot be invoked in the same instruction as <-MD of a previous access."
// This rule is broken by the Butte microcode used by BravoX. It appears to expect that
// the MAR load takes place after MD has been read, which makes sense.
//
if (_memoryOperationActive)
{
// This should not happen; CPU implementation should check whether the operation is possible
@ -229,13 +246,14 @@ namespace Contralto.Memory
else
{
_memoryOperationActive = true;
_doubleWordStore = false;
_doubleWordMixed = false;
_firstWordStored = false;
_firstWordRead = false;
_memoryAddress = address;
_extendedMemoryReference = extendedMemoryReference;
_task = task;
_memoryCycle = 1;
}
_memoryCycle = 1;
}
}
public ushort ReadMD()
@ -264,15 +282,15 @@ namespace Contralto.Memory
case 3:
case 4:
// This should not happen; CPU should check whether the operation is possible using Ready and stall if not.
throw new InvalidOperationException("Invalid ReadMR request during cycle 3 or 4 of memory operation.");
throw new InvalidOperationException("Invalid ReadMD request during cycle 3 or 4 of memory operation.");
case 5:
// Single word read
return _memoryData;
return _memoryDataLow;
case 6:
// Double word read, return other half of double word.
return _memoryData2;
return _memoryDataHigh;
default:
// Invalid state.
@ -299,11 +317,16 @@ namespace Contralto.Memory
case 3:
case 4:
// This should not happen; CPU should check whether the operation is possible using Ready and stall if not.
throw new InvalidOperationException("Invalid ReadMR request during cycle 3 or 4 of memory operation.");
throw new InvalidOperationException("Invalid ReadMD request during cycle 3 or 4 of memory operation.");
case 5:
// Single word read
return _memoryData;
// Single word read.
// If this is memory cycle 5 of a double-word *store* (started in cycle 3) then the second word can be *read* here.
// (An example of this is provided in the hardware ref, section 2, pg 8. and is done by the Ethernet microcode on
// the Alto II, see the code block starting at address 0224 -- EPLOC (600) is loaded with the interface status,
// EBLOC (601) is read and OR'd with NWW in the same memory op.)
_firstWordRead = true;
return _firstWordStored ? _memoryDataHigh : _memoryDataLow;
// ***
// NB: Handler for double-word read (cycle 6) is in the "else" clause below; this is kind of a hack.
@ -315,21 +338,15 @@ namespace Contralto.Memory
}
}
else
{
// memory state machine not running, just return last latched contents.
{
//
// Memory state machine not running, just return last latched contents.
// ("Because the Alto II latches memory contents, it is possible to execute _MD anytime after
// cycle 5 of a reference and obtain the results of the read operation")
// If this is memory cycle 6 we will return the last half of the doubleword to complete a double-word read.
if (_memoryCycle == 6 || (_memoryCycle == 5 && _doubleWordMixed))
{
_doubleWordMixed = false;
return _memoryData2;
}
else
{
_doubleWordMixed = false;
return _memoryData;
}
// We will return the last half of the doubleword to complete a double-word read.
// (If the first half hasn't yet been read, we return the first half instead...)
//
return _firstWordRead ? _memoryDataHigh : _memoryDataLow;
}
}
@ -346,6 +363,17 @@ namespace Contralto.Memory
LoadMDAltoII(data);
}
}
else
{
//
// This is illegal behavior but we won't throw here;
// ST80 will cause this, for example, if you run it in a 1K CRAM configuration.
// Because it expects 3K CRAM, it jumps into the middle of ROM1 and weird things happen.
// We don't want to kill the emulator when this happens, but we will log the result.
//
Log.Write(LogType.Warning, LogComponent.Memory,
"Unexpected microcode behavior -- LoadMD while memory inactive (cycle {0}).", _memoryCycle);
}
}
private void LoadMDAltoI(ushort data)
@ -356,25 +384,24 @@ namespace Contralto.Memory
case 2:
case 3:
case 4:
// TODO: good microcode should never do this
// Good microcode should never do this
throw new InvalidOperationException("Unexpected microcode behavior -- LoadMD during incorrect memory cycle.");
case 5:
_memoryData = data; // Only really necessary to show in debugger
// Start of doubleword write:
_memoryDataWrite = data;
// Start of doubleword write:
WriteToBus(_memoryAddress, data, _task, _extendedMemoryReference);
_doubleWordStore = true;
_doubleWordMixed = true;
_firstWordStored = true;
break;
case 6:
if (!_doubleWordStore)
if (!_firstWordStored)
{
throw new InvalidOperationException("Unexpected microcode behavior -- LoadMD on cycle 6, no LoadMD on cycle 5.");
}
_memoryData = data; // Only really necessary to show in debugger
_memoryDataWrite = data;
ushort actualAddress = (ushort)(_memoryAddress | 1);
WriteToBus(actualAddress, data, _task, _extendedMemoryReference);
@ -388,26 +415,36 @@ namespace Contralto.Memory
switch (_memoryCycle)
{
case 1:
case 2:
case 5:
// TODO: good microcode should never do this
throw new InvalidOperationException("Unexpected microcode behavior -- LoadMD during incorrect memory cycle.");
case 2:
// Good microcode should never do this
throw new InvalidOperationException(
String.Format("Unexpected microcode behavior -- LoadMD during incorrect memory cycle {0}.", _memoryCycle));
case 3:
_memoryData = data; // Only really necessary to show in debugger
// Start of doubleword write:
_memoryDataWrite = data;
// Start of doubleword write:
WriteToBus(_memoryAddress, data, _task, _extendedMemoryReference);
_doubleWordStore = true;
_doubleWordMixed = true;
_firstWordStored = true;
break;
case 4:
_memoryData = data; // Only really necessary to show in debugger
ushort actualAddress = _doubleWordStore ? (ushort)(_memoryAddress ^ 1) : _memoryAddress;
_memoryDataWrite = data;
ushort actualAddress = _firstWordStored ? (ushort)(_memoryAddress ^ 1) : _memoryAddress;
WriteToBus(actualAddress, data, _task, _extendedMemoryReference);
break;
case 5:
//
// This case is not documented in the HW ref. The ALU portion of MADTEST executes an instruction
// including an <-MD Bus Source (ANDed with Constant value) and an MD<- F2, which makes
// very little sense. Since the read can't be accomplished until cycle 5, the instruction
// is blocked until then. MADTEST doesn't seem to care what the result is, and I can't find
// any other code that uses microcode in this way.
// For now, this is a no-op.
//
Log.Write(LogType.Warning, LogComponent.Memory,
"Unexpected microcode behavior -- LoadMD during cycle 5.");
break;
}
}
@ -490,13 +527,16 @@ namespace Contralto.Memory
private TaskType _task;
// Buffered read data (on cycles 3 and 4)
private ushort _memoryData;
private ushort _memoryData2;
private ushort _memoryDataLow;
private ushort _memoryDataHigh;
// Indicates a double-word store (started on cycle 3)
private bool _doubleWordStore;
// Write data (used for debugger UI only)
private ushort _memoryDataWrite;
// Indicates a mixed double-word store/load (started in cycle 3)
private bool _doubleWordMixed;
// Indicates that the first word of a double-word store has taken place (started on cycle 3)
private bool _firstWordStored;
// Indicates tghat the first word of a double-word read has taken place (started on cycle 5)
private bool _firstWordRead;
}
}

View File

@ -96,7 +96,7 @@ namespace Contralto
private static void PrintHerald()
{
Console.WriteLine("ContrAlto v1.0 (c) 2015, 2016 Living Computer Museum.");
Console.WriteLine("ContrAlto v1.1 (c) 2015, 2016 Living Computer Museum.");
Console.WriteLine("Bug reports to joshd@livingcomputermuseum.org");
Console.WriteLine();
}

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.1.*")]
[assembly: AssemblyFileVersion("1.1.0.0")]

View File

@ -29,39 +29,40 @@
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox));
this.label1 = new System.Windows.Forms.Label();
this.VersionLabel = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.OkButton = new System.Windows.Forms.Button();
this.label4 = new System.Windows.Forms.Label();
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
this.emailLink = new System.Windows.Forms.LinkLabel();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.websiteLink = new System.Windows.Forms.LinkLabel();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// label1
// VersionLabel
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(88, 18);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(74, 13);
this.label1.TabIndex = 0;
this.label1.Text = "ContrAlto v1.0";
this.VersionLabel.Location = new System.Drawing.Point(12, 17);
this.VersionLabel.Name = "VersionLabel";
this.VersionLabel.Size = new System.Drawing.Size(224, 14);
this.VersionLabel.TabIndex = 0;
this.VersionLabel.Text = "ContrAlto v";
this.VersionLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(41, 63);
this.label2.Location = new System.Drawing.Point(41, 59);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(168, 13);
this.label2.Size = new System.Drawing.Size(46, 13);
this.label2.TabIndex = 1;
this.label2.Text = "(c) 2016 Living Computer Museum";
this.label2.Text = "(c) 2016";
this.label2.Click += new System.EventHandler(this.label2_Click);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(69, 41);
this.label3.Location = new System.Drawing.Point(69, 38);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(109, 13);
this.label3.TabIndex = 2;
@ -85,16 +86,16 @@
this.label4.TabIndex = 4;
this.label4.Text = "Bug reports, comments and miscellanea to";
//
// linkLabel1
// emailLink
//
this.linkLabel1.AutoSize = true;
this.linkLabel1.Location = new System.Drawing.Point(41, 338);
this.linkLabel1.Name = "linkLabel1";
this.linkLabel1.Size = new System.Drawing.Size(168, 13);
this.linkLabel1.TabIndex = 5;
this.linkLabel1.TabStop = true;
this.linkLabel1.Text = "joshd@livingcomputermuseum.org";
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
this.emailLink.AutoSize = true;
this.emailLink.Location = new System.Drawing.Point(41, 338);
this.emailLink.Name = "emailLink";
this.emailLink.Size = new System.Drawing.Size(168, 13);
this.emailLink.TabIndex = 5;
this.emailLink.TabStop = true;
this.emailLink.Text = "joshd@livingcomputermuseum.org";
this.emailLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
//
// pictureBox1
//
@ -106,19 +107,31 @@
this.pictureBox1.TabIndex = 6;
this.pictureBox1.TabStop = false;
//
// websiteLink
//
this.websiteLink.AutoSize = true;
this.websiteLink.Location = new System.Drawing.Point(84, 60);
this.websiteLink.Name = "websiteLink";
this.websiteLink.Size = new System.Drawing.Size(126, 13);
this.websiteLink.TabIndex = 7;
this.websiteLink.TabStop = true;
this.websiteLink.Text = "Living Computer Museum";
this.websiteLink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.OnSiteLinkClicked);
//
// AboutBox
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(248, 393);
this.ControlBox = false;
this.Controls.Add(this.websiteLink);
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.linkLabel1);
this.Controls.Add(this.emailLink);
this.Controls.Add(this.label4);
this.Controls.Add(this.OkButton);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.VersionLabel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
@ -137,12 +150,13 @@
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label VersionLabel;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button OkButton;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.LinkLabel linkLabel1;
private System.Windows.Forms.LinkLabel emailLink;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.LinkLabel websiteLink;
}
}

View File

@ -16,6 +16,7 @@
*/
using System;
using System.Reflection;
using System.Windows.Forms;
namespace Contralto
@ -25,6 +26,8 @@ namespace Contralto
public AboutBox()
{
InitializeComponent();
VersionLabel.Text += typeof(Program).Assembly.GetName().Version;
}
private void OkButton_Click(object sender, EventArgs e)
@ -41,5 +44,10 @@ namespace Contralto
{
System.Diagnostics.Process.Start("mailto:joshd@livingcomputermuseum.org");
}
private void OnSiteLinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("http://www.livingcomputermuseum.org");
}
}
}

View File

@ -125,12 +125,12 @@ namespace Contralto
_otherRegs.Rows[1].Cells[1].Value = Conversion.ToOctal(_system.CPU.T, 6);
_otherRegs.Rows[2].Cells[1].Value = Conversion.ToOctal(_system.CPU.M, 6);
_otherRegs.Rows[3].Cells[1].Value = Conversion.ToOctal(_system.CPU.IR, 6);
_otherRegs.Rows[4].Cells[1].Value = Conversion.ToOctal(_system.CPU.ALUC0, 1);
//_otherRegs.Rows[4].Cells[1].Value = OctalHelpers.ToOctal(_system.CPU.Carry, 1);
//_otherRegs.Rows[4].Cells[1].Value = OctalHelpers.ToOctal(_system.CPU.Skip, 1);
_otherRegs.Rows[4].Cells[1].Value = Conversion.ToOctal(_system.CPU.ALUC0, 1);
_otherRegs.Rows[5].Cells[1].Value = Conversion.ToOctal(_system.MemoryBus.MAR, 6);
_otherRegs.Rows[6].Cells[1].Value = Conversion.ToOctal(_system.MemoryBus.MD, 6);
_otherRegs.Rows[7].Cells[1].Value = Conversion.ToOctal(_system.MemoryBus.Cycle & 0x3f, 2);
_otherRegs.Rows[6].Cells[1].Value = Conversion.ToOctal(_system.MemoryBus.MDLow, 6);
_otherRegs.Rows[7].Cells[1].Value = Conversion.ToOctal(_system.MemoryBus.MDHigh, 6);
_otherRegs.Rows[8].Cells[1].Value = Conversion.ToOctal(_system.MemoryBus.MDWrite, 6);
_otherRegs.Rows[9].Cells[1].Value = Conversion.ToOctal(_system.MemoryBus.Cycle & 0x3f, 2);
// Reserved memory locations
for (int i = 0; i < _reservedMemoryEntries.Length; i++)
@ -247,11 +247,11 @@ namespace Contralto
_otherRegs.Rows.Add("T", "0");
_otherRegs.Rows.Add("M", "0");
_otherRegs.Rows.Add("IR", "0");
_otherRegs.Rows.Add("ALUC0", "0");
//_otherRegs.Rows.Add("CARRY", "0");
//_otherRegs.Rows.Add("SKIP", "0");
_otherRegs.Rows.Add("ALUC0", "0");
_otherRegs.Rows.Add("MAR", "0");
_otherRegs.Rows.Add("MD", "0");
_otherRegs.Rows.Add("←MDL", "0");
_otherRegs.Rows.Add("←MDH", "0");
_otherRegs.Rows.Add("MD←", "0");
_otherRegs.Rows.Add("MCycle", "0");
for (int i = 0; i < _reservedMemoryEntries.Length; i++)

View File

@ -31,7 +31,7 @@ keyset input device.
================
ContrAlto will run on any Windows PC running Windows Vista or later, with version
4.6 or later of the .NET Framework installed. .NET should be present by default
4.5.3 or later of the .NET Framework installed. .NET should be present by default
on Windows Vista and later; if it is not installed on your computer it can be
obtained at https://www.microsoft.com/net.
@ -475,3 +475,21 @@ Contributions are welcome!
ContrAlto would not have been possible without the amazing preservation work of
the Computer History Museum.
10.0 Change History
===================
V1.1
----
- A few minor performance tweaks, adding to a 5% speed increase.
- Switched back to targeting .NET 4.5.3 rather than 4.6; this works better under Mono
and avoids odd issues on Windows machines running pre-4.6 frameworks.
- Microcode disassembly improved slightly, annotated microcode source updated.
- Nova disassembler now handles BRI, DIR, EIR, DIRS instructions rather than treating
them all as TRAPs.
- Fixed serious bugs in memory state machine, BravoX now runs.
- Fixed minor bug in Constant ROM selection.
V1.0
----
Initial release.

View File

@ -17,10 +17,24 @@
-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="CE5F3D08-3BD6-4BDF-9C64-0C2B852B899C" Name="ContrAlto" Language="1033" Version="1.0.0.0" Manufacturer="Living Computer Museum" UpgradeCode="38d6b09f-6e7b-4854-844a-5d4ab707a357">
<Package Id="*" InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<Product Id="CE5F3D08-3BD6-4BDF-9C64-0C2B852B899C" Name="ContrAlto" Language="1033" Version="1.1.0" Manufacturer="Living Computer Museum" UpgradeCode="38d6b09f-6e7b-4854-844a-5d4ab707a357">
<Package Id="*" InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Upgrade Id="38d6b09f-6e7b-4854-844a-5d4ab707a357">
<UpgradeVersion OnlyDetect="yes" Property="SELFFOUND"
Minimum="1.1.0" IncludeMinimum="yes"
Maximum="1.1.0" IncludeMaximum="yes" />
<UpgradeVersion OnlyDetect="yes" Property="NEWERFOUND"
Minimum="1.1.0" IncludeMinimum="no" />
</Upgrade>
<CustomAction Id="AlreadyUpdated" Error="[ProductName] 1.0 has already been updated to 1.1.0 or newer." />
<CustomAction Id="NoDowngrade" Error="A later version of [ProductName] is already installed." />
<InstallExecuteSequence>
<Custom Action="AlreadyUpdated" After="FindRelatedProducts">SELFFOUND</Custom>
<Custom Action="NoDowngrade" After="FindRelatedProducts">NEWERFOUND</Custom>
</InstallExecuteSequence>
<Media Id="1" Cabinet="ContrAlto.cab" EmbedCab="yes"/>