TZX tape format handling re-write nearly complete (supporting advanced protection/loader schemes)

This commit is contained in:
Asnivor 2018-02-15 14:37:22 +00:00
parent 42b5f5dc5d
commit b9729d0dc2
6 changed files with 1809 additions and 14 deletions

View File

@ -281,6 +281,7 @@
<Compile Include="Computers\SinclairSpectrum\Media\Tape\TapeCommand.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Tape\TapeDataBlock.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Tape\TapSerializer.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Tape\TzxSerializer.cs" />
<Compile Include="Computers\SinclairSpectrum\SoundProviderMixer.cs" />
<Compile Include="Computers\SinclairSpectrum\Machine\MachineType.cs" />
<Compile Include="Computers\SinclairSpectrum\Machine\SpectrumBase.cs" />

View File

@ -233,12 +233,25 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <param name="tapeData"></param>
public void LoadTape(byte[] tapeData)
{
// attempt TZX deserialization
TzxSerializer tzxSer = new TzxSerializer(this);
try
{
tzxSer.DeSerialize(tapeData);
return;
}
catch (Exception ex)
{
// TAP format not detected
var e = ex;
}
// attempt TAP deserialization
TapSerializer tapSer = new TapSerializer(this);
try
{
tapSer.DeSerialize(tapeData);
return;
}
catch (Exception ex)
{

View File

@ -92,7 +92,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <param name="buf"></param>
/// <param name="offsetIndex"></param>
/// <returns></returns>
protected static ushort GetUInt16(byte[] buf, int offsetIndex)
protected static ushort GetWordValue(byte[] buf, int offsetIndex)
{
return (ushort)(buf[offsetIndex] | buf[offsetIndex + 1] << 8);
}
@ -103,7 +103,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
/// <param name="buf"></param>
/// <param name="offsetIndex"></param>
/// <param name="value"></param>
protected static void setUint16(byte[] buf, int offsetIndex, ushort value)
protected static void SetWordValue(byte[] buf, int offsetIndex, ushort value)
{
buf[offsetIndex] = (byte)value;
buf[offsetIndex + 1] = (byte)(value >> 8);

View File

@ -126,6 +126,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
checksum (checkbittoggle would be a better name!).............^^
*/
// clear existing tape blocks
_datacorder.DataBlocks.Clear();
// convert bytearray to memory stream
MemoryStream stream = new MemoryStream(data);
@ -174,7 +176,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
}
}
// process the flag byte
// process the type byte
/* (The type is 0,1,2 or 3 for a Program, Number array, Character array or Code file.
A SCREEN$ file is regarded as a Code file with start address 16384 and length 6912 decimal.
If the file is a Program file, parameter 1 holds the autostart line number (or a number >=32768 if no LINE parameter was given)
@ -206,9 +208,9 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
StringBuilder sb = new StringBuilder();
sb.Append(type + ": ");
sb.Append(fileName + " ");
sb.Append(GetUInt16(blockdata, 14));
sb.Append(GetWordValue(blockdata, 14));
sb.Append(":");
sb.Append(GetUInt16(blockdata, 12));
sb.Append(GetWordValue(blockdata, 12));
description = sb.ToString();
}
else if (blockdata[0] == 0xFF)
@ -223,7 +225,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
description += string.Format(", crc {0}", ((crc != 0) ? string.Format("bad (#{0:X2}!=#{1:X2})", crcFile, crcValue) : "ok"));
}
tdb.BlockDescription = description;
tdb.BlockDescription = BlockType.Standard_Speed_Data_Block;
// calculate the data periods for this block
int pilotLength = 0;

View File

@ -19,17 +19,28 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public int BlockID
{
get { return _blockID; }
set { _blockID = value; }
set {
_blockID = value;
if (MetaData == null)
MetaData = new Dictionary<BlockDescriptorTitle, string>();
AddMetaData(BlockDescriptorTitle.Block_ID, value.ToString());
}
}
/// <summary>
/// Description of the block
/// The block type
/// </summary>
private string _blockDescription;
public string BlockDescription
private BlockType _blockType;
public BlockType BlockDescription
{
get { return _blockDescription; }
set { _blockDescription = value; }
get { return _blockType; }
set {
_blockType = value;
if (MetaData == null)
MetaData = new Dictionary<BlockDescriptorTitle, string>();
}
}
/// <summary>
@ -42,6 +53,63 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
set { _blockData = value; }
}
/// <summary>
/// An array of bytearray encoded strings (stored in this format for easy Bizhawk serialization)
/// Its basically tape information
/// </summary>
private byte[][] _tapeDescriptionData;
/// <summary>
/// Returns the Tape Description Data in a human readable format
/// </summary>
public List<string> TapeDescriptionData
{
get
{
List<string> data = new List<string>();
foreach (byte[] b in _tapeDescriptionData)
{
data.Add(Encoding.ASCII.GetString(b));
}
return data;
}
}
#region Block Meta Data
/// <summary>
/// Dictionary of block related data
/// </summary>
public Dictionary<BlockDescriptorTitle, string> MetaData { get; set; }
/// <summary>
/// Adds a single metadata item to the Dictionary
/// </summary>
/// <param name="descriptor"></param>
/// <param name="data"></param>
public void AddMetaData(BlockDescriptorTitle descriptor, string data)
{
// check whether entry already exists
bool check = MetaData.ContainsKey(descriptor);
if (check)
{
// already exists - update
MetaData[descriptor] = data;
}
else
{
// create new
MetaData.Add(descriptor, data);
}
}
#endregion
/// <summary>
/// List containing the pulse timing values
/// </summary>
@ -92,7 +160,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ser.BeginSection("DataBlock" + blockPosition);
ser.Sync("_blockID", ref _blockID);
ser.SyncFixedString("_blockDescription", ref _blockDescription, 50);
//ser.SyncFixedString("_blockDescription", ref _blockDescription, 200);
ser.SyncEnum("_blockType", ref _blockType);
ser.Sync("_blockData", ref _blockData, true);
ser.SyncEnum("_command", ref _command);
@ -112,4 +181,84 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
ser.EndSection();
}
}
/// <summary>
/// The types of TZX blocks
/// </summary>
public enum BlockType
{
Standard_Speed_Data_Block = 0x10,
Turbo_Speed_Data_Block = 0x11,
Pure_Tone = 0x12,
Pulse_Sequence = 0x13,
Pure_Data_Block = 0x14,
Direct_Recording = 0x15,
CSW_Recording = 0x18,
Generalized_Data_Block = 0x19,
Pause_or_Stop_the_Tape = 0x20,
Group_Start = 0x21,
Group_End = 0x22,
Jump_to_Block = 0x23,
Loop_Start = 0x24,
Loop_End = 0x25,
Call_Sequence = 0x26,
Return_From_Sequence = 0x27,
Select_Block = 0x28,
Stop_the_Tape_48K = 0x2A,
Set_Signal_Level = 0x2B,
Text_Description = 0x30,
Message_Block = 0x31,
Archive_Info = 0x32,
Hardware_Type = 0x33,
Custom_Info_Block = 0x35,
Glue_Block = 0x5A,
// depreciated blocks
C64_ROM_Type_Data_Block = 0x16,
C64_Turbo_Tape_Data_Block = 0x17,
Emulation_Info = 0x34,
Snapshot_Block = 0x40,
// unsupported / undetected
Unsupported
}
/// <summary>
/// Different title possibilities
/// </summary>
public enum BlockDescriptorTitle
{
Undefined,
Block_ID,
Program,
Data_Bytes,
Bytes,
Pilot_Pulse_Length,
Pilot_Pulse_Count,
First_Sync_Length,
Second_Sync_Length,
Zero_Bit_Length,
One_Bit_Length,
Data_Length,
Bits_In_Last_Byte,
Pause_After_Data,
Pulse_Length,
Pulse_Count,
Text_Description,
Title,
Publisher,
Author,
Year,
Language,
Type,
Price,
Protection,
Origin,
Comments,
Needs_Parsing
}
}

File diff suppressed because it is too large Load Diff