diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index 537435d739..8d0bceb934 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -275,6 +275,10 @@
+
+
+
+
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaSerializationType.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaSerializationType.cs
new file mode 100644
index 0000000000..def321b245
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaSerializationType.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
+{
+ ///
+ /// Represents the different types of media serializer avaiable
+ ///
+ public enum MediaSerializationType
+ {
+ NONE,
+ TZX,
+ TAP
+ }
+}
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaSerializer.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaSerializer.cs
new file mode 100644
index 0000000000..b20a6aa8b1
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaSerializer.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
+{
+ ///
+ /// Abtract class that represents all Media Serializers
+ ///
+ public abstract class MediaSerializer
+ {
+ ///
+ /// The type of serializer
+ ///
+ public abstract MediaSerializationType FormatType { get; }
+
+ ///
+ /// Signs whether this class can be used to serialize
+ ///
+ public virtual bool IsSerializer
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Signs whether this class can be used to de-serialize
+ ///
+ public virtual bool IsDeSerializer
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Serialization method
+ ///
+ ///
+ public virtual void Serialize(byte[] data)
+ {
+ throw new NotImplementedException(this.GetType().ToString() +
+ "Serialize operation is not implemented for this serializer");
+ }
+
+ ///
+ /// DeSerialization method
+ ///
+ ///
+ public virtual void DeSerialize(byte[] data)
+ {
+ throw new NotImplementedException(this.GetType().ToString() +
+ "DeSerialize operation is not implemented for this serializer");
+ }
+
+ #region Static Tools
+
+ ///
+ /// Converts an int32 value into a byte array
+ ///
+ ///
+ ///
+ protected static byte[] GetBytes(int value)
+ {
+ byte[] buf = new byte[4];
+ buf[0] = (byte)value;
+ buf[1] = (byte)(value >> 8);
+ buf[2] = (byte)(value >> 16);
+ buf[3] = (byte)(value >> 24);
+ return buf;
+ }
+
+ ///
+ /// Returns an int32 from a byte array based on offset
+ ///
+ ///
+ ///
+ ///
+ protected static int GetInt32(byte[] buf, int offsetIndex)
+ {
+ return buf[offsetIndex] | buf[offsetIndex + 1] << 8 | buf[offsetIndex + 2] << 16 | buf[offsetIndex + 3] << 24;
+ }
+
+ ///
+ /// Returns an uint16 from a byte array based on offset
+ ///
+ ///
+ ///
+ ///
+ protected static ushort GetUInt16(byte[] buf, int offsetIndex)
+ {
+ return (ushort)(buf[offsetIndex] | buf[offsetIndex + 1] << 8);
+ }
+
+ ///
+ /// Updates a byte array with a uint16 value based on offset
+ ///
+ ///
+ ///
+ ///
+ protected static void setUint16(byte[] buf, int offsetIndex, ushort value)
+ {
+ buf[offsetIndex] = (byte)value;
+ buf[offsetIndex + 1] = (byte)(value >> 8);
+ }
+
+ #endregion
+ }
+}
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TapeCommand.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TapeCommand.cs
new file mode 100644
index 0000000000..14fc54a460
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TapeCommand.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
+{
+ ///
+ /// Represents the possible commands that can be raised from each tape block
+ ///
+ public enum TapeCommand
+ {
+ NONE,
+ STOP_THE_TAPE,
+ STOP_THE_TAPE_48K,
+ BEGIN_GROUP,
+ END_GROUP,
+ SHOW_MESSAGE,
+ }
+}
diff --git a/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TapeDataBlock.cs b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TapeDataBlock.cs
new file mode 100644
index 0000000000..796bee81d9
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TapeDataBlock.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
+{
+ ///
+ /// Represents a tape block
+ ///
+ public class TapeDataBlock
+ {
+ ///
+ /// Either the TZX block ID, or -1 in the case of non-tzx blocks
+ ///
+ public int BlockID = -1;
+
+ ///
+ /// Description of the block
+ ///
+ public string BlockDescription { get; set; }
+
+ ///
+ /// Byte array containing the raw block data
+ ///
+ public byte[] BlockData = null;
+
+ ///
+ /// List containing the pulse timing values
+ ///
+ public List DataPeriods = new List();
+
+ ///
+ /// Command that is raised by this data block
+ /// (that may or may not need to be acted on)
+ ///
+ public TapeCommand Command = TapeCommand.NONE;
+
+ ///
+ /// Returns the data periods as an array
+ /// (primarily to aid in bizhawk state serialization)
+ ///
+ ///
+ public int[] GetDataPeriodsArray()
+ {
+ return DataPeriods.ToArray();
+ }
+
+ ///
+ /// Accepts an array of data periods and updates the DataPeriods list accordingly
+ /// (primarily to aid in bizhawk state serialization)
+ ///
+ ///
+ public void SetDataPeriodsArray(int[] periodArray)
+ {
+ DataPeriods = new List();
+
+ if (periodArray == null)
+ return;
+
+ DataPeriods = periodArray.ToList();
+ }
+ }
+}