1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-17 08:34:15 +00:00

291 lines
9.8 KiB
C#

using Contralto.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Contralto
{
/// <summary>
/// The configuration of an Alto II to emulate
/// </summary>
public enum SystemType
{
/// <summary>
/// System with the standard 1K ROM, 1K RAM
/// </summary>
OneKRom,
/// <summary>
/// System with 2K ROM, 1K RAM
/// </summary>
TwoKRom,
/// <summary>
/// System with 3K RAM
/// </summary>
ThreeKRam,
}
public enum PacketInterfaceType
{
/// <summary>
/// Encapsulate frames inside raw ethernet frames on the host interface.
/// Requires PCAP.
/// </summary>
EthernetEncapsulation,
/// <summary>
/// Encapsulate frames inside UDP datagrams on the host interface.
/// </summary>
UDPEncapsulation,
/// <summary>
/// No encapsulation; sent packets are dropped on the floor and no packets are received.
/// </summary>
None,
}
public enum AlternateBootType
{
None,
Disk,
Ethernet,
}
/// <summary>
/// Encapsulates user-configurable settings. To be enhanced.
/// </summary>
public class Configuration
{
static Configuration()
{
// Initialize things to defaults.
HostAddress = 0x22;
AlternateBootType = AlternateBootType.Disk;
BootAddress = 0;
BootFile = 0;
SystemType = SystemType.TwoKRom;
InterlaceDisplay = false;
ThrottleSpeed = true;
ReadConfiguration();
}
/// <summary>
/// The type of Alto II to emulate
/// </summary>
public static SystemType SystemType;
/// <summary>
/// The currently loaded image for Drive 0
/// </summary>
public static string Drive0Image;
/// <summary>
/// The currently loaded image for Drive 1
/// </summary>
public static string Drive1Image;
/// <summary>
/// The Ethernet host address for this Alto
/// </summary>
public static byte HostAddress;
/// <summary>
/// The name of the Ethernet adaptor on the emulator host to use for Ethernet emulation
/// </summary>
public static string HostPacketInterfaceName;
/// <summary>
/// Whether any packet interfaces are available on the host
/// </summary>
public static bool HostRawEthernetInterfacesAvailable;
/// <summary>
/// The type of interface to use to host networking.
/// </summary>
public static PacketInterfaceType HostPacketInterfaceType;
/// <summary>
/// The type of Alternate Boot to apply
/// </summary>
public static AlternateBootType AlternateBootType;
/// <summary>
/// The address to boot at reset for a disk alternate boot
/// </summary>
public static ushort BootAddress;
/// <summary>
/// The file to boot at reset for an ethernet alternate boot
/// </summary>
public static ushort BootFile;
/// <summary>
/// Whether to render the display "interlaced" or not.
/// </summary>
public static bool InterlaceDisplay;
/// <summary>
/// Whether to cap execution speed at native execution speed or not.
/// </summary>
public static bool ThrottleSpeed;
/// <summary>
/// Reads the current configuration file from disk.
///
/// TODO: use reflection to do this.
/// </summary>
public static void ReadConfiguration()
{
try
{
using (StreamReader configStream = new StreamReader("contralto.cfg"))
{
//
// Config file consists of text lines containing name / value pairs:
// <Name> <Value>
// Whitespace is ignored
//
int lineNumber = 0;
while (!configStream.EndOfStream)
{
lineNumber++;
string line = configStream.ReadLine().Trim();
if (string.IsNullOrEmpty(line))
{
continue;
}
// Find whitespace separating tokens
int ws = line.IndexOfAny(new char[] { ' ', '\t' });
if (ws < 1)
{
Log.Write(LogType.Warning, LogComponent.Configuration, "Syntax error on line {0}. Ignoring.", lineNumber);
continue;
}
string parameter = line.Substring(0, ws);
string value = line.Substring(ws + 1, line.Length - ws - 1);
try
{
switch (parameter.ToLowerInvariant())
{
case "drive0image":
Drive0Image = value;
break;
case "drive1image":
Drive1Image = value;
break;
case "systemtype":
SystemType = (SystemType)Enum.Parse(typeof(SystemType), value, true);
break;
case "hostaddress":
HostAddress = Convert.ToByte(value, 8);
break;
case "hostpacketinterfacename":
HostPacketInterfaceName = value;
break;
case "hostpacketinterfacetype":
HostPacketInterfaceType = (PacketInterfaceType)Enum.Parse(typeof(PacketInterfaceType), value, true);
break;
case "alternateboottype":
AlternateBootType = (AlternateBootType)Enum.Parse(typeof(AlternateBootType), value, true);
break;
case "bootaddress":
BootAddress = Convert.ToUInt16(value, 8);
break;
case "bootfile":
BootFile = Convert.ToUInt16(value, 8);
break;
case "interlacedisplay":
InterlaceDisplay = bool.Parse(value);
break;
case "throttlespeed":
ThrottleSpeed = bool.Parse(value);
break;
default:
Log.Write(LogType.Warning, LogComponent.Configuration, "Invalid parameter on line {0}. Ignoring.", lineNumber);
break;
}
}
catch
{
Log.Write(LogType.Warning, LogComponent.Configuration, "Invalid value on line {0}. Ignoring.", lineNumber);
continue;
}
}
}
}
catch (Exception)
{
Log.Write(LogType.Warning, LogComponent.Configuration, "Configuration file 'contralto.cfg' could not be read; assuming default settings.");
WriteConfiguration();
}
}
/// <summary>
/// Commits the current configuration to disk.
/// </summary>
public static void WriteConfiguration()
{
try
{
using (StreamWriter configStream = new StreamWriter("contralto.cfg"))
{
if (!string.IsNullOrEmpty(Drive0Image))
{
configStream.WriteLine("Drive0Image {0}", Drive0Image);
}
if (!string.IsNullOrEmpty(Drive1Image))
{
configStream.WriteLine("Drive1Image {0}", Drive1Image);
}
configStream.WriteLine("SystemType {0}", SystemType);
configStream.WriteLine("HostAddress {0}", Conversion.ToOctal(HostAddress));
if (!string.IsNullOrEmpty(HostPacketInterfaceName))
{
configStream.WriteLine("HostPacketInterfaceName {0}", HostPacketInterfaceName);
}
configStream.WriteLine("HostPacketInterfaceType {0}", HostPacketInterfaceType);
configStream.WriteLine("AlternateBootType {0}", AlternateBootType);
configStream.WriteLine("BootAddress {0}", Conversion.ToOctal(BootAddress));
configStream.WriteLine("BootFile {0}", Conversion.ToOctal(BootFile));
configStream.WriteLine("InterlaceDisplay {0}", InterlaceDisplay);
configStream.WriteLine("ThrottleSpeed {0}", ThrottleSpeed);
}
}
catch (Exception)
{
Log.Write(LogType.Warning, LogComponent.Configuration, "Configuration file 'contralto.cfg' could not be opened for writing.");
}
}
}
}