/* This file is part of ContrAlto. ContrAlto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. ContrAlto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with ContrAlto. If not, see . */ using System; using System.Threading; namespace Contralto.SdlUI { public enum CommandResult { Normal, Quit } /// /// Provides a command-line interface to ContrAlto controls, /// as a substitute for the GUI interface of the Windows version. /// public class SdlConsole { public SdlConsole(AltoSystem system) { _system = system; _controller = new ExecutionController(_system); _controller.ErrorCallback += OnExecutionError; } /// /// Invoke the CLI loop in a separate thread. /// public void Run(SdlAltoWindow mainWindow) { Console.WriteLine("You are at the ContrAlto console. Type 'show commands' to see"); Console.WriteLine("a list of possible commands, and hit Tab to see possible command completions."); _mainWindow = mainWindow; _mainWindow.OnClosed += OnMainWindowClosed; _cliThread = new Thread(RunCliThread); _cliThread.Start(); } /// /// The CLI thread /// private void RunCliThread() { ConsoleExecutor executor = new ConsoleExecutor(this); CommandResult state = CommandResult.Normal; while (state != CommandResult.Quit) { state = executor.Prompt(); } // // Ensure the emulator is stopped. // _controller.StopExecution(); // // Ensure the main window is closed. // _mainWindow.Close(); } private void OnMainWindowClosed(object sender, EventArgs e) { // // Make sure the emulator is stopped. // _controller.StopExecution(); _system.Shutdown(); // // The Alto window was closed, shut down the CLI. // _cliThread.Abort(); } /// /// Error handling /// /// private void OnExecutionError(Exception e) { Console.WriteLine("Execution error: {0} - {1}", e.Message, e.StackTrace); System.Diagnostics.Debugger.Break(); } [DebuggerFunction("quit", "Exits ContrAlto.")] private CommandResult Quit() { _controller.StopExecution(); return CommandResult.Quit; } // // Console commands // [DebuggerFunction("start", "Starts the emulated Alto normally.")] private CommandResult Start() { if (_controller.IsRunning) { Console.WriteLine("Alto is already running."); } else { _controller.StartExecution(AlternateBootType.None); Console.WriteLine("Alto started."); } return CommandResult.Normal; } [DebuggerFunction("stop", "Stops the emulated Alto.")] private CommandResult Stop() { _controller.StopExecution(); Console.WriteLine("Alto stopped."); return CommandResult.Normal; } [DebuggerFunction("reset", "Resets the emulated Alto.")] private CommandResult Reset() { _controller.Reset(AlternateBootType.None); Console.WriteLine("Alto reset."); return CommandResult.Normal; } [DebuggerFunction("start with keyboard disk boot", "Starts the emulated Alto with the specified keyboard disk boot address.")] private CommandResult StartDisk() { if (_controller.IsRunning) { Console.WriteLine("Alto is already running. Use 'stop' to stop the Alto first."); } else { _controller.StartExecution(AlternateBootType.Disk); } return CommandResult.Normal; } [DebuggerFunction("start with keyboard net boot", "Starts the emulated Alto with the specified keyboard ethernet boot number.")] private CommandResult StartNet() { if (_controller.IsRunning) { Console.WriteLine("Alto is already running. Use 'stop' to stop the Alto first."); } else { _controller.StartExecution(AlternateBootType.Ethernet); } return CommandResult.Normal; } [DebuggerFunction("load disk", "Loads the specified drive with the requested disk image.", " ")] private CommandResult LoadDisk(ushort drive, string path) { if (drive > 1) { throw new InvalidOperationException("Drive specification out of range."); } // Save current drive contents. _system.CommitDiskPack(drive); // Load the new pack. _system.LoadDrive(drive, path); Console.WriteLine("Drive {0} loaded.", drive); return CommandResult.Normal; } [DebuggerFunction("unload disk", "Unloads the specified drive.", "")] private CommandResult UnloadDisk(ushort drive) { if (drive > 1) { throw new InvalidOperationException("Drive specification out of range."); } // Save current drive contents. _system.CommitDiskPack(drive); // Unload the current pack. _system.UnloadDrive(drive); Console.WriteLine("Drive {0} unloaded.", drive); return CommandResult.Normal; } [DebuggerFunction("show disk", "Displays the contents of the specified drive.", "")] private CommandResult ShowDisk(ushort drive) { if (drive > 1) { throw new InvalidOperationException("Drive specification out of range."); } // Save current drive contents. if (_system.DiskController.Drives[drive].IsLoaded) { Console.WriteLine("Drive {0} contains image {1}", drive, _system.DiskController.Drives[drive].Pack.PackName); } else { Console.WriteLine("Drive {0} is not loaded.", drive); } return CommandResult.Normal; } [DebuggerFunction("show system type", "Displays the Alto system type.")] private CommandResult ShowSystemType() { Console.WriteLine("System type is {0}", Configuration.SystemType); return CommandResult.Normal; } [DebuggerFunction("set ethernet address", "Sets the Alto's host Ethernet address.")] private CommandResult SetEthernetAddress(byte address) { if (address == 0 || address == 0xff) { Console.WriteLine("Address {0} is invalid.", Conversion.ToOctal(address)); } else { Configuration.HostAddress = address; } return CommandResult.Normal; } [DebuggerFunction("show ethernet address", "Displays the Alto's host Ethernet address.")] private CommandResult ShowEthernetAddress() { Console.WriteLine("Ethernet address is {0}", Conversion.ToOctal(Configuration.HostAddress)); return CommandResult.Normal; } [DebuggerFunction("show host network interface name", "Displays the host network interface used for Ethernet emulation")] private CommandResult ShowHostNetworkInterfaceName() { Console.WriteLine("Network interface is '{0}'", Configuration.HostPacketInterfaceName); return CommandResult.Normal; } [DebuggerFunction("show host network interface type", "Displays the host network interface type (RAW or UDP)")] private CommandResult ShowHostNetworkInterfaceType() { Console.WriteLine("Network interface type is '{0}'", Configuration.HostPacketInterfaceType); return CommandResult.Normal; } [DebuggerFunction("set keyboard net boot file", "Sets the boot file used for net booting.")] private CommandResult SetKeyboardBootFile(ushort file) { Configuration.BootFile = file; return CommandResult.Normal; } [DebuggerFunction("set keyboard disk boot address", "Sets the boot address used for disk booting.")] private CommandResult SetKeyboardBootAddress(ushort address) { Configuration.BootFile = address; return CommandResult.Normal; } // Not yet supported on non-Windows platforms /* [DebuggerFunction("enable display interlacing", "Enables interlaced display.")] private CommandResult EnableDisplayInterlacing() { Configuration.InterlaceDisplay = true; return CommandResult.Normal; } [DebuggerFunction("disable display interlacing", "Disables interlaced display.")] private CommandResult DisableDisplayInterlacing() { Configuration.InterlaceDisplay = false; return CommandResult.Normal; } [DebuggerFunction("enable speed throttling", "Limits execution speed to 60 fields/sec.")] private CommandResult EnableSpeedThrottling() { Configuration.ThrottleSpeed = true; return CommandResult.Normal; } [DebuggerFunction("disable speed throttling", "Removes speed limits.")] private CommandResult DisableSpeedThrottling() { Configuration.ThrottleSpeed = false; return CommandResult.Normal; } [DebuggerFunction("enable audio dac", "Enables the Audio DAC.")] private CommandResult EnableAudioDAC() { Configuration.EnableAudioDAC = true; return CommandResult.Normal; } [DebuggerFunction("disable audio dac", "Disables the Audio DAC.")] private CommandResult DisableAudioDAC() { Configuration.EnableAudioDAC = false; return CommandResult.Normal; } [DebuggerFunction("enable audio capture", "Enables capture of DAC output.")] private CommandResult EnableAudioDACCapture() { Configuration.EnableAudioDACCapture = true; return CommandResult.Normal; } [DebuggerFunction("disable audio capture", "Disables capture of DAC output.")] private CommandResult DisableAudioDACCapture() { Configuration.EnableAudioDACCapture = false; return CommandResult.Normal; } [DebuggerFunction("set audio capture path", "Configures the path for capture output.")] private CommandResult SetAudioCapturePath(string path) { Configuration.AudioDACCapturePath = path; return CommandResult.Normal; } */ private AltoSystem _system; private ExecutionController _controller; private SdlAltoWindow _mainWindow; private Thread _cliThread; } }