BizHawk/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.ISettable.cs

351 lines
12 KiB
C#

using BizHawk.Common;
using BizHawk.Emulation.Common;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
/// <summary>
/// CPCHawk: Core Class
/// * ISettable *
/// </summary>
public partial class AmstradCPC : ISettable<AmstradCPC.AmstradCPCSettings, AmstradCPC.AmstradCPCSyncSettings>
{
internal AmstradCPCSettings Settings = new AmstradCPCSettings();
internal AmstradCPCSyncSettings SyncSettings = new AmstradCPCSyncSettings();
public AmstradCPCSettings GetSettings()
{
return Settings.Clone();
}
public AmstradCPCSyncSettings GetSyncSettings()
{
return SyncSettings.Clone();
}
public bool PutSettings(AmstradCPCSettings o)
{
// restore user settings to devices
if (_machine != null && _machine.AYDevice != null)
{
((AY38912)_machine.AYDevice as AY38912).PanningConfiguration = o.AYPanConfig;
_machine.AYDevice.Volume = o.AYVolume;
}
if (_machine != null && _machine.TapeBuzzer != null)
{
((Beeper)_machine.TapeBuzzer as Beeper).Volume = o.TapeVolume;
}
Settings = o;
return false;
}
public bool PutSyncSettings(AmstradCPCSyncSettings o)
{
bool ret = AmstradCPCSyncSettings.NeedsReboot(SyncSettings, o);
SyncSettings = o;
return ret;
}
public class AmstradCPCSettings
{
[DisplayName("AY-3-8912 Panning Config")]
[Description("Set the PSG panning configuration.\nThe chip has 3 audio channels that can be outputed in different configurations")]
[DefaultValue(AY38912.AYPanConfig.ABC)]
public AY38912.AYPanConfig AYPanConfig { get; set; }
[DisplayName("AY-3-8912 Volume")]
[Description("The AY chip volume")]
[DefaultValue(75)]
public int AYVolume { get; set; }
[DisplayName("Core OSD Message Verbosity")]
[Description("Full: Display all GUI messages\nMedium: Display only emulator/device generated messages\nNone: Show no messages")]
[DefaultValue(OSDVerbosity.Medium)]
public OSDVerbosity OSDMessageVerbosity { get; set; }
[DisplayName("Tape Loading Volume")]
[Description("The buzzer volume when the tape is playing")]
[DefaultValue(50)]
public int TapeVolume { get; set; }
public AmstradCPCSettings Clone()
{
return (AmstradCPCSettings)MemberwiseClone();
}
public AmstradCPCSettings()
{
BizHawk.Common.SettingsUtil.SetDefaultValues(this);
}
}
public class AmstradCPCSyncSettings
{
[DisplayName("Deterministic Emulation")]
[Description("If true, the core agrees to behave in a completely deterministic manner")]
[DefaultValue(true)]
public bool DeterministicEmulation { get; set; }
[DisplayName("CPC Model")]
[Description("The model of Amstrad CPC machine to be emulated")]
[DefaultValue(MachineType.CPC464)]
public MachineType MachineType { get; set; }
[DisplayName("Auto Start/Stop Tape")]
[Description("If true, CPCHawk will automatically start and stop the tape when the tape motor is triggered")]
[DefaultValue(true)]
public bool AutoStartStopTape { get; set; }
[DisplayName("Border type")]
[Description("Select how to show the border area")]
[DefaultValue(BorderType.Uniform)]
public BorderType BorderType { get; set; }
public AmstradCPCSyncSettings Clone()
{
return (AmstradCPCSyncSettings)MemberwiseClone();
}
public AmstradCPCSyncSettings()
{
BizHawk.Common.SettingsUtil.SetDefaultValues(this);
}
public static bool NeedsReboot(AmstradCPCSyncSettings x, AmstradCPCSyncSettings y)
{
return !DeepEquality.DeepEquals(x, y);
}
}
/// <summary>
/// Verbosity of the CPCHawk generated OSD messages
/// </summary>
public enum OSDVerbosity
{
/// <summary>
/// Show all OSD messages
/// </summary>
Full,
/// <summary>
/// Only show machine/device generated messages
/// </summary>
Medium,
/// <summary>
/// No core-driven OSD messages
/// </summary>
None
}
/// <summary>
/// Provides information on each emulated machine
/// </summary>
public class CPCMachineMetaData
{
public MachineType MachineType { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Released { get; set; }
public string CPU { get; set; }
public string Memory { get; set; }
public string Video { get; set; }
public string Audio { get; set; }
public string Media { get; set; }
public string OtherMisc { get; set; }
Dictionary<string, string> Data = new Dictionary<string, string>();
public static CPCMachineMetaData GetMetaObject(MachineType type)
{
CPCMachineMetaData m = new CPCMachineMetaData();
m.MachineType = type;
switch (type)
{
case MachineType.CPC464:
m.Name = "Amstrad CPC 464";
m.Description = "The CPC 464 was the first personal home computer built by Amstrad in 1984. ";
m.Description += "The 464 was popular with consumers for various reasons. Aside from the joystick port, the computer, keyboard, and tape deck were all combined into one unit.";
m.Released = "1984";
m.CPU = "Zilog Z80A @ 4MHz";
m.Memory = "64KB RAM / 32KB ROM";
m.Video = "Amstrad Gate Array @ 16Mhz & CRCT @ 1Mhz";
m.Audio = "General Instruments AY-3-8912 PSG (3ch)";
m.Media = "Cassette Tape (via built-in Datacorder)";
break;
case MachineType.CPC6128:
m.Name = "Amstrad CPC 6128";
m.Description = "The CPC6128 features 128 KB RAM and an internal 3-inch floppy disk drive. ";
m.Description += "Aside from various hardware and firmware improvements, one of the CPC6128's most prominent features is the compatibility with the CP/M+ operating system that rendered it attractive for business uses.";
m.Released = "1985";
m.CPU = "Zilog Z80A @ 4MHz";
m.Memory = "64KB RAM / 32KB ROM";
m.Video = "Amstrad Gate Array @ 16Mhz & CRCT @ 1Mhz";
m.Audio = "General Instruments AY-3-8912 PSG (3ch)";
m.Media = "3\" Floppy Disk (via built-in Floppy Drive) & Cassette Tape (via external cassette player)";
break;
}
m.Data.Add(AmstradCPC.GetMemberName((CPCMachineMetaData c) => c.Name), m.Name.Trim());
m.Data.Add(AmstradCPC.GetMemberName((CPCMachineMetaData c) => c.Description), m.Description.Trim());
m.Data.Add(AmstradCPC.GetMemberName((CPCMachineMetaData c) => c.Released), m.Released.Trim());
m.Data.Add(AmstradCPC.GetMemberName((CPCMachineMetaData c) => c.CPU), m.CPU.Trim());
m.Data.Add(AmstradCPC.GetMemberName((CPCMachineMetaData c) => c.Memory), m.Memory.Trim());
m.Data.Add(AmstradCPC.GetMemberName((CPCMachineMetaData c) => c.Video), m.Video.Trim());
m.Data.Add(AmstradCPC.GetMemberName((CPCMachineMetaData c) => c.Audio), m.Audio.Trim());
m.Data.Add(AmstradCPC.GetMemberName((CPCMachineMetaData c) => c.Media), m.Media.Trim());
return m;
}
public static string GetMetaString(MachineType type)
{
var m = GetMetaObject(type);
StringBuilder sb = new StringBuilder();
// get longest title
int titleLen = 0;
foreach (var d in m.Data)
{
if (d.Key.Length > titleLen)
titleLen = d.Key.Length;
}
var maxDataLineLen = 40;
// generate layout
foreach (var d in m.Data)
{
var tLen = d.Key.Length;
var makeup = (titleLen - tLen) / 4;
sb.Append(d.Key + ":\t");
for (int i = 0; i < makeup; i++)
{
if (tLen > 4)
sb.Append("\t");
else
{
makeup--;
sb.Append("\t");
}
}
// output the data splitting and tabbing as neccessary
var arr = d.Value.Split(' ');
int cnt = 0;
List<string> builder = new List<string>();
string working = "";
foreach (var s in arr)
{
var len = s.Length;
if (working.Length + 1 + len > maxDataLineLen)
{
// new line needed
builder.Add(working.Trim(' '));
working = "";
}
working += s + " ";
}
builder.Add(working.Trim(' '));
// output the data
for (int i = 0; i < builder.Count; i++)
{
if (i != 0)
{
sb.Append("\t");
sb.Append("\t");
}
sb.Append(builder[i]);
sb.Append("\r\n");
}
//sb.Append("\r\n");
}
return sb.ToString();
}
public static string GetMetaStringOld(MachineType type)
{
var m = GetMetaObject(type);
StringBuilder sb = new StringBuilder();
sb.Append(m.Name);
sb.Append("\n");
sb.Append("-----------------------------------------------------------------\n");
// Release
sb.Append("Released:");
sb.Append(" ");
sb.Append(m.Released);
sb.Append("\n");
// CPU
sb.Append("CPU:");
sb.Append(" ");
sb.Append(m.CPU);
sb.Append("\n");
// Memory
sb.Append("Memory:");
sb.Append(" ");
sb.Append(m.Memory);
sb.Append("\n");
// Video
sb.Append("Video:");
sb.Append(" ");
sb.Append(m.Video);
sb.Append("\n");
// Audio
sb.Append("Audio:");
sb.Append(" ");
sb.Append(m.Audio);
sb.Append("\n");
// Audio
sb.Append("Media:");
sb.Append(" ");
sb.Append(m.Media);
sb.Append("\n");
sb.Append("-----------------------------------------------------------------\n");
// description
sb.Append(m.Description);
if (m.OtherMisc != null)
sb.Append("\n" + m.OtherMisc);
return sb.ToString();
}
}
/// <summary>
/// The size of the Spectrum border
/// </summary>
public enum BorderType
{
/// <summary>
/// Attempts to equalise the border areas
/// </summary>
Uniform,
/// <summary>
/// Pretty much the signal the gate array is generating (looks shit)
/// </summary>
Uncropped,
/// <summary>
/// Top and bottom border removed so that the result is *almost* 16:9
/// </summary>
Widescreen,
}
}
}