From 6429c3ae7a27a7735e6f07e63ba0fa816e32102e Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Thu, 5 May 2016 18:56:29 -0700 Subject: [PATCH] General code cleanup. Fixed debugger display of RAM banks for 3K systems, cleaned up logic for displaying ucode memory. Implemented memory timing for Alto I systems, incorporated Alto I uCode ROMs from Al K, which now boot. ST-74 runs better now. --- Contralto/AltoSystem.cs | 4 +- Contralto/CPU/CPU.cs | 8 +- Contralto/CPU/ConstantMemory.cs | 86 ++--- Contralto/CPU/MicroInstruction.cs | 15 +- Contralto/CPU/Tasks/CursorTask.cs | 10 +- Contralto/CPU/Tasks/DiskTask.cs | 18 +- Contralto/CPU/Tasks/DisplayHorizontalTask.cs | 8 +- Contralto/CPU/Tasks/DisplayVerticalTask.cs | 9 +- Contralto/CPU/Tasks/EmulatorTask.cs | 60 +--- Contralto/CPU/Tasks/MemoryRefreshTask.cs | 2 +- Contralto/CPU/Tasks/Task.cs | 70 +++- Contralto/CPU/UCodeDisassembler.cs | 3 + Contralto/CPU/UCodeMemory.cs | 123 +++---- Contralto/Configuration.cs | 17 +- Contralto/Contralto.csproj | 161 ++++----- Contralto/Display/DisplayController.cs | 43 ++- Contralto/Display/IAltoDisplay.cs | 8 +- Contralto/IO/DiabloDrive.cs | 9 +- Contralto/IO/DiabloPack.cs | 12 +- Contralto/IO/DiskController.cs | 66 ++-- Contralto/IO/EthernetController.cs | 24 +- Contralto/IO/HostEthernetEncapsulation.cs | 24 +- Contralto/IO/IPacketEncapsulation.cs | 8 +- Contralto/IO/Keyboard.cs | 7 +- Contralto/IO/Mouse.cs | 8 +- Contralto/IO/UDPEncapsulation.cs | 3 - Contralto/Memory/Memory.cs | 4 + Contralto/Memory/MemoryBus.cs | 323 ++++++++++++------- Contralto/Program.cs | 3 +- Contralto/ROM/0.2 | Bin 256 -> 0 bytes Contralto/ROM/1.2 | Bin 256 -> 0 bytes Contralto/ROM/10.2 | Bin 256 -> 0 bytes Contralto/ROM/11.2 | 7 - Contralto/ROM/12.2 | 17 - Contralto/ROM/13.2 | Bin 256 -> 0 bytes Contralto/ROM/14.2 | Bin 256 -> 0 bytes Contralto/ROM/16.2 | Bin 256 -> 0 bytes Contralto/ROM/17.2 | Bin 256 -> 0 bytes Contralto/ROM/2.2 | Bin 256 -> 0 bytes Contralto/ROM/20.2 | Bin 256 -> 0 bytes Contralto/ROM/21.2 | 3 - Contralto/ROM/23.2 | Bin 256 -> 0 bytes Contralto/ROM/24.2 | Bin 256 -> 0 bytes Contralto/ROM/25.2 | Bin 256 -> 0 bytes Contralto/ROM/26.2 | Bin 256 -> 0 bytes Contralto/ROM/27.2 | Bin 256 -> 0 bytes Contralto/ROM/3.2 | Bin 256 -> 0 bytes Contralto/ROM/30.2 | Bin 256 -> 0 bytes Contralto/ROM/31.2 | 3 - Contralto/ROM/32.2 | 28 -- Contralto/ROM/33.2 | Bin 256 -> 0 bytes Contralto/ROM/34.2 | Bin 256 -> 0 bytes Contralto/ROM/35.2 | Bin 256 -> 0 bytes Contralto/ROM/36.2 | Bin 256 -> 0 bytes Contralto/ROM/37.2 | Bin 256 -> 0 bytes Contralto/ROM/4.2 | Bin 256 -> 0 bytes Contralto/ROM/5.2 | Bin 256 -> 0 bytes Contralto/ROM/6.2 | Bin 256 -> 0 bytes Contralto/ROM/7.2 | Bin 256 -> 0 bytes Contralto/ROM/ACSOURCE.NEW | Bin 0 -> 256 bytes Contralto/ROM/{2kctl.u3 => ACSOURCE.OLD} | Bin Contralto/ROM/AltoI/00_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/01_23.BIN | 5 + Contralto/ROM/AltoI/02_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/03_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/04_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/05_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/06_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/07_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/10_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/11_23.BIN | 8 + Contralto/ROM/AltoI/12_23.BIN | 17 + Contralto/ROM/AltoI/13_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/14_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/{15.2 => AltoI/15_23.BIN} | Bin 256 -> 256 bytes Contralto/ROM/AltoI/16_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/17_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/20_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/21_23.BIN | 4 + Contralto/ROM/{22.2 => AltoI/22_23.BIN} | Bin 256 -> 256 bytes Contralto/ROM/AltoI/23_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/24_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/25_23.BIN | 11 + Contralto/ROM/AltoI/26_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/27_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/30_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/31_23.BIN | 3 + Contralto/ROM/AltoI/32_23.BIN | 35 ++ Contralto/ROM/AltoI/33_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/34_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/35_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/36_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/37_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/C0_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/C1_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/C2_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/AltoI/C3_23.BIN | Bin 0 -> 256 bytes Contralto/ROM/{ => AltoII}/C0 | Bin Contralto/ROM/{ => AltoII}/C1 | Bin Contralto/ROM/{ => AltoII}/C2 | Bin Contralto/ROM/{ => AltoII}/C3 | Bin Contralto/ROM/{ => AltoII}/U52 | Bin Contralto/ROM/{ => AltoII}/U53 | Bin Contralto/ROM/{ => AltoII}/U54 | Bin Contralto/ROM/{ => AltoII}/U55 | Bin Contralto/ROM/{ => AltoII}/U60 | Bin Contralto/ROM/{ => AltoII}/U61 | Bin Contralto/ROM/{ => AltoII}/U62 | Bin Contralto/ROM/{ => AltoII}/U63 | Bin Contralto/ROM/{ => AltoII}/U64 | Bin Contralto/ROM/{ => AltoII}/U65 | Bin Contralto/ROM/{ => AltoII}/U70 | Bin Contralto/ROM/{ => AltoII}/U71 | Bin Contralto/ROM/{ => AltoII}/U72 | Bin Contralto/ROM/{ => AltoII}/U73 | Bin Contralto/ROM/{ => AltoII}/U74 | Bin Contralto/ROM/{ => AltoII}/U75 | Bin Contralto/ROM/C0.2 | Bin 256 -> 0 bytes Contralto/ROM/C1.2 | Bin 256 -> 0 bytes Contralto/ROM/C2.2 | Bin 256 -> 0 bytes Contralto/ROM/C3.2 | Bin 256 -> 0 bytes Contralto/ROM/U52_2k | Bin 1024 -> 0 bytes Contralto/ROM/U53_2k | Bin 1024 -> 0 bytes Contralto/ROM/U54_2k | Bin 1024 -> 0 bytes Contralto/ROM/U55_2k | Bin 1024 -> 0 bytes Contralto/ROM/U60_2k | Bin 1024 -> 0 bytes Contralto/ROM/U61_2k | Bin 1024 -> 0 bytes Contralto/ROM/U62_2k | Bin 1024 -> 0 bytes Contralto/ROM/U63_2k | Bin 1024 -> 0 bytes Contralto/ROM/U64_2k | Bin 1024 -> 0 bytes Contralto/ROM/U65_2k | Bin 1024 -> 0 bytes Contralto/ROM/U70_2k | Bin 1024 -> 0 bytes Contralto/ROM/U71_2k | Bin 1024 -> 0 bytes Contralto/ROM/U72_2k | Bin 1024 -> 0 bytes Contralto/ROM/U73_2k | Bin 1024 -> 0 bytes Contralto/ROM/U74_2k | Bin 1024 -> 0 bytes Contralto/ROM/U75_2k | Bin 1024 -> 0 bytes Contralto/Scheduler.cs | 34 +- Contralto/UI/AltoWindow.Designer.cs | 2 +- 139 files changed, 725 insertions(+), 588 deletions(-) delete mode 100644 Contralto/ROM/0.2 delete mode 100644 Contralto/ROM/1.2 delete mode 100644 Contralto/ROM/10.2 delete mode 100644 Contralto/ROM/11.2 delete mode 100644 Contralto/ROM/12.2 delete mode 100644 Contralto/ROM/13.2 delete mode 100644 Contralto/ROM/14.2 delete mode 100644 Contralto/ROM/16.2 delete mode 100644 Contralto/ROM/17.2 delete mode 100644 Contralto/ROM/2.2 delete mode 100644 Contralto/ROM/20.2 delete mode 100644 Contralto/ROM/21.2 delete mode 100644 Contralto/ROM/23.2 delete mode 100644 Contralto/ROM/24.2 delete mode 100644 Contralto/ROM/25.2 delete mode 100644 Contralto/ROM/26.2 delete mode 100644 Contralto/ROM/27.2 delete mode 100644 Contralto/ROM/3.2 delete mode 100644 Contralto/ROM/30.2 delete mode 100644 Contralto/ROM/31.2 delete mode 100644 Contralto/ROM/32.2 delete mode 100644 Contralto/ROM/33.2 delete mode 100644 Contralto/ROM/34.2 delete mode 100644 Contralto/ROM/35.2 delete mode 100644 Contralto/ROM/36.2 delete mode 100644 Contralto/ROM/37.2 delete mode 100644 Contralto/ROM/4.2 delete mode 100644 Contralto/ROM/5.2 delete mode 100644 Contralto/ROM/6.2 delete mode 100644 Contralto/ROM/7.2 create mode 100644 Contralto/ROM/ACSOURCE.NEW rename Contralto/ROM/{2kctl.u3 => ACSOURCE.OLD} (100%) create mode 100644 Contralto/ROM/AltoI/00_23.BIN create mode 100644 Contralto/ROM/AltoI/01_23.BIN create mode 100644 Contralto/ROM/AltoI/02_23.BIN create mode 100644 Contralto/ROM/AltoI/03_23.BIN create mode 100644 Contralto/ROM/AltoI/04_23.BIN create mode 100644 Contralto/ROM/AltoI/05_23.BIN create mode 100644 Contralto/ROM/AltoI/06_23.BIN create mode 100644 Contralto/ROM/AltoI/07_23.BIN create mode 100644 Contralto/ROM/AltoI/10_23.BIN create mode 100644 Contralto/ROM/AltoI/11_23.BIN create mode 100644 Contralto/ROM/AltoI/12_23.BIN create mode 100644 Contralto/ROM/AltoI/13_23.BIN create mode 100644 Contralto/ROM/AltoI/14_23.BIN rename Contralto/ROM/{15.2 => AltoI/15_23.BIN} (55%) create mode 100644 Contralto/ROM/AltoI/16_23.BIN create mode 100644 Contralto/ROM/AltoI/17_23.BIN create mode 100644 Contralto/ROM/AltoI/20_23.BIN create mode 100644 Contralto/ROM/AltoI/21_23.BIN rename Contralto/ROM/{22.2 => AltoI/22_23.BIN} (64%) create mode 100644 Contralto/ROM/AltoI/23_23.BIN create mode 100644 Contralto/ROM/AltoI/24_23.BIN create mode 100644 Contralto/ROM/AltoI/25_23.BIN create mode 100644 Contralto/ROM/AltoI/26_23.BIN create mode 100644 Contralto/ROM/AltoI/27_23.BIN create mode 100644 Contralto/ROM/AltoI/30_23.BIN create mode 100644 Contralto/ROM/AltoI/31_23.BIN create mode 100644 Contralto/ROM/AltoI/32_23.BIN create mode 100644 Contralto/ROM/AltoI/33_23.BIN create mode 100644 Contralto/ROM/AltoI/34_23.BIN create mode 100644 Contralto/ROM/AltoI/35_23.BIN create mode 100644 Contralto/ROM/AltoI/36_23.BIN create mode 100644 Contralto/ROM/AltoI/37_23.BIN create mode 100644 Contralto/ROM/AltoI/C0_23.BIN create mode 100644 Contralto/ROM/AltoI/C1_23.BIN create mode 100644 Contralto/ROM/AltoI/C2_23.BIN create mode 100644 Contralto/ROM/AltoI/C3_23.BIN rename Contralto/ROM/{ => AltoII}/C0 (100%) rename Contralto/ROM/{ => AltoII}/C1 (100%) rename Contralto/ROM/{ => AltoII}/C2 (100%) rename Contralto/ROM/{ => AltoII}/C3 (100%) rename Contralto/ROM/{ => AltoII}/U52 (100%) rename Contralto/ROM/{ => AltoII}/U53 (100%) rename Contralto/ROM/{ => AltoII}/U54 (100%) rename Contralto/ROM/{ => AltoII}/U55 (100%) rename Contralto/ROM/{ => AltoII}/U60 (100%) rename Contralto/ROM/{ => AltoII}/U61 (100%) rename Contralto/ROM/{ => AltoII}/U62 (100%) rename Contralto/ROM/{ => AltoII}/U63 (100%) rename Contralto/ROM/{ => AltoII}/U64 (100%) rename Contralto/ROM/{ => AltoII}/U65 (100%) rename Contralto/ROM/{ => AltoII}/U70 (100%) rename Contralto/ROM/{ => AltoII}/U71 (100%) rename Contralto/ROM/{ => AltoII}/U72 (100%) rename Contralto/ROM/{ => AltoII}/U73 (100%) rename Contralto/ROM/{ => AltoII}/U74 (100%) rename Contralto/ROM/{ => AltoII}/U75 (100%) delete mode 100644 Contralto/ROM/C0.2 delete mode 100644 Contralto/ROM/C1.2 delete mode 100644 Contralto/ROM/C2.2 delete mode 100644 Contralto/ROM/C3.2 delete mode 100644 Contralto/ROM/U52_2k delete mode 100644 Contralto/ROM/U53_2k delete mode 100644 Contralto/ROM/U54_2k delete mode 100644 Contralto/ROM/U55_2k delete mode 100644 Contralto/ROM/U60_2k delete mode 100644 Contralto/ROM/U61_2k delete mode 100644 Contralto/ROM/U62_2k delete mode 100644 Contralto/ROM/U63_2k delete mode 100644 Contralto/ROM/U64_2k delete mode 100644 Contralto/ROM/U65_2k delete mode 100644 Contralto/ROM/U70_2k delete mode 100644 Contralto/ROM/U71_2k delete mode 100644 Contralto/ROM/U72_2k delete mode 100644 Contralto/ROM/U73_2k delete mode 100644 Contralto/ROM/U74_2k delete mode 100644 Contralto/ROM/U75_2k 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 a42e7ebef19ac280585b346ab69f256062e380de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmZ9GQ4Rzl2t!Q}91!UJZ@XpYZ(od&(jw5fC!d7_NB}ssc=7SFcAf2OQ5$H8;PHr# zP<3UsMuVa!UWfubB)ri^(}dhdp)Z8cCag&y|6p$>&nSUym|bPS%w7dtL~egn-kUHH gqmg9Kt-85>aSP^lR5u&FH*!AXu(rd_d7ezGA5TsSq5uE@ diff --git a/Contralto/ROM/1.2 b/Contralto/ROM/1.2 deleted file mode 100644 index b2cf4b87e44899ca3a92eb93fae678f6653b2aa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmYL@i4FrH2t;djcM^;6|9{)ZY?B(~nj?I)q)}J#GT&W9WX0)zXv;5qsxW$!Z*R?o z&wi#vsbmC~1KiH+uKw|;?D8{k`KQ(*wMk5dwXsKc`U0(&wIpE(tBIiGE)lST>GUby TwM2C$O}0&uK?kXe2r3UyF4$J0yY z(?O<=(cva9^3gs;qBZqgkR52iW06nE{Mqv^JtCB5p_z|?KRJAPNR8am&YKxF#BI~u c#FqDK{CYNDTrs2OBxfzIKUK?FGP14t0%l_jRR910 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 5b5e7a9724d4767adf855047e9da05d021c050f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmXAk(H6iU2trvNWpDfczum>Crb3CcJ#PE45{D%NJ`JE+$cd~A9iN=g6{=il>`F{F zTS~l6tKAgKQj%b2f5>~EDT4KkZ`wrSbogotqR&cmbq K(+m~wJLwO%#|2ja diff --git a/Contralto/ROM/14.2 b/Contralto/ROM/14.2 deleted file mode 100644 index 821d423f251ab87b169af5877296494f6d6ea8c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmYk00S?0;3ynze7EHFz0CQgd zs2ID;C>eUs2^9!@aEEF&;*jGph>|mM3N8G=~#+gx5oZg8$Wr{ uHktD^4J|ZJ*gQ0s^u1ta?fXS_Jc;cIioY;i?3AJR@%liGtaS)DI?0#MWk?p*;y-T|O|q`iUuqHl9FTjJu50+}3AjHll}zTr(V?1uH! eCrL~9aSVKrVn>GPZL|cMIr&fIkE7N4J@y4fvM5VpeAMZUphSA3zTh;i1$%h}8UwU2 zuViF)G7lT}L5QoOVd*-lohC+pd}#H!Thi{R?E!eeOnU!jmXQz63V}SJnbHXT0L=LX A!vFvP diff --git a/Contralto/ROM/24.2 b/Contralto/ROM/24.2 deleted file mode 100644 index 375adb693e69c9bedcc262565ee05aaa75bf7e15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmZ{f+Y*2v2t*-;eP|~C|8Ls`tEU*{a=0i7Ak%^d2%Kf7w8@_&E0Be$Lf)!;p~Pa% zkMvL_U(dRfEw&*^!>Sp3)Z3tVUYqJAuk(2h7vgQxc0CtcX-RV7odT-BU)&L#7?Fp Hl88({$Px!} diff --git a/Contralto/ROM/27.2 b/Contralto/ROM/27.2 deleted file mode 100644 index a67a321714fb94f4d508a6e2d887da91a48322c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmX|*TMoo92m>KN2;|}W-*!p6>ZdjG*xY$FX@(JbVgkfXhN@e16+7_BdnHlvx%lu# z3l&jc$->9>Tu>8#_&!fxtyjienfv;}x@fQdpZn$Z^fBh1nzk2QTuF1W{{tagJ&Z9gA6C5LX{#Mx0ZKUc@TOy!?z+2MWs UtdC?5%)_6`zA8TL+egFUf diff --git a/Contralto/ROM/34.2 b/Contralto/ROM/34.2 deleted file mode 100644 index 496034a443fd4eb05c9ef1de8f302356d886ee01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmZvVjSd1a2!o5Teeu-o{ohu=oH-La!cR-t-Y0Mj36ZgkNf@gJDIf@G=v*kaR92*6 z^V((1tuAQ>%b`&#vnw(=Te3uTk@I6;C@TDqS-p z2oZ<)yeNSYE&7;G*cXLn!lEXIqvENnWpRlSpcue#PrtAo}lkTPvKg|5t?E*y12nZ}7HxUE~s)z`gu%aCKG-trT zm?fxp4CtbDiffi4=I-ixO4WMduPW@r-D4d W_x>qbv~wL1JF+}mM&`J`ZkZ1r$Oqy8 diff --git a/Contralto/ROM/37.2 b/Contralto/ROM/37.2 deleted file mode 100644 index f21037ccbd1a5ef0902f7ffc20f39068a37bac66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmX|*(UwIq1Vc-Ts^b6ucAWb#-m)Uu>HfbPFRPZqp^DQK6vZvHN#fl|vs+%>X3k} v!#yLMb2WB<{WtnOO0j}y8!nKHHXfYP@F)`Ro%AS*;5XcAS$r1wm$$4xDE$ZP diff --git a/Contralto/ROM/4.2 b/Contralto/ROM/4.2 deleted file mode 100644 index 60cf83fb8d6e6fb3b5dfb1d1e2e2b70f51de06a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmYL?ffj`z2t%=md&-ym|KB#AdD=l`uuU*; zK^dEl1()?H`@v}@*63gGOn@O&y70F5WSMN$ElWyf#OvE@Wh4#JQOwh5(H?z^(QrN z3Q%UqF*S8`<31pv2yny@(D=jDSSJ}L7AZH{c9*)`x2&~f@9kAGz7s2=s_+$bO~a&$ UHZyI=sai|&y|9$wp9fLu12w@4Qvd(} diff --git a/Contralto/ROM/6.2 b/Contralto/ROM/6.2 deleted file mode 100644 index eb9fb2930fc047336c8cb21978041083fcc13999..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmYjJ3l2ju2vX~3c2)0x+eeoz83`?-Fhs&6Lc~zSGebnvUl21aI20n{q2j*&;7e6q zGfh+7RL3r^x0d1cC4$+YJS6?XBJTK+j9O;-ee8DkW|LK!m9_Wmi{ASjU35-IRe{|R juRc8o9_TLNr@CfvfHdOig$+s?`IZ8Csy8KCtLFUx@K6Uf diff --git a/Contralto/ROM/7.2 b/Contralto/ROM/7.2 deleted file mode 100644 index bcb2e81687e5b3e0e0d6abb3a384a47d300e217f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmXv|35rEA2-CXPrT4$>_rXj+G^j})pa?se(@pD#=yAyU52L6wRVp1fd)^y4#G>ZQ ztMLJzU_)`e9X-BW?U@%Khl@{jX3|r)H=Mq(E&7JFP3Kbs|1CAkS9i}VxBKez=cf@2 uCkSHjtOsP1EC6!%Oo*5yRtB4|zkD}((?*CMG*{z`c(5)G(Rup_%mF{-q6aYm diff --git a/Contralto/ROM/ACSOURCE.NEW b/Contralto/ROM/ACSOURCE.NEW new file mode 100644 index 0000000000000000000000000000000000000000..a627611190821ed80f1d118464ba19765868764f GIT binary patch literal 256 zcmXZVQ5J+C3`0@0V!&Fn|J}|&^7T%8dZD#KN1%;W;Mh%k9U5y32ejcD*a{#o8ln1Un=iSh!~AS e@_eXnUSIPI4(>oV8@)GDxyyxjQGn;kwE6*FJqpeM literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..7a2877a13a95ce4ae5736dae6db915ece7624ba9 GIT binary patch literal 256 zcmZ9HQ4Yl*2m~8nDi!MP{crmQKTColE|Vo~*{PB;^u9b-rlw|9*&)f?>o$>O>%7DV zHD{^;_OLQZ%4JWQ%Brl8ceJ2K;Wm&mUukb-pJ>=7@o+P$z)KD(#ykuT@Eu`2fQ|_b c8ke5yYC9M?gjV6nqtLR3Ci_JFXdgy%|4?@fXaE2J literal 0 HcmV?d00001 diff --git a/Contralto/ROM/AltoI/03_23.BIN b/Contralto/ROM/AltoI/03_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..1b2f98711356f42972ed15df3451ce4d091b1778 GIT binary patch literal 256 zcmX9(2@bhdfT{YS&-#VaTot?V^-8^}bspwog($|i#QkxUKU6}I PmMjyf#tgaI0bl`Qn1Ff530np6Q;5-TP9zP8F{LmYH^k=XokR hA_^I%^jK7OV}I>%yJo~r_zOvS@S?N!a5^Wm&kOr-2UP$7 literal 0 HcmV?d00001 diff --git a/Contralto/ROM/AltoI/07_23.BIN b/Contralto/ROM/AltoI/07_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..71ffb8c7bd0e2773cb27c63e4e5bcf5ca5c01a0b GIT binary patch literal 256 zcmXv|NrD4G2-0>hOa1?EW6va9To7;o9|}mpK%|vS1ft4t*FB2}EO z<~SQmak8tPx0(k((4e7gN>&YXrcb7_6$$>ID1T-^*! literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..b79e53245b3eeb6d2ffa3239fb164f0e350edbfd GIT binary patch literal 256 zcmXAk(H6iU2trvNWpDfcza7_H8XCbGx7@ae`eYYqtjs8#$e;yj5eEq!A2P6uLAk=o zD)tqj)76jG{VoSX`)i{c8=SIcCI@vM2L?O`toe(Q^p*mfZ*@M&IW)5?kbjQN1W%bVxwxOa$ Jhg1p)Dj#Zq25tZV literal 0 HcmV?d00001 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 ef36b00b06136c7b3a99a563243df3ced63754e3..a3955ef68638246219cc744fc316d3cdfdff2045 100644 GIT binary patch literal 256 zcmXv|3l2je44S+|Q#yI~zwN*{{LxxyNs97DUTPMSfv}4k4puKNc>!9d7)mubXO5W| zfg>5Fxt*h0Y|FwLW_V1Uef?j1e1@GOXpYS-?W&q=qb!f>AJ0W*wTG>8Wr~Y4MFt={ V&9Cqq2zER&JNn<=6YSarpb|t!7+%5)(_HD)y*~>!5(lllk2P;DIfkp W+VOMX2uWhfhKC%=0V1Zg$MXffTM5Si diff --git a/Contralto/ROM/AltoI/16_23.BIN b/Contralto/ROM/AltoI/16_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..0be533172e28920cd46b00b4229adf2a3ccf6404 GIT binary patch literal 256 zcmXZWixveD2nEn|>2a0*|8M6sW+%0%1dH;A7)(9O#|9`rB_#V<$iwcg9V-o1VR@5~3~ literal 0 HcmV?d00001 diff --git a/Contralto/ROM/AltoI/20_23.BIN b/Contralto/ROM/AltoI/20_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..976c6a159c53cd3cd063ebfdcca540201086e3d6 GIT binary patch literal 256 zcmXAj3lak%3_|0yJMB&a-2b+H*+$Jr5$I&%PD&x>lNl<*Tgr7MN2hAMuTKKtl=)Ub zO<%_?+0sB1ontU;(@yIwAJBkkkO;J+PAk0w>p)Y+$mCTdE)bwRcDypMINzp1wI;En b5ocqwHdc(6|J`=`897&O540DHf@?&6>}?Cl literal 0 HcmV?d00001 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 f766736ae8044c40f35b8b42fc160dafb89c8012..72f43c5d396b672c3c7be87b9929b0efe263960c 100644 GIT binary patch delta 99 zcmWNIyA6Oq3`3fX1tR224g4E`152hTXsPwM5a`!5MUHWH%!zX@00W+ dm8g*&o2wiO5_Iny86mbw?zX?Xdeyuo<`0qD2f_dV delta 80 zcmYkyF$#b%3hGXqwYC=KX=$I>F>A6Xmr zs;Bt`*lXprjIEMNS3}@2(}Qg=dlGwGilSrFfvdqb<~lOH{~eJl@^K1*ego%_KGuc> A!T@Ft+2y_- zWvAv@AK&8s*M0#Ftqr^e`Y-Q5ABPXm`s*HW?>-aGo}9C<4XXy%+Ot3s;36wKsf^G_ H8pwPAy0Qmt literal 0 HcmV?d00001 diff --git a/Contralto/ROM/AltoI/27_23.BIN b/Contralto/ROM/AltoI/27_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..091ee0a4234e8ce64127a315918afd9b973686aa GIT binary patch literal 256 zcmX|+Ne%-b3K;E$+mb-IleK_vfAN)J>4Gv9D^!lRPR%@ qV<)^(-hbj6>eilb;>+VazkXc>*j|xkC$os%eQ!=9dVCtrp85a=;0Nyj literal 0 HcmV?d00001 diff --git a/Contralto/ROM/AltoI/30_23.BIN b/Contralto/ROM/AltoI/30_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..f9e0b050281bc0414e3df61b0b5b3a4806a4b296 GIT binary patch literal 256 zcmXAj2@(S#2m}`_5>o>6|KFx@y%?bxm1cyORPLjFt%>ZVAT+9(^7ww^2MFvD!$Jb= zb!c_pyVih*I?ZL0P5u_^Rrd)nic1GV2JBuNGmh4>shS~+wZ{fiM%5T!hxe<}lhK*Q dibA`UrIw&+2GlV$Upjs3QGV0 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5e452efab0e7705cf4d8ed841dbbc5150c2bb0f4 GIT binary patch literal 256 zcmXv}0S*Hp3?f-6UOjjJ|LtJQ)M8sm(dWrxi;zJw{;myPi`$fY=$RyDk2JNc;j+A% zq)=6KjLxkaSn{3*nnzVR(-|(k#fm}9(6Xe`w(?rvI*bz@hb?;|hFv%Zo~CV1I>5&M Zz4edM%cJsvM8^7U!4wF_H41#&WVS+V5-tK-i;TW{;y)ew_I6BH>4;ZmeCdF-ju&}5bzn*BW@!UP MlHV>#nx#?y9(|Tg}YBLNVJ1_q~uhw7h4Rn%a)XpIyg$6PAt#Xs~_OW_36UWw3_=;F;bTE?2|AXLvZscvUa+6fMobKx*g-p;rH$H@jkwc uk6DF=MWp2C5fQT@;NSOj_`9%E$z-204`iPufDop%t0-sv|IxU&>G%Wo&Ig46 literal 0 HcmV?d00001 diff --git a/Contralto/ROM/AltoI/C0_23.BIN b/Contralto/ROM/AltoI/C0_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..302a6c14d45916c8945735a6f9cbb5d4c4501840 GIT binary patch literal 256 zcmZ`yK@Pwm3_`bcW-;>r-wx`Gr*UX$ffgWyEGDQ`oP!Y^*Ffo{Rd(Pw)A1Fp$-<)1 z`jP^n?1mJ}e{j;5Y)XWFHx5)i<_U(?hqpyGwCPH>@6OzgL!S|FGZWPrM-!{h$@K*T C2L`>`JTz$N|5dX#U}K_54Ca^kgYR~*S{eKdKLgj S-*5o;dh>{gY<}V4ugnSWi3n`~ literal 0 HcmV?d00001 diff --git a/Contralto/ROM/AltoI/C2_23.BIN b/Contralto/ROM/AltoI/C2_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..7abb4fc2d2e8568f8993d85fcb53589ec9cc02ae GIT binary patch literal 256 zcmZ`!OA4xb4wD=|0K%TrJ)OPTyZV0fjyXpa1{> literal 0 HcmV?d00001 diff --git a/Contralto/ROM/AltoI/C3_23.BIN b/Contralto/ROM/AltoI/C3_23.BIN new file mode 100644 index 0000000000000000000000000000000000000000..291441815950ad3c485f288a029cef7ad0974750 GIT binary patch literal 256 zcmZ`zOA{~1G)Bhbm&%6MG%m=&x literal 0 HcmV?d00001 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 56422194193de7b05cf47343d828d73ce7eab6e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmZuqK@Pwm48oYjbx!&JZwK9smvKNU(2}5#WWh0{Q4mpi70wFSMJ4Z^iI4OROiYdT zmlX_kH{{6c%KpMlZ*nLRy4_GXbQqloy9Z92Xl!pP)1t4p>(pfi{a8tAjjM_EzLWU@ Djdci6 diff --git a/Contralto/ROM/C1.2 b/Contralto/ROM/C1.2 deleted file mode 100644 index 582bfdc17a6790469655ad348bfa72219e488330..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmZurTMmRU5JGEZv=8ooTN#b+&(dUQ31yHVBL_7^P6Z}_Q$Qs(5$e0C&^CSu*nqNH zO*ux!P-XNzq8#gs5yXLE?_cEVO!A5n_Yd;s^SC3c%Kq#`|9dLoEx4 TwQX9YXT7;bL^i+i@~_GTq80|C diff --git a/Contralto/ROM/C2.2 b/Contralto/ROM/C2.2 deleted file mode 100644 index de596dd997987c9d9ed2ca8593a2b9a230d96927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmZvXiwZ*_3`0}BUF53G|Nrgc1{;F~gg(-qDnS;A&8Z?!B8=9zbm!E@Yzmi=%f9pi8GiW4@R8(D a>knnzNgTc|?^qwYzhpl9t~dPL`>Q7nq6cvR diff --git a/Contralto/ROM/C3.2 b/Contralto/ROM/C3.2 deleted file mode 100644 index 609e9593576abccd2ecbfd2f96f36df047725355..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmZ`zOBMqm3__zu&4>HnwwdX&uPj&u0#MLwA_+c-Q*?PayiRjn2JMxAlFE0?m|?;` zuyvuR`(CEwnCKeRH;65|tur>}7C7+-8pwT+AQWs>;8oX2sTg0iXh?AZ?QuvG(K{LY fX4KaL(;F-mEvCwTz3H0M<<=L@h)Vp{|IYXT4-^Mg diff --git a/Contralto/ROM/U52_2k b/Contralto/ROM/U52_2k deleted file mode 100644 index 5e85cc17c79b84583779e73dfae0e1c099dfe714..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmZ9Kfs(@@2t@TXG7U4A|Nq;2yO{J^I@KV{0;>_NwFuTo*4x9u&5Tp~0#KIUMlJy5 zx8_)_N?PC8fBvRpJ54~jIq)(?NWB?7Uay>U^Hu`kA`x`TMBt+W#29X;qB;{u(274_ z&S{=fW5@6q_4T)LmTncV;= zj diff --git a/Contralto/ROM/U53_2k b/Contralto/ROM/U53_2k deleted file mode 100644 index de3148144889be76c1ad2aca6eb906c2bfec4e64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmZ9Lfwtoy2t=__IZe{||9|`L0JeLUril#WAgE^Mhd1YA&hs>%-kU#id<16RAMf7H zc#6jd^779Tk7)3n$?i>_OyBO8`HN@|^i6o0kq}5T8P?ctKmBZxQqXa19SK3h4o#0y zAS!r9biMu)JOtZ=LqJs2ofKcSdrB zlwJ10qM{}l70R5$Bmgvz2@U* zr(KCiYOp)kyZ1?0eIz#hq#UD8HU|%aUY|OR;%o)li6xRlI`@|PTDmk_6Q4TJ%oK4C gaAO&JdXP_DTu5{Ug~b(svnR#02Nj|;R9(LQ0GTxzL;wH) diff --git a/Contralto/ROM/U54_2k b/Contralto/ROM/U54_2k deleted file mode 100644 index 1800c8c824629839396e2d72be957c2521c072bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmX|vlmTMa>y|plUDb@QvY6^Un%T1^vDWWDl_K32ICY*(c z4T5pP_f!Hljhgk^EU$5Z=wcQQT{HScrvN$t@9~-~Yhtn8NQokhSgjS*SHGgoh(%Dw znxjQOe*Wc6Q5Dg&pWG0HLcUcNEuSaBZo!OxuA^&@Qt@{kT-RiVYD_)>NfV?y_j%O{ z$V=TVkVsrDfKQ9w(4^#{k}YXp$Xrc=1X$7Jx_7ts=8?&i()U6D-OFiGN?9hB`M_b} zmsLFjE%Zi$7y()GDSMadIX9Z(yLQ0ZorDo6yA^?d?KrnwH7c8B`PP8duwCxV!c~|` Y^`n|(FvMIh;%$iLqrqg=&hB0H5BB;g6#xJL diff --git a/Contralto/ROM/U55_2k b/Contralto/ROM/U55_2k deleted file mode 100644 index 4064bc862d071e86060037c731efb8688ced1d8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmY+D2@>2O3RBNK-} zbml!2iz^gL$I04NDBa)_Ap|SDlKZV6_y?1jwCZ!oFN{dT>aa8l(dFO+4OvmwQJYk^ ztd7}-e`3+3yGN)>0zz2PnfsBSWW+&-TrhTJh%36m;E0)9%|vMGzmlge+g8nJuDs~{ zx3Fs}D@6CB{bF?C_tqIlU7J$<2*+4C?bSK*Bk?au-;3L9Po;0`j1#)z5i3_ucw%rT zUe?I5&uaPd1n77xn?Q@n{70qx>L2&Et_;B5tZ(nwn^!Y9$&3k;vC{u`+e%G<1lji7 z`={7rHwaKe4s8|wA0=)+x#EG%o^zf7e$Gj!^%fys!;ct6jn-^!&Z_{zQy8O@EfInD WtwG`bIy0~FK^Su}eq+66)BgbFfGoiP diff --git a/Contralto/ROM/U60_2k b/Contralto/ROM/U60_2k deleted file mode 100644 index b229aefddd81338f2aa6f89eb752c0a736ee6cdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmYk436{e!2t&OjjSV)w|83`swC@e^!XgRMw3K3HjKyM)mHv`{DOQ?bjgpp#RRATU ztgidVm6r;tI)qWEBDuyTKgHi>KcMPw=M<8#Y!zY0x)4zNbtzYl(CLxXKtt!CK|viH zmmqmbm|(7*q&zf=h9U)TY2>-7HNOaYN4kYXNx^;x7O^j$JxQtS^}a4pk|+sHiQU+&TuEU zymeR|m+Vm^u+DspRH`^T=sHc7A`*)JwK+fL7zY9JI){rb4vrt3LoAWZkvPa=q6i?y zYu{`p1<r;Jv~?Yc1G?Zn6UD;x3{dy0q5Ye`wR*wNyP;)Yp|Nwaq@dWBi~to(Dge zlQbQRw0?PwwZ6>)X0~h-&9=jAoE)}~Ll}YJFdD=U5^&N7us(1JzHogUrD*x#<^N5W z_Zv~5HFf$YkVkVx(5Yhwm-LBUdix5XR|k6)Aipw9o9=VAS+~I*G@J&i4YLS!mx10^ z=N`jRfME1PP^a&(eN<=~IZVWoqC@7=vpc~%DL3?h`HQ1MX;`tkYPI7_NKc)xo}x=k z9)Y*C{&2Qk%a}C`eVo`6T`^go%XU7F=V|Ka9z*AS=GVTCdw5qZW?rykotF%oK<5Lm zfP?@b9rmsP#(_2Oy!=vdBupcJmQ>Pf)8nBrfaIs z;=M$b^V~kNif`?6bsFuwH!_-74)EwGUYvZsD)8M9m3lbjom(f7IO|orS(31?=#aq8Yp?%W-harN&3oq`EavjEx#kzlB)xe2TV}UC_+6a z?6&qMCQbObw~2aqih%79)|(c6wpV@k4bDkRn8mg?_tg_SfBF6KK^0HWjO~7ar%MNm z{O8O1?)lfJWr7CGypA61#sleL{MCbEypw+PT0eS04}SQM`AtT9UVOiJzq9e=AU+o0 zqNsZD)FG&!zxNRF)yMRke?=R7`tm_De4vB; zl|7l4x>_^v8ub|(l11GGd_>EJer2!!-7b@RP)`emAQe8ZpN*0Fwf;4v_jeQw=Ql5n z`5QbJJ^sLb^EEISMEuOHQ^NeSo`QOQ`r)xYz4X7o>GA!h26`&+9_Kiuiw?1Vhy z_4C-{segD+&u_j@@GLhw*Gn|93z(^eDJw7?IM?m5(B2bCFm)$=2VxDO@_qmQ0xPoO zLca?&ur5vG<->-!fFo87JB77Lza%1n@iTD$s3S0xp#RT2JLJw8poaFpU+&&FccCOK IY^d4Jf0>9LH2?qr diff --git a/Contralto/ROM/U63_2k b/Contralto/ROM/U63_2k deleted file mode 100644 index eccc8584ddb88d3167007ae12514d9f67cc9feeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmX|=fwsah2t(Oc%G})Z|Nr*ggepgE3xuRlBcfz;##42Tv$FEcn#E@1HFU0+W5gIE zpXVL#h;yEGUNwe3*G!lAt5i17ocu(@z%OvV&X7YPHu*TE=B4bo6T2SxN8MG(cp~ml zDOoR5B!>^nKP~Z>;%hi-#fu8cVX=ohaT4Jwz3`BOT_6@Ep;Uc|ipIJ)vCa}8>)3y4 zd^QTm%F<@RSeo)jLKB=vYaHy<=AuOuR%!-~jM^J^G{g~aT|+y$ob&hHfRjbOD6e`t zFQ+p#h{n(qJR4JDT`|pdrb|lbJ)xqU6F4@Ro)sPQ|7Og^QsNqNVxB%7c{oD9hga$ xK#fjU5UtvyUU-dqKI~3hv3(>)88tVQxKTdl;9C3x;DdA92K7E}*SeBq&wnyX7Ayb& diff --git a/Contralto/ROM/U64_2k b/Contralto/ROM/U64_2k deleted file mode 100644 index 4ca9317e901e5acd06161b4cc81b252022a057ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmX|=i?YNZ2t&73o2f7U|8MUJcCKSx1rj2%zuzyaq#7aS2x-My1q)VeSovnUy|p!> zM-5Fa#ljS0{rfkuTHBGtVQ0HcAJ0|?VJckBAtodw(VLSeDZi|04?w*tuOriE=W|7Q zK6U43qnw9)&>^Vl~qr33ta~vj4 z#QD7*9*|TvKtZu(a3Ii(<~$pjIS=UNy>V)~1*nZx&<1|6ce@uGwzhq*9CWcO7#A%I zBEcN32?4C`KRcWOY@tlPH5oCSnUY9MuiNF3APfhW1jqEho+z&|=>}CEX(B$=xa+<_ j)|1^SPlvP4d5$#9NlEtWTH+rA*KSn1%4)1T3O)7*FXt;Q diff --git a/Contralto/ROM/U65_2k b/Contralto/ROM/U65_2k deleted file mode 100644 index 9b4b584425691add220457433984ecfd71eb3f27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmZ9L+oJ0r2t?B~6$OO<|J%LB_PiY0Br3OI!0WoYtH(gFUyT|q@w~pPp zt1HXhrS2SU-Np*R7AJYNW!Zxok4_A>&Z2z`^enr#XWcFza=m5I?N5Cp1(CvI*K8b~ z8d*be$T|e7r&6D^LM)kgwz*Gbot4x3nKfgAD0}CeUDSYKhTvgeDBc}2qtSNO)BGbZ zmF{qHg_$i9WG00RI^I|W2TuwBc!7m4cTAVI4l9AW1T*6)rYzrUY$O<&{zK?4^0WbTT;nHt82XbFY@|AODWnc0KuUvOxr ztix+jE3qTGI8fX_gC{UO diff --git a/Contralto/ROM/U70_2k b/Contralto/ROM/U70_2k deleted file mode 100644 index c6f6188fcb203b058912e8f9b38e9276abfff21d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmZ9L+X9?02t*T7H9!LY|F=Cvw+|gx7h$*s9AjteyJt?%HCJYvd#1Qr@9w_#oNLbg z!N-4CZJApe0m|g*qe!`N{vkj3KVkf&Tx||ZQ!D>9ZM8o(r_LF=*1T_s70-?XafvzH zMdU4|QQS#W$pP%b@CJ@pkDq+hN2{unU(U94?X9s*cip->_wIe~3)#AMh(DMXBjCKy zE|38Fpu=3IN)Hh= z5fLlS`&WgNqzb%Fv6bo2hnU43*L|Da5t%izSo;zg)-UV!A}r`yOe`RlE^a{#3>;A2 zEJ@iaoCUsS9w84B!)J=Tl>YdekcjEoJDuUUys?gZT7~BNCdJ}K8td?bpSf`#kK0ddG8wf>|G3OwJ;iAM>;|D0kflV|h4RdFTU diff --git a/Contralto/ROM/U71_2k b/Contralto/ROM/U71_2k deleted file mode 100644 index b4d56760393bfbd52167aa7daf174742181fe8cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmZ8gi?S>!2*W221^)kUH`r%tt8RKwbksH>eJ=%3YY}3pb4HMo2HB#u!a`=Bv-kZ6 zyZ=CXr_9+B=s-mDKtHf${)_d4{m$FA@P-UsV%qzisj4YSs)m^7;J`Z1F|SzhhGFhr z;h4VH3UA~t-2~`w{4#7d?5Z5oxaP}<=;D_ki-#zCBkD+IYrP?=0j#$!Us`R9g8ffy z&=?q106Ev(Ah~m`hW;#%qRN|@|2Q+d6Nb!`XzEt)Msm(Uq90R`y&9(Z1Tj1K1MN1f zIuL6gM}j~-yrLT5pg(x_RgKc51bc9nSi16D<{L@$6l(+JKW#Gw1b`FZg+_Uv3VoCi z512*IB(g-F3iC-Z8pz+Vroku{3l3UbWp)HqSUckQ-X&fgp^$-xh+&bj@ZsbX{nLi_ zl~C(kb}H~yGd9!>CGLoT2w?pwhBi)@DEbcu=0(=;w;in$1w276l5kQv9io}{Oc*z{ zgs7y*Q@;xSW=-?BgaDJhobViQE$j$V6R2qV1to1 diff --git a/Contralto/ROM/U72_2k b/Contralto/ROM/U72_2k deleted file mode 100644 index e89dd8179fa78219534cf27eedd4a11fb924cb5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmZ8g!M0-|2m=H~5&8eWo#^e`Og25V7(znNaiL93JXNb6$ zf9ORl&8h$VVCB+)qTx->uH+JF>Sy?UKl60-D;ZmRe6xu5nf?AgBhTea%tJj#zx71_ ztIOAbbx^Ua`9}Mm2t)_fx~jp)@BQt!@##&%^x$zWJ71(W?%_4V zh1LcOb5m|UxmrSPvzJK(Z8l<;-@OzLs}FHDxICAEn6tR+Uq7w~#Xje`jkK!HoSEGJ z7^2U_Z3h&FMB*lqQXS7Wu&-4l7#m(7LSfX!c4~0_ZZ+UVwSuBPI`)nF^1-2I>_E-3 z*V;`oo!z5A<7ti)u(2zmD!U`Vfo+gx79#xeF8r5nrB_u+i|WM52#$IiVG~DPb;G(n yAHp^0c!%KfQr^3*opnyS;4ERV-h^_A)QbV?4yNh$!ht{YgtevCiY3prv^^lZYl>1A|a}bBeR#l*y)K7pWsGIR|v7U(;vos>8wc2n=A-L02w}QeyVkp&}#MWP_p%2jkaTpmSY(RxW-PO+?)73LtCEBTr|{D5~wVIzXdY$LhPrX6E?As(12Hj2$f zMU-&CJ%LrAAzZ;-i-LP_U!-v7UVYu2p;Qf{-m!kpd4h0*w5OkRn;-$oUls^3FLj$& Guzvx*LlTz& diff --git a/Contralto/ROM/U74_2k b/Contralto/ROM/U74_2k deleted file mode 100644 index 808d30dbcaf13cc18379a44afd4e182c0cc9d03a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmYL|fwtoy2t+rHc1{%K|Nr*g!SpO?ECPcAn9S5aC9ASGEwQttZOG;g-ZGZ$EGH;K z6_M@u4LjIrFfhMw?5maizwtRyGh==1TFYx4;v9A(vQFm0m13P%~q zF})d9DyFpZXSU=xr=>_us*yf}ZD?dX`Q?NvjezrH-uDowcWcBX<1(3EM%0-%c4CG} z27bFkZ4{2wYPwtAj%k-q54x<+L;PSVfe!7MIX!^N;H12vuNCCl>~7CMLk?qKF7lh& z$XPVzos>0uc4F+|Z|yx}2`;cYwzE}^E=&tThcJGQdxy9oXS439dow1|6D!a-f zclFMjx9xw&s@?7pg!1eJRCPL$R+;R{=3l;Q$9WyU4X`g>m38g7T}a6U-prcJEGZ{b z68OjvFoE~nS$E%@o@(8c32wY!Km$bps-Zi(`P;ue1m9bt@9MDp5K2KY7zvHmot}Di zp+;$!TTq}N@hn0Kdbm<0SKm-=$paK_J3AyH(H)2c+48>f;!yNxv3McGS5Mh2qcw`0 z6d(QggvWeQ1x;F&Fd{ZL#&@h$dbTxZ()+CVR-Fk&RjdFVWwwLb;|n@WCDv%7q9Ova zvPK)RG+zj;kwbpmn_c_tpAym3d%O(pzSf|6VR*yzAk?gEr;SFtl}Za= z|EuFX7Z)69$XZ$^?(Y>es*Zv0BJvVmnWGD37#Fz)k1n3oreplR-ZevU`vr%eUqtUs z#)v*m>6pxHCyXf;C1{52pB{LWlo@QnQ;g(;d iI7psp;fF&PP)CyafVk^?S|i2BBD%m26h6HG(*6f6NG%Zn 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 //