diff --git a/Contralto/AltoSystem.cs b/Contralto/AltoSystem.cs index f210436..6fb8c9d 100644 --- a/Contralto/AltoSystem.cs +++ b/Contralto/AltoSystem.cs @@ -125,9 +125,9 @@ namespace Contralto DiabloPack newPack = new DiabloPack(type); using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) - { + { newPack.Load(fs, path, false); - fs.Close(); + fs.Close(); } _diskController.Drives[drive].LoadPack(newPack); diff --git a/Contralto/CPU/CPU.cs b/Contralto/CPU/CPU.cs index bee96de..16d5e09 100644 --- a/Contralto/CPU/CPU.cs +++ b/Contralto/CPU/CPU.cs @@ -135,6 +135,7 @@ namespace Contralto.CPU // If we have a new task, switch to it now. _currentTask = _nextTask; _nextTask = null; + _currentTask.OnTaskSwitch(); } break; @@ -164,7 +165,10 @@ namespace Contralto.CPU } Log.Write(LogComponent.CPU, "Silent Boot; microcode banks initialized to {0}", Conversion.ToOctal(_rmr)); - UCodeMemory.LoadBanksFromRMR(_rmr); + UCodeMemory.LoadBanksFromRMR(_rmr); + + // Reset RMR after reset. + _rmr = 0x0; // Start in Emulator _currentTask = _tasks[0]; @@ -175,7 +179,7 @@ namespace Contralto.CPU // itself as soon as the Emulator task yields after the reset. (CopyDisk is broken otherwise due to the // sector task stomping over the KBLK CopyDisk sets up after the reset. This is a race of sorts.) // Unsure if there is a deeper issue here or if there are other reset semantics - // in play here. + // in play that are not understood. // WakeupTask(CPU.TaskType.DiskSector); } diff --git a/Contralto/CPU/ConstantMemory.cs b/Contralto/CPU/ConstantMemory.cs index 1b0e836..706e451 100644 --- a/Contralto/CPU/ConstantMemory.cs +++ b/Contralto/CPU/ConstantMemory.cs @@ -3,42 +3,28 @@ using System.IO; namespace Contralto.CPU { + /// + /// Maintains a set of Control ROM images dumped from real Alto hardware. + /// static class ControlROM { static ControlROM() { - Init(); - - /* - LoadConstants(_constantRomsAltoI); - - ushort[] temp = new ushort[256]; - - _constantRom.CopyTo(temp, 0); - - LoadConstants(_constantRomsAltoII); - - for(int i=0;i<256;i++) - { - if (temp[i] != _constantRom[i]) - { - Console.WriteLine("Diff at {0:x} - {1:x} vs {2:x}", i, temp[i], _constantRom[i]); - } - } */ - + Init(); } private static void Init() { if (Configuration.SystemType == SystemType.AltoI) { - LoadConstants(_constantRomsAltoI); + LoadConstants(_constantRomsAltoI, true); + LoadACSource(_acSourceRoms, true); } else { - LoadConstants(_constantRomsAltoI); - } - LoadACSource(_acSourceRoms); + LoadConstants(_constantRomsAltoII, false); + LoadACSource(_acSourceRoms, true); + } } public static ushort[] ConstantROM @@ -51,7 +37,7 @@ namespace Contralto.CPU get { return _acSourceRom; } } - private static void LoadConstants(RomFile[] romInfo) + private static void LoadConstants(RomFile[] romInfo, bool flip) { _constantRom = new ushort[256]; @@ -60,7 +46,7 @@ namespace Contralto.CPU // // Each file contains 256 bytes, each byte containing one nybble in the low 4 bits. // - using (FileStream fs = new FileStream(Path.Combine("ROM", file.Filename), FileMode.Open, FileAccess.Read)) + using (FileStream fs = new FileStream(file.Filename, FileMode.Open, FileAccess.Read)) { int length = (int)fs.Length; if (length != 256) @@ -74,7 +60,14 @@ namespace Contralto.CPU // OR in the data for (int i = 0; i < length; i++) { - _constantRom[file.StartingAddress + i] |= (ushort)((DataMapConstantRom(data[AddressMapConstantRom(i)]) & 0xf) << file.BitPosition); + if (flip) + { + _constantRom[file.StartingAddress + i] |= (ushort)((DataMapConstantRom(~data[AddressMapConstantRom(i)]) & 0xf) << file.BitPosition); + } + else + { + _constantRom[file.StartingAddress + i] |= (ushort)((DataMapConstantRom(data[AddressMapConstantRom(i)]) & 0xf) << file.BitPosition); + } } } } @@ -86,11 +79,11 @@ namespace Contralto.CPU } } - private static void LoadACSource(RomFile romInfo) + private static void LoadACSource(RomFile romInfo, bool reverseBits) { _acSourceRom = new byte[256]; - using (FileStream fs = new FileStream(Path.Combine("ROM", romInfo.Filename), FileMode.Open, FileAccess.Read)) + using (FileStream fs = new FileStream(romInfo.Filename, FileMode.Open, FileAccess.Read)) { int length = (int)fs.Length; if (length != 256) @@ -103,7 +96,14 @@ namespace Contralto.CPU // Copy in the data, modifying the address as required. for (int i = 0; i < length; i++) { - _acSourceRom[i] = (byte)((~data[AddressMapACSourceRom(i)]) & 0xf); + if (reverseBits) + { + _acSourceRom[i] = (byte)((~DataMapConstantRom(data[AddressMapACSourceRom(i)])) & 0xf); + } + else + { + _acSourceRom[i] = (byte)((~data[AddressMapACSourceRom(i)]) & 0xf); + } } } } @@ -158,24 +158,24 @@ namespace Contralto.CPU // And invert data lines return (~mappedData) & 0xff; } - - private static RomFile[] _constantRomsAltoII = - { - new RomFile("c0", 0x000, 12), - new RomFile("c1", 0x000, 8), - new RomFile("c2", 0x000, 4), - new RomFile("c3", 0x000, 0), - }; - + private static RomFile[] _constantRomsAltoI = { - new RomFile("c0.2", 0x000, 12), - new RomFile("c1.2", 0x000, 8), - new RomFile("c2.2", 0x000, 4), - new RomFile("c3.2", 0x000, 0), + new RomFile(Configuration.GetAltoIRomPath("c0_23.BIN"), 0x000, 12), + new RomFile(Configuration.GetAltoIRomPath("c1_23.BIN"), 0x000, 8), + new RomFile(Configuration.GetAltoIRomPath("c2_23.BIN"), 0x000, 4), + new RomFile(Configuration.GetAltoIRomPath("c3_23.BIN"), 0x000, 0), }; - private static RomFile _acSourceRoms = new RomFile("2kctl.u3", 0x000, 0); + private static RomFile[] _constantRomsAltoII = + { + new RomFile(Configuration.GetAltoIIRomPath("c0"), 0x000, 12), + new RomFile(Configuration.GetAltoIIRomPath("c1"), 0x000, 8), + new RomFile(Configuration.GetAltoIIRomPath("c2"), 0x000, 4), + new RomFile(Configuration.GetAltoIIRomPath("c3"), 0x000, 0), + }; + + private static RomFile _acSourceRoms = new RomFile(Configuration.GetRomPath("ACSOURCE.NEW"), 0x000, 0); private static ushort[] _constantRom; private static byte[] _acSourceRom; diff --git a/Contralto/CPU/MicroInstruction.cs b/Contralto/CPU/MicroInstruction.cs index beccf3f..c94b76f 100644 --- a/Contralto/CPU/MicroInstruction.cs +++ b/Contralto/CPU/MicroInstruction.cs @@ -177,6 +177,11 @@ namespace Contralto.CPU EISFCT = 14, } + /// + /// MicroInstruction encapsulates the decoding of a microinstruction word. + /// It also caches precomputed metadata related to the microinstruction that + /// help speed microcode execution. + /// public class MicroInstruction { public MicroInstruction(UInt32 code) @@ -228,14 +233,14 @@ namespace Contralto.CPU // What kind of memory access this instruction performs, if any. if (MemoryAccess) { - if (BS == BusSource.ReadMD) - { - MemoryOperation = MemoryOperation.Read; - } - else if (F1 == SpecialFunction1.LoadMAR) + if (F1 == SpecialFunction1.LoadMAR) { MemoryOperation = MemoryOperation.LoadAddress; } + else if (BS == BusSource.ReadMD) + { + MemoryOperation = MemoryOperation.Read; + } else { MemoryOperation = MemoryOperation.Store; diff --git a/Contralto/CPU/Tasks/CursorTask.cs b/Contralto/CPU/Tasks/CursorTask.cs index 4d73647..9e0bc01 100644 --- a/Contralto/CPU/Tasks/CursorTask.cs +++ b/Contralto/CPU/Tasks/CursorTask.cs @@ -5,7 +5,7 @@ namespace Contralto.CPU public partial class AltoCPU { /// - /// CursorTask provides functionality for the Cursor-specific task functions + /// CursorTask provides the implementation of Cursor-specific task functions /// private sealed class CursorTask : Task { @@ -15,12 +15,10 @@ namespace Contralto.CPU _wakeup = false; } - protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) + public override void OnTaskSwitch() { - // We put ourselves back to sleep immediately once we've started running - _wakeup = false; - - return base.ExecuteInstruction(instruction); + // We put ourselves back to sleep immediately once we've started running. + _wakeup = false; } protected override void ExecuteSpecialFunction2(MicroInstruction instruction) diff --git a/Contralto/CPU/Tasks/DiskTask.cs b/Contralto/CPU/Tasks/DiskTask.cs index d5c4f53..0f000df 100644 --- a/Contralto/CPU/Tasks/DiskTask.cs +++ b/Contralto/CPU/Tasks/DiskTask.cs @@ -7,9 +7,9 @@ namespace Contralto.CPU public partial class AltoCPU { /// - /// DiskTask provides implementation for disk-specific special functions + /// DiskTask provides implementations of disk-specific special functions /// (for both Disk Sector and Disk Word tasks, since the special functions are - /// identical between the two) + /// identical between the two). /// private sealed class DiskTask : Task { @@ -19,12 +19,10 @@ namespace Contralto.CPU _wakeup = false; _diskController = _cpu._system.DiskController; - } - - protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) - { - InstructionCompletion completion = base.ExecuteInstruction(instruction); + } + public override void OnTaskSwitch() + { // Deal with SECLATE semantics: If the Disk Sector task wakes up and runs before // the Disk Controller hits the SECLATE trigger time, then SECLATE remains false. // Otherwise, when the trigger time is hit SECLATE is raised until @@ -32,10 +30,8 @@ namespace Contralto.CPU if (_taskType == TaskType.DiskSector) { // Sector task is running; clear enable for seclate signal - _diskController.DisableSeclate(); - } - - return completion; + _diskController.DisableSeclate(); + } } protected override ushort GetBusSource(int bs) diff --git a/Contralto/CPU/Tasks/DisplayHorizontalTask.cs b/Contralto/CPU/Tasks/DisplayHorizontalTask.cs index 4a7d16e..0501254 100644 --- a/Contralto/CPU/Tasks/DisplayHorizontalTask.cs +++ b/Contralto/CPU/Tasks/DisplayHorizontalTask.cs @@ -6,7 +6,7 @@ namespace Contralto.CPU public partial class AltoCPU { /// - /// DisplayWordTask provides functionality for the DHT task + /// DisplayHorizontalTask provides implementations of the DHT task functions. /// private sealed class DisplayHorizontalTask : Task { @@ -18,12 +18,10 @@ namespace Contralto.CPU _displayController = _cpu._system.DisplayController; } - protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) + public override void OnTaskSwitch() { - // We put ourselves back to sleep immediately once we've started running + // We put ourselves back to sleep immediately once we've started running. _wakeup = false; - - return base.ExecuteInstruction(instruction); } protected override void ExecuteSpecialFunction2(MicroInstruction instruction) diff --git a/Contralto/CPU/Tasks/DisplayVerticalTask.cs b/Contralto/CPU/Tasks/DisplayVerticalTask.cs index 8228f4e..117886a 100644 --- a/Contralto/CPU/Tasks/DisplayVerticalTask.cs +++ b/Contralto/CPU/Tasks/DisplayVerticalTask.cs @@ -18,15 +18,10 @@ namespace Contralto.CPU _displayController = _cpu._system.DisplayController; } - protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) + public override void OnTaskSwitch() { - // We put ourselves back to sleep immediately once we've started running - // TODO: for this and other similar patterns: rework this so we don't need to - // override ExecuteInstruction just to do this (or similar polling). Virtual calls - // are expensive, especially when millions of them are being made a second. + // We put ourselves back to sleep immediately once we've started running. _wakeup = false; - - return base.ExecuteInstruction(instruction); } protected override void ExecuteSpecialFunction2(MicroInstruction instruction) diff --git a/Contralto/CPU/Tasks/EmulatorTask.cs b/Contralto/CPU/Tasks/EmulatorTask.cs index 727d39d..bd17898 100644 --- a/Contralto/CPU/Tasks/EmulatorTask.cs +++ b/Contralto/CPU/Tasks/EmulatorTask.cs @@ -22,8 +22,6 @@ namespace Contralto.CPU { base.Reset(); _wakeup = true; - - _systemType = Configuration.SystemType; } public override void BlockTask() @@ -126,7 +124,7 @@ namespace Contralto.CPU // Dispatch to the appropriate device. // The Ethernet controller is the only common device that is documented // to have used STARTF, so we'll just go there directly; if other - // hardware is discovered to be worth emulating we'll put together a more flexible dispatch. + // hardware is determined to be worth emulating we'll put together a more flexible dispatch. // if (_busData < 4) { @@ -226,49 +224,18 @@ namespace Contralto.CPU // elseif IR[4-7] = 16B 6 // else IR[4-7] // NB: as always, Xerox labels bits in the opposite order from modern convention; - // (bit 0 is the msb...) - /* - if (Configuration.SystemType == SystemType.AltoI && UCodeMemory.GetBank(TaskType.Emulator) == MicrocodeBank.RAM0) + // (bit 0 is the msb...) + // + // NOTE: The above table is accurate and functions correctly; using the PROM is faster. + // + if ((_cpu._ir & 0x8000) != 0) { - if ((_cpu._ir & 0x8000) != 0) - {1 - _nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6)); - } - else if ((_cpu._ir & 0x6000) == 0x0000) - { - _nextModifier = (ushort)((_cpu._ir & 0x3000) >> 12); - } - else if ((_cpu._ir & 0x6000) == 0x2000) - { - _nextModifier = 4; - } - else if ((_cpu._ir & 0x6000) == 0x4000) - { - _nextModifier = 5; - } - else if ((_cpu._ir & 0x6000) == 0x6000) - { - if ((_cpu._ir & 0x1f00) == 0x0e00) - { - _nextModifier = 6; - } - else - { - _nextModifier = 1; - } - } + _nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6)); } - else */ + else { - if ((_cpu._ir & 0x8000) != 0) - { - _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; case EmulatorF2.ACSOURCE: @@ -290,7 +257,8 @@ namespace Contralto.CPU // else 16B ROMTRAP // - // NOTE: the above table from the Hardware Manual is incorrect (or at least incomplete / misleading). + // NOTE: the above table from the Hardware Manual is incorrect + // (or at least incomplete / out of date / misleading). // There is considerably more that goes into determining the dispatch, which is controlled by a 256x8 // PROM. We just use the PROM rather than implementing the above logic (because it works.) // @@ -462,9 +430,7 @@ namespace Contralto.CPU // BUS+SKIP(ALUF= 13B). IR<- clears SKIP." // // NB: _skip is in the encapsulating AltoCPU class to make it easier to reference since the ALU needs to know about it. - private int _carry; - - private SystemType _systemType; + private int _carry; } } } diff --git a/Contralto/CPU/Tasks/MemoryRefreshTask.cs b/Contralto/CPU/Tasks/MemoryRefreshTask.cs index 0b73a6a..f485be2 100644 --- a/Contralto/CPU/Tasks/MemoryRefreshTask.cs +++ b/Contralto/CPU/Tasks/MemoryRefreshTask.cs @@ -23,7 +23,7 @@ // // "; This version assumes MRTACT is cleared by BLOCK, not MAR<- R37" // - if (Configuration.SystemType == SystemType.AltoI && + if (_systemType == SystemType.AltoI && instruction.F1 == SpecialFunction1.LoadMAR && _rSelect == 31) { diff --git a/Contralto/CPU/Tasks/Task.cs b/Contralto/CPU/Tasks/Task.cs index 3e5abb4..884d3e4 100644 --- a/Contralto/CPU/Tasks/Task.cs +++ b/Contralto/CPU/Tasks/Task.cs @@ -26,7 +26,9 @@ namespace Contralto.CPU _wakeup = false; _mpc = 0xffff; // invalid, for sanity checking _taskType = TaskType.Invalid; - _cpu = cpu; + _cpu = cpu; + + _systemType = Configuration.SystemType; } public int Priority @@ -84,16 +86,26 @@ namespace Contralto.CPU _mpc = (ushort)_taskType; } + /// + /// Removes the Wakeup signal for this task. + /// public virtual void BlockTask() { _wakeup = false; } + /// + /// Sets the Wakeup signal for this task. + /// public virtual void WakeupTask() { _wakeup = true; } + /// + /// Executes a single microinstruction. + /// + /// An InstructionCompletion indicating whether this instruction calls for a task switch or not. public InstructionCompletion ExecuteNext() { MicroInstruction instruction = UCodeMemory.GetInstruction(_mpc, _taskType); @@ -102,10 +114,10 @@ namespace Contralto.CPU /// /// ExecuteInstruction causes the Task to execute the next instruction (the one - /// _mpc is pointing to). The base implementation covers non-task specific logic; subclasses may - /// provide their own overrides. + /// _mpc is pointing to). The base implementation covers non-task specific logic, + /// subclasses (specific task implementations) may provide their own implementations. /// - /// True if a task switch has been requested by a TASK instruction, false otherwise. + /// An InstructionCompletion indicating whether this instruction calls for a task switch or not. protected virtual InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { InstructionCompletion completion = InstructionCompletion.Normal; @@ -281,7 +293,7 @@ namespace Contralto.CPU _cpu._system.MemoryBus.LoadMAR( aluData, _taskType, - Configuration.SystemType == SystemType.AltoI ? false : instruction.F2 == SpecialFunction2.StoreMD); + _systemType == SystemType.AltoI ? false : instruction.F2 == SpecialFunction2.StoreMD); break; case SpecialFunction1.Task: @@ -364,9 +376,13 @@ namespace Contralto.CPU break; case SpecialFunction2.StoreMD: - // Special case for XMAR; if F1 is a LoadMAR we do nothing here; + // Special case for XMAR on non-Alto I machines: if F1 is a LoadMAR we do nothing here; // the handler for LoadMAR will load the correct bank. - if (instruction.F1 != SpecialFunction1.LoadMAR) + if (_systemType == SystemType.AltoI) + { + _cpu._system.MemoryBus.LoadMD(_busData); + } + else if(instruction.F1 != SpecialFunction1.LoadMAR) { _cpu._system.MemoryBus.LoadMD(_busData); } @@ -510,24 +526,39 @@ namespace Contralto.CPU return completion; } + /// + /// Provides task-specific implementations the opportunity to handle task-specific bus sources. + /// + /// + /// protected virtual ushort GetBusSource(int bs) { // Nothing by default. return 0; } + /// + /// Executes before the ALU runs but after bus sources have been selected. + /// + /// protected virtual void ExecuteSpecialFunction1Early(MicroInstruction instruction) { // Nothing by default } + /// + /// Executes after the ALU has run but before the shifter runs, provides task-specific implementations + /// the opportunity to handle task-specific F1s. + /// + /// protected virtual void ExecuteSpecialFunction1(MicroInstruction instruction) { // Nothing by default } /// - /// Used to allow Task-specific F2s that need to modify RSELECT to do so. + /// Executes before bus sources are selected. Used to allow Task-specific F2s that need to + /// modify RSELECT to do so. /// /// protected virtual void ExecuteSpecialFunction2Early(MicroInstruction instruction) @@ -535,11 +566,20 @@ namespace Contralto.CPU // Nothing by default. } + /// + /// Executes after the ALU has run but before the shifter runs, provides task-specific implementations + /// the opportunity to handle task-specific F2s. + /// protected virtual void ExecuteSpecialFunction2(MicroInstruction instruction) { // Nothing by default. } + /// + /// Executes after the shifter has run, provides task-specific implementations the opportunity + /// to handle task-specific F2s late in the cycle. + /// + /// protected virtual void ExecuteSpecialFunction2Late(MicroInstruction instruction) { // Nothing by default. @@ -554,6 +594,20 @@ namespace Contralto.CPU // Nothing by default } + /// + /// Allows task-specific behavior when a new task begins execution. + /// (Generally this is used to remove wakeup immediately.) + /// + public virtual void OnTaskSwitch() + { + // Nothing by default + } + + /// + /// Cache the system type. + /// + protected SystemType _systemType; + // // Per uInstruction Task Data: // Modified by both the base Task implementation and any subclasses diff --git a/Contralto/CPU/UCodeDisassembler.cs b/Contralto/CPU/UCodeDisassembler.cs index 1a77fa9..a78083f 100644 --- a/Contralto/CPU/UCodeDisassembler.cs +++ b/Contralto/CPU/UCodeDisassembler.cs @@ -3,6 +3,9 @@ using System.Text; namespace Contralto.CPU { + /// + /// Provides a facility for doing a (crude) disassembly of microcode. + /// public static class UCodeDisassembler { diff --git a/Contralto/CPU/UCodeMemory.cs b/Contralto/CPU/UCodeMemory.cs index 5c9193f..d8cedac 100644 --- a/Contralto/CPU/UCodeMemory.cs +++ b/Contralto/CPU/UCodeMemory.cs @@ -27,6 +27,10 @@ namespace Contralto.CPU public int BitPosition; } + /// + /// UCodeMemory maintains a set of Microcode ROM images and provides facilities + /// for accessing them. + /// static class UCodeMemory { static UCodeMemory() @@ -278,7 +282,7 @@ namespace Contralto.CPU // // Each file contains 1024 bytes, each byte containing one nybble in the low 4 bits. // - using(FileStream fs = new FileStream(Path.Combine("ROM", file.Filename), FileMode.Open, FileAccess.Read)) + using(FileStream fs = new FileStream(file.Filename, FileMode.Open, FileAccess.Read)) { int length = (int)fs.Length; if (length != 1024) @@ -312,7 +316,7 @@ namespace Contralto.CPU // // Each file contains 256 bytes, each byte containing one nybble in the low 4 bits. // - using (FileStream fs = new FileStream(Path.Combine("ROM", file.Filename), FileMode.Open, FileAccess.Read)) + using (FileStream fs = new FileStream(file.Filename, FileMode.Open, FileAccess.Read)) { int length = (int)fs.Length; if (length != 256) @@ -384,73 +388,74 @@ namespace Contralto.CPU { UInt32 instructionWord = _uCodeRam[address]; _decodeCache[2048 + address] = new MicroInstruction(instructionWord); - } - - private static RomFile[] _uCodeRomsAltoII = - { - // first K - new RomFile("u55", 0x000, 28), - new RomFile("u64", 0x000, 24), - new RomFile("u65", 0x000, 20), - new RomFile("u63", 0x000, 16), - new RomFile("u53", 0x000, 12), - new RomFile("u60", 0x000, 8), - new RomFile("u61", 0x000, 4), - new RomFile("u62", 0x000, 0), - - // second K - new RomFile("u54", 0x400, 28), - new RomFile("u74", 0x400, 24), - new RomFile("u75", 0x400, 20), - new RomFile("u73", 0x400, 16), - new RomFile("u52", 0x400, 12), - new RomFile("u70", 0x400, 8), - new RomFile("u71", 0x400, 4), - new RomFile("u72", 0x400, 0) - }; + } private static RomFile[] _uCodeRomsAltoI = { // 0 to 377 - new RomFile("0.2", 0x000, 28), - new RomFile("1.2", 0x000, 24), - new RomFile("2.2", 0x000, 20), - new RomFile("3.2", 0x000, 16), - new RomFile("4.2", 0x000, 12), - new RomFile("5.2", 0x000, 8), - new RomFile("6.2", 0x000, 4), - new RomFile("7.2", 0x000, 0), + new RomFile(Configuration.GetAltoIRomPath("00_23.BIN"), 0x000, 28), + new RomFile(Configuration.GetAltoIRomPath("01_23.BIN"), 0x000, 24), + new RomFile(Configuration.GetAltoIRomPath("02_23.BIN"), 0x000, 20), + new RomFile(Configuration.GetAltoIRomPath("03_23.BIN"), 0x000, 16), + new RomFile(Configuration.GetAltoIRomPath("04_23.BIN"), 0x000, 12), + new RomFile(Configuration.GetAltoIRomPath("05_23.BIN"), 0x000, 8), + new RomFile(Configuration.GetAltoIRomPath("06_23.BIN"), 0x000, 4), + new RomFile(Configuration.GetAltoIRomPath("07_23.BIN"), 0x000, 0), // 400 to 777 - new RomFile("10.2", 0x100, 28), - new RomFile("11.2", 0x100, 24), - new RomFile("12.2", 0x100, 20), - new RomFile("13.2", 0x100, 16), - new RomFile("14.2", 0x100, 12), - new RomFile("15.2", 0x100, 8), - new RomFile("16.2", 0x100, 4), - new RomFile("17.2", 0x100, 0), + new RomFile(Configuration.GetAltoIRomPath("10_23.BIN"), 0x100, 28), + new RomFile(Configuration.GetAltoIRomPath("11_23.BIN"), 0x100, 24), + new RomFile(Configuration.GetAltoIRomPath("12_23.BIN"), 0x100, 20), + new RomFile(Configuration.GetAltoIRomPath("13_23.BIN"), 0x100, 16), + new RomFile(Configuration.GetAltoIRomPath("14_23.BIN"), 0x100, 12), + new RomFile(Configuration.GetAltoIRomPath("15_23.BIN"), 0x100, 8), + new RomFile(Configuration.GetAltoIRomPath("16_23.BIN"), 0x100, 4), + new RomFile(Configuration.GetAltoIRomPath("17_23.BIN"), 0x100, 0), // 1000 to 1377 - new RomFile("20.2", 0x200, 28), - new RomFile("21.2", 0x200, 24), - new RomFile("22.2", 0x200, 20), - new RomFile("23.2", 0x200, 16), - new RomFile("24.2", 0x200, 12), - new RomFile("25.2", 0x200, 8), - new RomFile("26.2", 0x200, 4), - new RomFile("27.2", 0x200, 0), + new RomFile(Configuration.GetAltoIRomPath("20_23.BIN"), 0x200, 28), + new RomFile(Configuration.GetAltoIRomPath("21_23.BIN"), 0x200, 24), + new RomFile(Configuration.GetAltoIRomPath("22_23.BIN"), 0x200, 20), + new RomFile(Configuration.GetAltoIRomPath("23_23.BIN"), 0x200, 16), + new RomFile(Configuration.GetAltoIRomPath("24_23.BIN"), 0x200, 12), + new RomFile(Configuration.GetAltoIRomPath("25_23.BIN"), 0x200, 8), + new RomFile(Configuration.GetAltoIRomPath("26_23.BIN"), 0x200, 4), + new RomFile(Configuration.GetAltoIRomPath("27_23.BIN"), 0x200, 0), // 1400 to 1777 - new RomFile("30.2", 0x300, 28), - new RomFile("31.2", 0x300, 24), - new RomFile("32.2", 0x300, 20), - new RomFile("33.2", 0x300, 16), - new RomFile("34.2", 0x300, 12), - new RomFile("35.2", 0x300, 8), - new RomFile("36.2", 0x300, 4), - new RomFile("37.2", 0x300, 0), - }; + new RomFile(Configuration.GetAltoIRomPath("30_23.BIN"), 0x300, 28), + new RomFile(Configuration.GetAltoIRomPath("31_23.BIN"), 0x300, 24), + new RomFile(Configuration.GetAltoIRomPath("32_23.BIN"), 0x300, 20), + new RomFile(Configuration.GetAltoIRomPath("33_23.BIN"), 0x300, 16), + new RomFile(Configuration.GetAltoIRomPath("34_23.BIN"), 0x300, 12), + new RomFile(Configuration.GetAltoIRomPath("35_23.BIN"), 0x300, 8), + new RomFile(Configuration.GetAltoIRomPath("36_23.BIN"), 0x300, 4), + new RomFile(Configuration.GetAltoIRomPath("37_23.BIN"), 0x300, 0), + }; + + private static RomFile[] _uCodeRomsAltoII = + { + // first K (standard uCode) + new RomFile(Configuration.GetAltoIIRomPath("u55"), 0x000, 28), + new RomFile(Configuration.GetAltoIIRomPath("u64"), 0x000, 24), + new RomFile(Configuration.GetAltoIIRomPath("u65"), 0x000, 20), + new RomFile(Configuration.GetAltoIIRomPath("u63"), 0x000, 16), + new RomFile(Configuration.GetAltoIIRomPath("u53"), 0x000, 12), + new RomFile(Configuration.GetAltoIIRomPath("u60"), 0x000, 8), + new RomFile(Configuration.GetAltoIIRomPath("u61"), 0x000, 4), + new RomFile(Configuration.GetAltoIIRomPath("u62"), 0x000, 0), + + // second K (MESA 5.0) + new RomFile(Configuration.GetAltoIIRomPath("u54"), 0x400, 28), + new RomFile(Configuration.GetAltoIIRomPath("u74"), 0x400, 24), + new RomFile(Configuration.GetAltoIIRomPath("u75"), 0x400, 20), + new RomFile(Configuration.GetAltoIIRomPath("u73"), 0x400, 16), + new RomFile(Configuration.GetAltoIIRomPath("u52"), 0x400, 12), + new RomFile(Configuration.GetAltoIIRomPath("u70"), 0x400, 8), + new RomFile(Configuration.GetAltoIIRomPath("u71"), 0x400, 4), + new RomFile(Configuration.GetAltoIIRomPath("u72"), 0x400, 0) + }; + private static UInt32[] _uCodeRom; private static UInt32[] _uCodeRam; diff --git a/Contralto/Configuration.cs b/Contralto/Configuration.cs index 4319a41..ef4a3e2 100644 --- a/Contralto/Configuration.cs +++ b/Contralto/Configuration.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace Contralto { /// - /// The configuration of an Alto II to emulate + /// The configuration of the Alto to emulate /// public enum SystemType { @@ -166,6 +166,21 @@ namespace Contralto /// public static bool ThrottleSpeed; + public static string GetAltoIRomPath(string romFileName) + { + return Path.Combine("ROM", "AltoI", romFileName); + } + + public static string GetAltoIIRomPath(string romFileName) + { + return Path.Combine("ROM", "AltoII", romFileName); + } + + public static string GetRomPath(string romFileName) + { + return Path.Combine("ROM", romFileName); + } + /// /// Reads the current configuration file from disk. /// diff --git a/Contralto/Contralto.csproj b/Contralto/Contralto.csproj index fabe0da..c8398df 100644 --- a/Contralto/Contralto.csproj +++ b/Contralto/Contralto.csproj @@ -258,223 +258,178 @@ PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - + PreserveNewest diff --git a/Contralto/Display/DisplayController.cs b/Contralto/Display/DisplayController.cs index cfd56c4..988486f 100644 --- a/Contralto/Display/DisplayController.cs +++ b/Contralto/Display/DisplayController.cs @@ -91,6 +91,9 @@ namespace Contralto.Display _system.Scheduler.Schedule(_verticalBlankScanlineWakeup); } + /// + /// Begins the next display field. + /// private void FieldStart() { // Start of Vertical Blanking (end of last field). This lasts for 34 scanline times or so. @@ -117,6 +120,12 @@ namespace Contralto.Display _system.Scheduler.Schedule(_verticalBlankScanlineWakeup); } + /// + /// Callback for each scanline during vblank. + /// + /// + /// + /// private void VerticalBlankScanlineCallback(ulong timeNsec, ulong skewNsec, object context) { // End of VBlank scanline. @@ -157,6 +166,12 @@ namespace Contralto.Display } } + /// + /// Callback for the end of each horizontal blank period. + /// + /// + /// + /// private void HorizontalBlankEndCallback(ulong timeNsec, ulong skewNsec, object context) { // Reset scanline word counter @@ -182,6 +197,12 @@ namespace Contralto.Display _system.Scheduler.Schedule(_wordWakeup); } + /// + /// Callback for each word of visible display lines. + /// + /// + /// + /// private void WordCallback(ulong timeNsec, ulong skewNsec, object context) { if (_display == null) @@ -268,6 +289,10 @@ namespace Contralto.Display } } + /// + /// Check to see if a Display Word task wakeup should be generated based on the current + /// state of the FIFO and task wakeup bits. + /// private void CheckWordWakeup() { if (FIFOFULL || @@ -290,6 +315,10 @@ namespace Contralto.Display } } + /// + /// Enqueues a display word on the display controller's FIFO. + /// + /// public void LoadDDR(ushort word) { _dataBuffer.Enqueue(word); @@ -303,6 +332,10 @@ namespace Contralto.Display CheckWordWakeup(); } + /// + /// Loads the X position register for the cursor + /// + /// public void LoadXPREG(ushort word) { if (!_cursorXLatch) @@ -312,6 +345,10 @@ namespace Contralto.Display } } + /// + /// Loads the cursor register + /// + /// public void LoadCSR(ushort word) { if (!_cursorRegLatch) @@ -321,6 +358,10 @@ namespace Contralto.Display } } + /// + /// Sets the mode (low res and white on black bits) + /// + /// public void SETMODE(ushort word) { // These take effect at the beginning of the next scanline. @@ -358,7 +399,7 @@ namespace Contralto.Display private ushort _cursorX; private ushort _cursorXLatched; - // Indicates whether the DWT or DHT blocked itself + // Indicates whether the DWT or DHT blocked themselves // in which case they cannot be reawakened until the next field. private bool _dwtBlocked; private bool _dhtBlocked; diff --git a/Contralto/Display/IAltoDisplay.cs b/Contralto/Display/IAltoDisplay.cs index eb389b3..e3e3f0f 100644 --- a/Contralto/Display/IAltoDisplay.cs +++ b/Contralto/Display/IAltoDisplay.cs @@ -6,6 +6,10 @@ using System.Threading.Tasks; namespace Contralto.Display { + /// + /// IAltoDisplay defines the interface necessary for generating and rendering the Alto's + /// bitmapped display. + /// public interface IAltoDisplay { /// @@ -18,7 +22,7 @@ namespace Contralto.Display void DrawDisplayWord(int scanline, int wordOffset, ushort dataWord, bool lowRes); /// - /// Renders the cursor word for the specified scanline + /// Renders the cursor word for the specified scanline. /// /// /// @@ -27,7 +31,7 @@ namespace Contralto.Display void DrawCursorWord(int scanline, int xOffset, bool whiteOnBlack, ushort cursorWord); /// - /// Causes the display to be rendered + /// Indicates that an entire frame is ready for display and should be rendered. /// void Render(); } diff --git a/Contralto/IO/DiabloDrive.cs b/Contralto/IO/DiabloDrive.cs index 13eda50..755443e 100644 --- a/Contralto/IO/DiabloDrive.cs +++ b/Contralto/IO/DiabloDrive.cs @@ -9,7 +9,9 @@ using System.Threading.Tasks; namespace Contralto.IO { - // The data for the current sector + /// + /// Defines the "type" of data in the current sector timeslice. + /// public enum CellType { Data, @@ -17,6 +19,11 @@ namespace Contralto.IO Sync, } + /// + /// Represents the data (or lack thereof) in the current sector timeslice. + /// This may be actual data (header, label, or data), interrecord gaps, or + /// sync words. + /// public struct DataCell { public DataCell(ushort data, CellType type) diff --git a/Contralto/IO/DiabloPack.cs b/Contralto/IO/DiabloPack.cs index 14e0b36..bd48304 100644 --- a/Contralto/IO/DiabloPack.cs +++ b/Contralto/IO/DiabloPack.cs @@ -4,6 +4,9 @@ using System.IO; namespace Contralto.IO { + /// + /// DiskGeometry encapsulates the geometry of a disk. + /// public struct DiskGeometry { public DiskGeometry(int cylinders, int tracks, int sectors) @@ -24,6 +27,10 @@ namespace Contralto.IO Diablo44 } + /// + /// DiabloDiskSector encapsulates the records contained in a single Alto disk sector + /// on a Diablo disk. This includes the header, label, and data records. + /// public class DiabloDiskSector { public DiabloDiskSector(byte[] header, byte[] label, byte[] data) @@ -106,13 +113,14 @@ namespace Contralto.IO // Bitsavers images have an extra word in the header for some reason. // ignore it. // TODO: should support different formats ("correct" raw, Alto CopyDisk format, etc.) - // + // imageStream.Seek(2, SeekOrigin.Current); + if (imageStream.Read(header, 0, header.Length) != header.Length) { throw new InvalidOperationException("Short read while reading sector header."); - } + } if (imageStream.Read(label, 0, label.Length) != label.Length) { diff --git a/Contralto/IO/DiskController.cs b/Contralto/IO/DiskController.cs index e937e34..7c77d60 100644 --- a/Contralto/IO/DiskController.cs +++ b/Contralto/IO/DiskController.cs @@ -15,6 +15,10 @@ namespace Contralto.IO public delegate void DiskActivity(DiskActivityType activity); + /// + /// DiskController provides an implementation for the logic in the standard Alto disk controller, + /// which talks to a Diablo model 31 or 44 removable pack drive. + /// public class DiskController { public DiskController(AltoSystem system) @@ -28,11 +32,7 @@ namespace Contralto.IO Reset(); } - - /// - /// According to docs, on a Write, eventually it appears on the Read side during an actual write to the disk - /// but not right away. - /// + public ushort KDATA { get @@ -165,37 +165,7 @@ namespace Contralto.IO public bool DataXfer { get { return _dataXfer; } - } - - public int Cylinder - { - get { return SelectedDrive.Cylinder; } - } - - public int SeekCylinder - { - get { return _destCylinder; } - } - - public int Head - { - get { return SelectedDrive.Head; } - } - - public int Sector - { - get { return SelectedDrive.Sector; } - } - - public int Drive - { - get { return _disk; } - } - - public double ClocksUntilNextSector - { - get { return 0; } // _sectorClocks - _elapsedSectorTime; } - } + } public bool Ready { @@ -292,6 +262,12 @@ namespace Contralto.IO _seclateEnable = false; } + /// + /// Called back 12 times per rotation of the disk to kick off a new disk sector. + /// + /// + /// + /// private void SectorCallback(ulong timeNsec, ulong skewNsec, object context) { // @@ -351,6 +327,12 @@ namespace Contralto.IO } } + /// + /// Called back for every word time in this sector. + /// + /// + /// + /// private void WordCallback(ulong timeNsec, ulong skewNsec, object context) { SpinDisk(); @@ -369,6 +351,13 @@ namespace Contralto.IO } } + /// + /// Called back if the sector task doesn't start in time, providing SECLATE + /// semantics. + /// + /// + /// + /// private void SeclateCallback(ulong timeNsec, ulong skewNsec, object context) { if (_seclateEnable) @@ -405,6 +394,9 @@ namespace Contralto.IO } } + /// + /// Starts a seek operation. + /// public void Strobe() { // @@ -487,7 +479,7 @@ namespace Contralto.IO // for lead-in or inter-record delays, but the slices are still used to // keep things in line time-wise; the real hardware uses a crystal-controlled clock // to generate these slices during these periods (and the clock comes from the - // disk itself when actual data is present). For our purposes, the two clocks + // drive itself when actual data is present). For our purposes, the two clocks // are one and the same. // diff --git a/Contralto/IO/EthernetController.cs b/Contralto/IO/EthernetController.cs index db620fa..8cedec9 100644 --- a/Contralto/IO/EthernetController.cs +++ b/Contralto/IO/EthernetController.cs @@ -9,6 +9,9 @@ using System.Threading.Tasks; namespace Contralto.IO { + /// + /// EthernetController implements the logic for the Alto's 3Mbit Ethernet controller. + /// public class EthernetController { public EthernetController(AltoSystem system) @@ -345,7 +348,7 @@ namespace Contralto.IO /// /// Invoked when the host ethernet interface receives a packet destined for us. - /// NOTE: This runs on the PCap receiver thread (see HostEthernet), not the main emulator thread. + /// NOTE: This runs on the PCap or UDP receiver thread, not the main emulator thread. /// Any access to emulator structures must be properly protected. /// /// Due to the nature of the "ethernet" we're simulating, there will never be any collisions or corruption and @@ -502,18 +505,7 @@ namespace Contralto.IO // Schedule the next wakeup. _inputPollEvent.TimestampNsec = _inputPollPeriod - skewNsec; _system.Scheduler.Schedule(_inputPollEvent); - } - - private void LogPacket(int length, MemoryStream packet) - { - Log.Write(LogComponent.EthernetPacket, - " - Packet src {0}, dest {1}, length {2}", - packet.ReadByte(), packet.ReadByte(), length); - - - // Return to top of packet - packet.Position = 2; - } + } private Queue _fifo; @@ -555,11 +547,11 @@ namespace Contralto.IO private const int _maxQueuedPackets = 32; // The actual connection to a real network device of some sort on the host - IPacketEncapsulation _hostInterface; + private IPacketEncapsulation _hostInterface; // Buffer to hold outgoing data to the host ethernet - ushort[] _outputData; - int _outputIndex; + private ushort[] _outputData; + private int _outputIndex; // Incoming data and locking private MemoryStream _incomingPacket; diff --git a/Contralto/IO/HostEthernetEncapsulation.cs b/Contralto/IO/HostEthernetEncapsulation.cs index 1c9acb8..e95092e 100644 --- a/Contralto/IO/HostEthernetEncapsulation.cs +++ b/Contralto/IO/HostEthernetEncapsulation.cs @@ -15,7 +15,9 @@ using System.Threading; namespace Contralto.IO { - + /// + /// Represents a host ethernet interface. + /// public struct EthernetInterface { public EthernetInterface(string name, string description) @@ -249,19 +251,8 @@ namespace Contralto.IO } else { - // Check addressing table for external (non emulator) addresses; - // otherwise just address other emulators - // TODO: implement table. Currently hardcoded address 1 to test IFS on dev machine - // - if (destinationHost == 1) - { - destinationMac = new MacAddress((UInt48)(_ifsTestMAC)); - } - else - { - destinationMac = new MacAddress((UInt48)(_10mbitMACPrefix | destinationHost)); // emulator destination address - } - + // Build 10mbit address from 3mbit + destinationMac = new MacAddress((UInt48)(_10mbitMACPrefix | destinationHost)); // emulator destination address } return destinationMac; @@ -285,9 +276,6 @@ namespace Contralto.IO private UInt48 _10mbitMACPrefix = 0x0000aa010200; // 00-00-AA is the Xerox vendor code, used just to be cute. private UInt48 _10mbitBroadcast = (UInt48)0xffffffffffff; - private const int _3mbitBroadcast = 0; - - // Temporary; to be replaced with an external address mapping table - private UInt48 _ifsTestMAC = (UInt48)0x001060b88e3e; + private const int _3mbitBroadcast = 0; } } diff --git a/Contralto/IO/IPacketEncapsulation.cs b/Contralto/IO/IPacketEncapsulation.cs index b702b2e..a8c34ec 100644 --- a/Contralto/IO/IPacketEncapsulation.cs +++ b/Contralto/IO/IPacketEncapsulation.cs @@ -5,6 +5,10 @@ namespace Contralto.IO { public delegate void ReceivePacketDelegate(MemoryStream data); + /// + /// Provides a generic interface for host network devices that can encapsulate + /// Alto ethernet packets. + /// public interface IPacketEncapsulation { /// @@ -14,14 +18,14 @@ namespace Contralto.IO void RegisterReceiveCallback(ReceivePacketDelegate callback); /// - /// Sends the specified word array + /// Sends the specified word array over the device. /// /// /// void Send(ushort[] packet, int length); /// - /// Shuts down the encapsulation provider + /// Shuts down the encapsulation provider. /// void Shutdown(); } diff --git a/Contralto/IO/Keyboard.cs b/Contralto/IO/Keyboard.cs index d9c25f5..82b89f4 100644 --- a/Contralto/IO/Keyboard.cs +++ b/Contralto/IO/Keyboard.cs @@ -5,7 +5,9 @@ using Contralto.CPU; namespace Contralto.IO { - + /// + /// The keys on the Alto keyboard. + /// public enum AltoKey { None = 0, @@ -72,6 +74,9 @@ namespace Contralto.IO BlankBottom, } + /// + /// Specifies the word and bitmask for a given Alto keyboard key. + /// public struct AltoKeyBit { public AltoKeyBit(int word, ushort mask) diff --git a/Contralto/IO/Mouse.cs b/Contralto/IO/Mouse.cs index 6adc200..3aa960a 100644 --- a/Contralto/IO/Mouse.cs +++ b/Contralto/IO/Mouse.cs @@ -17,6 +17,9 @@ namespace Contralto.IO Left = 0x4, } + /// + /// Implements the hardware for the standard Alto mouse. + /// public class Mouse : IMemoryMappedDevice { public Mouse() @@ -27,10 +30,7 @@ namespace Contralto.IO public void Reset() { - // cheat for synchronization: this is approximately where the mouse is initialized to - // at alto boot. - _mouseY = 80; - _mouseX = 0; + } public ushort Read(int address, TaskType task, bool extendedMemoryReference) diff --git a/Contralto/IO/UDPEncapsulation.cs b/Contralto/IO/UDPEncapsulation.cs index 087e37a..a63367d 100644 --- a/Contralto/IO/UDPEncapsulation.cs +++ b/Contralto/IO/UDPEncapsulation.cs @@ -168,9 +168,6 @@ namespace Contralto.IO private void ReceiveThread() { - // Just call ReceivePackets, that's it. This will never return. - // (probably need to make this more elegant so we can tear down the thread - // properly.) Log.Write(LogComponent.HostNetworkInterface, "UDP Receiver thread started."); IPEndPoint groupEndPoint = new IPEndPoint(IPAddress.Any, _udpPort); diff --git a/Contralto/Memory/Memory.cs b/Contralto/Memory/Memory.cs index f8eb165..913f5a5 100644 --- a/Contralto/Memory/Memory.cs +++ b/Contralto/Memory/Memory.cs @@ -3,6 +3,10 @@ using Contralto.Logging; namespace Contralto.Memory { + /// + /// Implements the Alto's main memory, up to 4 banks of 64KW in 16-bit words. + /// Provides implementation of the IIXM's memory mapping hardware. + /// public class Memory : IMemoryMappedDevice { public Memory() diff --git a/Contralto/Memory/MemoryBus.cs b/Contralto/Memory/MemoryBus.cs index 6d7cfd2..27d892e 100644 --- a/Contralto/Memory/MemoryBus.cs +++ b/Contralto/Memory/MemoryBus.cs @@ -14,13 +14,14 @@ namespace Contralto.Memory /// /// Implements the memory bus and memory timings for the Alto system. - /// TODO: Currently only implements timings for Alto II systems. + /// This implements timings for both Alto I and Alto II systems. /// - public class MemoryBus : IClockable + public sealed class MemoryBus : IClockable { public MemoryBus() { _bus = new Dictionary(65536); + _systemType = Configuration.SystemType; Reset(); } @@ -106,25 +107,59 @@ namespace Contralto.Memory { _memoryCycle++; if (_memoryOperationActive) - { - switch (_memoryCycle) + { + if (_systemType == SystemType.AltoI) { - case 3: - // Buffered read of single word - _memoryData = ReadFromBus(_memoryAddress, _task, _extendedMemoryReference); - break; - - case 4: - // Buffered read of double-word - _memoryData2 = ReadFromBus((ushort)(_memoryAddress ^ 1), _task, _extendedMemoryReference); - break; - - case 5: - // End of memory operation - _memoryOperationActive = false; - _doubleWordStore = false; - break; + ClockAltoI(); } + else + { + ClockAltoII(); + } + } + } + + private void ClockAltoI() + { + switch (_memoryCycle) + { + case 4: + // Buffered read of single word + _memoryData = ReadFromBus(_memoryAddress, _task, _extendedMemoryReference); + break; + + case 5: + // Buffered read of double-word + _memoryData2 = ReadFromBus((ushort)(_memoryAddress | 1), _task, _extendedMemoryReference); + break; + + case 7: + // End of memory operation + _memoryOperationActive = false; + _doubleWordStore = false; + break; + } + } + + private void ClockAltoII() + { + switch (_memoryCycle) + { + case 3: + // Buffered read of single word + _memoryData = ReadFromBus(_memoryAddress, _task, _extendedMemoryReference); + break; + + case 4: + // Buffered read of double-word + _memoryData2 = ReadFromBus((ushort)(_memoryAddress ^ 1), _task, _extendedMemoryReference); + break; + + case 5: + // End of memory operation + _memoryOperationActive = false; + _doubleWordStore = false; + break; } } @@ -143,8 +178,16 @@ namespace Contralto.Memory return _memoryCycle > 4; case MemoryOperation.Store: - // Write operations take place on cycles 3 and 4 - return _memoryCycle > 2; + if (_systemType == SystemType.AltoI) + { + // // Store operations take place on cycles 5 and 6 + return _memoryCycle > 4; + } + else + { + // Store operations take place on cycles 3 and 4 + return _memoryCycle > 2; + } default: throw new InvalidOperationException(String.Format("Unexpected memory operation {0}", op)); @@ -161,7 +204,8 @@ namespace Contralto.Memory { if (_memoryOperationActive) { - // This should not happen; CPU should check whether the operation is possible using Ready and stall if not. + // This should not happen; CPU implementation should check whether the operation is possible + // using Ready and stall if not. throw new InvalidOperationException("Invalid LoadMAR request during active memory operation."); } else @@ -177,31 +221,71 @@ namespace Contralto.Memory } public ushort ReadMD() + { + if (_systemType == SystemType.AltoI) + { + return ReadMDAltoI(); + } + else + { + return ReadMDAltoII(); + } + } + + private ushort ReadMDAltoI() { if (_memoryOperationActive) { switch (_memoryCycle) { - case 1: + case 1: + case 2: + + // TODO: good microcode should never do this + throw new InvalidOperationException("Unexpected microcode behavior -- ReadMD too soon after start of memory cycle."); + 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."); + + case 5: + // Single word read + return _memoryData; + + case 6: + // Double word read, return other half of double word. + return _memoryData2; + + default: + // Invalid state. + throw new InvalidOperationException(string.Format("Unexpected memory cycle {0} in memory state machine.", _memoryCycle)); + } + } + else + { + // The Alto I does not latch memory contents, an <-MD operation returns undefined results + return 0xffff; + } + } + + private ushort ReadMDAltoII() + { + if (_memoryOperationActive) + { + switch (_memoryCycle) + { + case 1: case 2: // TODO: good microcode should never do this throw new InvalidOperationException("Unexpected microcode behavior -- ReadMD too soon after start of memory cycle."); 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 ReadMR request during cycle 3 or 4 of memory operation."); case 5: - // Single word read - //Log.Write(LogType.Verbose, LogComponent.Memory, "Single-word read of {0} from {1} (cycle 5)", Conversion.ToOctal(_memoryData), Conversion.ToOctal(_memoryAddress ^ 1)); - - // debug - /* - if (_memoryAddress == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk - { - Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData); - } */ - return _memoryData; + // Single word read + return _memoryData; // *** // NB: Handler for double-word read (cycle 6) is in the "else" clause below; this is kind of a hack. @@ -219,104 +303,97 @@ namespace Contralto.Memory // 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)) - { - - //Log.Write(LogType.Verbose, LogComponent.Memory, "Double-word read of {0} from {1} (cycle 6)", Conversion.ToOctal(_memoryData2), Conversion.ToOctal(_memoryAddress ^ 1)); - _doubleWordMixed = false; - // debug - /* - if ((_memoryAddress ^ 1) == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk - { - Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData2); - } */ + { + _doubleWordMixed = false; return _memoryData2; } else { - _doubleWordMixed = false; - // debug - /* - if (_memoryAddress == 0xfc90 && _task != TaskType.Emulator) // 176220 -- status word for disk - { - Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} read {1} from 176220.", _task, _memoryData); - } */ - //Log.Write(LogType.Verbose, LogComponent.Memory, "Single-word read of {0} from {1} (post cycle 6)", Conversion.ToOctal(_memoryData), Conversion.ToOctal(_memoryAddress)); + _doubleWordMixed = false; return _memoryData; } - } + } } public void LoadMD(ushort data) { if (_memoryOperationActive) { - switch (_memoryCycle) + if (_systemType == SystemType.AltoI) { - 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 3: - - // debug - /* - if (_memoryAddress == 0xfc90 || _memoryAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk - { - Logging.Log.Write(Logging.LogComponent.Debug, "++> Task {0} wrote {1} to {3} (was {2}).", _task, Conversion.ToOctal(data), Conversion.ToOctal(DebugReadWord(_task, _memoryAddress)), Conversion.ToOctal(_memoryAddress)); - }*/ - - _memoryData = data; // Only really necessary to show in debugger - // Start of doubleword write: - WriteToBus(_memoryAddress, data, _task, _extendedMemoryReference); - _doubleWordStore = true; - _doubleWordMixed = true; - - - - /* - Log.Write( - LogType.Verbose, - LogComponent.Memory, - "Single-word store of {0} to {1} (cycle 3)", - Conversion.ToOctal(data), - Conversion.ToOctal(_memoryAddress)); */ - break; - - case 4: - _memoryData = data; // Only really necessary to show in debugger - - /* - Log.Write( - LogType.Verbose, - LogComponent.Memory, - _doubleWordStore ? "Double-word store of {0} to {1} (cycle 4)" : "Single-word store of {0} to {1} (cycle 4)", - Conversion.ToOctal(data), - _doubleWordStore ? Conversion.ToOctal(_memoryAddress ^ 1) : Conversion.ToOctal(_memoryAddress)); - */ - // debug - ushort actualAddress = _doubleWordStore ? (ushort)(_memoryAddress ^ 1) : _memoryAddress; - - /* - if (actualAddress == 0xfc90 || actualAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk - { - Logging.Log.Write(Logging.LogComponent.Debug, "--> Task {0} wrote {1} to {4} (was {2}). Extd {3}", _task, Conversion.ToOctal(data), Conversion.ToOctal(DebugReadWord(_task, actualAddress)), _extendedMemoryReference, Conversion.ToOctal(actualAddress)); - } */ - - WriteToBus(actualAddress, data, _task, _extendedMemoryReference); - - /* - if (actualAddress == 0xfc90 || actualAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk - { - Logging.Log.Write(Logging.LogComponent.Debug, "--> Now {0}.", Conversion.ToOctal(DebugReadWord(_task, actualAddress))); - } */ - break; - } - + LoadMDAltoI(data); + } + else + { + LoadMDAltoII(data); + } } } + private void LoadMDAltoI(ushort data) + { + switch (_memoryCycle) + { + case 1: + case 2: + case 3: + case 4: + // TODO: 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: + WriteToBus(_memoryAddress, data, _task, _extendedMemoryReference); + _doubleWordStore = true; + _doubleWordMixed = true; + break; + + case 6: + if (!_doubleWordStore) + { + throw new InvalidOperationException("Unexpected microcode behavior -- LoadMD on cycle 6, no LoadMD on cycle 5."); + } + + _memoryData = data; // Only really necessary to show in debugger + ushort actualAddress = (ushort)(_memoryAddress | 1); + + WriteToBus(actualAddress, data, _task, _extendedMemoryReference); + break; + } + + } + + private void LoadMDAltoII(ushort data) + { + 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 3: + + _memoryData = data; // Only really necessary to show in debugger + // Start of doubleword write: + WriteToBus(_memoryAddress, data, _task, _extendedMemoryReference); + _doubleWordStore = true; + _doubleWordMixed = true; + break; + + case 4: + _memoryData = data; // Only really necessary to show in debugger + ushort actualAddress = _doubleWordStore ? (ushort)(_memoryAddress ^ 1) : _memoryAddress; + + WriteToBus(actualAddress, data, _task, _extendedMemoryReference); + break; + } + + } + /// /// Dispatches reads to memory mapped hardware (RAM, I/O) /// @@ -340,8 +417,7 @@ namespace Contralto.Memory return memoryMappedDevice.Read(address, task, extendedMemoryReference); } else - { - //throw new NotImplementedException(String.Format("Read from unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address))); + { return 0; } } @@ -369,11 +445,7 @@ namespace Contralto.Memory if (_bus.TryGetValue(address, out memoryMappedDevice)) { memoryMappedDevice.Load(address, data, task, extendedMemoryReference); - } - else - { - // throw new NotImplementedException(String.Format("Write to unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address))); - } + } } } @@ -382,6 +454,11 @@ namespace Contralto.Memory /// private Dictionary _bus; + /// + /// Cache the system type since we rely on it + /// + private SystemType _systemType; + // // Optimzation: keep reference to main memory; since 99.9999% of accesses go directly there, // we can avoid the hashtable overhead using a simple address check. diff --git a/Contralto/Program.cs b/Contralto/Program.cs index 598d670..b3cf373 100644 --- a/Contralto/Program.cs +++ b/Contralto/Program.cs @@ -103,7 +103,6 @@ namespace Contralto } } - private static AltoSystem _system; - private static ManualResetEvent _closeEvent; + private static AltoSystem _system; } } diff --git a/Contralto/ROM/0.2 b/Contralto/ROM/0.2 deleted file mode 100644 index a42e7eb..0000000 Binary files a/Contralto/ROM/0.2 and /dev/null differ diff --git a/Contralto/ROM/1.2 b/Contralto/ROM/1.2 deleted file mode 100644 index b2cf4b8..0000000 Binary files a/Contralto/ROM/1.2 and /dev/null differ diff --git a/Contralto/ROM/10.2 b/Contralto/ROM/10.2 deleted file mode 100644 index f4586cb..0000000 Binary files a/Contralto/ROM/10.2 and /dev/null differ diff --git a/Contralto/ROM/11.2 b/Contralto/ROM/11.2 deleted file mode 100644 index 76fce7e..0000000 --- a/Contralto/ROM/11.2 +++ /dev/null @@ -1,7 +0,0 @@ -       -      - -    - - -      \ No newline at end of file diff --git a/Contralto/ROM/12.2 b/Contralto/ROM/12.2 deleted file mode 100644 index 773887a..0000000 --- a/Contralto/ROM/12.2 +++ /dev/null @@ -1,17 +0,0 @@ - -  -    -  - -  -  -   - - -  - - -      -  - - \ No newline at end of file diff --git a/Contralto/ROM/13.2 b/Contralto/ROM/13.2 deleted file mode 100644 index 5b5e7a9..0000000 Binary files a/Contralto/ROM/13.2 and /dev/null differ diff --git a/Contralto/ROM/14.2 b/Contralto/ROM/14.2 deleted file mode 100644 index 821d423..0000000 Binary files a/Contralto/ROM/14.2 and /dev/null differ diff --git a/Contralto/ROM/16.2 b/Contralto/ROM/16.2 deleted file mode 100644 index c469133..0000000 Binary files a/Contralto/ROM/16.2 and /dev/null differ diff --git a/Contralto/ROM/17.2 b/Contralto/ROM/17.2 deleted file mode 100644 index b625c88..0000000 Binary files a/Contralto/ROM/17.2 and /dev/null differ diff --git a/Contralto/ROM/2.2 b/Contralto/ROM/2.2 deleted file mode 100644 index afa2d3c..0000000 Binary files a/Contralto/ROM/2.2 and /dev/null differ diff --git a/Contralto/ROM/20.2 b/Contralto/ROM/20.2 deleted file mode 100644 index d863b7a..0000000 Binary files a/Contralto/ROM/20.2 and /dev/null differ diff --git a/Contralto/ROM/21.2 b/Contralto/ROM/21.2 deleted file mode 100644 index 350c44e..0000000 --- a/Contralto/ROM/21.2 +++ /dev/null @@ -1,3 +0,0 @@ -                 -          -     diff --git a/Contralto/ROM/23.2 b/Contralto/ROM/23.2 deleted file mode 100644 index 79cbafd..0000000 Binary files a/Contralto/ROM/23.2 and /dev/null differ diff --git a/Contralto/ROM/24.2 b/Contralto/ROM/24.2 deleted file mode 100644 index 375adb6..0000000 Binary files a/Contralto/ROM/24.2 and /dev/null differ diff --git a/Contralto/ROM/25.2 b/Contralto/ROM/25.2 deleted file mode 100644 index dd1405e..0000000 Binary files a/Contralto/ROM/25.2 and /dev/null differ diff --git a/Contralto/ROM/26.2 b/Contralto/ROM/26.2 deleted file mode 100644 index 38eed62..0000000 Binary files a/Contralto/ROM/26.2 and /dev/null differ diff --git a/Contralto/ROM/27.2 b/Contralto/ROM/27.2 deleted file mode 100644 index a67a321..0000000 Binary files a/Contralto/ROM/27.2 and /dev/null differ diff --git a/Contralto/ROM/3.2 b/Contralto/ROM/3.2 deleted file mode 100644 index 7cb371a..0000000 Binary files a/Contralto/ROM/3.2 and /dev/null differ diff --git a/Contralto/ROM/30.2 b/Contralto/ROM/30.2 deleted file mode 100644 index e0b5c95..0000000 Binary files a/Contralto/ROM/30.2 and /dev/null differ diff --git a/Contralto/ROM/31.2 b/Contralto/ROM/31.2 deleted file mode 100644 index 56c950a..0000000 --- a/Contralto/ROM/31.2 +++ /dev/null @@ -1,3 +0,0 @@ -     -         -               \ No newline at end of file diff --git a/Contralto/ROM/32.2 b/Contralto/ROM/32.2 deleted file mode 100644 index 0b4094e..0000000 --- a/Contralto/ROM/32.2 +++ /dev/null @@ -1,28 +0,0 @@ - -   - -   - -     - - - -    -      -  - - -  - - -  -  -   - -  -  - -  -    - -   \ No newline at end of file diff --git a/Contralto/ROM/33.2 b/Contralto/ROM/33.2 deleted file mode 100644 index 8daf422..0000000 Binary files a/Contralto/ROM/33.2 and /dev/null differ diff --git a/Contralto/ROM/34.2 b/Contralto/ROM/34.2 deleted file mode 100644 index 496034a..0000000 Binary files a/Contralto/ROM/34.2 and /dev/null differ diff --git a/Contralto/ROM/35.2 b/Contralto/ROM/35.2 deleted file mode 100644 index abd0a6b..0000000 Binary files a/Contralto/ROM/35.2 and /dev/null differ diff --git a/Contralto/ROM/36.2 b/Contralto/ROM/36.2 deleted file mode 100644 index 1363d07..0000000 Binary files a/Contralto/ROM/36.2 and /dev/null differ diff --git a/Contralto/ROM/37.2 b/Contralto/ROM/37.2 deleted file mode 100644 index f21037c..0000000 Binary files a/Contralto/ROM/37.2 and /dev/null differ diff --git a/Contralto/ROM/4.2 b/Contralto/ROM/4.2 deleted file mode 100644 index 60cf83f..0000000 Binary files a/Contralto/ROM/4.2 and /dev/null differ diff --git a/Contralto/ROM/5.2 b/Contralto/ROM/5.2 deleted file mode 100644 index ef94e44..0000000 Binary files a/Contralto/ROM/5.2 and /dev/null differ diff --git a/Contralto/ROM/6.2 b/Contralto/ROM/6.2 deleted file mode 100644 index eb9fb29..0000000 Binary files a/Contralto/ROM/6.2 and /dev/null differ diff --git a/Contralto/ROM/7.2 b/Contralto/ROM/7.2 deleted file mode 100644 index bcb2e81..0000000 Binary files a/Contralto/ROM/7.2 and /dev/null differ diff --git a/Contralto/ROM/ACSOURCE.NEW b/Contralto/ROM/ACSOURCE.NEW new file mode 100644 index 0000000..a627611 Binary files /dev/null and b/Contralto/ROM/ACSOURCE.NEW differ diff --git a/Contralto/ROM/2kctl.u3 b/Contralto/ROM/ACSOURCE.OLD similarity index 100% rename from Contralto/ROM/2kctl.u3 rename to Contralto/ROM/ACSOURCE.OLD diff --git a/Contralto/ROM/AltoI/00_23.BIN b/Contralto/ROM/AltoI/00_23.BIN new file mode 100644 index 0000000..f7c0985 Binary files /dev/null and b/Contralto/ROM/AltoI/00_23.BIN differ diff --git a/Contralto/ROM/AltoI/01_23.BIN b/Contralto/ROM/AltoI/01_23.BIN new file mode 100644 index 0000000..fce814c --- /dev/null +++ b/Contralto/ROM/AltoI/01_23.BIN @@ -0,0 +1,5 @@ +  +  +      +          +  \ No newline at end of file diff --git a/Contralto/ROM/AltoI/02_23.BIN b/Contralto/ROM/AltoI/02_23.BIN new file mode 100644 index 0000000..7a2877a Binary files /dev/null and b/Contralto/ROM/AltoI/02_23.BIN differ diff --git a/Contralto/ROM/AltoI/03_23.BIN b/Contralto/ROM/AltoI/03_23.BIN new file mode 100644 index 0000000..1b2f987 Binary files /dev/null and b/Contralto/ROM/AltoI/03_23.BIN differ diff --git a/Contralto/ROM/AltoI/04_23.BIN b/Contralto/ROM/AltoI/04_23.BIN new file mode 100644 index 0000000..f951f39 Binary files /dev/null and b/Contralto/ROM/AltoI/04_23.BIN differ diff --git a/Contralto/ROM/AltoI/05_23.BIN b/Contralto/ROM/AltoI/05_23.BIN new file mode 100644 index 0000000..5467401 Binary files /dev/null and b/Contralto/ROM/AltoI/05_23.BIN differ diff --git a/Contralto/ROM/AltoI/06_23.BIN b/Contralto/ROM/AltoI/06_23.BIN new file mode 100644 index 0000000..294445f Binary files /dev/null and b/Contralto/ROM/AltoI/06_23.BIN differ diff --git a/Contralto/ROM/AltoI/07_23.BIN b/Contralto/ROM/AltoI/07_23.BIN new file mode 100644 index 0000000..71ffb8c Binary files /dev/null and b/Contralto/ROM/AltoI/07_23.BIN differ diff --git a/Contralto/ROM/AltoI/10_23.BIN b/Contralto/ROM/AltoI/10_23.BIN new file mode 100644 index 0000000..5a3bf2e Binary files /dev/null and b/Contralto/ROM/AltoI/10_23.BIN differ diff --git a/Contralto/ROM/AltoI/11_23.BIN b/Contralto/ROM/AltoI/11_23.BIN new file mode 100644 index 0000000..0718659 --- /dev/null +++ b/Contralto/ROM/AltoI/11_23.BIN @@ -0,0 +1,8 @@ +  +       +     + + +    + +       \ No newline at end of file diff --git a/Contralto/ROM/AltoI/12_23.BIN b/Contralto/ROM/AltoI/12_23.BIN new file mode 100644 index 0000000..707bc88 --- /dev/null +++ b/Contralto/ROM/AltoI/12_23.BIN @@ -0,0 +1,17 @@ +  +  +    +  + +  +  +   + + +  + + +      + +  + \ No newline at end of file diff --git a/Contralto/ROM/AltoI/13_23.BIN b/Contralto/ROM/AltoI/13_23.BIN new file mode 100644 index 0000000..b79e532 Binary files /dev/null and b/Contralto/ROM/AltoI/13_23.BIN differ diff --git a/Contralto/ROM/AltoI/14_23.BIN b/Contralto/ROM/AltoI/14_23.BIN new file mode 100644 index 0000000..e92be1f Binary files /dev/null and b/Contralto/ROM/AltoI/14_23.BIN differ diff --git a/Contralto/ROM/15.2 b/Contralto/ROM/AltoI/15_23.BIN similarity index 55% rename from Contralto/ROM/15.2 rename to Contralto/ROM/AltoI/15_23.BIN index ef36b00..a3955ef 100644 Binary files a/Contralto/ROM/15.2 and b/Contralto/ROM/AltoI/15_23.BIN differ diff --git a/Contralto/ROM/AltoI/16_23.BIN b/Contralto/ROM/AltoI/16_23.BIN new file mode 100644 index 0000000..0be5331 Binary files /dev/null and b/Contralto/ROM/AltoI/16_23.BIN differ diff --git a/Contralto/ROM/AltoI/17_23.BIN b/Contralto/ROM/AltoI/17_23.BIN new file mode 100644 index 0000000..960b1f7 Binary files /dev/null and b/Contralto/ROM/AltoI/17_23.BIN differ diff --git a/Contralto/ROM/AltoI/20_23.BIN b/Contralto/ROM/AltoI/20_23.BIN new file mode 100644 index 0000000..976c6a1 Binary files /dev/null and b/Contralto/ROM/AltoI/20_23.BIN differ diff --git a/Contralto/ROM/AltoI/21_23.BIN b/Contralto/ROM/AltoI/21_23.BIN new file mode 100644 index 0000000..cdc55dc --- /dev/null +++ b/Contralto/ROM/AltoI/21_23.BIN @@ -0,0 +1,4 @@ +   +                  +         +    \ No newline at end of file diff --git a/Contralto/ROM/22.2 b/Contralto/ROM/AltoI/22_23.BIN similarity index 64% rename from Contralto/ROM/22.2 rename to Contralto/ROM/AltoI/22_23.BIN index f766736..72f43c5 100644 Binary files a/Contralto/ROM/22.2 and b/Contralto/ROM/AltoI/22_23.BIN differ diff --git a/Contralto/ROM/AltoI/23_23.BIN b/Contralto/ROM/AltoI/23_23.BIN new file mode 100644 index 0000000..ed00bcc Binary files /dev/null and b/Contralto/ROM/AltoI/23_23.BIN differ diff --git a/Contralto/ROM/AltoI/24_23.BIN b/Contralto/ROM/AltoI/24_23.BIN new file mode 100644 index 0000000..bb5fa4c Binary files /dev/null and b/Contralto/ROM/AltoI/24_23.BIN differ diff --git a/Contralto/ROM/AltoI/25_23.BIN b/Contralto/ROM/AltoI/25_23.BIN new file mode 100644 index 0000000..53c61c2 --- /dev/null +++ b/Contralto/ROM/AltoI/25_23.BIN @@ -0,0 +1,11 @@ +                                     + + +   +    + + +  +  +  +    \ No newline at end of file diff --git a/Contralto/ROM/AltoI/26_23.BIN b/Contralto/ROM/AltoI/26_23.BIN new file mode 100644 index 0000000..d6fbbb5 Binary files /dev/null and b/Contralto/ROM/AltoI/26_23.BIN differ diff --git a/Contralto/ROM/AltoI/27_23.BIN b/Contralto/ROM/AltoI/27_23.BIN new file mode 100644 index 0000000..091ee0a Binary files /dev/null and b/Contralto/ROM/AltoI/27_23.BIN differ diff --git a/Contralto/ROM/AltoI/30_23.BIN b/Contralto/ROM/AltoI/30_23.BIN new file mode 100644 index 0000000..f9e0b05 Binary files /dev/null and b/Contralto/ROM/AltoI/30_23.BIN differ diff --git a/Contralto/ROM/AltoI/31_23.BIN b/Contralto/ROM/AltoI/31_23.BIN new file mode 100644 index 0000000..cb2bbfb --- /dev/null +++ b/Contralto/ROM/AltoI/31_23.BIN @@ -0,0 +1,3 @@ +         +         +           \ No newline at end of file diff --git a/Contralto/ROM/AltoI/32_23.BIN b/Contralto/ROM/AltoI/32_23.BIN new file mode 100644 index 0000000..d067eb3 --- /dev/null +++ b/Contralto/ROM/AltoI/32_23.BIN @@ -0,0 +1,35 @@ +  +  +  + + + +  + + + +   + +  +  +   + + + +    +      +  + + +  + + +  +  +   + + +      + + +   \ No newline at end of file diff --git a/Contralto/ROM/AltoI/33_23.BIN b/Contralto/ROM/AltoI/33_23.BIN new file mode 100644 index 0000000..5e452ef Binary files /dev/null and b/Contralto/ROM/AltoI/33_23.BIN differ diff --git a/Contralto/ROM/AltoI/34_23.BIN b/Contralto/ROM/AltoI/34_23.BIN new file mode 100644 index 0000000..386286a Binary files /dev/null and b/Contralto/ROM/AltoI/34_23.BIN differ diff --git a/Contralto/ROM/AltoI/35_23.BIN b/Contralto/ROM/AltoI/35_23.BIN new file mode 100644 index 0000000..1a47102 Binary files /dev/null and b/Contralto/ROM/AltoI/35_23.BIN differ diff --git a/Contralto/ROM/AltoI/36_23.BIN b/Contralto/ROM/AltoI/36_23.BIN new file mode 100644 index 0000000..555cd36 Binary files /dev/null and b/Contralto/ROM/AltoI/36_23.BIN differ diff --git a/Contralto/ROM/AltoI/37_23.BIN b/Contralto/ROM/AltoI/37_23.BIN new file mode 100644 index 0000000..8fced69 Binary files /dev/null and b/Contralto/ROM/AltoI/37_23.BIN differ diff --git a/Contralto/ROM/AltoI/C0_23.BIN b/Contralto/ROM/AltoI/C0_23.BIN new file mode 100644 index 0000000..302a6c1 Binary files /dev/null and b/Contralto/ROM/AltoI/C0_23.BIN differ diff --git a/Contralto/ROM/AltoI/C1_23.BIN b/Contralto/ROM/AltoI/C1_23.BIN new file mode 100644 index 0000000..1720ef5 Binary files /dev/null and b/Contralto/ROM/AltoI/C1_23.BIN differ diff --git a/Contralto/ROM/AltoI/C2_23.BIN b/Contralto/ROM/AltoI/C2_23.BIN new file mode 100644 index 0000000..7abb4fc Binary files /dev/null and b/Contralto/ROM/AltoI/C2_23.BIN differ diff --git a/Contralto/ROM/AltoI/C3_23.BIN b/Contralto/ROM/AltoI/C3_23.BIN new file mode 100644 index 0000000..2914418 Binary files /dev/null and b/Contralto/ROM/AltoI/C3_23.BIN differ diff --git a/Contralto/ROM/C0 b/Contralto/ROM/AltoII/C0 similarity index 100% rename from Contralto/ROM/C0 rename to Contralto/ROM/AltoII/C0 diff --git a/Contralto/ROM/C1 b/Contralto/ROM/AltoII/C1 similarity index 100% rename from Contralto/ROM/C1 rename to Contralto/ROM/AltoII/C1 diff --git a/Contralto/ROM/C2 b/Contralto/ROM/AltoII/C2 similarity index 100% rename from Contralto/ROM/C2 rename to Contralto/ROM/AltoII/C2 diff --git a/Contralto/ROM/C3 b/Contralto/ROM/AltoII/C3 similarity index 100% rename from Contralto/ROM/C3 rename to Contralto/ROM/AltoII/C3 diff --git a/Contralto/ROM/U52 b/Contralto/ROM/AltoII/U52 similarity index 100% rename from Contralto/ROM/U52 rename to Contralto/ROM/AltoII/U52 diff --git a/Contralto/ROM/U53 b/Contralto/ROM/AltoII/U53 similarity index 100% rename from Contralto/ROM/U53 rename to Contralto/ROM/AltoII/U53 diff --git a/Contralto/ROM/U54 b/Contralto/ROM/AltoII/U54 similarity index 100% rename from Contralto/ROM/U54 rename to Contralto/ROM/AltoII/U54 diff --git a/Contralto/ROM/U55 b/Contralto/ROM/AltoII/U55 similarity index 100% rename from Contralto/ROM/U55 rename to Contralto/ROM/AltoII/U55 diff --git a/Contralto/ROM/U60 b/Contralto/ROM/AltoII/U60 similarity index 100% rename from Contralto/ROM/U60 rename to Contralto/ROM/AltoII/U60 diff --git a/Contralto/ROM/U61 b/Contralto/ROM/AltoII/U61 similarity index 100% rename from Contralto/ROM/U61 rename to Contralto/ROM/AltoII/U61 diff --git a/Contralto/ROM/U62 b/Contralto/ROM/AltoII/U62 similarity index 100% rename from Contralto/ROM/U62 rename to Contralto/ROM/AltoII/U62 diff --git a/Contralto/ROM/U63 b/Contralto/ROM/AltoII/U63 similarity index 100% rename from Contralto/ROM/U63 rename to Contralto/ROM/AltoII/U63 diff --git a/Contralto/ROM/U64 b/Contralto/ROM/AltoII/U64 similarity index 100% rename from Contralto/ROM/U64 rename to Contralto/ROM/AltoII/U64 diff --git a/Contralto/ROM/U65 b/Contralto/ROM/AltoII/U65 similarity index 100% rename from Contralto/ROM/U65 rename to Contralto/ROM/AltoII/U65 diff --git a/Contralto/ROM/U70 b/Contralto/ROM/AltoII/U70 similarity index 100% rename from Contralto/ROM/U70 rename to Contralto/ROM/AltoII/U70 diff --git a/Contralto/ROM/U71 b/Contralto/ROM/AltoII/U71 similarity index 100% rename from Contralto/ROM/U71 rename to Contralto/ROM/AltoII/U71 diff --git a/Contralto/ROM/U72 b/Contralto/ROM/AltoII/U72 similarity index 100% rename from Contralto/ROM/U72 rename to Contralto/ROM/AltoII/U72 diff --git a/Contralto/ROM/U73 b/Contralto/ROM/AltoII/U73 similarity index 100% rename from Contralto/ROM/U73 rename to Contralto/ROM/AltoII/U73 diff --git a/Contralto/ROM/U74 b/Contralto/ROM/AltoII/U74 similarity index 100% rename from Contralto/ROM/U74 rename to Contralto/ROM/AltoII/U74 diff --git a/Contralto/ROM/U75 b/Contralto/ROM/AltoII/U75 similarity index 100% rename from Contralto/ROM/U75 rename to Contralto/ROM/AltoII/U75 diff --git a/Contralto/ROM/C0.2 b/Contralto/ROM/C0.2 deleted file mode 100644 index 5642219..0000000 Binary files a/Contralto/ROM/C0.2 and /dev/null differ diff --git a/Contralto/ROM/C1.2 b/Contralto/ROM/C1.2 deleted file mode 100644 index 582bfdc..0000000 Binary files a/Contralto/ROM/C1.2 and /dev/null differ diff --git a/Contralto/ROM/C2.2 b/Contralto/ROM/C2.2 deleted file mode 100644 index de596dd..0000000 Binary files a/Contralto/ROM/C2.2 and /dev/null differ diff --git a/Contralto/ROM/C3.2 b/Contralto/ROM/C3.2 deleted file mode 100644 index 609e959..0000000 Binary files a/Contralto/ROM/C3.2 and /dev/null differ diff --git a/Contralto/ROM/U52_2k b/Contralto/ROM/U52_2k deleted file mode 100644 index 5e85cc1..0000000 Binary files a/Contralto/ROM/U52_2k and /dev/null differ diff --git a/Contralto/ROM/U53_2k b/Contralto/ROM/U53_2k deleted file mode 100644 index de31481..0000000 Binary files a/Contralto/ROM/U53_2k and /dev/null differ diff --git a/Contralto/ROM/U54_2k b/Contralto/ROM/U54_2k deleted file mode 100644 index 1800c8c..0000000 Binary files a/Contralto/ROM/U54_2k and /dev/null differ diff --git a/Contralto/ROM/U55_2k b/Contralto/ROM/U55_2k deleted file mode 100644 index 4064bc8..0000000 Binary files a/Contralto/ROM/U55_2k and /dev/null differ diff --git a/Contralto/ROM/U60_2k b/Contralto/ROM/U60_2k deleted file mode 100644 index b229aef..0000000 Binary files a/Contralto/ROM/U60_2k and /dev/null differ diff --git a/Contralto/ROM/U61_2k b/Contralto/ROM/U61_2k deleted file mode 100644 index d151140..0000000 Binary files a/Contralto/ROM/U61_2k and /dev/null differ diff --git a/Contralto/ROM/U62_2k b/Contralto/ROM/U62_2k deleted file mode 100644 index a283def..0000000 Binary files a/Contralto/ROM/U62_2k and /dev/null differ diff --git a/Contralto/ROM/U63_2k b/Contralto/ROM/U63_2k deleted file mode 100644 index eccc858..0000000 Binary files a/Contralto/ROM/U63_2k and /dev/null differ diff --git a/Contralto/ROM/U64_2k b/Contralto/ROM/U64_2k deleted file mode 100644 index 4ca9317..0000000 Binary files a/Contralto/ROM/U64_2k and /dev/null differ diff --git a/Contralto/ROM/U65_2k b/Contralto/ROM/U65_2k deleted file mode 100644 index 9b4b584..0000000 Binary files a/Contralto/ROM/U65_2k and /dev/null differ diff --git a/Contralto/ROM/U70_2k b/Contralto/ROM/U70_2k deleted file mode 100644 index c6f6188..0000000 Binary files a/Contralto/ROM/U70_2k and /dev/null differ diff --git a/Contralto/ROM/U71_2k b/Contralto/ROM/U71_2k deleted file mode 100644 index b4d5676..0000000 Binary files a/Contralto/ROM/U71_2k and /dev/null differ diff --git a/Contralto/ROM/U72_2k b/Contralto/ROM/U72_2k deleted file mode 100644 index e89dd81..0000000 Binary files a/Contralto/ROM/U72_2k and /dev/null differ diff --git a/Contralto/ROM/U73_2k b/Contralto/ROM/U73_2k deleted file mode 100644 index 3e3f017..0000000 Binary files a/Contralto/ROM/U73_2k and /dev/null differ diff --git a/Contralto/ROM/U74_2k b/Contralto/ROM/U74_2k deleted file mode 100644 index 808d30d..0000000 Binary files a/Contralto/ROM/U74_2k and /dev/null differ diff --git a/Contralto/ROM/U75_2k b/Contralto/ROM/U75_2k deleted file mode 100644 index 87eed96..0000000 Binary files a/Contralto/ROM/U75_2k and /dev/null differ diff --git a/Contralto/Scheduler.cs b/Contralto/Scheduler.cs index c62a5b0..7d52dbb 100644 --- a/Contralto/Scheduler.cs +++ b/Contralto/Scheduler.cs @@ -14,7 +14,7 @@ namespace Contralto public delegate void SchedulerEventCallback(ulong timeNsec, ulong skewNsec, object context); /// - /// + /// An Event represents a callback and associated context that is scheduled for a future timestamp. /// public class Event { @@ -88,24 +88,20 @@ namespace Contralto // // See if we have any events waiting to fire at this timestep. - // - while (true) - { - if (_schedule.Top != null && _currentTimeNsec >= _schedule.Top.TimestampNsec) - { - // Pop the top event and fire the callback. - Event e = _schedule.Pop(); - e.EventCallback(_currentTimeNsec, _currentTimeNsec - e.TimestampNsec, e.Context); - } - else - { - // All done. - break; - } - } + // + while (_schedule.Top != null && _currentTimeNsec >= _schedule.Top.TimestampNsec) + { + // Pop the top event and fire the callback. + Event e = _schedule.Pop(); + e.EventCallback(_currentTimeNsec, _currentTimeNsec - e.TimestampNsec, e.Context); + } } - + /// + /// Add a new event to the schedule. + /// + /// + /// public Event Schedule(Event e) { e.TimestampNsec += _currentTimeNsec; @@ -114,6 +110,10 @@ namespace Contralto return e; } + /// + /// Remove an event from the schedule. + /// + /// public void CancelEvent(Event e) { _schedule.Remove(e); diff --git a/Contralto/UI/AltoWindow.Designer.cs b/Contralto/UI/AltoWindow.Designer.cs index 4d925f9..b7493a7 100644 --- a/Contralto/UI/AltoWindow.Designer.cs +++ b/Contralto/UI/AltoWindow.Designer.cs @@ -253,7 +253,7 @@ this.StatusLine.Size = new System.Drawing.Size(608, 25); this.StatusLine.TabIndex = 3; this.StatusLine.Text = "statusStrip1"; - this.StatusLine.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnKeyDown); + this.StatusLine.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnKeyDown); // // DiskStatusLabel //