using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
public class TapeFilePlayer : ISupportsTapeBlockPlayback
{
private readonly BinaryReader _reader;
private TapeBlockSetPlayer _player;
///
/// Data blocks to play back
///
public List DataBlocks { get; private set; }
///
/// Signs that the player completed playing back the file
///
public bool Eof => _player.Eof;
///
/// Initializes the player from the specified reader
///
/// BinaryReader instance to get tape file data from
public TapeFilePlayer(BinaryReader reader)
{
_reader = reader;
}
///
/// Reads in the content of the tape file so that it can be played
///
/// True, if read was successful; otherwise, false
public bool ReadContent()
{
// --- First try TzxReader
var tzxReader = new TzxReader(_reader);
var readerFound = false;
try
{
readerFound = tzxReader.ReadContent();
}
catch (Exception)
{
// --- This exception is intentionally ingnored
}
if (readerFound)
{
// --- This is a .TZX format
DataBlocks = tzxReader.DataBlocks.Where(b => b is ISupportsTapeBlockPlayback)
.Cast()
.ToList();
_player = new TapeBlockSetPlayer(DataBlocks);
return true;
}
// --- Let's assume .TAP tap format
_reader.BaseStream.Seek(0, SeekOrigin.Begin);
var tapReader = new TapReader(_reader);
readerFound = tapReader.ReadContent();
DataBlocks = tapReader.DataBlocks.Cast()
.ToList();
_player = new TapeBlockSetPlayer(DataBlocks);
return readerFound;
}
///
/// Gets the currently playing block's index
///
public int CurrentBlockIndex => _player.CurrentBlockIndex;
///
/// The current playable block
///
public ISupportsTapeBlockPlayback CurrentBlock => _player.CurrentBlock;
///
/// The current playing phase
///
public PlayPhase PlayPhase => _player.PlayPhase;
///
/// The tact count of the CPU when playing starts
///
public long StartCycle => _player.StartCycle;
///
/// Initializes the player
///
public void InitPlay(long startCycle)
{
_player.InitPlay(startCycle);
}
///
/// Gets the EAR bit value for the specified cycle
///
/// Tacts to retrieve the EAR bit
///
/// A tuple of the EAR bit and a flag that indicates it is time to move to the next block
///
public bool GetEarBit(long currentCycle) => _player.GetEarBit(currentCycle);
///
/// Moves the current block index to the next playable block
///
/// Tacts time to start the next block
public void NextBlock(long currentCycle) => _player.NextBlock(currentCycle);
}
}