104 lines
2.9 KiB
C#
104 lines
2.9 KiB
C#
using System;
|
|
using System.Text;
|
|
using BizHawk.Common;
|
|
|
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
|
{
|
|
public class Tape
|
|
{
|
|
[SaveState.DoNotSave] private readonly byte[] _tapeData;
|
|
[SaveState.DoNotSave] private readonly byte _version;
|
|
[SaveState.DoNotSave] private readonly int _start;
|
|
[SaveState.DoNotSave] private readonly int _end;
|
|
|
|
[SaveState.SaveWithName("Position")]
|
|
private int _pos;
|
|
[SaveState.SaveWithName("Cycle")]
|
|
private int _cycle;
|
|
[SaveState.SaveWithName("Data")]
|
|
private bool _data;
|
|
|
|
public Tape(byte version, byte[] tapeData, int start, int end)
|
|
{
|
|
_version = version;
|
|
_tapeData = tapeData;
|
|
_start = start;
|
|
_end = end;
|
|
Rewind();
|
|
}
|
|
|
|
public void ExecuteCycle()
|
|
{
|
|
if (_cycle == 0)
|
|
{
|
|
if (_pos >= _end)
|
|
{
|
|
_data = true;
|
|
return;
|
|
}
|
|
|
|
_cycle = _tapeData[_pos++] * 8;
|
|
if (_cycle == 0)
|
|
{
|
|
if (_version == 0)
|
|
{
|
|
_cycle = 256 * 8; // unspecified overflow condition
|
|
}
|
|
else
|
|
{
|
|
_cycle = (int)(BitConverter.ToUInt32(_tapeData, _pos - 1) >> 8);
|
|
_pos += 3;
|
|
if (_cycle == 0)
|
|
{
|
|
throw new Exception("Bad tape data");
|
|
}
|
|
}
|
|
}
|
|
|
|
_cycle++;
|
|
}
|
|
|
|
// Send a single negative pulse at the end of a cycle
|
|
_data = --_cycle != 0;
|
|
}
|
|
|
|
// Rewinds the tape back to start
|
|
public void Rewind()
|
|
{
|
|
_pos = _start;
|
|
_cycle = 0;
|
|
}
|
|
|
|
// Reads from tape, this will tell the caller if the flag pin should be raised
|
|
public bool Read()
|
|
{
|
|
return _data;
|
|
}
|
|
|
|
// Try to construct a tape file from file data. Returns null if not a tape file, throws exceptions for bad tape files.
|
|
// (Note that some error conditions aren't caught right here.)
|
|
public static Tape Load(byte[] tapeFile)
|
|
{
|
|
Tape result = null;
|
|
|
|
if (Encoding.ASCII.GetString(tapeFile, 0, 12) == "C64-TAPE-RAW")
|
|
{
|
|
var version = tapeFile[12];
|
|
if (version > 1) throw new Exception("This tape has an unsupported version");
|
|
var size = BitConverter.ToUInt32(tapeFile, 16);
|
|
if (size + 20 != tapeFile.Length)
|
|
{
|
|
throw new Exception("Tape file header specifies a length that doesn't match the file size");
|
|
}
|
|
result = new Tape(version, tapeFile, 20, tapeFile.Length);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void SyncState(Serializer ser)
|
|
{
|
|
SaveState.SyncObject(ser, this);
|
|
}
|
|
}
|
|
}
|