├── .gitattributes ├── .gitignore ├── Contralto.sln ├── Contralto ├── App.config ├── Contralto.cfg ├── Contralto.csproj ├── Disks │ ├── animation.dsk │ ├── bcpl.dsk │ ├── bravox54.dsk │ ├── diag.dsk │ ├── games.dsk │ ├── music.dsk │ ├── nonprog.dsk │ ├── spruce-server-t300.zip │ ├── spruce-server.dsk │ └── xmsmall.dsk ├── Program.cs ├── app.manifest ├── packages.config └── readme.txt ├── ContraltoLib ├── AltoSystem.cs ├── CPU │ ├── ALU.cs │ ├── CPU.cs │ ├── ConstantMemory.cs │ ├── MicroInstruction.cs │ ├── NovaDisassembler.cs │ ├── Shifter.cs │ ├── Tasks │ │ ├── CursorTask.cs │ │ ├── DiskTask.cs │ │ ├── DisplayHorizontalTask.cs │ │ ├── DisplayVerticalTask.cs │ │ ├── DisplayWordTask.cs │ │ ├── EmulatorTask.cs │ │ ├── EthernetTask.cs │ │ ├── MemoryRefreshTask.cs │ │ ├── OrbitTask.cs │ │ ├── ParityTask.cs │ │ ├── Task.cs │ │ └── TridentTask.cs │ ├── UCodeDisassembler.cs │ └── UCodeMemory.cs ├── Configuration.cs ├── ContraltoLib.csproj ├── Conversion.cs ├── Disassembly │ ├── MesaROM.mu │ ├── altoIIcode3.mu │ └── altocode24.mu ├── Display │ ├── DisplayController.cs │ └── IAltoDisplay.cs ├── ExecutionController.cs ├── HighResTimer.cs ├── IClockable.cs ├── IO │ ├── AudioDAC.cs │ ├── DiabloDrive.cs │ ├── DiskController.cs │ ├── DiskPack.cs │ ├── DoverROS.cs │ ├── EthernetController.cs │ ├── HostEthernetEncapsulation.cs │ ├── IAudioSink.cs │ ├── IPacketEncapsulation.cs │ ├── Keyboard.cs │ ├── MouseAndKeyset.cs │ ├── OrbitController.cs │ ├── OrganKeyboard.cs │ ├── Printing │ │ ├── IPageSink.cs │ │ ├── NullPageSink.cs │ │ └── PdfPageSink.cs │ ├── TridentController.cs │ ├── TridentDrive.cs │ └── UDPEncapsulation.cs ├── Logging │ └── Log.cs ├── Memory │ ├── IMemoryMappedDevice.cs │ ├── Memory.cs │ └── MemoryBus.cs ├── ROM │ ├── ACSOURCE.NEW │ ├── ACSOURCE.OLD │ ├── AltoI │ │ ├── 00_23.BIN │ │ ├── 01_23.BIN │ │ ├── 02_23.BIN │ │ ├── 03_23.BIN │ │ ├── 04_23.BIN │ │ ├── 05_23.BIN │ │ ├── 06_23.BIN │ │ ├── 07_23.BIN │ │ ├── 10_23.BIN │ │ ├── 11_23.BIN │ │ ├── 12_23.BIN │ │ ├── 13_23.BIN │ │ ├── 14_23.BIN │ │ ├── 15_23.BIN │ │ ├── 16_23.BIN │ │ ├── 17_23.BIN │ │ ├── 20_23.BIN │ │ ├── 21_23.BIN │ │ ├── 22_23.BIN │ │ ├── 23_23.BIN │ │ ├── 24_23.BIN │ │ ├── 25_23.BIN │ │ ├── 26_23.BIN │ │ ├── 27_23.BIN │ │ ├── 30_23.BIN │ │ ├── 31_23.BIN │ │ ├── 32_23.BIN │ │ ├── 33_23.BIN │ │ ├── 34_23.BIN │ │ ├── 35_23.BIN │ │ ├── 36_23.BIN │ │ ├── 37_23.BIN │ │ ├── C0_23.BIN │ │ ├── C1_23.BIN │ │ ├── C2_23.BIN │ │ └── C3_23.BIN │ └── AltoII │ │ ├── C0 │ │ ├── C1 │ │ ├── C2 │ │ ├── C3 │ │ ├── U52 │ │ ├── U53 │ │ ├── U54 │ │ ├── U55 │ │ ├── U60 │ │ ├── U61 │ │ ├── U62 │ │ ├── U63 │ │ ├── U64 │ │ ├── U65 │ │ ├── U70 │ │ ├── U71 │ │ ├── U72 │ │ ├── U73 │ │ ├── U74 │ │ └── U75 ├── Scheduler.cs └── Scripting │ ├── CommandExecutor.cs │ ├── ControlCommands.cs │ ├── DebuggerAttributes.cs │ ├── ScriptAction.cs │ ├── ScriptManager.cs │ ├── ScriptPlayback.cs │ ├── ScriptReader.cs │ ├── ScriptRecorder.cs │ └── ScriptWriter.cs ├── ContraltoUI ├── App.axaml ├── App.axaml.cs ├── Assets │ ├── Alto.ico │ └── DisplayCursor.png ├── ContraltoUI.csproj ├── Converters │ ├── BoolToWindowStateConverter.cs │ └── EnumToBoolConverter.cs ├── HighResolutionTimer.cs ├── SDLAudioSink.cs ├── ViewModels │ ├── AltoUIViewModel.cs │ ├── ConfigurationViewModel.cs │ ├── LogViewModel.cs │ └── ViewModelBase.cs └── Views │ ├── AboutDialog.axaml │ ├── AboutDialog.axaml.cs │ ├── AlternateBootDialog.axaml │ ├── AlternateBootDialog.axaml.cs │ ├── AltoDisplay.axaml │ ├── AltoDisplay.axaml.cs │ ├── ConfigurationDialog.axaml │ ├── ConfigurationDialog.axaml.cs │ ├── DebuggerWindow.axaml │ ├── DebuggerWindow.axaml.cs │ ├── LogWindow.axaml │ ├── LogWindow.axaml.cs │ ├── MainWindow.axaml │ └── MainWindow.axaml.cs ├── Directory.Build.props ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Contralto.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33627.172 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ContraltoUI", "ContraltoUI\ContraltoUI.csproj", "{E84024BF-708F-403A-8306-2D39BC8CA8E3}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Contralto", "Contralto\Contralto.csproj", "{32B69575-A26F-4B09-9C7A-228B9CCD1C27}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ContraltoLib", "ContraltoLib\ContraltoLib.csproj", "{F679C754-43AE-4199-B22B-460F8F3E0E52}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {E84024BF-708F-403A-8306-2D39BC8CA8E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {E84024BF-708F-403A-8306-2D39BC8CA8E3}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {E84024BF-708F-403A-8306-2D39BC8CA8E3}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {E84024BF-708F-403A-8306-2D39BC8CA8E3}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {32B69575-A26F-4B09-9C7A-228B9CCD1C27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {32B69575-A26F-4B09-9C7A-228B9CCD1C27}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {32B69575-A26F-4B09-9C7A-228B9CCD1C27}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {32B69575-A26F-4B09-9C7A-228B9CCD1C27}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {F679C754-43AE-4199-B22B-460F8F3E0E52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {F679C754-43AE-4199-B22B-460F8F3E0E52}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {F679C754-43AE-4199-B22B-460F8F3E0E52}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {F679C754-43AE-4199-B22B-460F8F3E0E52}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {A986B277-2686-4768-8F55-EDD68BA466DB} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Contralto/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Contralto/Contralto.cfg: -------------------------------------------------------------------------------- 1 | # contralto.cfg: 2 | # 3 | # This file contains configuration parameters for ContrAlto. 4 | # All integers are specified in octal. 5 | # 6 | 7 | # System configuration 8 | SystemType = TwoKRom 9 | HostAddress = 42 10 | 11 | # Host networking configuration 12 | HostPacketInterfaceType = None 13 | HostPacketInterfaceName = None 14 | 15 | # Emulation Options 16 | ThrottleSpeed = True 17 | BootAddress = 0 18 | BootFile = 0 19 | AlternateBootType = Ethernet 20 | 21 | # Display / Interface options 22 | KioskMode = False 23 | AllowKioskExit = True 24 | PauseWhenNotActive = False 25 | FullScreenStretch = False 26 | SlowPhosphorSimulation = True 27 | DisplayScale = 1 28 | 29 | # Printing options 30 | EnablePrinting = true 31 | PrintOutputPath = . 32 | ReversePageOrder = true 33 | 34 | # Disk options 35 | # 36 | 37 | # Diablo images: These specify a single image file for drive 0 and drive 1 38 | # 39 | Drive0Image = Disk\diag.dsk 40 | # Drive1Image = 41 | 42 | # Trident images: This specifies up to eight images for Trident drives 0 through 8 43 | # in a comma-delimited list. Empty entries are allowed, as below: 44 | # TridentImages = image0.dsk80, , image2.dsk300, image3.disk80 45 | -------------------------------------------------------------------------------- /Contralto/Contralto.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | WinExe 4 | 6 | net8.0 7 | enable 8 | true 9 | app.manifest 10 | Contralto.Program 11 | 2.0.0.0 12 | 2.0.0.0 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | PreserveNewest 31 | 32 | 33 | PreserveNewest 34 | 35 | 36 | PreserveNewest 37 | 38 | 39 | PreserveNewest 40 | 41 | 42 | PreserveNewest 43 | 44 | 45 | PreserveNewest 46 | 47 | 48 | PreserveNewest 49 | 50 | 51 | PreserveNewest 52 | 53 | 54 | PreserveNewest 55 | 56 | 57 | PreserveNewest 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | PreserveNewest 78 | 79 | 80 | 81 | 82 | 83 | PreserveNewest 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Contralto/Disks/animation.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/animation.dsk -------------------------------------------------------------------------------- /Contralto/Disks/bcpl.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/bcpl.dsk -------------------------------------------------------------------------------- /Contralto/Disks/bravox54.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/bravox54.dsk -------------------------------------------------------------------------------- /Contralto/Disks/diag.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/diag.dsk -------------------------------------------------------------------------------- /Contralto/Disks/games.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/games.dsk -------------------------------------------------------------------------------- /Contralto/Disks/music.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/music.dsk -------------------------------------------------------------------------------- /Contralto/Disks/nonprog.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/nonprog.dsk -------------------------------------------------------------------------------- /Contralto/Disks/spruce-server-t300.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/spruce-server-t300.zip -------------------------------------------------------------------------------- /Contralto/Disks/spruce-server.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/spruce-server.dsk -------------------------------------------------------------------------------- /Contralto/Disks/xmsmall.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/Contralto/Disks/xmsmall.dsk -------------------------------------------------------------------------------- /Contralto/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using System; 24 | 25 | using Avalonia; 26 | using Avalonia.ReactiveUI; 27 | using ContraltoUI; 28 | 29 | namespace Contralto; 30 | 31 | class Program 32 | { 33 | // Initialization code. Don't use any Avalonia, third-party APIs or any 34 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 35 | // yet and stuff might break. 36 | [STAThread] 37 | public static void Main(string[] args) 38 | { 39 | BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); 40 | } 41 | 42 | // Avalonia configuration, don't remove; also used by visual designer. 43 | public static AppBuilder BuildAvaloniaApp() 44 | => AppBuilder.Configure() 45 | .UsePlatformDetect() 46 | .UseReactiveUI() 47 | .LogToTrace(); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Contralto/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Contralto/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ContraltoLib/CPU/ALU.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using System.Runtime.CompilerServices; 24 | 25 | namespace Contralto.CPU 26 | { 27 | // 28 | // This implements the stripped-down version of the 74181 ALU 29 | // that the Alto exposes to the microcode, and nothing more. 30 | // 31 | static class ALU 32 | { 33 | static ALU() 34 | { 35 | Reset(); 36 | } 37 | 38 | public static void Reset() 39 | { 40 | _carry = 0; 41 | } 42 | 43 | public static int Carry 44 | { 45 | get { return _carry; } 46 | set { _carry = value; } 47 | } 48 | 49 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 50 | public static ushort Execute(AluFunction fn, ushort bus, ushort t, int skip) 51 | { 52 | int r; 53 | switch (fn) 54 | { 55 | case AluFunction.Bus: 56 | _carry = 0; // M = 1 57 | r = bus; 58 | break; 59 | 60 | case AluFunction.T: 61 | _carry = 0; // M = 1 62 | r = t; 63 | break; 64 | 65 | case AluFunction.BusOrT: 66 | _carry = 0; // M = 1 67 | r = (bus | t); 68 | break; 69 | 70 | case AluFunction.BusAndT: 71 | case AluFunction.AluBusAndT: 72 | _carry = 0; // M = 1 73 | r = (bus & t); 74 | break; 75 | 76 | case AluFunction.BusXorT: 77 | _carry = 0; // M = 1 78 | r = (bus ^ t); 79 | break; 80 | 81 | case AluFunction.BusPlus1: 82 | r = bus + 1; 83 | _carry = (r > 0xffff) ? 1 : 0; 84 | break; 85 | 86 | case AluFunction.BusMinus1: 87 | r = bus - 1; 88 | 89 | // Just for clarification; the datasheet specifies: 90 | // "Because subtraction is actually performed by complementary 91 | // addition (1s complement), a carry out means borrow; thus, 92 | // a carry is generated when there is no underflow and no carry 93 | // is generated when there is underflow." 94 | _carry = (r < 0) ? 0 : 1; 95 | break; 96 | 97 | case AluFunction.BusPlusT: 98 | r = bus + t; 99 | _carry = (r > 0xffff) ? 1 : 0; 100 | break; 101 | 102 | case AluFunction.BusMinusT: 103 | r = bus - t; 104 | _carry = (r < 0) ? 0 : 1; 105 | break; 106 | 107 | case AluFunction.BusMinusTMinus1: 108 | r = bus - t - 1; 109 | _carry = (r < 0) ? 0 : 1; 110 | break; 111 | 112 | case AluFunction.BusPlusTPlus1: 113 | r = bus + t + 1; 114 | _carry = (r > 0xffff) ? 1 : 0; 115 | break; 116 | 117 | case AluFunction.BusPlusSkip: 118 | r = bus + skip; 119 | _carry = (r > 0xffff) ? 1 : 0; 120 | break; 121 | 122 | case AluFunction.BusAndNotT: 123 | r = bus & (~t); 124 | _carry = 0; 125 | break; 126 | 127 | default: 128 | throw new InvalidOperationException(String.Format("Unhandled ALU function {0}", fn)); 129 | } 130 | 131 | return (ushort)r; 132 | } 133 | 134 | private static int _carry; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /ContraltoLib/CPU/Tasks/CursorTask.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.CPU 24 | { 25 | public partial class AltoCPU 26 | { 27 | /// 28 | /// CursorTask provides the implementation of Cursor-specific task functions 29 | /// 30 | private sealed class CursorTask : Task 31 | { 32 | public CursorTask(AltoCPU cpu) : base(cpu) 33 | { 34 | _taskType = TaskType.Cursor; 35 | _wakeup = false; 36 | } 37 | 38 | public override void OnTaskSwitch() 39 | { 40 | // We put ourselves back to sleep immediately once we've started running. 41 | _wakeup = false; 42 | } 43 | 44 | protected override void ExecuteSpecialFunction2(MicroInstruction instruction) 45 | { 46 | CursorF2 cf2 = (CursorF2)instruction.F2; 47 | switch (cf2) 48 | { 49 | case CursorF2.LoadXPREG: 50 | // Load cursor X-position register from bus 51 | _cpu._system.DisplayController.LoadXPREG(_busData); 52 | break; 53 | 54 | case CursorF2.LoadCSR: 55 | // Load cursor shift register from bus 56 | _cpu._system.DisplayController.LoadCSR(_busData); 57 | break; 58 | 59 | default: 60 | throw new InvalidOperationException(String.Format("Unhandled cursor F2 {0}.", cf2)); 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ContraltoLib/CPU/Tasks/DisplayHorizontalTask.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.Display; 24 | 25 | namespace Contralto.CPU 26 | { 27 | public partial class AltoCPU 28 | { 29 | /// 30 | /// DisplayHorizontalTask provides implementations of the DHT task functions. 31 | /// 32 | private sealed class DisplayHorizontalTask : Task 33 | { 34 | public DisplayHorizontalTask(AltoCPU cpu) : base(cpu) 35 | { 36 | _taskType = TaskType.DisplayHorizontal; 37 | _wakeup = false; 38 | 39 | _displayController = _cpu._system.DisplayController; 40 | } 41 | 42 | public override void OnTaskSwitch() 43 | { 44 | // We put ourselves back to sleep immediately once we've started running. 45 | _wakeup = false; 46 | } 47 | 48 | protected override void ExecuteSpecialFunction2(MicroInstruction instruction) 49 | { 50 | DisplayHorizontalF2 dh2 = (DisplayHorizontalF2)instruction.F2; 51 | switch (dh2) 52 | { 53 | case DisplayHorizontalF2.EVENFIELD: 54 | _nextModifier |= (ushort)(_displayController.EVENFIELD ? 1 : 0); 55 | break; 56 | 57 | case DisplayHorizontalF2.SETMODE: 58 | // "If bit 0 = 1, the bit clock rate is set to 100ns period (at the start of the next scan line), 59 | // and a 1 is merged into NEXT[9]." 60 | _displayController.SETMODE(_busData); 61 | 62 | if ((_busData & 0x8000) != 0) 63 | { 64 | _nextModifier |= 1; 65 | } 66 | break; 67 | 68 | default: 69 | throw new InvalidOperationException(String.Format("Unhandled display word F2 {0}.", dh2)); 70 | } 71 | } 72 | 73 | protected override void ExecuteBlock() 74 | { 75 | _displayController.DHTBLOCK = true; 76 | } 77 | 78 | private DisplayController _displayController; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /ContraltoLib/CPU/Tasks/DisplayVerticalTask.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.Display; 24 | 25 | namespace Contralto.CPU 26 | { 27 | public partial class AltoCPU 28 | { 29 | /// 30 | /// DisplayVerticalTask provides functionality for the DVT task 31 | /// 32 | private sealed class DisplayVerticalTask : Task 33 | { 34 | public DisplayVerticalTask(AltoCPU cpu) : base(cpu) 35 | { 36 | _taskType = TaskType.DisplayVertical; 37 | _wakeup = false; 38 | 39 | _displayController = _cpu._system.DisplayController; 40 | } 41 | 42 | public override void OnTaskSwitch() 43 | { 44 | // We put ourselves back to sleep immediately once we've started running. 45 | _wakeup = false; 46 | } 47 | 48 | protected override void ExecuteSpecialFunction2(MicroInstruction instruction) 49 | { 50 | DisplayVerticalF2 dv2 = (DisplayVerticalF2)instruction.F2; 51 | switch (dv2) 52 | { 53 | case DisplayVerticalF2.EVENFIELD: 54 | _nextModifier |= (ushort)(_displayController.EVENFIELD ? 1 : 0); 55 | break; 56 | 57 | default: 58 | throw new InvalidOperationException(String.Format("Unhandled display vertical F2 {0}.", dv2)); 59 | } 60 | } 61 | 62 | private DisplayController _displayController; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ContraltoLib/CPU/Tasks/DisplayWordTask.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.Display; 24 | 25 | 26 | namespace Contralto.CPU 27 | { 28 | public partial class AltoCPU 29 | { 30 | /// 31 | /// DisplayWordTask provides functionality for the DWT task 32 | /// 33 | private sealed class DisplayWordTask : Task 34 | { 35 | public DisplayWordTask(AltoCPU cpu) : base(cpu) 36 | { 37 | _taskType = TaskType.DisplayWord; 38 | _wakeup = false; 39 | 40 | _displayController = _cpu._system.DisplayController; 41 | } 42 | 43 | protected override void ExecuteSpecialFunction2(MicroInstruction instruction) 44 | { 45 | DisplayWordF2 dw2 = (DisplayWordF2)instruction.F2; 46 | switch (dw2) 47 | { 48 | case DisplayWordF2.LoadDDR: 49 | _displayController.LoadDDR(_busData); 50 | break; 51 | 52 | default: 53 | throw new InvalidOperationException(String.Format("Unhandled display word F2 {0}.", dw2)); 54 | } 55 | } 56 | 57 | protected override void ExecuteBlock() 58 | { 59 | _displayController.DWTBLOCK = true; 60 | 61 | // 62 | // Wake up DHT if it has not blocked itself. 63 | // 64 | if (!_displayController.DHTBLOCK) 65 | { 66 | _cpu.WakeupTask(TaskType.DisplayHorizontal); 67 | } 68 | } 69 | 70 | private DisplayController _displayController; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ContraltoLib/CPU/Tasks/MemoryRefreshTask.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.CPU 24 | { 25 | public partial class AltoCPU 26 | { 27 | /// 28 | /// DisplayWordTask provides functionality for the Memory Refresh task. 29 | /// 30 | private sealed class MemoryRefreshTask : Task 31 | { 32 | public MemoryRefreshTask(AltoCPU cpu) : base(cpu) 33 | { 34 | _taskType = TaskType.MemoryRefresh; 35 | 36 | _wakeup = false; 37 | } 38 | 39 | protected override void ExecuteSpecialFunction1Early(MicroInstruction instruction) 40 | { 41 | // 42 | // Based on readings of the below MRT microcode comment, the MRT keeps its wakeup 43 | // until it executes a BLOCK on Alto IIs. (i.e. no special wakeup handling at all.) 44 | // On Alto Is, this was accomplished by doing an MAR <- R37. 45 | // 46 | // "; This version assumes MRTACT is cleared by BLOCK, not MAR<- R37" 47 | // 48 | if (_systemType == SystemType.AltoI && 49 | instruction.F1 == SpecialFunction1.LoadMAR && 50 | _rSelect == 31) 51 | { 52 | BlockTask(); 53 | } 54 | 55 | base.ExecuteSpecialFunction1Early(instruction); 56 | } 57 | 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ContraltoLib/CPU/Tasks/ParityTask.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.CPU 24 | { 25 | public partial class AltoCPU 26 | { 27 | /// 28 | /// ParityTask is provided for completeness only, and implements the logic for the Parity task. 29 | /// The Parity Task will never actually be woken because I'm not planning on emulating faulty memory. 30 | /// 31 | private sealed class ParityTask : Task 32 | { 33 | public ParityTask(AltoCPU cpu) : base(cpu) 34 | { 35 | _taskType = TaskType.Parity; 36 | _wakeup = false; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ContraltoLib/Conversion.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto 24 | { 25 | public static class Conversion 26 | { 27 | public static string ToOctal(int i) 28 | { 29 | return Convert.ToString(i, 8); 30 | } 31 | 32 | public static string ToOctal(sbyte s) 33 | { 34 | if (s < 0) 35 | { 36 | return "-" + Convert.ToString(-s, 8); 37 | } 38 | else 39 | { 40 | return Convert.ToString(s, 8); 41 | } 42 | } 43 | 44 | public static string ToOctal(int i, int digits) 45 | { 46 | string octalString = Convert.ToString(i, 8); 47 | return new String('0', digits - octalString.Length) + octalString; 48 | } 49 | 50 | /// 51 | /// Conversion from millseconds to nanoseconds 52 | /// 53 | public static readonly ulong MsecToNsec = 1000000; 54 | 55 | /// 56 | /// Conversion from nanoseconds to milliseconds 57 | /// 58 | public static readonly double NsecToMsec = 0.000001; 59 | 60 | /// 61 | /// Conversion from microseconds to nanoseconds 62 | /// 63 | public static readonly ulong UsecToNsec = 1000; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ContraltoLib/Display/IAltoDisplay.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.Display 24 | { 25 | /// 26 | /// IAltoDisplay defines the interface necessary for generating and rendering the Alto's 27 | /// bitmapped display. 28 | /// 29 | public interface IAltoDisplay 30 | { 31 | 32 | /// 33 | /// Renders a word's worth of data to the specified scanline and word offset. 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | void DrawDisplayWord(int scanline, int wordOffset, ushort dataWord, bool lowRes); 40 | 41 | /// 42 | /// Renders the cursor word for the specified scanline. 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | void DrawCursorWord(int scanline, int xOffset, bool whiteOnBlack, ushort cursorWord); 49 | 50 | /// 51 | /// Indicates that an entire frame is ready for display and should be rendered. 52 | /// 53 | void Render(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ContraltoLib/IClockable.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto 24 | { 25 | /// 26 | /// Used by classes implementing devices that are clocked (i.e. that are dependent 27 | /// on time passing in units of a single CPU clock.) 28 | /// 29 | public interface IClockable 30 | { 31 | void Clock(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ContraltoLib/IO/AudioDAC.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.CPU; 24 | using Contralto.Memory; 25 | 26 | namespace Contralto.IO 27 | { 28 | /// 29 | /// Implements the hardware for the Audio DAC used by Ted Kaehler's 30 | /// ST-74 Music System (either the FM-synthesis "TWANG" system or the 31 | /// Sampling system.) 32 | /// 33 | public class AudioDAC : IMemoryMappedDevice 34 | { 35 | public AudioDAC() 36 | { 37 | 38 | } 39 | 40 | public void AttachSink(IAudioSink sink) 41 | { 42 | _audioSink = sink; 43 | } 44 | 45 | public void Shutdown() 46 | { 47 | if (_audioSink != null) 48 | { 49 | _audioSink.Shutdown(); 50 | } 51 | } 52 | 53 | /// 54 | /// Comments in the FM synthesis microcode indicate: 55 | /// "240 SAMPLES = 18 msec" 56 | /// Which works out to about 13.3333...Khz. 57 | /// 58 | /// Unsure if this value also applies to the Sampling microcode, but 59 | /// it sounds about right in action. 60 | /// 61 | /// TODO: This is set to 13.3Khz below to allow audio production to keep up with 62 | /// the consumption on the host output side; this may be an indication that our 63 | /// execution frequency is slightly off. This should be investigated. 64 | /// 65 | public static readonly int AudioDACSamplingRate = 13000; 66 | 67 | /// 68 | /// Reads a word from the specified address. 69 | /// 70 | /// 71 | /// 72 | /// 73 | public ushort Read(int address, TaskType task, bool extendedMemory) 74 | { 75 | // The DAC is, as far as I can tell, write-only. 76 | return 0; 77 | } 78 | 79 | /// 80 | /// Writes a word to the specified address. 81 | /// 82 | /// 83 | /// 84 | public void Load(int address, ushort data, TaskType task, bool extendedMemory) 85 | { 86 | if (_audioSink != null) 87 | { 88 | _audioSink.WriteSample(data); 89 | } 90 | } 91 | 92 | /// 93 | /// Specifies the range (or ranges) of addresses decoded by this device. 94 | /// 95 | public MemoryRange[] Addresses 96 | { 97 | get { return _addresses; } 98 | } 99 | 100 | /// 101 | /// From: http://bitsavers.org/pdf/xerox/alto/memos_1975/Reserved_Alto_Memory_Locations_Jan75.pdf 102 | /// 103 | /// #177776: Digital-Analog Converter (DAC Hardware - Kaehler) 104 | /// 105 | private readonly MemoryRange[] _addresses = 106 | { 107 | new MemoryRange(0xfffe, 0xfffe), 108 | }; 109 | 110 | private IAudioSink? _audioSink; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /ContraltoLib/IO/IAudioSink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Contralto.IO 8 | { 9 | /// 10 | /// IAudioSink provides a method for outputting audio samples to a variety of targets. 11 | /// 12 | public interface IAudioSink 13 | { 14 | /// 15 | /// Writes a single audio sample to the sink. 16 | /// 17 | /// 18 | void WriteSample(ushort sample); 19 | 20 | void Shutdown(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ContraltoLib/IO/IPacketEncapsulation.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.IO 24 | { 25 | public delegate void ReceivePacketDelegate(MemoryStream data); 26 | 27 | /// 28 | /// Provides a generic interface for host network devices that can encapsulate 29 | /// Alto ethernet packets. 30 | /// 31 | public interface IPacketEncapsulation 32 | { 33 | /// 34 | /// Registers a callback delegate to handle packets that are received. 35 | /// 36 | /// 37 | void RegisterReceiveCallback(ReceivePacketDelegate callback); 38 | 39 | /// 40 | /// Sends the specified word array over the device. 41 | /// 42 | /// 43 | /// 44 | void Send(ushort[] packet, int length); 45 | 46 | /// 47 | /// Shuts down the encapsulation provider. 48 | /// 49 | void Shutdown(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ContraltoLib/IO/OrganKeyboard.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.CPU; 24 | using Contralto.Logging; 25 | using Contralto.Memory; 26 | 27 | namespace Contralto.IO 28 | { 29 | /// 30 | /// Implements the Organ Keyboard interface used by the ST-74 31 | /// Music System. Very little is known about the hardware at this time, 32 | /// so most of this is speculation or based on disassembly/reverse-engineering 33 | /// of the music system code. 34 | /// 35 | /// This is currently a stub that implements the bare minimum to make the 36 | /// music system think there's a keyboard attached to the system. 37 | /// 38 | public class OrganKeyboard : IMemoryMappedDevice 39 | { 40 | public OrganKeyboard(AltoSystem system) 41 | { 42 | _system = system; 43 | Reset(); 44 | } 45 | 46 | public void Reset() 47 | { 48 | // 49 | // Initialize keyboard registers. 50 | // Based on disassembly of the Nova code that drives the keyboard 51 | // interface, the top 6 bits are active low. 52 | // 53 | for (int i = 0; i < 16; i++) 54 | { 55 | _keyData[i] = (ushort)(0xfc00); 56 | } 57 | } 58 | 59 | /// 60 | /// Reads a word from the specified address. 61 | /// 62 | /// 63 | /// 64 | /// 65 | public ushort Read(int address, TaskType task, bool extendedMemory) 66 | { 67 | 68 | Log.Write(LogType.Verbose, LogComponent.Organ, "Organ read from {0} by task {1} (bank {2}), Nova PC {3}", 69 | Conversion.ToOctal(address), 70 | task, 71 | _system.CPU.UCodeMemory.GetBank(task), 72 | Conversion.ToOctal(_system.CPU.R[6])); 73 | 74 | return _keyData[address - 0xfe60]; 75 | 76 | } 77 | 78 | /// 79 | /// Writes a word to the specified address. 80 | /// 81 | /// 82 | /// 83 | public void Load(int address, ushort data, TaskType task, bool extendedMemory) 84 | { 85 | 86 | // The registers are write-only as far as I've been able to ascertain. 87 | Log.Write(LogType.Verbose, LogComponent.Organ, "Unexpected organ write to {0} ({1}) by task {2} (bank {3})", 88 | Conversion.ToOctal(address), 89 | Conversion.ToOctal(data), 90 | task, 91 | _system.CPU.UCodeMemory.GetBank(task)); 92 | } 93 | 94 | /// 95 | /// Specifies the range (or ranges) of addresses decoded by this device. 96 | /// 97 | public MemoryRange[] Addresses 98 | { 99 | get { return _addresses; } 100 | } 101 | 102 | 103 | /// 104 | /// From: http://bitsavers.org/pdf/xerox/alto/memos_1975/Reserved_Alto_Memory_Locations_Jan75.pdf 105 | /// 106 | /// #177140 - #177157: Organ Keyboard (Organ Hardware - Kaehler) 107 | /// 108 | private readonly MemoryRange[] _addresses = 109 | { 110 | new MemoryRange(0xfe60, 0xfe6f), 111 | }; 112 | 113 | private ushort[] _keyData = new ushort[16]; 114 | 115 | private AltoSystem _system; 116 | } 117 | 118 | } -------------------------------------------------------------------------------- /ContraltoLib/IO/Printing/IPageSink.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.IO.Printing 24 | { 25 | /// 26 | /// IPageSink defines the interface between a ROS device and physical output 27 | /// on the emulated host (be it real paper on a printer or PDF, Postscript, etc). 28 | /// 29 | public interface IPageSink 30 | { 31 | /// 32 | /// Starts a new document to be printed. 33 | /// 34 | void StartDoc(); 35 | 36 | /// 37 | /// Adds a new page to the output. This is provided as a byte array containing 'height' scanlines of the specified width. 38 | /// 39 | /// 40 | /// 41 | /// 42 | void AddPage(byte[] raster, int width, int height); 43 | 44 | /// 45 | /// Ends the document being printed. 46 | /// 47 | void EndDoc(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ContraltoLib/IO/Printing/NullPageSink.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.IO.Printing 24 | { 25 | /// 26 | /// The NullPageSink: All pages go to the bit-bucket, for the true paperless office. 27 | /// 28 | public class NullPageSink : IPageSink 29 | { 30 | public NullPageSink() 31 | { 32 | 33 | } 34 | 35 | public void StartDoc() 36 | { 37 | 38 | } 39 | 40 | public void AddPage(byte[] rasters, int width, int height) 41 | { 42 | 43 | } 44 | 45 | public void EndDoc() 46 | { 47 | 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ContraltoLib/IO/Printing/PdfPageSink.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using iText.Kernel.Pdf; 24 | using Contralto.Logging; 25 | using iText.Layout; 26 | using iText.Kernel.Geom; 27 | using iText.Layout.Element; 28 | using iText.IO.Image; 29 | using iText.Layout.Properties; 30 | 31 | namespace Contralto.IO.Printing 32 | { 33 | /// 34 | /// PdfPageSink takes output from the ROS and turns it into 35 | /// PDF documents in the PrintOutputPath folder. 36 | /// 37 | /// This uses the iTextSharp PDF creation libraries to do the hard work. 38 | /// 39 | public class PdfPageSink : IPageSink 40 | { 41 | public PdfPageSink(Configuration configuration) 42 | { 43 | _pageImages = new List(); 44 | _configuration = configuration; 45 | } 46 | 47 | public void StartDoc() 48 | { 49 | _pageImages.Clear(); 50 | 51 | try 52 | { 53 | string path = System.IO.Path.Combine( 54 | _configuration.PrintOutputPath, 55 | String.Format("AltoDocument-{0}.pdf", DateTime.Now.ToString("yyyyMMdd-hhmmss"))); 56 | 57 | // Start a new document. 58 | 59 | PdfDocument doc = new PdfDocument(new PdfWriter(path)); 60 | 61 | // All output to a Dover printer is letter-sized. 62 | _pdf = new Document(doc, PageSize.LETTER); 63 | 64 | // Let the Orbit deal with the margins. 65 | _pdf.SetMargins(0, 0, 0, 0); 66 | } 67 | catch(Exception e) 68 | { 69 | // 70 | // Most likely we couldn't create the output file; log the failure. 71 | // All output will be relegated to the bit bucket. 72 | // 73 | _pdf = null; 74 | 75 | Log.Write(LogType.Error, LogComponent.DoverROS, "Failed to create output PDF. Error {0}", e.Message); 76 | } 77 | } 78 | 79 | public void AddPage(byte[] rasters, int width, int height) 80 | { 81 | if (_pdf != null) 82 | { 83 | ImageData pageImageData = ImageDataFactory.Create(height, width, 1 /* greyscale */, 1 /* 1bpp */, rasters, null); 84 | Image pageImage = new Image(pageImageData); 85 | pageImage.SetFixedPosition(_configuration.PageRasterOffsetX, _configuration.PageRasterOffsetY); 86 | pageImage.SetRotationAngle(90.0 * (Math.PI / 180.0)); 87 | 88 | Rectangle pageRect = _pdf.GetPageEffectiveArea(PageSize.LETTER); 89 | pageImage.ScaleToFit(pageRect.GetHeight(), pageRect.GetWidth()); 90 | 91 | _pageImages.Add(pageImage); 92 | } 93 | } 94 | 95 | public void EndDoc() 96 | { 97 | if (_pdf != null) 98 | { 99 | try 100 | { 101 | // Grab the configuration here so that if some joker changes the configuration 102 | // while we're printing we don't do something weird. 103 | bool reversePageOrder = _configuration.ReversePageOrder; 104 | 105 | // Actually write out the pages now, in the proper order. 106 | for (int i = 0; i < _pageImages.Count; i++) 107 | { 108 | _pdf.Add(_pageImages[reversePageOrder ? (_pageImages.Count - 1) - i : i]); 109 | _pdf.Add(new AreaBreak(i < _pageImages.Count - 1 ? AreaBreakType.NEXT_PAGE : AreaBreakType.LAST_PAGE)); 110 | } 111 | 112 | _pdf.Close(); 113 | } 114 | catch (Exception e) 115 | { 116 | // Something bad happened during creation, log an error. 117 | Log.Write(LogComponent.DoverROS, "Failed to create output PDF. Error {0}", e.Message); 118 | } 119 | } 120 | } 121 | 122 | /// 123 | /// List of page images in this document. 124 | /// Since Alto software typically prints the document in reverse-page-order due to the way the 125 | /// Dover produces output, we need be able to produce the PDF in reverse order. 126 | /// This uses extra memory, (about 1.7mb per page printed.) 127 | /// 128 | private List _pageImages; 129 | private Document _pdf; 130 | private Configuration _configuration; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /ContraltoLib/Logging/Log.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | #define LOGGING_ENABLED 24 | 25 | namespace Contralto.Logging 26 | { 27 | /// 28 | /// Specifies a component to specify logging for 29 | /// 30 | [Flags] 31 | public enum LogComponent 32 | { 33 | None = 0, 34 | EmulatorTask = 0x1, 35 | DiskSectorTask = 0x2, 36 | DiskWordTask = 0x4, 37 | DiskController = 0x8, 38 | Alu = 0x10, 39 | Memory = 0x20, 40 | Keyboard = 0x40, 41 | Display = 0x80, 42 | Microcode = 0x100, 43 | CPU = 0x200, 44 | EthernetController = 0x400, 45 | EthernetTask = 0x800, 46 | TaskSwitch = 0x1000, 47 | HostNetworkInterface = 0x2000, 48 | EthernetPacket = 0x4000, 49 | Configuration = 0x8000, 50 | DAC = 0x10000, 51 | Organ = 0x20000, 52 | Orbit = 0x40000, 53 | DoverROS = 0x80000, 54 | TridentTask = 0x100000, 55 | TridentController = 0x200000, 56 | TridentDisk = 0x400000, 57 | 58 | Scripting = 0x2000000, 59 | Debug = 0x40000000, 60 | All = 0x7fffffff 61 | } 62 | 63 | /// 64 | /// Specifies the type (or severity) of a given log message 65 | /// 66 | [Flags] 67 | public enum LogType 68 | { 69 | None = 0, 70 | Normal = 0x1, 71 | Warning = 0x2, 72 | Error = 0x4, 73 | Verbose = 0x8, 74 | All = 0x7fffffff 75 | } 76 | 77 | /// 78 | /// Provides basic functionality for logging messages of all types. 79 | /// 80 | public static class Log 81 | { 82 | static Log() 83 | { 84 | _components = Configuration.LogComponents; 85 | _type = Configuration.LogTypes; 86 | _logText = new List(); 87 | } 88 | 89 | public static event EventHandler? Updated; 90 | 91 | public static LogComponent LogComponents 92 | { 93 | get { return _components; } 94 | set { _components = value; } 95 | } 96 | 97 | public static IEnumerable LogText => _logText; 98 | 99 | public static void Clear() 100 | { 101 | _logText.Clear(); 102 | } 103 | 104 | #if LOGGING_ENABLED 105 | /// 106 | /// Logs a message without specifying type/severity for terseness; 107 | /// will not log if Type has been set to None. 108 | /// 109 | /// 110 | /// 111 | /// 112 | public static void Write(LogComponent component, string message, params object[] args) 113 | { 114 | Write(LogType.Normal, component, message, args); 115 | } 116 | 117 | public static void Write(LogType type, LogComponent component, string message, params object[] args) 118 | { 119 | if ((_type & type) != 0 && 120 | (_components & component) != 0) 121 | { 122 | // 123 | // My log has something to tell you... 124 | string format = $"{_logText.Count}: {component.ToString()} : {message}"; 125 | string output = String.Format(format, args); 126 | _logText.Add(output); 127 | 128 | Updated?.Invoke(output, new EventArgs()); 129 | } 130 | } 131 | #else 132 | public static void Write(LogComponent component, string message, params object[] args) 133 | { 134 | 135 | } 136 | 137 | public static void Write(LogType type, LogComponent component, string message, params object[] args) 138 | { 139 | 140 | } 141 | 142 | #endif 143 | 144 | private static LogComponent _components; 145 | private static LogType _type; 146 | private static List _logText; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /ContraltoLib/Memory/IMemoryMappedDevice.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.CPU; 24 | 25 | namespace Contralto.Memory 26 | { 27 | /// 28 | /// Specifies a range of memory from Start to End, inclusive. 29 | /// 30 | public struct MemoryRange 31 | { 32 | public MemoryRange(ushort start, ushort end) 33 | { 34 | if (!(end >= start)) 35 | { 36 | throw new ArgumentOutOfRangeException("end must be greater than or equal to start."); 37 | } 38 | 39 | Start = start; 40 | End = end; 41 | } 42 | 43 | public bool Overlaps(MemoryRange other) 44 | { 45 | return ((other.Start >= this.Start && other.Start <= this.End) || 46 | (other.End >= this.Start && other.End <= this.End)); 47 | } 48 | 49 | public ushort Start; 50 | public ushort End; 51 | } 52 | 53 | /// 54 | /// Specifies an interfaces for devices that appear in mapped memory. This includes 55 | /// RAM as well as regular I/O devices. 56 | /// 57 | public interface IMemoryMappedDevice 58 | { 59 | /// 60 | /// Reads a word from the specified address. 61 | /// 62 | /// 63 | /// 64 | /// 65 | ushort Read(int address, TaskType task, bool extendedMemory); 66 | 67 | /// 68 | /// Writes a word to the specified address. 69 | /// 70 | /// 71 | /// 72 | void Load(int address, ushort data, TaskType task, bool extendedMemory); 73 | 74 | /// 75 | /// Specifies the range (or ranges) of addresses decoded by this device. 76 | /// 77 | MemoryRange[] Addresses { get; } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /ContraltoLib/Memory/Memory.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.CPU; 24 | using Contralto.Logging; 25 | using System.Diagnostics.CodeAnalysis; 26 | using System.Runtime.CompilerServices; 27 | 28 | namespace Contralto.Memory 29 | { 30 | /// 31 | /// Implements the Alto's main memory, up to 4 banks of 64KW in 16-bit words. 32 | /// Provides implementation of the IIXM's memory mapping hardware. 33 | /// 34 | public class Memory : IMemoryMappedDevice 35 | { 36 | public Memory(Configuration configuration) 37 | { 38 | // Set up handled addresses based on the system type. 39 | if (configuration.SystemType == SystemType.AltoI) 40 | { 41 | _addresses = new MemoryRange[] 42 | { 43 | new MemoryRange(0, _memTop), // Main bank of RAM to 176777; IO page above this. 44 | }; 45 | } 46 | else 47 | { 48 | _addresses = new MemoryRange[] 49 | { 50 | new MemoryRange(0, _memTop), // Main bank of RAM to 176777; IO page above this. 51 | new MemoryRange(_xmBanksStart, (ushort)(_xmBanksStart + 16)), // Memory bank registers 52 | }; 53 | } 54 | 55 | Reset(); 56 | } 57 | 58 | /// 59 | /// The top address of main memory (above which lies the I/O space) 60 | /// 61 | public static ushort RamTop 62 | { 63 | get { return _memTop; } 64 | } 65 | 66 | /// 67 | /// Full reset, clears all memory. 68 | /// 69 | [MemberNotNull(nameof(_mem), nameof(_xmBanks), nameof(_xmBanksAlternate), nameof(_xmBanksNormal))] 70 | public void Reset() 71 | { 72 | // 4 64K banks, regardless of system type. (Alto Is just won't use the extra memory.) 73 | _mem = new ushort[0x40000]; 74 | _xmBanks = new ushort[16]; 75 | _xmBanksAlternate = new int[16]; 76 | _xmBanksNormal = new int[16]; 77 | } 78 | 79 | /// 80 | /// Soft reset, clears XM bank registers. 81 | /// 82 | public void SoftReset() 83 | { 84 | _xmBanks = new ushort[16]; 85 | _xmBanksAlternate = new int[16]; 86 | _xmBanksNormal = new int[16]; 87 | } 88 | 89 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 90 | public ushort Read(int address, TaskType task, bool extendedMemory) 91 | { 92 | // Check for XM registers; this occurs regardless of XM flag since it's in the I/O page. 93 | if (address >= _xmBanksStart && address < _xmBanksStart + 16) 94 | { 95 | // NB: While not specified in documentation, some code (IFS in particular) relies on the fact that 96 | // the upper 12 bits of the bank registers are all 1s. 97 | return (ushort)(0xfff0 | _xmBanks[address - _xmBanksStart]); 98 | } 99 | else 100 | { 101 | return _mem[address + 0x10000 * GetBankNumber(task, extendedMemory)]; 102 | } 103 | } 104 | 105 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 106 | public void Load(int address, ushort data, TaskType task, bool extendedMemory) 107 | { 108 | // Check for XM registers; this occurs regardless of XM flag since it's in the I/O page. 109 | if (address >= _xmBanksStart && address < _xmBanksStart + 16) 110 | { 111 | _xmBanks[address - _xmBanksStart] = data; 112 | 113 | // Precalc bank numbers to speed memory accesses that use them 114 | _xmBanksAlternate[address - _xmBanksStart] = data & 0x3; 115 | _xmBanksNormal[address - _xmBanksStart] = (data & 0xc) >> 2; 116 | 117 | Log.Write(LogComponent.Memory, "XM register for task {0} set to bank {1} (normal), {2} (xm)", 118 | (TaskType)(address - _xmBanksStart), 119 | (data & 0xc) >> 2, 120 | (data & 0x3)); 121 | } 122 | else 123 | { 124 | _mem[address + 0x10000 * GetBankNumber(task, extendedMemory)] = data; 125 | } 126 | } 127 | 128 | public MemoryRange[] Addresses 129 | { 130 | get { return _addresses; } 131 | } 132 | 133 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 134 | private int GetBankNumber(TaskType task, bool extendedMemory) 135 | { 136 | return extendedMemory ? 137 | _xmBanksAlternate[(int)task] : _xmBanksNormal[(int)task]; 138 | } 139 | 140 | private readonly MemoryRange[] _addresses; 141 | 142 | private static readonly ushort _memTop = 0xfdff; // 176777 143 | private static readonly ushort _xmBanksStart = 0xffe0; // 177740 144 | 145 | private ushort[] _mem; 146 | 147 | private ushort[] _xmBanks; 148 | private int[] _xmBanksAlternate; 149 | private int[] _xmBanksNormal; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /ContraltoLib/ROM/ACSOURCE.NEW: -------------------------------------------------------------------------------- 1 |                            2 |   3 |                     -------------------------------------------------------------------------------- /ContraltoLib/ROM/ACSOURCE.OLD: -------------------------------------------------------------------------------- 1 |  2 |    3 |   4 |    5 |   6 |    7 |    8 |     9 |   10 |    11 |  12 |   13 |   14 |   15 |   16 |    17 |   18 |    19 |    20 |     21 |   22 |    23 |   24 |    25 |    26 |    27 |   28 |    29 |    30 |     31 |   32 |    33 |   34 |    35 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/00_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |      3 |  4 | 5 |  6 | 7 | 8 | 9 |  10 | 11 |  12 |  13 | 14 | 15 |  16 |   17 |  18 |  19 |  20 | 21 |  22 | 23 | 24 |  25 | 26 |  27 |  28 |  29 |   30 |  31 |       32 |      -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/01_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |   3 |       4 |           5 |   -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/02_23.BIN: -------------------------------------------------------------------------------- 1 | 2 |  3 |   4 |   5 | 6 |     7 |  8 |   9 |  10 | 11 |  12 |   13 | 14 |   15 |    16 | 17 |  18 |  19 |   20 |  21 | 22 |  23 | 24 |  25 | 26 |      27 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/03_23.BIN: -------------------------------------------------------------------------------- 1 |       2 |  3 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/04_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |    3 |       4 |   -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/05_23.BIN: -------------------------------------------------------------------------------- 1 |      2 |                           3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |          19 | 20 |       21 |     22 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/06_23.BIN: -------------------------------------------------------------------------------- 1 |      2 |  3 | 4 | 5 | 6 | 7 |  8 |          9 | 10 | 11 |  12 | 13 |    14 |   -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/07_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |      3 |  4 |           5 |  6 |  7 |  8 |       9 |       10 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/10_23.BIN: -------------------------------------------------------------------------------- 1 |                      2 |       3 |                     -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/11_23.BIN: -------------------------------------------------------------------------------- 1 |  2 |        3 |      4 |  5 |  6 |    7 |  8 |        -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/12_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |   3 |     4 |  5 | 6 |   7 |   8 |   9 | 10 |  11 |   12 |  13 | 14 |       15 |  16 |   17 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/13_23.BIN: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/14_23.BIN: -------------------------------------------------------------------------------- 1 |        2 |      -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/15_23.BIN: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |  5 |  6 |  7 |  8 |  9 |   10 | 11 |  12 |  13 |  14 | 15 |   16 |  17 |  18 |  19 |  20 |  21 |  22 |  23 | 24 |  25 |  26 |  27 |  28 | 29 | 30 |   31 |  32 | 33 |    34 | 35 |   36 |   37 |  38 |  39 |   40 | 41 | 42 | 43 | 44 | 45 |  46 |  47 | 48 | 49 |  50 |  51 |  52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |  60 | 61 | 62 |  63 | 64 | 65 |  66 | 67 |   68 | 69 | 70 |  71 |  72 | 73 |  74 |  75 | 76 |  77 | -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/16_23.BIN: -------------------------------------------------------------------------------- 1 |          2 |           -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/17_23.BIN: -------------------------------------------------------------------------------- 1 |  2 |            3 | 4 |         5 |     6 |    7 |  8 |   9 |   10 |  11 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/20_23.BIN: -------------------------------------------------------------------------------- 1 |                                                 -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/21_23.BIN: -------------------------------------------------------------------------------- 1 |    2 |                  3 |         4 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/22_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |  3 |       4 |  5 | 6 |           7 | 8 |  9 |             10 |   11 |     12 |  13 |  14 |  15 | 16 |      17 |  18 |   19 |  20 |  21 |  22 |  23 |  24 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/23_23.BIN: -------------------------------------------------------------------------------- 1 |   -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/24_23.BIN: -------------------------------------------------------------------------------- 1 |      -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/25_23.BIN: -------------------------------------------------------------------------------- 1 |                                     2 | 3 |  4 |    5 |     6 |  7 | 8 |  9 |  10 |  11 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/26_23.BIN: -------------------------------------------------------------------------------- 1 |    2 |  3 |   4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |  15 |          -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/27_23.BIN: -------------------------------------------------------------------------------- 1 |    2 |  3 |    4 |     5 | 6 |        7 |   8 |   9 |  10 |   11 |       12 |   13 |     14 |     -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/30_23.BIN: -------------------------------------------------------------------------------- 1 |                                   -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/31_23.BIN: -------------------------------------------------------------------------------- 1 |          2 |          3 |            -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/32_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |  3 |   4 | 5 |  6 |  7 |   8 | 9 |  10 | 11 |    12 |  13 |  14 |  15 |    16 | 17 | 18 | 19 |     20 |       21 |   22 |  23 |  24 |  25 |  26 |  27 |   28 |   29 |   30 | 31 |  32 |      33 |  34 |  35 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/33_23.BIN: -------------------------------------------------------------------------------- 1 |     2 | 3 |   4 |  5 |    6 |   7 |    8 |  9 |     -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/34_23.BIN: -------------------------------------------------------------------------------- 1 |      2 |  3 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/35_23.BIN: -------------------------------------------------------------------------------- 1 |       2 |                                           -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/36_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |  3 | 4 |   5 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |  14 |   15 |     16 |           -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/37_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |    3 |          4 | 5 |  6 |     7 |    8 |  9 |  10 |    11 |      12 |    13 |     14 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/C0_23.BIN: -------------------------------------------------------------------------------- 1 |      2 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/C1_23.BIN: -------------------------------------------------------------------------------- 1 |  2 |           3 |  4 |   5 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/C2_23.BIN: -------------------------------------------------------------------------------- 1 |   2 |   3 |   4 |    5 |  6 |  7 |  8 |  9 |  10 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoI/C3_23.BIN: -------------------------------------------------------------------------------- 1 |  2 |   3 |            4 |        5 |   6 |   7 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/C0: -------------------------------------------------------------------------------- 1 |    2 |             -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/C1: -------------------------------------------------------------------------------- 1 |   2 |              -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/C2: -------------------------------------------------------------------------------- 1 |     2 |          3 |     -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/C3: -------------------------------------------------------------------------------- 1 |    2 |    3 |                   4 |   5 |        6 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U52: -------------------------------------------------------------------------------- 1 |      2 |       3 |           4 |                        5 |  6 |     7 |  8 |  9 |            10 |   11 |   12 |    13 |  14 |       15 |   16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |     -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U53: -------------------------------------------------------------------------------- 1 |      2 |  3 |            4 |        5 |    6 |  7 |      8 |   -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U54: -------------------------------------------------------------------------------- 1 |      2 |  3 |             4 |  5 | 6 |    7 |      8 | 9 | 10 | 11 | 12 |  13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |  21 | 22 | 23 | 24 | 25 | 26 |  27 | 28 | 29 | 30 | 31 |     32 | 33 |   34 |        35 |          36 |   37 |   38 |  39 |  40 |      41 |        42 |    43 |    44 | 45 |           46 |      47 |                 48 | 49 |         50 |                       51 | 52 |             53 |          -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U55: -------------------------------------------------------------------------------- 1 |                                                                                                      2 |     3 |                           4 |  5 |     6 |  7 | 8 |  9 | 10 | 11 | 12 |  13 | 14 |   15 |  16 | 17 |  18 |   19 |  20 |  21 | 22 |  23 | 24 |  25 |  26 | 27 |  28 | 29 |  30 |  31 |  32 |   33 |  34 |       35 |     -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U60: -------------------------------------------------------------------------------- 1 | 2 |                                                                                  3 | 4 |  5 |    6 |        7 |  8 | 9 |  10 |  11 |  12 |    13 | 14 |   15 |  16 |  17 |  18 | 19 |  20 |  21 |  22 |  23 |   24 |  25 |  26 |  27 |  28 |  29 |  30 |  31 | 32 |  33 |  34 |  35 |   36 | 37 |   38 |  39 | 40 |   41 |  42 | 43 |   44 |  45 |  46 |   47 |  48 | 49 | 50 | 51 | 52 |   53 | 54 |  55 | 56 | 57 |  58 |  59 |  60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |  68 | 69 |  70 |  71 | 72 | 73 | 74 | 75 | 76 |  77 | 78 | 79 |  80 | 81 |  82 |  83 | 84 |  85 |  86 |  87 |  88 | 89 |    90 |    91 |                   92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |    108 | 109 |      110 | 111 |       112 |    113 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U61: -------------------------------------------------------------------------------- 1 |       2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |  14 | 15 | 16 | 17 | 18 |   19 |  20 |  21 |     22 |   23 | 24 | 25 | 26 | 27 | 28 | 29 |  30 | 31 | 32 | 33 | 34 | 35 |  36 |         37 |           38 |  39 |  40 | 41 | 42 | 43 |  44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |  52 | 53 |  54 | 55 | 56 | 57 | 58 | 59 |        60 |  61 | 62 | 63 | 64 | 65 |  66 |     67 |      68 | 69 |  70 |  71 |   72 |    73 | -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U62: -------------------------------------------------------------------------------- 1 |   2 |    3 |  4 |   5 |     6 |  7 |     8 |   9 |         10 |        11 |    12 |     13 |    14 |   15 |    16 |  17 |    18 |   19 |  20 |  21 |   22 |  23 |   24 |  25 |   26 |  27 |  28 |  29 |      30 |  31 |   32 |         33 |       34 |       35 |   36 |      37 |  38 |   39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |   47 |   48 |     49 |     50 |  51 |   52 |               53 | 54 |   55 | -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U63: -------------------------------------------------------------------------------- 1 |   2 |  3 |   4 |  5 |    6 |   7 |           8 |  9 |    -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U64: -------------------------------------------------------------------------------- 1 |      2 |          3 |              4 |                   5 |           6 |    7 |        8 |       9 |  10 |  11 |    12 |  13 |          14 |       15 |           16 |   -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U65: -------------------------------------------------------------------------------- 1 |  2 |   3 |  4 |  5 |   6 |  7 |     8 | 9 | 10 |    11 |      12 |   13 |  14 |  15 |  16 |  17 |  18 |   19 |   20 |    21 | 22 |  23 |     24 | 25 |    26 |       27 |  28 |       29 |  30 | 31 |           32 | 33 |  34 |             35 |   36 |    37 |  38 |  39 |  40 |   41 |      42 |  43 |  44 | 45 |   46 |  47 |  48 |  49 |  50 |  51 |   52 |   53 |   54 |  55 |  56 | 57 |   58 |   59 |   60 | 61 |  62 |   63 |  64 | 65 |        66 |   67 |  68 |  69 |       70 | 71 |    72 |  73 |   74 |  75 |  76 | 77 |  78 |      79 |   80 |    81 | 82 |  83 |  84 |  85 |  86 |  87 |  88 | 89 |  90 | 91 |  92 |    93 |  94 |  95 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U70: -------------------------------------------------------------------------------- 1 |        2 |     3 | 4 |         5 |  6 | 7 |   8 |  9 |     10 |            11 | 12 |     13 |   14 |      15 | 16 |  17 |  18 |                           19 |    20 | 21 |  22 | 23 |   24 |  25 |  26 | 27 | 28 | 29 | 30 | 31 | 32 |  33 |  34 |  35 |  36 |  37 | 38 |  39 | 40 | 41 | 42 |  43 | 44 |  45 |  46 |   47 |  48 |  49 | 50 |  51 |  52 | 53 | 54 |  55 |   56 |  57 |  58 | 59 | 60 |  61 | 62 |   63 |  64 | 65 |  66 |  67 | 68 |  69 |  70 |  71 |  72 |   73 | 74 |  75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |  86 | 87 |  88 | 89 |  90 |  91 |  92 | 93 | 94 | 95 | 96 |   97 |  98 | 99 | 100 | 101 |  102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 |  111 |     112 | 113 | 114 | 115 |  116 |  117 |   118 |   119 | 120 |     121 |         122 |  123 |  124 |     125 | 126 | 127 | 128 |  129 | 130 |     131 |         132 | 133 |  134 |  135 | 136 |  137 | 138 | 139 |   140 |  141 |   142 |      143 | 144 |      -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U71: -------------------------------------------------------------------------------- 1 |  2 |    3 |  4 |  5 |  6 |  7 |   8 |    9 |    10 | 11 | 12 | 13 | 14 | 15 | 16 |  17 |  18 |  19 |  20 |    21 |  22 |       23 |   24 | 25 |  26 | 27 |  28 |  29 |             30 |  31 |     32 |  33 |     34 |  35 | 36 |  37 |  38 |  39 | 40 | 41 |  42 | 43 | 44 |  45 | 46 |   47 |    48 |   49 |     50 | 51 |      52 |   53 |          54 |    55 |  56 | 57 |  58 |       59 |      60 | 61 | 62 |   -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U72: -------------------------------------------------------------------------------- 1 |    2 |    3 |  4 | 5 | 6 | 7 |  8 |    9 |  10 |   11 | 12 |         13 | 14 | 15 |     16 |  17 |  18 |     19 |  20 |     21 |       22 |  23 |  24 |  25 |  26 |  27 |      28 |      29 |    30 |    31 |    32 |  33 |     34 |    35 |     36 |      37 |                      38 | 39 |                    40 |    41 |  42 |   43 |     44 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U73: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U74: -------------------------------------------------------------------------------- 1 |                2 |   3 |      4 |   5 |   6 |   7 |     8 |  9 |   10 |      11 |       12 |   13 |   14 |  15 |      16 |  17 |  18 |              19 |             20 |  21 |     22 |    23 | 24 |     25 |       26 |  27 |           28 |   29 | 30 |  31 |  32 | 33 | 34 | 35 | 36 | 37 |      -------------------------------------------------------------------------------- /ContraltoLib/ROM/AltoII/U75: -------------------------------------------------------------------------------- 1 |      2 |     3 |   4 |  5 |  6 |    7 | 8 |   9 |   10 |   11 |  12 |   13 |   14 |     15 | 16 |  17 |   18 |    19 |      20 |                      21 |  22 |   23 |                 24 |  25 |    26 |  27 |     28 |     29 |   30 |  31 |         32 | 33 |  34 |  35 |           36 |     37 |  38 |     39 |   40 |   41 |              42 |  43 |   44 |  45 |     46 | 47 |            48 |  49 |     50 |      51 |   52 | 53 |   54 |    55 |         56 |   57 |  -------------------------------------------------------------------------------- /ContraltoLib/Scripting/DebuggerAttributes.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.Scripting 24 | 25 | { 26 | public class DebuggerFunction : Attribute 27 | { 28 | public DebuggerFunction(string commandName) 29 | { 30 | _commandName = commandName; 31 | _usage = ""; 32 | _description = ""; 33 | } 34 | 35 | public DebuggerFunction(string commandName, string description) 36 | { 37 | _usage = ""; 38 | _commandName = commandName; 39 | _description = description; 40 | } 41 | 42 | public DebuggerFunction(string commandName, string description, string usage) 43 | { 44 | _commandName = commandName; 45 | _description = description; 46 | _usage = usage; 47 | } 48 | 49 | public string CommandName 50 | { 51 | get { return _commandName; } 52 | } 53 | 54 | public string Usage 55 | { 56 | get { return _usage; } 57 | } 58 | 59 | public string Description 60 | { 61 | get { return _description; } 62 | } 63 | 64 | private string _commandName; 65 | private string _description; 66 | private string _usage; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /ContraltoLib/Scripting/ScriptManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.Logging; 24 | 25 | namespace Contralto.Scripting 26 | { 27 | public static class ScriptManager 28 | { 29 | static ScriptManager() 30 | { 31 | _scheduler = new Scheduler(); 32 | } 33 | 34 | public static Scheduler ScriptScheduler 35 | { 36 | get { return _scheduler; } 37 | } 38 | 39 | /// 40 | /// Fired when playback of a script has completed or is stopped. 41 | /// 42 | public static event EventHandler? PlaybackCompleted; 43 | 44 | public static void StartRecording(AltoSystem system, string scriptPath) 45 | { 46 | // Stop any pending actions 47 | StopRecording(); 48 | StopPlayback(); 49 | 50 | _scriptRecorder = new ScriptRecorder(system, scriptPath); 51 | 52 | Log.Write(LogComponent.Scripting, "Starting recording to {0}", scriptPath); 53 | 54 | // 55 | // Record the absolute position of the mouse (as held in MOUSELOC in system memory). 56 | // All other mouse movements in the script will be recorded relative to this point. 57 | // 58 | int x = system.Memory.Read(0x114, CPU.TaskType.Ethernet, false); 59 | int y = system.Memory.Read(0x115, CPU.TaskType.Ethernet, false); 60 | _scriptRecorder.MouseMoveAbsolute(x, y); 61 | } 62 | 63 | public static void StopRecording() 64 | { 65 | if (IsRecording) 66 | { 67 | _scriptRecorder?.End(); 68 | _scriptRecorder = null; 69 | } 70 | 71 | Log.Write(LogComponent.Scripting, "Stopped recording."); 72 | } 73 | 74 | public static void StartPlayback(AltoSystem system, string scriptPath) 75 | { 76 | // Stop any pending actions 77 | StopRecording(); 78 | StopPlayback(); 79 | 80 | _scheduler.Reset(); 81 | 82 | _scriptPlayback = new ScriptPlayback(scriptPath, system); 83 | _scriptPlayback.PlaybackCompleted += OnPlaybackCompleted; 84 | _scriptPlayback.Start(); 85 | 86 | Log.Write(LogComponent.Scripting, "Starting playback of {0}", scriptPath); 87 | } 88 | 89 | public static void StopPlayback() 90 | { 91 | if (IsPlaying) 92 | { 93 | _scriptPlayback?.Stop(); 94 | _scriptPlayback = null; 95 | 96 | PlaybackCompleted?.Invoke(null, null!); 97 | } 98 | 99 | Log.Write(LogComponent.Scripting, "Stopped playback."); 100 | } 101 | 102 | public static void CompleteWait() 103 | { 104 | if (IsPlaying) 105 | { 106 | _scriptPlayback?.Start(); 107 | 108 | Log.Write(LogComponent.Scripting, "Playback resumed after Wait."); 109 | } 110 | } 111 | 112 | public static ScriptRecorder? Recorder 113 | { 114 | get { return _scriptRecorder; } 115 | } 116 | 117 | public static ScriptPlayback? Playback 118 | { 119 | get { return _scriptPlayback; } 120 | } 121 | 122 | public static bool IsRecording 123 | { 124 | get { return _scriptRecorder != null; } 125 | } 126 | 127 | public static bool IsPlaying 128 | { 129 | get { return _scriptPlayback != null; } 130 | } 131 | 132 | private static void OnPlaybackCompleted(object? sender, EventArgs e) 133 | { 134 | _scriptPlayback = null; 135 | PlaybackCompleted?.Invoke(null, null!); 136 | } 137 | 138 | private static ScriptRecorder? _scriptRecorder; 139 | private static ScriptPlayback? _scriptPlayback; 140 | 141 | private static Scheduler _scheduler; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /ContraltoLib/Scripting/ScriptPlayback.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.Logging; 24 | 25 | namespace Contralto.Scripting 26 | { 27 | public class ScriptPlayback 28 | { 29 | public ScriptPlayback(string scriptFile, AltoSystem system) 30 | { 31 | _scriptReader = new ScriptReader(scriptFile); 32 | _system = system; 33 | 34 | _currentAction = null; 35 | 36 | _stopPlayback = false; 37 | } 38 | 39 | /// 40 | /// Fired when playback of the script has completed or is stopped. 41 | /// 42 | public event EventHandler? PlaybackCompleted; 43 | 44 | public void Start() 45 | { 46 | _stopPlayback = false; 47 | 48 | // Schedule first event. 49 | ScheduleNextEvent(0); 50 | } 51 | 52 | public void Stop() 53 | { 54 | // We will stop after the next event is fired (if any) 55 | _stopPlayback = true; 56 | } 57 | 58 | private void ScheduleNextEvent(ulong skewNsec) 59 | { 60 | // 61 | // Grab the next action if the current one is done. 62 | // 63 | if (_currentAction == null || _currentAction.Completed) 64 | { 65 | _currentAction = _scriptReader.ReadNext(); 66 | } 67 | 68 | if (_currentAction != null) 69 | { 70 | // We have another action to queue up. 71 | Event scriptEvent = new Event(_currentAction.Timestamp, _currentAction, OnEvent); 72 | ScriptManager.ScriptScheduler.Schedule(scriptEvent); 73 | 74 | Log.Write(LogComponent.Scripting, "Queueing script action {0}", _currentAction); 75 | } 76 | else 77 | { 78 | // 79 | // Playback is complete. 80 | // 81 | Log.Write(LogComponent.Scripting, "Playback completed."); 82 | PlaybackCompleted?.Invoke(this, null!); 83 | } 84 | } 85 | 86 | private void OnEvent(ulong skewNsec, object? context) 87 | { 88 | // Replay the action. 89 | if (!_stopPlayback) 90 | { 91 | if (context == null) 92 | { 93 | throw new InvalidOperationException("Script event callback context cannot be null"); 94 | } 95 | 96 | ScriptAction action = (ScriptAction)context; 97 | Log.Write(LogComponent.Scripting, "Invoking action {0}", action); 98 | 99 | action.Replay(_system); 100 | 101 | // Special case for Wait -- this causes the script to stop here until the 102 | // Alto itself tells things to start up again. 103 | // 104 | if (action is WaitAction) 105 | { 106 | Log.Write(LogComponent.Scripting, "Playback paused, awaiting wakeup from Alto."); 107 | } 108 | else 109 | { 110 | // Kick off the next action in the script. 111 | ScheduleNextEvent(skewNsec); 112 | } 113 | } 114 | else 115 | { 116 | Log.Write(LogComponent.Scripting, "Playback stopped."); 117 | PlaybackCompleted?.Invoke(this, null!); 118 | } 119 | } 120 | 121 | private AltoSystem _system; 122 | private ScriptReader _scriptReader; 123 | 124 | private ScriptAction? _currentAction; 125 | 126 | private bool _stopPlayback; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /ContraltoLib/Scripting/ScriptReader.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.Logging; 24 | using System.Diagnostics.CodeAnalysis; 25 | 26 | namespace Contralto.Scripting 27 | { 28 | public class ScriptReader 29 | { 30 | public ScriptReader(string scriptPath) 31 | { 32 | _scriptReader = new StreamReader(scriptPath); 33 | } 34 | 35 | public ScriptAction? ReadNext() 36 | { 37 | if (_scriptReader == null || _scriptReader.EndOfStream) 38 | { 39 | return null; 40 | } 41 | 42 | // 43 | // Read the next action from the script file, 44 | // skipping over comments and empty lines. 45 | // 46 | while (true) 47 | { 48 | // The below null check should not be necessary; _scriptReader will never be null. 49 | // But try convincing C#'s static analyzer of this... 50 | if (_scriptReader == null || _scriptReader.EndOfStream) 51 | { 52 | // End of the stream, return null to indicate this, 53 | // and close the stream. 54 | _scriptReader?.Close(); 55 | return null; 56 | } 57 | 58 | string? line = _scriptReader?.ReadLine()?.Trim(); 59 | 60 | // Skip empty or comment lines. 61 | if (string.IsNullOrWhiteSpace(line) || 62 | line.StartsWith("#")) 63 | { 64 | continue; 65 | } 66 | 67 | try 68 | { 69 | return ScriptAction.Parse(line); 70 | } 71 | catch(Exception e) 72 | { 73 | Log.Write(LogComponent.Scripting, "Invalid script; error: {0}.", e.Message); 74 | _scriptReader?.Close(); 75 | return null; 76 | } 77 | } 78 | } 79 | 80 | private readonly StreamReader _scriptReader; 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /ContraltoLib/Scripting/ScriptRecorder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto.IO; 24 | 25 | namespace Contralto.Scripting 26 | { 27 | /// 28 | /// Records actions. 29 | /// 30 | public class ScriptRecorder 31 | { 32 | public ScriptRecorder(AltoSystem system, string scriptFile) 33 | { 34 | _script = new ScriptWriter(scriptFile); 35 | _system = system; 36 | _lastTimestamp = 0; 37 | 38 | _firstTime = true; 39 | } 40 | 41 | public void End() 42 | { 43 | _script.End(); 44 | } 45 | 46 | public void KeyDown(AltoKey key) 47 | { 48 | _script.AppendAction( 49 | new KeyAction( 50 | GetRelativeTimestamp(), 51 | key, 52 | true)); 53 | } 54 | 55 | public void KeyUp(AltoKey key) 56 | { 57 | _script.AppendAction( 58 | new KeyAction( 59 | GetRelativeTimestamp(), 60 | key, 61 | false)); 62 | } 63 | 64 | public void MouseDown(AltoMouseButton button) 65 | { 66 | _script.AppendAction( 67 | new MouseButtonAction( 68 | GetRelativeTimestamp(), 69 | button, 70 | true)); 71 | } 72 | 73 | public void MouseUp(AltoMouseButton button) 74 | { 75 | _script.AppendAction( 76 | new MouseButtonAction( 77 | GetRelativeTimestamp(), 78 | button, 79 | false)); 80 | } 81 | 82 | public void MouseMoveRelative(int dx, int dy) 83 | { 84 | _script.AppendAction( 85 | new MouseMoveAction( 86 | GetRelativeTimestamp(), 87 | dx, 88 | dy, 89 | false)); 90 | } 91 | 92 | public void MouseMoveAbsolute(int dx, int dy) 93 | { 94 | _script.AppendAction( 95 | new MouseMoveAction( 96 | GetRelativeTimestamp(), 97 | dx, 98 | dy, 99 | true)); 100 | } 101 | 102 | public void Command(string command) 103 | { 104 | _script.AppendAction( 105 | new CommandAction( 106 | GetRelativeTimestamp(), 107 | command)); 108 | } 109 | 110 | private ulong GetRelativeTimestamp() 111 | { 112 | if (_firstTime) 113 | { 114 | _firstTime = false; 115 | // 116 | // First item recorded, occurs at relative timestamp 0. 117 | // 118 | _lastTimestamp = ScriptManager.ScriptScheduler.CurrentTimeNsec; 119 | return 0; 120 | } 121 | else 122 | { 123 | // 124 | // relative time is delta between current system timestamp and the last 125 | // recorded entry. 126 | ulong relativeTimestamp = ScriptManager.ScriptScheduler.CurrentTimeNsec - _lastTimestamp; 127 | _lastTimestamp = ScriptManager.ScriptScheduler.CurrentTimeNsec; 128 | 129 | return relativeTimestamp; 130 | } 131 | } 132 | 133 | private AltoSystem _system; 134 | private ulong _lastTimestamp; 135 | private bool _firstTime; 136 | private ScriptWriter _script; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /ContraltoLib/Scripting/ScriptWriter.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | namespace Contralto.Scripting 24 | { 25 | /// 26 | /// 27 | /// 28 | public class ScriptWriter 29 | { 30 | public ScriptWriter(string scriptPath) 31 | { 32 | _scriptWriter = new StreamWriter(scriptPath); 33 | } 34 | 35 | /// 36 | /// Adds a new ScriptAction to the queue 37 | /// 38 | /// 39 | public void AppendAction(ScriptAction action) 40 | { 41 | if (_scriptWriter == null) 42 | { 43 | throw new InvalidOperationException("Cannot write to closed ScriptWriter."); 44 | } 45 | 46 | _scriptWriter.WriteLine(action.ToString()); 47 | } 48 | 49 | public void End() 50 | { 51 | _scriptWriter?.Close(); 52 | _scriptWriter = null; 53 | } 54 | 55 | private StreamWriter? _scriptWriter; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ContraltoUI/App.axaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ContraltoUI/App.axaml.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Avalonia; 24 | using Avalonia.Controls.ApplicationLifetimes; 25 | using Avalonia.Data.Core.Plugins; 26 | using Avalonia.Markup.Xaml; 27 | using Contralto; 28 | using ContraltoUI.ViewModels; 29 | using ContraltoUI.Views; 30 | using System; 31 | 32 | namespace ContraltoUI; 33 | 34 | public partial class App : Application 35 | { 36 | public override void Initialize() 37 | { 38 | AvaloniaXamlLoader.Load(this); 39 | } 40 | 41 | public override void OnFrameworkInitializationCompleted() 42 | { 43 | IClassicDesktopStyleApplicationLifetime? desktop = ApplicationLifetime as IClassicDesktopStyleApplicationLifetime; 44 | 45 | if (desktop == null) 46 | { 47 | return; 48 | } 49 | 50 | ParseArgs(desktop.Args); 51 | 52 | // TODO: move this inside AltoUIViewModel entirely? 53 | Configuration config = new Configuration(true); 54 | _system = new AltoSystem(config); 55 | 56 | if (config.EnableAudioDAC) 57 | { 58 | SDLAudioSink audioSink = new SDLAudioSink(); 59 | _system.AudioDAC.AttachSink(audioSink); 60 | } 61 | 62 | AltoUIViewModel vm = new AltoUIViewModel(_system); 63 | 64 | // Line below is needed to remove Avalonia data validation. 65 | // Without this line you will get duplicate validations from both Avalonia and CT 66 | BindingPlugins.DataValidators.RemoveAt(0); 67 | 68 | desktop.MainWindow = new MainWindow() 69 | { 70 | DataContext = vm 71 | }; 72 | 73 | 74 | base.OnFrameworkInitializationCompleted(); 75 | } 76 | 77 | private void ParseArgs(string[]? args) 78 | { 79 | if (args == null || args.Length == 0) 80 | { 81 | return; 82 | } 83 | 84 | for (int i = 0; i < args.Length; i++) 85 | { 86 | switch (args[i++].ToLowerInvariant()) 87 | { 88 | case "-config": 89 | if (i < args.Length) 90 | { 91 | StartupOptions.ConfigurationFile = args[i]; 92 | } 93 | else 94 | { 95 | PrintUsage(); 96 | return; 97 | } 98 | break; 99 | 100 | case "-script": 101 | if (i < args.Length) 102 | { 103 | StartupOptions.ScriptFile = args[i]; 104 | } 105 | else 106 | { 107 | PrintUsage(); 108 | return; 109 | } 110 | break; 111 | 112 | case "-rompath": 113 | if (i < args.Length) 114 | { 115 | StartupOptions.RomPath = args[i]; 116 | } 117 | else 118 | { 119 | PrintUsage(); 120 | return; 121 | } 122 | break; 123 | 124 | default: 125 | PrintUsage(); 126 | return; 127 | } 128 | } 129 | } 130 | 131 | private static void PrintUsage() 132 | { 133 | Console.WriteLine("Usage: ContrAlto [-config ] [-script ]"); 134 | } 135 | 136 | private AltoSystem _system = null!; 137 | } 138 | -------------------------------------------------------------------------------- /ContraltoUI/Assets/Alto.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/ContraltoUI/Assets/Alto.ico -------------------------------------------------------------------------------- /ContraltoUI/Assets/DisplayCursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdersch/Contralto2/3fa39763320c9fcf6ca6baf5ae94bbc0f38a95c5/ContraltoUI/Assets/DisplayCursor.png -------------------------------------------------------------------------------- /ContraltoUI/ContraltoUI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | enable 5 | latest 6 | 2.0.0.0 7 | 2.0.0.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | AltoDisplay.axaml 39 | 40 | 41 | LogWindow.axaml 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /ContraltoUI/Converters/BoolToWindowStateConverter.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Avalonia.Data.Converters; 24 | using Avalonia.Data; 25 | using System; 26 | using System.Globalization; 27 | using Avalonia.Controls; 28 | 29 | namespace ContraltoUI.Converters 30 | { 31 | public class BoolToWindowStateConverter : IValueConverter 32 | { 33 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 34 | { 35 | if (value == null) 36 | { 37 | return false; 38 | } 39 | 40 | WindowState? val = (bool)value ? WindowState.FullScreen : WindowState.Normal; 41 | return val; 42 | } 43 | 44 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 45 | { 46 | throw new NotSupportedException(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ContraltoUI/Converters/EnumToBoolConverter.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Avalonia.Data.Converters; 24 | using Avalonia.Data; 25 | using System; 26 | using System.Globalization; 27 | 28 | namespace ContraltoUI.Converters 29 | { 30 | public class EnumToBoolConverter : IValueConverter 31 | { 32 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 33 | { 34 | return value?.Equals(parameter); 35 | } 36 | 37 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 38 | { 39 | return value?.Equals(true) == true ? parameter : BindingOperations.DoNothing; 40 | } 41 | } 42 | 43 | public class InvertedEnumToBoolConverter : IValueConverter 44 | { 45 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 46 | { 47 | return !value?.Equals(parameter); 48 | } 49 | 50 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 51 | { 52 | return !value?.Equals(true) == true ? parameter : BindingOperations.DoNothing; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ContraltoUI/HighResolutionTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Threading; 4 | 5 | 6 | namespace ContraltoUI 7 | { 8 | /// 9 | /// High-Resolution timer for frame-rate throttling; based on a gist at https://gist.github.com/DraTeots/436019368d32007284f8a12f1ba0f545 10 | /// 11 | public class HighResolutionTimer 12 | { 13 | /// 14 | /// Tick time length in [ms] 15 | /// 16 | public static readonly double TickLength = 1000f / Stopwatch.Frequency; 17 | 18 | /// 19 | /// Tick frequency 20 | /// 21 | public static readonly double Frequency = Stopwatch.Frequency; 22 | 23 | /// 24 | /// True if the system/operating system supports HighResolution timer 25 | /// 26 | public static bool IsHighResolution = Stopwatch.IsHighResolution; 27 | 28 | /// 29 | /// Indicates whether the timer is currently running. 30 | /// 31 | public bool IsRunning => _isRunning; 32 | 33 | 34 | /// 35 | /// Creates timer with interval in [ms] 36 | /// 37 | /// Interval time in [ms] 38 | public HighResolutionTimer(float interval) 39 | { 40 | Interval = interval; 41 | _event = new AutoResetEvent(false); 42 | } 43 | 44 | /// 45 | /// The interval of a timer in [ms] 46 | /// 47 | public float Interval 48 | { 49 | get { return _interval; } 50 | set 51 | { 52 | if (value < 0f || Single.IsNaN(value)) 53 | { 54 | throw new ArgumentOutOfRangeException(nameof(value)); 55 | } 56 | _interval = value; 57 | } 58 | } 59 | 60 | /// 61 | /// If true, sets the execution thread to ThreadPriority.Highest 62 | /// (works after the next Start()) 63 | /// 64 | /// 65 | /// It might help in some cases and get things worse in others. 66 | /// It suggested that you do some studies if you apply 67 | /// 68 | public bool UseHighPriorityThread { get; set; } = false; 69 | 70 | /// 71 | /// Starts the timer 72 | /// 73 | public void Start() 74 | { 75 | if (_isRunning) 76 | { 77 | return; 78 | } 79 | 80 | _isRunning = true; 81 | _thread = new Thread(ExecuteTimer) 82 | { 83 | IsBackground = true, 84 | }; 85 | 86 | if (UseHighPriorityThread) 87 | { 88 | _thread.Priority = ThreadPriority.Highest; 89 | } 90 | _thread.Start(); 91 | } 92 | 93 | /// 94 | /// Stops the timer 95 | /// 96 | /// 97 | /// This function is waiting an executing thread (which do to stop and join. 98 | /// 99 | public void Stop(bool joinThread = true) 100 | { 101 | if (!_isRunning || _thread == null) 102 | { 103 | return; 104 | } 105 | 106 | _isRunning = false; 107 | 108 | if (joinThread && Thread.CurrentThread != _thread) 109 | { 110 | _thread.Join(); 111 | } 112 | } 113 | 114 | /// 115 | /// Waits for the timer to tick. 116 | /// 117 | public void Wait() 118 | { 119 | _event.WaitOne(); 120 | } 121 | 122 | private void ExecuteTimer() 123 | { 124 | float nextTrigger = 0f; 125 | 126 | Stopwatch stopwatch = new Stopwatch(); 127 | stopwatch.Start(); 128 | 129 | while (_isRunning) 130 | { 131 | nextTrigger += _interval; 132 | double elapsed; 133 | 134 | while (true) 135 | { 136 | elapsed = ElapsedHiRes(stopwatch); 137 | double diff = nextTrigger - elapsed; 138 | if (diff <= 0.0f) 139 | { 140 | break; 141 | } 142 | 143 | if (diff < 1.0f) 144 | { 145 | Thread.SpinWait(10); 146 | } 147 | else if (diff < 5.0f) 148 | { 149 | Thread.SpinWait(100); 150 | } 151 | else if (diff < 15.0f) 152 | { 153 | Thread.Sleep(1); 154 | } 155 | else 156 | { 157 | Thread.Sleep(10); 158 | } 159 | 160 | if (!_isRunning) 161 | { 162 | return; 163 | } 164 | } 165 | 166 | double delay = elapsed - nextTrigger; 167 | _event.Set(); 168 | 169 | if (!_isRunning) 170 | { 171 | return; 172 | } 173 | 174 | // restarting the timer in every hour to prevent precision problems 175 | if (stopwatch.Elapsed.TotalHours >= 1d) 176 | { 177 | stopwatch.Restart(); 178 | nextTrigger = 0f; 179 | } 180 | } 181 | 182 | stopwatch.Stop(); 183 | } 184 | 185 | private static double ElapsedHiRes(Stopwatch stopwatch) 186 | { 187 | return stopwatch.ElapsedTicks * TickLength; 188 | } 189 | 190 | 191 | private volatile float _interval; 192 | private volatile bool _isRunning; 193 | private Thread? _thread; 194 | private AutoResetEvent _event; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /ContraltoUI/SDLAudioSink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Runtime.InteropServices; 4 | using Contralto.IO; 5 | using Contralto.Logging; 6 | using SDL2; 7 | 8 | namespace ContraltoUI 9 | { 10 | public class SDLAudioSink : IAudioSink 11 | { 12 | public SDLAudioSink() 13 | { 14 | InitializeSDL(); 15 | _audioBuffer = new ConcurrentQueue(); 16 | _sampleBuffer = new byte[0x10000]; 17 | } 18 | 19 | public void WriteSample(ushort sample) 20 | { 21 | _audioBuffer.Enqueue(sample); 22 | } 23 | 24 | public void Shutdown() 25 | { 26 | SDL.SDL_Quit(); 27 | } 28 | 29 | private void InitializeSDL() 30 | { 31 | SDL.SDL_SetHint("SDL_WINDOWS_DISABLE_THREAD_NAMING", "1"); 32 | 33 | int retVal; 34 | if ((retVal = SDL.SDL_Init(SDL.SDL_INIT_EVERYTHING)) < 0) 35 | { 36 | Log.Write(LogType.Error, LogComponent.DAC, "Failed to initialize SDL, retval 0x{0:x}", retVal); 37 | return; 38 | } 39 | 40 | // 41 | // Initialize SDL Audio: 42 | // 43 | SDL.SDL_AudioSpec desired = new SDL.SDL_AudioSpec(); 44 | 45 | _audioCallback = AudioCallback; 46 | 47 | desired.freq = AudioDAC.AudioDACSamplingRate; 48 | desired.format = SDL.AUDIO_U16LSB; // the default is little-endian but we'll make it explicit. 49 | desired.channels = 1; 50 | desired.callback = _audioCallback; 51 | desired.samples = 4096; 52 | 53 | uint deviceId = 1; 54 | if (SDL.SDL_OpenAudio(ref desired, IntPtr.Zero) < 0) 55 | { 56 | Log.Write(LogType.Error, LogComponent.DAC, "Failed to open default audio device, error 0x{0:x}", SDL.SDL_GetError()); 57 | return; 58 | } 59 | 60 | SDL.SDL_PauseAudioDevice(deviceId, 0); 61 | 62 | 63 | Log.Write(LogComponent.DAC, "SDL Audio initialized, device id {0}", deviceId); 64 | } 65 | 66 | private void AudioCallback(IntPtr userData, IntPtr stream, int length) 67 | { 68 | ushort lastSample = 0; 69 | for (int i = 0; i < length / 2; i++) 70 | { 71 | if (_audioBuffer.TryDequeue(out ushort sample)) 72 | { 73 | _sampleBuffer[i * 2] = (byte)sample; 74 | _sampleBuffer[i * 2 + 1] = (byte)(sample >> 8); 75 | lastSample = sample; 76 | } 77 | else 78 | { 79 | // Out of data, just send the last sample to try to reduce popping. 80 | _sampleBuffer[i * 2] = (byte)lastSample; 81 | _sampleBuffer[i * 2 + 1] = (byte)(lastSample >> 8); 82 | } 83 | } 84 | 85 | Marshal.Copy(_sampleBuffer, 0, stream, length); 86 | } 87 | 88 | /// 89 | /// Reused buffer for marshaling to SDL2. 90 | /// 91 | private byte[] _sampleBuffer; 92 | 93 | /// 94 | /// Audio samples waiting to be written out. 95 | /// 96 | private ConcurrentQueue _audioBuffer; 97 | 98 | // 99 | // Local reference for the SDL Audio callback: 100 | // SDL-CS doesn't hold this reference which causes 101 | // problems when the GC runs. 102 | // 103 | private SDL.SDL_AudioCallback _audioCallback; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /ContraltoUI/ViewModels/LogViewModel.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Contralto; 24 | using Contralto.Logging; 25 | using System.Collections.Generic; 26 | 27 | 28 | namespace ContraltoUI.ViewModels 29 | { 30 | public partial class LogViewModel : ViewModelBase 31 | { 32 | public LogViewModel(AltoSystem system) 33 | { 34 | _system = system; 35 | 36 | Log.Updated += OnLogUpdated; 37 | } 38 | 39 | private void OnLogUpdated(object? sender, System.EventArgs e) 40 | { 41 | OnPropertyChanged(nameof(LogText)); 42 | } 43 | 44 | public override void OnApplicationExit() 45 | { 46 | 47 | } 48 | 49 | public IEnumerable LogText => Log.LogText; 50 | 51 | 52 | private AltoSystem _system; 53 | 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ContraltoUI/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Avalonia.Controls.ApplicationLifetimes; 24 | using Avalonia.Controls; 25 | using CommunityToolkit.Mvvm.ComponentModel; 26 | using System.Collections.Generic; 27 | using System.ComponentModel; 28 | using Avalonia; 29 | using System; 30 | using System.Linq; 31 | 32 | namespace ContraltoUI.ViewModels; 33 | 34 | 35 | public abstract class ViewModelBase : ObservableObject 36 | { 37 | // Let the VM know if the application is exiting so it can yell at the model about it. 38 | public abstract void OnApplicationExit(); 39 | 40 | public static IEnumerable Windows => 41 | (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.Windows ?? Array.Empty(); 42 | 43 | /// 44 | /// This is a hack to kinda sorta let viewmodels find an appropriate window for doing things like parenting file picker dialogs. 45 | /// 46 | /// 47 | /// 48 | public static Window FindWindowByViewModel(INotifyPropertyChanged viewModel) 49 | { 50 | Window? window = Windows.FirstOrDefault(x => ReferenceEquals(viewModel, x.DataContext)); 51 | 52 | if (window == null) 53 | { 54 | throw new InvalidOperationException("No parent window found."); 55 | } 56 | 57 | return window; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ContraltoUI/Views/AboutDialog.axaml: -------------------------------------------------------------------------------- 1 | 22 | 23 | 41 | 42 | 43 | ContrAlto v 44 | 45 | 46 | A Xerox Alto Emulator 47 | (c) 2016-2020 Living Computers: Museum+Labs 48 | (c) 2016-2024 Josh Dersch 49 | Bug reports or comments to derschjo@gmail.com 50 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ContraltoUI/Views/LogWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace ContraltoUI.Views 4 | { 5 | public partial class LogWindow : Window 6 | { 7 | public LogWindow() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ContraltoUI/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024 Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from 12 | this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | */ 22 | 23 | using Avalonia.Controls; 24 | using Avalonia.Input; 25 | using Avalonia.Interactivity; 26 | using ContraltoUI.ViewModels; 27 | 28 | namespace ContraltoUI.Views; 29 | 30 | public partial class MainWindow : Window 31 | { 32 | public MainWindow() 33 | { 34 | InitializeComponent(); 35 | } 36 | 37 | protected override void OnLoaded(RoutedEventArgs e) 38 | { 39 | if (DataContext is AltoUIViewModel vm) 40 | { 41 | // Pass along the scale factor to the viewmodel so we can compensate. 42 | vm.HostDesktopDisplayScale = DesktopScaling; 43 | } 44 | 45 | base.OnLoaded(e); 46 | } 47 | 48 | protected override void OnClosing(WindowClosingEventArgs e) 49 | { 50 | // Is this tight coupling? Is this private action? Do I care? 51 | // (If there's a better way to do this, I'm unaware of it.) 52 | // Anyway -- let our viewmodel know what's going on so it can stop things. 53 | if (DataContext is ViewModelBase vm) 54 | { 55 | vm.OnApplicationExit(); 56 | } 57 | } 58 | 59 | protected override void OnLostFocus(RoutedEventArgs e) 60 | { 61 | if (DataContext is AltoUIViewModel vm) 62 | { 63 | vm.OnLostFocus(); 64 | } 65 | base.OnLostFocus(e); 66 | } 67 | 68 | protected override void OnGotFocus(GotFocusEventArgs e) 69 | { 70 | if (DataContext is AltoUIViewModel vm) 71 | { 72 | vm.OnFocused(); 73 | } 74 | base.OnGotFocus(e); 75 | } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | enable 4 | 11.0.2 5 | 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016-2020 Living Computers: Museum+Labs 4 | Copyright (c) 2016-2024, Josh Dersch 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ContrAlto 2.0 2 | 3 | ContrAlto aspires to be a faithful emulation of the Xerox Alto series of 4 | pioneering graphical workstations developed at Xerox PARC starting in 1973. 5 | 6 | At this time, it runs all known software, though some may make use of hardware 7 | that is not yet implemented (RS232, IMP interfaces, etc.) 8 | 9 | For releases, please see: https://github.com/jdersch/Contralto2/releases. 10 | 11 | For documentation, please see: https://github.com/jdersch/Contralto2/blob/master/Contralto/readme.txt --------------------------------------------------------------------------------