diff --git a/Contralto/CPU/MicroInstruction.cs b/Contralto/CPU/MicroInstruction.cs index bc3b178..bf42f62 100644 --- a/Contralto/CPU/MicroInstruction.cs +++ b/Contralto/CPU/MicroInstruction.cs @@ -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." diff --git a/Contralto/CPU/NovaDisassembler.cs b/Contralto/CPU/NovaDisassembler.cs index 5eb093a..efe07c7 100644 --- a/Contralto/CPU/NovaDisassembler.cs +++ b/Contralto/CPU/NovaDisassembler.cs @@ -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"); } /// diff --git a/Contralto/CPU/Tasks/DiskTask.cs b/Contralto/CPU/Tasks/DiskTask.cs index b35263b..9f585e2 100644 --- a/Contralto/CPU/Tasks/DiskTask.cs +++ b/Contralto/CPU/Tasks/DiskTask.cs @@ -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)); } } diff --git a/Contralto/CPU/Tasks/EmulatorTask.cs b/Contralto/CPU/Tasks/EmulatorTask.cs index 30ecb2a..9871498 100644 --- a/Contralto/CPU/Tasks/EmulatorTask.cs +++ b/Contralto/CPU/Tasks/EmulatorTask.cs @@ -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; diff --git a/Contralto/CPU/Tasks/EthernetTask.cs b/Contralto/CPU/Tasks/EthernetTask.cs index deb96eb..7100e69 100644 --- a/Contralto/CPU/Tasks/EthernetTask.cs +++ b/Contralto/CPU/Tasks/EthernetTask.cs @@ -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) { diff --git a/Contralto/CPU/Tasks/Task.cs b/Contralto/CPU/Tasks/Task.cs index 1be4517..6de4d3a 100644 --- a/Contralto/CPU/Tasks/Task.cs +++ b/Contralto/CPU/Tasks/Task.cs @@ -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 /// /// /// - 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. diff --git a/Contralto/Memory/MemoryBus.cs b/Contralto/Memory/MemoryBus.cs index 3b21e23..43ed2e0 100644 --- a/Contralto/Memory/MemoryBus.cs +++ b/Contralto/Memory/MemoryBus.cs @@ -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; } } diff --git a/Contralto/Program.cs b/Contralto/Program.cs index 784902f..fa34ce6 100644 --- a/Contralto/Program.cs +++ b/Contralto/Program.cs @@ -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(); } diff --git a/Contralto/Properties/AssemblyInfo.cs b/Contralto/Properties/AssemblyInfo.cs index 0066d30..17b5f9d 100644 --- a/Contralto/Properties/AssemblyInfo.cs +++ b/Contralto/Properties/AssemblyInfo.cs @@ -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")] diff --git a/Contralto/UI/AboutBox.Designer.cs b/Contralto/UI/AboutBox.Designer.cs index 1b298d5..f57e88d 100644 --- a/Contralto/UI/AboutBox.Designer.cs +++ b/Contralto/UI/AboutBox.Designer.cs @@ -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; } } \ No newline at end of file diff --git a/Contralto/UI/AboutBox.cs b/Contralto/UI/AboutBox.cs index 1af79f1..e1587d9 100644 --- a/Contralto/UI/AboutBox.cs +++ b/Contralto/UI/AboutBox.cs @@ -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"); + } } } diff --git a/Contralto/UI/Debugger.cs b/Contralto/UI/Debugger.cs index 9f16aae..0d53c3b 100644 --- a/Contralto/UI/Debugger.cs +++ b/Contralto/UI/Debugger.cs @@ -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++) diff --git a/Contralto/readme.txt b/Contralto/readme.txt index 56625fb..4f19b0a 100644 --- a/Contralto/readme.txt +++ b/Contralto/readme.txt @@ -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. diff --git a/ContraltoSetup/Product.wxs b/ContraltoSetup/Product.wxs index 0511177..55ca61b 100644 --- a/ContraltoSetup/Product.wxs +++ b/ContraltoSetup/Product.wxs @@ -17,10 +17,24 @@ --> - - + + - + + + + + + + + + + SELFFOUND + NEWERFOUND +