ZXHawk: debug only zx-state snapshot export
This commit is contained in:
parent
e3736bdaa7
commit
16d68ea813
|
@ -389,7 +389,9 @@
|
|||
this.ZXSpectrumPokeMemoryMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ZXSpectrumMediaMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ZXSpectrumTapesSubMenu = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.zxt1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ZXSpectrumDisksSubMenu = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.zxt2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.Atari7800HawkCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.MainStatusBar = new StatusStripEx();
|
||||
this.DumpStatusButton = new System.Windows.Forms.ToolStripDropDownButton();
|
||||
|
@ -462,8 +464,7 @@
|
|||
this.ShowMenuContextMenuSeparator = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.ShowMenuContextMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.timerMouseIdle = new System.Windows.Forms.Timer(this.components);
|
||||
this.zxt1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.zxt2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ZXSpectrumExportSnapshotMenuItemMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.MainformMenu.SuspendLayout();
|
||||
this.MainStatusBar.SuspendLayout();
|
||||
this.MainFormContextMenu.SuspendLayout();
|
||||
|
@ -3454,7 +3455,8 @@
|
|||
//
|
||||
this.ZXSpectrumMediaMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ZXSpectrumTapesSubMenu,
|
||||
this.ZXSpectrumDisksSubMenu});
|
||||
this.ZXSpectrumDisksSubMenu,
|
||||
this.ZXSpectrumExportSnapshotMenuItemMenuItem});
|
||||
this.ZXSpectrumMediaMenuItem.Name = "ZXSpectrumMediaMenuItem";
|
||||
this.ZXSpectrumMediaMenuItem.Size = new System.Drawing.Size(201, 22);
|
||||
this.ZXSpectrumMediaMenuItem.Text = "Media";
|
||||
|
@ -3465,19 +3467,31 @@
|
|||
this.ZXSpectrumTapesSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.zxt1ToolStripMenuItem});
|
||||
this.ZXSpectrumTapesSubMenu.Name = "ZXSpectrumTapesSubMenu";
|
||||
this.ZXSpectrumTapesSubMenu.Size = new System.Drawing.Size(152, 22);
|
||||
this.ZXSpectrumTapesSubMenu.Size = new System.Drawing.Size(159, 22);
|
||||
this.ZXSpectrumTapesSubMenu.Text = "Tapes";
|
||||
this.ZXSpectrumTapesSubMenu.DropDownOpened += new System.EventHandler(this.ZXSpectrumTapesSubMenu_DropDownOpened);
|
||||
//
|
||||
// zxt1ToolStripMenuItem
|
||||
//
|
||||
this.zxt1ToolStripMenuItem.Name = "zxt1ToolStripMenuItem";
|
||||
this.zxt1ToolStripMenuItem.Size = new System.Drawing.Size(94, 22);
|
||||
this.zxt1ToolStripMenuItem.Text = "zxt1";
|
||||
//
|
||||
// ZXSpectrumDisksSubMenu
|
||||
//
|
||||
this.ZXSpectrumDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.zxt2ToolStripMenuItem});
|
||||
this.ZXSpectrumDisksSubMenu.Name = "ZXSpectrumDisksSubMenu";
|
||||
this.ZXSpectrumDisksSubMenu.Size = new System.Drawing.Size(152, 22);
|
||||
this.ZXSpectrumDisksSubMenu.Size = new System.Drawing.Size(159, 22);
|
||||
this.ZXSpectrumDisksSubMenu.Text = "Disks";
|
||||
this.ZXSpectrumDisksSubMenu.DropDownOpened += new System.EventHandler(this.ZXSpectrumDisksSubMenu_DropDownOpened);
|
||||
//
|
||||
// zxt2ToolStripMenuItem
|
||||
//
|
||||
this.zxt2ToolStripMenuItem.Name = "zxt2ToolStripMenuItem";
|
||||
this.zxt2ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.zxt2ToolStripMenuItem.Text = "zxt2";
|
||||
//
|
||||
// Atari7800HawkCoreMenuItem
|
||||
//
|
||||
this.Atari7800HawkCoreMenuItem.Name = "Atari7800HawkCoreMenuItem";
|
||||
|
@ -4104,17 +4118,12 @@
|
|||
this.timerMouseIdle.Interval = 2000;
|
||||
this.timerMouseIdle.Tick += new System.EventHandler(this.TimerMouseIdle_Tick);
|
||||
//
|
||||
// zxt1ToolStripMenuItem
|
||||
// ZXSpectrumExportSnapshotMenuItemMenuItem
|
||||
//
|
||||
this.zxt1ToolStripMenuItem.Name = "zxt1ToolStripMenuItem";
|
||||
this.zxt1ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.zxt1ToolStripMenuItem.Text = "zxt1";
|
||||
//
|
||||
// zxt2ToolStripMenuItem
|
||||
//
|
||||
this.zxt2ToolStripMenuItem.Name = "zxt2ToolStripMenuItem";
|
||||
this.zxt2ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.zxt2ToolStripMenuItem.Text = "zxt2";
|
||||
this.ZXSpectrumExportSnapshotMenuItemMenuItem.Name = "ZXSpectrumExportSnapshotMenuItemMenuItem";
|
||||
this.ZXSpectrumExportSnapshotMenuItemMenuItem.Size = new System.Drawing.Size(159, 22);
|
||||
this.ZXSpectrumExportSnapshotMenuItemMenuItem.Text = "Export Snapshot";
|
||||
this.ZXSpectrumExportSnapshotMenuItemMenuItem.Click += new System.EventHandler(this.ZXSpectrumExportSnapshotMenuItemMenuItem_Click);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
|
@ -4591,5 +4600,6 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem ZXSpectrumDisksSubMenu;
|
||||
private System.Windows.Forms.ToolStripMenuItem zxt1ToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem zxt2ToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem ZXSpectrumExportSnapshotMenuItemMenuItem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2564,6 +2564,32 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
}
|
||||
|
||||
private void ZXSpectrumExportSnapshotMenuItemMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
SaveFileDialog zxSnapExpDialog = new SaveFileDialog();
|
||||
zxSnapExpDialog.RestoreDirectory = true;
|
||||
zxSnapExpDialog.Title = "EXPERIMENTAL - Export 3rd party snapshot formats";
|
||||
zxSnapExpDialog.DefaultExt = "szx";
|
||||
zxSnapExpDialog.Filter = "ZX-State files (*.szx)|*.szx";
|
||||
zxSnapExpDialog.SupportMultiDottedExtensions = true;
|
||||
|
||||
try
|
||||
{
|
||||
var res = zxSnapExpDialog.ShowDialog();
|
||||
if (res == DialogResult.OK)
|
||||
{
|
||||
var speccy = (ZXSpectrum)Emulator;
|
||||
var snap = speccy.GetSZXSnapshot();
|
||||
File.WriteAllBytes(zxSnapExpDialog.FileName, snap);
|
||||
//File.WriteAllText(zxSnapExpDialog.FileName, snap);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var ee = ex;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Help
|
||||
|
|
|
@ -1834,6 +1834,11 @@ namespace BizHawk.Client.EmuHawk
|
|||
break;
|
||||
case "ZXSpectrum":
|
||||
zXSpectrumToolStripMenuItem.Visible = true;
|
||||
#if DEBUG
|
||||
ZXSpectrumExportSnapshotMenuItemMenuItem.Visible = true;
|
||||
#else
|
||||
ZXSpectrumExportSnapshotMenuItemMenuItem.Visible = false;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4368,7 +4373,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
GenericCoreConfig.DoDialog(this, "PC-FX Settings");
|
||||
}
|
||||
|
||||
|
||||
private bool Rewind(ref bool runFrame, long currentTimestamp, out bool returnToRecording)
|
||||
{
|
||||
|
|
|
@ -293,6 +293,8 @@
|
|||
<Compile Include="Computers\SinclairSpectrum\Media\Disk\DiskType.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\MediaConverter.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\MediaConverterType.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\Snapshot\SZX\SZX.Objects.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\Snapshot\SZX\SZX.Methods.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\Tape\CSW\CswConverter.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\Tape\PZX\PzxConverter.cs" />
|
||||
<Compile Include="Computers\SinclairSpectrum\Media\Tape\TapeCommand.cs" />
|
||||
|
|
|
@ -7,6 +7,8 @@ namespace BizHawk.Emulation.Cores.Components.Z80A
|
|||
public long TotalExecutedCycles;
|
||||
|
||||
private int EI_pending;
|
||||
// ZXHawk needs to be able to read this for zx-state snapshot export
|
||||
public int EIPending { get { return EI_pending; } }
|
||||
|
||||
public const ushort CBpre = 0;
|
||||
public const ushort EXTDpre = 1;
|
||||
|
|
|
@ -19,6 +19,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// Activates a register
|
||||
/// </summary>
|
||||
int SelectedRegister { get; set; }
|
||||
|
||||
int[] ExportRegisters();
|
||||
|
||||
/// <summary>
|
||||
/// Writes to the PSG
|
||||
|
|
|
@ -167,6 +167,15 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for snapshot generation
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int[] ExportRegisters()
|
||||
{
|
||||
return _registers;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
@ -176,6 +185,14 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (i == 6)
|
||||
_registers[i] = 0xff;
|
||||
else
|
||||
_registers[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
_noiseVal = 0x0FFFF;
|
||||
_outABC = 0;
|
||||
|
|
|
@ -389,6 +389,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
{
|
||||
// fetch instruction without incrementing pc
|
||||
//_cpu.FetchInstruction(_cpu.FetchMemory(firstByte));
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// Signs that the shadow screen is now displaying
|
||||
/// Note: normal screen memory in RAM5 is not altered, the ULA just outputs Screen1 instead (RAM7)
|
||||
/// </summary>
|
||||
protected bool SHADOWPaged;
|
||||
public bool SHADOWPaged;
|
||||
|
||||
/// <summary>
|
||||
/// Index of the current RAM page
|
||||
|
@ -66,22 +66,22 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// <summary>
|
||||
/// High bit of the ROM selection (in normal paging mode)
|
||||
/// </summary>
|
||||
protected bool ROMhigh = false;
|
||||
public bool ROMhigh = false;
|
||||
|
||||
/// <summary>
|
||||
/// Low bit of the ROM selection (in normal paging mode)
|
||||
/// </summary>
|
||||
protected bool ROMlow = false;
|
||||
public bool ROMlow = false;
|
||||
|
||||
/// <summary>
|
||||
/// Signs that the +2a/+3 special paging mode is activated
|
||||
/// </summary>
|
||||
protected bool SpecialPagingMode;
|
||||
public bool SpecialPagingMode;
|
||||
|
||||
/// <summary>
|
||||
/// Index of the current special paging mode (0-3)
|
||||
/// </summary>
|
||||
protected int PagingConfiguration;
|
||||
public int PagingConfiguration;
|
||||
|
||||
/// <summary>
|
||||
/// The last byte that was read after contended cycles
|
||||
|
|
|
@ -17,6 +17,10 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
set { LastULAOutByte = value; }
|
||||
}
|
||||
|
||||
public byte Last7ffd;
|
||||
public byte LastFe;
|
||||
public byte Last1ffd;
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte of data from a specified port address
|
||||
/// </summary>
|
||||
|
|
|
@ -96,6 +96,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
// but it is only partially decoded so it actually responds to any port with bits 1 and 15 reset
|
||||
if (portBits[1] == false && portBits[15] == false)
|
||||
{
|
||||
Last7ffd = value;
|
||||
|
||||
// if paging is disabled then all writes to this port are ignored until the next reboot
|
||||
if (!PagingDisabled)
|
||||
{
|
||||
|
@ -136,6 +138,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
// Only even addresses address the ULA
|
||||
if (lowBitReset)
|
||||
{
|
||||
LastFe = value;
|
||||
|
||||
// store the last OUT byte
|
||||
LastULAOutByte = value;
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
// port 0x7ffd - hardware should only respond when bits 1 & 15 are reset and bit 14 is set
|
||||
if (!portBits[1] && !portBits[15] && portBits[14])
|
||||
{
|
||||
Last7ffd = value;
|
||||
|
||||
if (!PagingDisabled)
|
||||
{
|
||||
// bits 0, 1, 2 select the RAM page
|
||||
|
@ -97,6 +99,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
// port 0x1ffd - hardware should only respond when bits 1, 13, 14 & 15 are reset and bit 12 is set
|
||||
if (!portBits[1] && portBits[12] && !portBits[13] && !portBits[14] && !portBits[15])
|
||||
{
|
||||
Last1ffd = value;
|
||||
|
||||
if (!PagingDisabled)
|
||||
{
|
||||
if (!bits[0])
|
||||
|
@ -134,6 +138,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
// Only even addresses address the ULA
|
||||
if (lowBitReset)
|
||||
{
|
||||
LastFe = value;
|
||||
|
||||
// store the last OUT byte
|
||||
LastULAOutByte = value;
|
||||
|
||||
|
|
|
@ -68,6 +68,13 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// <param name="value"></param>
|
||||
public override void WritePort(ushort port, byte value)
|
||||
{
|
||||
if (port == 0x7ffd)
|
||||
Last7ffd = value;
|
||||
else if (port == 0x1ffd)
|
||||
Last1ffd = value;
|
||||
else if ((port & 0x01) == 0)
|
||||
LastFe = value;
|
||||
|
||||
// get a BitArray of the port
|
||||
BitArray portBits = new BitArray(BitConverter.GetBytes(port));
|
||||
// get a BitArray of the value byte
|
||||
|
|
|
@ -71,6 +71,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
if ((port & 0x0001) != 0)
|
||||
return;
|
||||
|
||||
LastFe = value;
|
||||
|
||||
// store the last OUT byte
|
||||
LastULAOutByte = value;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||
{
|
||||
|
@ -89,11 +90,22 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
/// <param name="buf"></param>
|
||||
/// <param name="offsetIndex"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetInt32(byte[] buf, int offsetIndex)
|
||||
public static int GetInt32(byte[] buf, int offsetIndex)
|
||||
{
|
||||
return buf[offsetIndex] | buf[offsetIndex + 1] << 8 | buf[offsetIndex + 2] << 16 | buf[offsetIndex + 3] << 24;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an int32 from a byte array based on offset
|
||||
/// </summary>
|
||||
/// <param name="buf"></param>
|
||||
/// <param name="offsetIndex"></param>
|
||||
/// <returns></returns>
|
||||
public static uint GetUInt32(byte[] buf, int offsetIndex)
|
||||
{
|
||||
return (uint)(buf[offsetIndex] | buf[offsetIndex + 1] << 8 | buf[offsetIndex + 2] << 16 | buf[offsetIndex + 3] << 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an uint16 from a byte array based on offset
|
||||
/// </summary>
|
||||
|
@ -148,6 +160,29 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
ds.Read(destBuffer, 0, destBuffer.Length);
|
||||
}
|
||||
|
||||
|
||||
public static byte[] SerializeRaw(object obj)
|
||||
{
|
||||
int rSize = Marshal.SizeOf(obj);
|
||||
IntPtr buff = Marshal.AllocHGlobal(rSize);
|
||||
Marshal.StructureToPtr(obj, buff, false);
|
||||
byte[] rData = new byte[rSize];
|
||||
Marshal.Copy(buff, rData, 0, rSize);
|
||||
return rData;
|
||||
}
|
||||
|
||||
public static T DeserializeRaw<T>(byte[] rData, int pos)
|
||||
{
|
||||
int rSize = Marshal.SizeOf(typeof(T));
|
||||
if (rSize > rData.Length - pos)
|
||||
throw new Exception();
|
||||
IntPtr buff = Marshal.AllocHGlobal(rSize);
|
||||
Marshal.Copy(rData, pos, buff, rSize);
|
||||
T rObj = (T)Marshal.PtrToStructure(buff, typeof(T));
|
||||
Marshal.FreeHGlobal(buff);
|
||||
return rObj;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,425 @@
|
|||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Emulation.Cores.Components.Z80A;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||
{
|
||||
/// <summary>
|
||||
/// SZX Methods
|
||||
/// Based on the work done by ArjunNair in ZERO spectrum emulator: https://github.com/ArjunNair/Zero-Emulator/blob/master/Ziggy/Peripherals/SZXFile.cs
|
||||
/// </summary>
|
||||
public partial class SZX
|
||||
{
|
||||
private SpectrumBase _machine;
|
||||
|
||||
private Z80A _cpu => _machine.CPU;
|
||||
|
||||
private SZX(SpectrumBase machine)
|
||||
{
|
||||
_machine = machine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports state information to a byte array in ZX-State format
|
||||
/// </summary>
|
||||
/// <param name="machine"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ExportSZX(SpectrumBase machine)
|
||||
{
|
||||
var s = new SZX(machine);
|
||||
|
||||
byte[] result = null;
|
||||
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter r = new BinaryWriter(ms))
|
||||
{
|
||||
// temp buffer
|
||||
byte[] buff;
|
||||
// working block
|
||||
ZXSTBLOCK block = new ZXSTBLOCK();
|
||||
|
||||
// header
|
||||
ZXSTHEADER header = new ZXSTHEADER();
|
||||
header.dwMagic = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("ZXST"), 0);
|
||||
header.chMajorVersion = 1;
|
||||
header.chMinorVersion = 4;
|
||||
header.chFlags = 0;
|
||||
switch (s._machine.Spectrum.MachineType)
|
||||
{
|
||||
case MachineType.ZXSpectrum16: header.chMachineId = (int)MachineIdentifier.ZXSTMID_16K; break;
|
||||
case MachineType.ZXSpectrum48: header.chMachineId = (int)MachineIdentifier.ZXSTMID_48K; break;
|
||||
case MachineType.ZXSpectrum128: header.chMachineId = (int)MachineIdentifier.ZXSTMID_128K; break;
|
||||
case MachineType.ZXSpectrum128Plus2: header.chMachineId = (int)MachineIdentifier.ZXSTMID_PLUS2; break;
|
||||
case MachineType.ZXSpectrum128Plus2a: header.chMachineId = (int)MachineIdentifier.ZXSTMID_PLUS2A; break;
|
||||
case MachineType.ZXSpectrum128Plus3: header.chMachineId = (int)MachineIdentifier.ZXSTMID_PLUS3; break;
|
||||
}
|
||||
buff = MediaConverter.SerializeRaw(header);
|
||||
r.Write(buff);
|
||||
|
||||
// ZXSTCREATOR
|
||||
var bStruct = s.GetZXSTCREATOR();
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("CRTR"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(bStruct);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(bStruct);
|
||||
r.Write(buff);
|
||||
|
||||
// ZXSTZ80REGS
|
||||
var cStruct = s.GetZXSTZ80REGS();
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("Z80R"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(cStruct);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(cStruct);
|
||||
r.Write(buff);
|
||||
|
||||
// ZXSTSPECREGS
|
||||
var dStruct = s.GetZXSTSPECREGS();
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("SPCR"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(dStruct);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(dStruct);
|
||||
r.Write(buff);
|
||||
|
||||
// ZXSTKEYBOARD
|
||||
var eStruct = s.GetZXSTKEYBOARD();
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("KEYB"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(eStruct);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(eStruct);
|
||||
r.Write(buff);
|
||||
|
||||
// ZXSTJOYSTICK
|
||||
var fStruct = s.GetZXSTJOYSTICK();
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("JOY\0"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(fStruct);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(fStruct);
|
||||
r.Write(buff);
|
||||
|
||||
|
||||
// ZXSTAYBLOCK
|
||||
if (s._machine.Spectrum.MachineType != MachineType.ZXSpectrum16 && s._machine.Spectrum.MachineType != MachineType.ZXSpectrum48)
|
||||
{
|
||||
var gStruct = s.GetZXSTAYBLOCK();
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("AY\0\0"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(gStruct);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(gStruct);
|
||||
r.Write(buff);
|
||||
}
|
||||
|
||||
// ZXSTRAMPAGE
|
||||
switch (s._machine.Spectrum.MachineType)
|
||||
{
|
||||
// For 16k Spectrums, only page 5 (0x4000 - 0x7fff) is saved.
|
||||
case MachineType.ZXSpectrum16:
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("RAMP"), 0);
|
||||
var rp16 = s.GetZXSTRAMPAGE(5, s._machine.RAM0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(rp16);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(rp16);
|
||||
r.Write(buff);
|
||||
break;
|
||||
// For 48k Spectrums and Timex TS/TC models, pages 5, 2 (0x8000 - 0xbfff) and 0 (0xc000 - 0xffff) are saved.
|
||||
case MachineType.ZXSpectrum48:
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("RAMP"), 0);
|
||||
var rp48_0 = s.GetZXSTRAMPAGE(5, s._machine.RAM0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(rp48_0);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(rp48_0);
|
||||
r.Write(buff);
|
||||
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("RAMP"), 0);
|
||||
var rp48_1 = s.GetZXSTRAMPAGE(5, s._machine.RAM1);
|
||||
block.dwSize = (uint)Marshal.SizeOf(rp48_1);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(rp48_1);
|
||||
r.Write(buff);
|
||||
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("RAMP"), 0);
|
||||
var rp48_2 = s.GetZXSTRAMPAGE(5, s._machine.RAM2);
|
||||
block.dwSize = (uint)Marshal.SizeOf(rp48_2);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(rp48_2);
|
||||
r.Write(buff);
|
||||
break;
|
||||
// For 128k Spectrums and the Pentagon 128, all pages (0-7) are saved.
|
||||
case MachineType.ZXSpectrum128:
|
||||
case MachineType.ZXSpectrum128Plus2:
|
||||
case MachineType.ZXSpectrum128Plus2a:
|
||||
case MachineType.ZXSpectrum128Plus3:
|
||||
List<byte[]> rams = new List<byte[]>
|
||||
{
|
||||
s._machine.RAM0, s._machine.RAM1, s._machine.RAM2, s._machine.RAM3,
|
||||
s._machine.RAM4, s._machine.RAM5, s._machine.RAM6, s._machine.RAM7
|
||||
};
|
||||
for (byte i = 0; i < 8; i++)
|
||||
{
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("RAMP"), 0);
|
||||
var rp = s.GetZXSTRAMPAGE(i, rams[i]);
|
||||
block.dwSize = (uint)Marshal.SizeOf(rp);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(rp);
|
||||
r.Write(buff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
// ZXSTPLUS3
|
||||
if (s._machine.Spectrum.MachineType == MachineType.ZXSpectrum128Plus3)
|
||||
{
|
||||
var iStruct = s.GetZXSTPLUS3();
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("+3\0\0"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(iStruct);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(iStruct);
|
||||
r.Write(buff);
|
||||
|
||||
// ZXSTDSKFILE
|
||||
if (s._machine.diskImages.Count() > 0)
|
||||
{
|
||||
var jStruct = s.GetZXSTDSKFILE();
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("DSK\0"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(jStruct);
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(jStruct);
|
||||
r.Write(buff);
|
||||
}
|
||||
}
|
||||
|
||||
// ZXSTTAPE
|
||||
if (s._machine.tapeImages.Count() > 0)
|
||||
{
|
||||
var hStruct = s.GetZXSTTAPE();
|
||||
var tapeData = s._machine.tapeImages[s._machine.TapeMediaIndex];
|
||||
block.dwId = MediaConverter.GetUInt32(Encoding.UTF8.GetBytes("TAPE"), 0);
|
||||
block.dwSize = (uint)Marshal.SizeOf(hStruct) + (uint)tapeData.Length;
|
||||
buff = MediaConverter.SerializeRaw(block);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(hStruct);
|
||||
r.Write(buff);
|
||||
buff = MediaConverter.SerializeRaw(tapeData);
|
||||
r.Write(buff);
|
||||
char[] terminator = "\0".ToCharArray();
|
||||
r.Write(terminator);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
result = ms.ToArray();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ZXSTRAMPAGE GetZXSTRAMPAGE(byte page, byte[] RAM)
|
||||
{
|
||||
var s = new ZXSTRAMPAGE();
|
||||
s.wFlags = 0; // uncompressed only at the moment
|
||||
s.chPageNo = page;
|
||||
s.ramPage = RAM;
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTCREATOR GetZXSTCREATOR()
|
||||
{
|
||||
var s = new ZXSTCREATOR();
|
||||
var str = "BIZHAWK EMULATOR".ToCharArray();
|
||||
s.szCreator = new char[32];
|
||||
for (int i = 0; i < str.Length; i++)
|
||||
s.szCreator[i] = str[i];
|
||||
s.chMajorVersion = 1;
|
||||
s.chMinorVersion = 4;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTZ80REGS GetZXSTZ80REGS()
|
||||
{
|
||||
var s = new ZXSTZ80REGS();
|
||||
s.AF = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["AF"].Value;
|
||||
s.BC = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["BC"].Value;
|
||||
s.DE = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["DE"].Value;
|
||||
s.HL = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["HL"].Value;
|
||||
s.AF1 = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["Shadow AF"].Value;
|
||||
s.BC1 = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["Shadow BC"].Value;
|
||||
s.DE1 = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["Shadow DE"].Value;
|
||||
s.HL1 = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["Shadow HL"].Value;
|
||||
s.IX = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["IX"].Value;
|
||||
s.IY = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["IY"].Value;
|
||||
s.SP = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["SP"].Value;
|
||||
s.PC = (ushort)_machine.Spectrum.GetCpuFlagsAndRegisters()["PC"].Value;
|
||||
s.I = (byte)_machine.CPU.Regs[_machine.CPU.I];
|
||||
s.R = (byte)_machine.CPU.Regs[_machine.CPU.R];
|
||||
s.IFF1 = (byte)(_machine.CPU.IFF1 ? 1 : 0);
|
||||
s.IFF2 = (byte)(_machine.CPU.IFF2 ? 1 : 0);
|
||||
s.IM = (byte)_machine.CPU.InterruptMode;
|
||||
s.dwCyclesStart = (uint)(_machine.CurrentFrameCycle + _machine.ULADevice.InterruptStartTime);
|
||||
s.wMemPtr = (ushort)(_machine.CPU.Regs[_machine.CPU.Z] + (_machine.CPU.Regs[_machine.CPU.W] << 8));
|
||||
//s.chHoldIntReqCycles = ?
|
||||
|
||||
if (_machine.CPU.EIPending > 0)
|
||||
{
|
||||
s.chFlags |= ZXSTZF_EILAST;
|
||||
}
|
||||
else if (_machine.CPU.halted)
|
||||
{
|
||||
s.chFlags |= ZXSTZF_HALTED;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTSPECREGS GetZXSTSPECREGS()
|
||||
{
|
||||
var s = new ZXSTSPECREGS();
|
||||
s.chBorder = _machine.ULADevice.BorderColor > 7 ? (byte)0 : (byte)_machine.ULADevice.BorderColor;
|
||||
s.chFe = _machine.LastFe;
|
||||
byte x7ffd = (byte)_machine.RAMPaged;
|
||||
byte x1ffd = 0;
|
||||
switch (_machine.Spectrum.MachineType)
|
||||
{
|
||||
case MachineType.ZXSpectrum16:
|
||||
case MachineType.ZXSpectrum48:
|
||||
s.ch7ffd = 0;
|
||||
s.unionPage = 0;
|
||||
break;
|
||||
|
||||
case MachineType.ZXSpectrum128:
|
||||
case MachineType.ZXSpectrum128Plus2:
|
||||
// 7FFD
|
||||
if (_machine._ROMpaged == 1)
|
||||
x7ffd |= 0x10;
|
||||
if (_machine.SHADOWPaged)
|
||||
x7ffd |= 0x08;
|
||||
if (_machine.PagingDisabled)
|
||||
x7ffd |= 0x20;
|
||||
break;
|
||||
|
||||
case MachineType.ZXSpectrum128Plus2a:
|
||||
case MachineType.ZXSpectrum128Plus3:
|
||||
if (_machine.UPDDiskDevice.FDD_FLAG_MOTOR)
|
||||
x1ffd |= 0x08;
|
||||
if (_machine.SpecialPagingMode)
|
||||
{
|
||||
x1ffd |= 0x01;
|
||||
switch (_machine.PagingConfiguration)
|
||||
{
|
||||
case 1:
|
||||
x1ffd |= 0x02;
|
||||
break;
|
||||
case 2:
|
||||
x1ffd |= 0x04;
|
||||
break;
|
||||
case 3:
|
||||
x1ffd |= 0x02;
|
||||
x1ffd |= 0x04;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_machine.ROMhigh)
|
||||
x1ffd |= 0x04;
|
||||
}
|
||||
if (_machine.ROMlow)
|
||||
x7ffd |= 0x10;
|
||||
if (_machine.SHADOWPaged)
|
||||
x7ffd |= 0x08;
|
||||
if (_machine.PagingDisabled)
|
||||
x7ffd |= 0x20;
|
||||
break;
|
||||
}
|
||||
|
||||
s.ch7ffd = x7ffd;
|
||||
s.unionPage = x1ffd;
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTKEYBOARD GetZXSTKEYBOARD()
|
||||
{
|
||||
var s = new ZXSTKEYBOARD();
|
||||
s.dwFlags = 0; //no issue 2 emulation
|
||||
s.chKeyboardJoystick |= (byte)JoystickTypes.ZXSTKJT_NONE;
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTJOYSTICK GetZXSTJOYSTICK()
|
||||
{
|
||||
var s = new ZXSTJOYSTICK();
|
||||
s.dwFlags = 0; //depreciated
|
||||
s.chTypePlayer1 |= (byte)JoystickTypes.ZXSTKJT_KEMPSTON;
|
||||
s.chTypePlayer2 |= (byte)JoystickTypes.ZXSTKJT_SINCLAIR1;
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTAYBLOCK GetZXSTAYBLOCK()
|
||||
{
|
||||
var s = new ZXSTAYBLOCK();
|
||||
s.cFlags = 0; // no external units
|
||||
s.chCurrentRegister = (byte)_machine.AYDevice.SelectedRegister;
|
||||
var regs = _machine.AYDevice.ExportRegisters();
|
||||
s.chAyRegs = new byte[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
s.chAyRegs[i] = (byte)regs[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTTAPE GetZXSTTAPE()
|
||||
{
|
||||
var s = new ZXSTTAPE();
|
||||
s.wFlags |= (int)CassetteRecorderState.ZXSTTP_EMBEDDED;
|
||||
s.wCurrentBlockNo = (ushort)_machine.TapeDevice.CurrentDataBlockIndex;
|
||||
s.dwCompressedSize = _machine.tapeImages[_machine.TapeDevice.CurrentDataBlockIndex].Length;
|
||||
s.dwUncompressedSize = _machine.tapeImages[_machine.TapeDevice.CurrentDataBlockIndex].Length;
|
||||
char[] ext = "tzx".ToCharArray();
|
||||
s.szFileExtension = new char[16];
|
||||
for (int f = 1; f < ext.Length; f++)
|
||||
{
|
||||
s.szFileExtension[f - 1] = ext[f];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTPLUS3 GetZXSTPLUS3()
|
||||
{
|
||||
var s = new ZXSTPLUS3();
|
||||
s.chNumDrives = 1;
|
||||
s.fMotorOn = _machine.UPDDiskDevice.FDD_FLAG_MOTOR ? (byte)1 : (byte)0;
|
||||
return s;
|
||||
}
|
||||
|
||||
private ZXSTDSKFILE GetZXSTDSKFILE()
|
||||
{
|
||||
var s = new ZXSTDSKFILE();
|
||||
s.wFlags = 0;
|
||||
s.chDriveNum = 0;
|
||||
s.dwUncompressedSize = 0;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,410 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
||||
{
|
||||
/// <summary>
|
||||
/// Structs, Constants and Enums
|
||||
/// http://www.spectaculator.com/docs/zx-state/intro.shtml
|
||||
/// </summary>
|
||||
public partial class SZX
|
||||
{
|
||||
#region ZX-State Header
|
||||
|
||||
public enum MachineIdentifier : byte
|
||||
{
|
||||
ZXSTMID_16K = 0,
|
||||
ZXSTMID_48K = 1,
|
||||
ZXSTMID_128K = 2,
|
||||
ZXSTMID_PLUS2 = 3,
|
||||
ZXSTMID_PLUS2A = 4,
|
||||
ZXSTMID_PLUS3 = 5,
|
||||
ZXSTMID_PLUS3E = 6,
|
||||
ZXSTMID_PENTAGON128 = 7,
|
||||
ZXSTMID_TC2048 = 8,
|
||||
ZXSTMID_TC2068 = 9,
|
||||
ZXSTMID_SCORPION = 10,
|
||||
ZXSTMID_SE = 11,
|
||||
ZXSTMID_TS2068 = 12,
|
||||
ZXSTMID_PENTAGON512 = 13,
|
||||
ZXSTMID_PENTAGON1024 = 14,
|
||||
ZXSTMID_NTSC48K = 15,
|
||||
ZXSTMID_128KE = 16
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If set, the emulated Spectrum uses alternate timings (one cycle later than normal timings). If reset, the emulated Spectrum uses standard timings.
|
||||
/// This flag is only applicable for the ZXSTMID_16K, ZXSTMID_48K and ZXSTMID_128K models.
|
||||
/// </summary>
|
||||
public const int ZXSTMF_ALTERNATETIMINGS = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The zx-state header appears right at the start of a zx-state (.szx) file.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTHEADER
|
||||
{
|
||||
public uint dwMagic;
|
||||
public byte chMajorVersion;
|
||||
public byte chMinorVersion;
|
||||
public byte chMachineId;
|
||||
public byte chFlags;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTBLOCK Header
|
||||
|
||||
/// <summary>
|
||||
/// Block Header. Each real block starts with this header.
|
||||
/// </summary>
|
||||
public struct ZXSTBLOCK
|
||||
{
|
||||
public uint dwId;
|
||||
public uint dwSize;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTCREATOR
|
||||
|
||||
/// <summary>
|
||||
/// This block identifies the program that created this zx-state file.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTCREATOR
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||
public char[] szCreator;
|
||||
public short chMajorVersion;
|
||||
public short chMinorVersion;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
|
||||
public byte[] chData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTZ80REGS
|
||||
|
||||
/// <summary>
|
||||
/// The last instruction executed was an EI instruction or an invalid $DD or $FD prefix.
|
||||
/// </summary>
|
||||
public const int ZXSTZF_EILAST = 1;
|
||||
/// <summary>
|
||||
/// The last instruction executed was a HALT instruction. The CPU is currently executing NOPs and will continue to do so until the next interrupt occurs.
|
||||
/// This flag is mutually exclusive with ZXSTZF_EILAST.
|
||||
/// </summary>
|
||||
public const int ZXSTZF_HALTED = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the Z80 registers and other internal state values. It does not contain any specific model registers.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTZ80REGS
|
||||
{
|
||||
public ushort AF, BC, DE, HL;
|
||||
public ushort AF1, BC1, DE1, HL1;
|
||||
public ushort IX, IY, SP, PC;
|
||||
public byte I;
|
||||
public byte R;
|
||||
public byte IFF1, IFF2;
|
||||
public byte IM;
|
||||
public uint dwCyclesStart;
|
||||
public byte chHoldIntReqCycles;
|
||||
public byte chFlags;
|
||||
public ushort wMemPtr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTSPECREGS
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTSPECREGS
|
||||
{
|
||||
public byte chBorder;
|
||||
public byte ch7ffd;
|
||||
public byte unionPage;
|
||||
public byte chFe;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[] chReserved;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTAYBLOCK
|
||||
|
||||
/// <summary>
|
||||
/// Fuller Box emulation
|
||||
/// </summary>
|
||||
public const int ZXSTAYF_FULLERBOX = 1;
|
||||
/// <summary>
|
||||
/// Melodik Soundbox emulation.
|
||||
/// This is essentially an AY chip for older Spectrums that uses the same ports as that found in 128k Spectrums
|
||||
/// </summary>
|
||||
public const int ZXSTAYF_128AY = 2;
|
||||
|
||||
/// <summary>
|
||||
/// The state of the AY chip found in all 128k Spectrums, Pentagons, Scorpions and Timex machines.
|
||||
/// This block may also be present for 16k/48k Spectrums if Fuller Box or Melodik emulation is enabled.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTAYBLOCK
|
||||
{
|
||||
public byte cFlags;
|
||||
public byte chCurrentRegister;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||
public byte[] chAyRegs;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTRAMPAGE
|
||||
|
||||
/// <summary>
|
||||
/// Ram pages are compressed using Zlib
|
||||
/// </summary>
|
||||
public const int ZXSTRF_COMPRESSED = 1;
|
||||
|
||||
/// <summary>
|
||||
/// zx-state files will contain a number of 16KB RAM page blocks, depending on the specific Spectrum model.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTRAMPAGE
|
||||
{
|
||||
public ushort wFlags;
|
||||
public byte chPageNo;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x4000)]
|
||||
public byte[] ramPage;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTKEYBOARD
|
||||
|
||||
/// <summary>
|
||||
/// Keyboard state
|
||||
/// </summary>
|
||||
public const int ZXSTKF_ISSUE2 = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Supported joystick types
|
||||
/// </summary>
|
||||
public enum JoystickTypes
|
||||
{
|
||||
ZXSTKJT_KEMPSTON = 0,
|
||||
ZXSTKJT_FULLER = 1,
|
||||
ZXSTKJT_CURSOR = 2,
|
||||
ZXSTKJT_SINCLAIR1 = 3,
|
||||
ZXSTKJT_SINCLAIR2 = 4,
|
||||
ZXSTKJT_SPECTRUMPLUS = 5,
|
||||
ZXSTKJT_TIMEX1 = 6,
|
||||
ZXSTKJT_TIMEX2 = 7,
|
||||
ZXSTKJT_NONE = 8
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The state of the Spectrum keyboard and any keyboard joystick emulation.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTKEYBOARD
|
||||
{
|
||||
public uint dwFlags;
|
||||
public byte chKeyboardJoystick;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTJOYSTICK
|
||||
|
||||
/// <summary>
|
||||
/// Joystick setup for both players.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTJOYSTICK
|
||||
{
|
||||
public uint dwFlags;
|
||||
public byte chTypePlayer1;
|
||||
public byte chTypePlayer2;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTTAPE
|
||||
|
||||
/// <summary>
|
||||
/// Cassette Recorder state
|
||||
/// </summary>
|
||||
public enum CassetteRecorderState
|
||||
{
|
||||
ZXSTTP_EMBEDDED = 1,
|
||||
ZXSTTP_COMPRESSED = 2
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTTAPE
|
||||
{
|
||||
public ushort wCurrentBlockNo;
|
||||
public ushort wFlags;
|
||||
public int dwUncompressedSize;
|
||||
public int dwCompressedSize;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||
public char[] szFileExtension;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTPLUS3
|
||||
|
||||
/// <summary>
|
||||
/// The number of drives connected to the Spectrum +3 and whether their motors are turned on.
|
||||
/// Any blocks specifying which disk files are in which drive will follow this one.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTPLUS3
|
||||
{
|
||||
public byte chNumDrives;
|
||||
public byte fMotorOn;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTDSKFILE
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented. All disk images are currently links to external .dsk or .ipf files
|
||||
/// </summary>
|
||||
public const int ZXSTDSKF_COMPRESSED = 1;
|
||||
/// <summary>
|
||||
/// Not implemented. All disk images are currently links to external .dsk or .ipf files
|
||||
/// </summary>
|
||||
public const int ZXSTDSKF_EMBEDDED = 2;
|
||||
/// <summary>
|
||||
/// When a double-sided disk is inserted into a single-sided drive, specifies the side being read from/written to.
|
||||
/// If set, Side B is the active side, otherwise it is Side A.
|
||||
/// </summary>
|
||||
public const int ZXSTDSKF_SIDEB = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Each +3 disk drive that has a disk inserted in it will have one of these blocks.
|
||||
/// They follow the ZXSTPLUS3 block which identifies the number of drives.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ZXSTDSKFILE
|
||||
{
|
||||
public ushort wFlags;
|
||||
public byte chDriveNum;
|
||||
public int dwUncompressedSize;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Not Yet Implemented
|
||||
|
||||
#region ZXSTATASP
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTATARAM
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTCF
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTCFRAM
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTCOVOX
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTBETA128
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTBETADISK
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTDOCK
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTGS
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTGSRAMPAGE
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTIF1
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTIF2ROM
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTMCART
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTMOUSE
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTMULTIFACE
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTOPUS
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTOPUSDISK
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTPLUSD
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTPLUSDDISK
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTROM
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTSCLDREGS
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTSIDE
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTSPECDRUM
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTUSPEECH
|
||||
|
||||
#endregion
|
||||
|
||||
#region ZXSTZXPRINTER
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -62,5 +62,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
|
||||
return m;
|
||||
}
|
||||
|
||||
public byte[] GetSZXSnapshot()
|
||||
{
|
||||
return SZX.ExportSZX(_machine);
|
||||
//return System.Text.Encoding.Default.GetString(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,9 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
deterministicEmulation = deterministic.Value;
|
||||
}
|
||||
|
||||
switch (SyncSettings.MachineType)
|
||||
MachineType = SyncSettings.MachineType;
|
||||
|
||||
switch (MachineType)
|
||||
{
|
||||
case MachineType.ZXSpectrum16:
|
||||
ControllerDefinition = ZXSpectrumControllerDefinition;
|
||||
|
@ -146,6 +148,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
|
|||
private readonly TraceBuffer _tracer;
|
||||
public IController _controller;
|
||||
public SpectrumBase _machine;
|
||||
public MachineType MachineType;
|
||||
|
||||
public List<GameInfo> _gameInfo;
|
||||
|
||||
|
|
Loading…
Reference in New Issue