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:
parent
39277a17a2
commit
ae0896b362
@ -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."
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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")]
|
||||
|
||||
66
Contralto/UI/AboutBox.Designer.cs
generated
66
Contralto/UI/AboutBox.Designer.cs
generated
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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++)
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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"/>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user