ZXHawk: disabled auto-tape detection routines when a disk is in the drive

This commit is contained in:
Asnivor 2018-04-27 10:57:54 +01:00
parent 85fb40ed02
commit 23a2550444
7 changed files with 11 additions and 989 deletions

View File

@ -293,11 +293,7 @@
<Compile Include="Computers\SinclairSpectrum\Machine\ZXSpectrum48K\ZX48.ULA.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Disk\CPCExtendedFloppyDisk.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Disk\CPCFloppyDisk.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Disk\DiskImage.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Disk\DiskType.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Disk\DskConverter.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Disk\Sector.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\Disk\Track.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\MediaConverter.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\MediaConverterType.cs" />
<Compile Include="Computers\SinclairSpectrum\Media\MediaSerializer.cs" />

View File

@ -836,10 +836,11 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
if (!TapeIsPlaying)
{
MonitorRead();
if (_machine.UPDDiskDevice == null || !_machine.UPDDiskDevice.FDD_IsDiskLoaded)
MonitorRead();
}
MonitorRead();
if (_machine.UPDDiskDevice == null || !_machine.UPDDiskDevice.FDD_IsDiskLoaded)
MonitorRead();
/*

View File

@ -147,12 +147,14 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
FrameCompleted = false;
TapeDevice.StartFrame();
if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded)
TapeDevice.StartFrame();
if (_renderSound)
{
BuzzerDevice.StartFrame();
TapeBuzzer.StartFrame();
if (AYDevice != null)
AYDevice.StartFrame();
}
@ -168,7 +170,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
CPU.ExecuteOne();
// cycle the tape device
TapeDevice.TapeCycle();
if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded)
TapeDevice.TapeCycle();
}
// we have reached the end of a frame
@ -192,7 +195,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
// setup for next frame
ULADevice.ResetInterrupt();
TapeDevice.EndFrame();
if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded)
TapeDevice.EndFrame();
FrameCompleted = true;

View File

@ -1,145 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
/// <summary>
/// Object that represents logical disk media once imported
/// </summary>
public class DiskImage
{
#region File Header Info
/// <summary>
/// The identified format
/// (in the case of .dsk files, this is probably "EXTENDED CPC DSK")
/// </summary>
public string Header_SystemIdent { get; set; }
/// <summary>
/// The software originally used to create thsi image
/// </summary>
public string Header_CreatorSoftware { get; set; }
/// <summary>
/// The number of tracks in the disk image (header specified)
/// </summary>
public int Header_TrackCount { get; set; }
/// <summary>
/// The number of sides on the disk (header specified)
/// </summary>
public int Header_SideCount { get; set; }
/// <summary>
/// Size of a track including 0x100 byte track information block
/// (in a .dsk all tracks will be the same size)
/// </summary>
public int Header_TrackSize { get; set; }
#endregion
public List<Track> Tracks = new List<Track>();
/// <summary>
/// Reads an entire sector
/// </summary>
/// <param name="side"></param>
/// <param name="track"></param>
/// <param name="sector"></param>
/// <returns></returns>
public CHRN ReadSector(int side, int track, int sector)
{
var t = Tracks.Where(a => a.TrackNumber == track).FirstOrDefault();
if (t == null)
return null;
var s = t.Sectors.Where(a => a.SectorID == sector).FirstOrDefault();
if (s == null)
return null;
var chrn = s.GetCHRN();
chrn.DataBytes = s.SectorData;
return chrn;
}
/// <summary>
/// Reads data from a sector based on offset and length
/// </summary>
/// <param name="side"></param>
/// <param name="track"></param>
/// <param name="sector"></param>
/// <returns></returns>
public CHRN ReadSector(int side, int track, int sector, int offset, int length)
{
var result = ReadSector(side, track, sector);
if (result == null)
return null;
if (offset > result.DataBytes.Length)
return null;
if (length + offset > result.DataBytes.Length)
return null;
// data is safe to read
var data = result.DataBytes.Skip(offset).Take(length).ToArray();
result.DataBytes = data;
return result;
}
/// <summary>
/// Reads an entire track
/// </summary>
/// <param name="side"></param>
/// <param name="track"></param>
/// <returns></returns>
public Track ReadTrack(int side, int track)
{
return Tracks.Where(a => a.TrackNumber == track).FirstOrDefault();
}
/// <summary>
/// Reads a track based on offset and length
/// </summary>
/// <param name="side"></param>
/// <param name="track"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
public Track ReadTrack(int side, int track, int offset, int length)
{
var t = ReadTrack(side, track);
if (t == null)
return null;
if (offset >= t.AllSectorBytes.Count() || offset + length >= t.AllSectorBytes.Count())
return null;
var data = t.AllSectorBytes.Skip(offset).Take(length).ToArray();
t.ResultBytes = data;
return t;
}
/// <summary>
/// Returns the number of tracks preset on the disk
/// </summary>
/// <returns></returns>
public int GetTrackCount()
{
return Tracks.Count();
}
}
}

View File

@ -1,511 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
/// <summary>
/// Reponsible for DSK format serializaton
/// File format info taken from: http://www.cpcwiki.eu/index.php/Format:DSK_disk_image_file_format
/// </summary>
public class DskConverter : MediaConverter
{
/// <summary>
/// The type of serializer
/// </summary>
private MediaConverterType _formatType = MediaConverterType.DSK;
public override MediaConverterType FormatType
{
get
{
return _formatType;
}
}
/// <summary>
/// Signs whether this class can be used to read data
/// </summary>
public override bool IsReader { get { return true; } }
/// <summary>
/// Signs whether this class can be used to write data
/// </summary>
public override bool IsWriter { get { return false; } }
/// <summary>
/// The disk image that we will be populating
/// </summary>
private DiskImage _diskImage = new DiskImage();
/// <summary>
/// The current position whilst parsing the incoming data
/// </summary>
private int _position = 0;
#region Construction
private IFDDHost _diskDrive;
public DskConverter(IFDDHost diskDrive)
{
_diskDrive = diskDrive;
}
#endregion
/// <summary>
/// Returns TRUE if dsk header is detected
/// </summary>
/// <param name="data"></param>
public override bool CheckType(byte[] data)
{
// check whether this is a valid dsk format file by looking at the identifier in the header
// (first 16 bytes of the file)
string ident = Encoding.ASCII.GetString(data, 0, 16);
if (!ident.ToUpper().Contains("EXTENDED CPC DSK") && !ident.ToUpper().Contains("MV - CPCEMU"))
{
// this is not a valid DSK format file
return false;
}
else
{
return true;
}
}
/// <summary>
/// Read method
/// </summary>
/// <param name="data"></param>
public override void Read(byte[] data)
{
// populate dsk header info
string ident = Encoding.ASCII.GetString(data, 0, 34);
_diskImage.Header_SystemIdent = ident;
if (ident.ToUpper().Contains("EXTENDED CPC DSK"))
ReadExtendedDsk(data);
else if (ident.ToUpper().Contains("MV - CPCEMU"))
ReadDsk(data);
// load the disk 'into' the controller
//_diskDrive.Disk = _diskImage;
}
/// <summary>
/// Parses the extended disk format
/// The extended DSK image is a file designed to describe copy-protected floppy disk software
/// </summary>
/// <param name="data"></param>
private void ReadExtendedDsk(byte[] data)
{
/* DISK INFORMATION BLOCK
offset description bytes
00 - 21 "EXTENDED CPC DSK File\r\nDisk-Info\r\n" 34
22 - 2f name of creator (utility/emulator) 14
30 number of tracks 1
31 number of sides 1
32 - 33 unused 2
34 - xx track size table number of tracks*number of sides
*/
// name of creator
_position = 0x22;
_diskImage.Header_CreatorSoftware = Encoding.ASCII.GetString(data, _position, 14);
// number of tracks
_position = 0x30;
_diskImage.Header_TrackCount = data[_position++];
// number of sides
_diskImage.Header_SideCount = data[_position++];
_position += 2;
/* TRACK OFFSET TABLE
offset description bytes
01 high byte of track 0 length (equivalent to track length/256) 1
... ... ...
track lengths are stored in the same order as the tracks in the image e.g. In the case of a double sided disk: Track 0 side 0, Track 0 side 1, Track 1 side 0 etc...
A size of "0" indicates an unformatted track. In this case there is no data, and no track information block for this track in the image file!
Actual length of track data = (high byte of track length) * 256
Track length includes the size of the TRACK INFORMATION BLOCK (256 bytes)
The location of a Track Information Block for a chosen track is found by summing the sizes of all tracks up to the chosen track plus the size of the Disc Information Block (&100 bytes). The first track is at offset &100 in the disc image.
*/
// iterate through the track size table and do an initial setup of all the tracks
// (this is just new tracks with the offset value saved)
int trkPos = 0x100;
for (int i = 0; i < _diskImage.Header_TrackCount * _diskImage.Header_SideCount; i++)
{
Track track = new Track();
// calc actual track length (including track info block)
int ts = data[_position++];
int tLen = ts * 256;
track.TrackStartOffset = trkPos;
track.TrackByteLength = tLen;
_diskImage.Tracks.Add(track);
trkPos += tLen;
}
// iterate through each newly created track and parse it based on the offset
List<Track> tracks = new List<Track>();
for (int tr = 0; tr < _diskImage.Tracks.Count(); tr++)
{
// get the track we are interested in
var t = _diskImage.Tracks[tr];
// validity check
if (t.TrackByteLength == 0)
{
// unformatted track that is not present in the disk image
Track trU = new Track();
trU.TrackNumber = (byte)tr;
trU.TrackByteLength = 0;
tracks.Add(trU);
continue;
}
Track track = new Track();
track.TrackStartOffset = t.TrackStartOffset;
track.TrackByteLength = t.TrackByteLength;
// get data for this track block
byte[] tData = data.Skip(t.TrackStartOffset).Take(t.TrackByteLength).ToArray();
// start of data block
int pos = 0;
// seek past track info ident
pos += 0x10;
/* TRACK INFORMATION BLOCK
offset description bytes
00 - 0b "Track-Info\r\n" 12
0c - 0f unused 4
10 track number 1
11 side number 1
12 data rate 1
13 recording mode 1
14 sector size 1
15 number of sectors 1
16 GAP#3 length 1
17 filler byte 1
18 - xx Sector Information List xx
*/
/* Format extensions
-----------------
Date rate description
0 Unknown.
1 Single or double density
2 High Density
3 Extended density
Data rate defines the rate at which data was written to the track. This value applies to the entire track.
Recording mode description
0 Unknown.
1 FM
2 MFM
Recording mode is used to define how the data was written. It defines the encoding used to write the data to the disc and the structure of the data on the disc including the layout of the sectors.
This value applies to the entire track
The NEC765 floppy disc controller is supplied with a single clock. When reading from and writing to a disc using the NEC765 you can choose
FM or MFM recording modes. Use of these modes and the clock into the NEC765 define the final rate at which the data is written to the disc.
When FM recording mode is used, data is read from or written to at a rate which is double that of when MFM is used.
The time for each bit will be twice the time for MFM
NEC765 Clock FM/MFM Actual rate
4Mhz FM 4us per bit
4Mhz MFM 2us per bit
*/
// track number
track.TrackNumber = tData[pos++];
// side number
track.SideNumber = tData[pos++];
// data rate
track.DataRate = tData[pos++];
// recording mode
track.RecordingMode = tData[pos++];
// sector size
track.SectorSize = tData[pos++];
// number of sectors
track.SectorCount = tData[pos++];
// GAP#3 Length
track.GAP3Length = tData[pos++];
// filler byte
track.FillerByte = tData[pos++];
/* SECTOR INFORMATION LIST
offset description bytes
00 track (equivalent to C parameter in NEC765 commands) 1
01 side (equivalent to H parameter in NEC765 commands) 1
02 sector ID (equivalent to R parameter in NEC765 commands) 1
03 sector size (equivalent to N parameter in NEC765 commands) 1
04 FDC status register 1 (equivalent to NEC765 ST1 status register) 1
05 FDC status register 2 (equivalent to NEC765 ST2 status register) 1
06 - 07 actual data length in bytes 2
*/
// parse sector information list
for (int s = 0; s < track.SectorCount; s++)
{
Sector sector = new Sector();
sector.Track = tData[pos++];
sector.Side = tData[pos++];
sector.SectorID = tData[pos++];
sector.SectorSize = tData[pos++];
sector.ST1 = tData[pos++];
sector.ST2 = tData[pos++];
sector.TotalDataLength = GetWordValue(tData, pos);
pos += 2;
// get the sector data - lives directly after the 256byte track info block
int secDataPos = 0x100;
/* Format extension
---------------_
It has been found that many protections using 8K Sectors (N="6") do store more than &1800 bytes of useable data.
It was thought that &1800 was the maximum useable limit, but this has proved wrong. So you should support 8K of data to ensure
this data is read correctly. The size of the sector will be reported in the SECTOR INFORMATION LIST as described above.
For sector size N="7" the full 16K will be stored. It is assumed that sector sizes are defined as 3 bits only,
so that a sector size of N="8" is equivalent to N="0".
*/
int bps = 0x80 << sector.SectorSize;
if (sector.SectorSize == 8 || sector.SectorSize == 0)
{
// no sector data
bps = 0x80 << 0;
//continue;
}
/* Format extension
----------------
Storing Multiple Versions of Weak/Random Sectors.
Some copy protections have what is described as 'weak/random' data. Each time the sector is read one or more bytes will change,
the value may be random between consecutive reads of the same sector.
To support these formats the following extension has been proposed.
Where a sector has weak/random data, there are multiple copies stored. The actual sector size field in the SECTOR INFORMATION LIST
describes the size of all the copies. To determine if a sector has multiple copies then compare the actual sector size field to the
size defined by the N parameter. For multiple copies the actual sector size field will have a value which is a multiple of the size
defined by the N parameter. The emulator should then choose which copy of the sector it should return on each read.
*/
int sizeOfAllCopies = sector.TotalDataLength;
if (sizeOfAllCopies % bps == 0)
{
// sector size is the same as total data length (indicating 1 sector data)
// or a factor of the total data length (indicating multiple copies)
for (int sd = 0; sd < sizeOfAllCopies / bps; sd++)
{
byte[] sData = new byte[bps];
for (int c = 0; c < bps; c++)
{
sData[c] = data[secDataPos++];
}
sector.AddSectorData(sd, sData);
}
}
else
{
// assume that there is one sector copy, but the total data length does not match
if (sector.TotalDataLength <= sizeOfAllCopies)
{
byte[] sData = new byte[bps];
for (int c = 0; c < bps; c++)
{
sData[c] = data[secDataPos++];
}
sector.AddSectorData(0, sData);
}
else
{
byte[] sData = new byte[sizeOfAllCopies];
for (int c = 0; c < sizeOfAllCopies; c++)
{
sData[c] = data[secDataPos++];
}
sector.AddSectorData(0, sData);
}
}
track.Sectors.Add(sector);
}
// add track to working list
tracks.Add(track);
}
// replace the tracks collection
_diskImage.Tracks = tracks;
}
/// <summary>
/// Parses the standard disk image format
/// </summary>
/// <param name="data"></param>
private void ReadDsk(byte[] data)
{
/* DISK INFORMATION BLOCK
offset description bytes
00-21 "MV - CPCEMU Disk-File\r\nDisk-Info\r\n" 34
22-2f name of creator 14
30 number of tracks 1
31 number of sides 1
32-33 size of a track (little endian; low byte followed by high byte) 2
34-ff not used (0) 204
*/
// name of creator
_position = 0x22;
_diskImage.Header_CreatorSoftware = Encoding.ASCII.GetString(data, _position, 14);
// number of tracks
_position = 0x30;
_diskImage.Header_TrackCount = data[_position++];
// number of sides
_diskImage.Header_SideCount = data[_position++];
// size of a track (little endian)
_diskImage.Header_TrackSize = GetWordValue(data, _position);
// 34-ff not used
// move to start of first track info block
_position = 0x100;
int tmpPos = _position;
// iterate through each track
for (int t = 0; t < _diskImage.Header_TrackCount; t++)
{
/* TRACK INFORMATION BLOCK
offset description bytes
00 - 0b "Track-Info\r\n" 12
0c - 0f unused 4
10 track number 1
11 side number 1
12 - 13 unused 2
14 sector size 1
15 number of sectors 1
16 GAP#3 length 1
17 filler byte 1
18 - xx Sector Information List xx
*/
Track track = new Track();
_position += 0x10;
track.TrackNumber = data[_position++];
track.SideNumber = data[_position++];
_position += 2;
/*
BPS (bytes per sector)
0 = 128 0x80
1 = 256 0x100
2 = 512 0x200
3 = 1024 0x400
4 = 2048 0x800
5 = 4096 0x1000
6 = 8192 0x2000
*/
track.SectorSize = data[_position++];
track.SectorCount = data[_position++];
track.GAP3Length = data[_position++];
track.FillerByte = data[_position++];
/* SECTOR INFORMATION LIST
offset description bytes
00 track (equivalent to C parameter in NEC765 commands) 1
01 side (equivalent to H parameter in NEC765 commands) 1
02 sector ID (equivalent to R parameter in NEC765 commands) 1
03 sector size (equivalent to N parameter in NEC765 commands) 1
04 FDC status register 1 (equivalent to NEC765 ST1 status register) 1
05 FDC status register 2 (equivalent to NEC765 ST2 status register) 1
06 - 07 notused (0) 2
*/
// get the sector info first
for (int s = 0; s < track.SectorCount; s++)
{
Sector sector = new Sector();
sector.Track = data[_position++];
sector.Side = data[_position++];
sector.SectorID = data[_position++];
sector.SectorSize = data[_position++];
sector.ST1 = data[_position++];
sector.ST2 = data[_position++];
track.Sectors.Add(sector);
_position += 2;
}
// now process the sector data - always offset 0x100 from the start of the track information block
tmpPos += 0x100;
_position = tmpPos;
// sectorsize in the track information list implies the boundaries of the sector data
// sectorsize in the sector info list gives us the actual size of each sector to read
for (int s = 0; s < track.SectorCount; s++)
{
var sec = track.Sectors[s];
List<byte> tmpData = new List<byte>();
// read the sector data bytes
int bps = 0x80 << sec.SectorSize;
if (bps > 0x1800)
bps = 0x1800;
for (int d = 0; d < bps; d++)
{
tmpData.Add(data[_position + d]);
}
sec.AddSectorData(0, tmpData.ToArray());
track.Sectors[s] = sec;
// sector data parsed - move to next sector data block
int trackBps = 0x80 << track.SectorSize;
if (trackBps > 0x1800)
trackBps = 0x1800;
_position += track.SectorSize;
}
// add the track to the disk image
_diskImage.Tracks.Add(track);
}
}
}
}

View File

@ -1,228 +0,0 @@
using BizHawk.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
/// <summary>
/// Represents a disk sector
/// </summary>
public class Sector
{
/// <summary>
/// Used when the FDD returns the sector
/// False means the sector does not exist
/// </summary>
public bool IsValid = true;
/// <summary>
/// track (equivalent to C parameter in NEC765 commands)
/// </summary>
private byte _track;
public byte Track
{
get { return _track; }
set { _track = value; }
}
/// <summary>
/// side (equivalent to H parameter in NEC765 commands)
/// </summary>
private byte _side;
public byte Side
{
get { return _side; }
set { _side = value; }
}
/// <summary>
/// sector ID (equivalent to R parameter in NEC765 commands)
/// </summary>
private byte _sectorID;
public byte SectorID
{
get { return _sectorID; }
set { _sectorID = value; }
}
/// <summary>
/// sector size (equivalent to N parameter in NEC765 commands)
/// </summary>
private byte _sectorSize;
public byte SectorSize
{
get { return _sectorSize; }
set { _sectorSize = value; }
}
/// <summary>
/// FDC status register 1 (equivalent to NEC765 ST1 status register)
/// </summary>
private byte _sT1;
public byte ST1
{
get { return _sT1; }
set { _sT1 = value; }
}
/// <summary>
/// FDC status register 2 (equivalent to NEC765 ST2 status register)
/// </summary>
private byte _sT2;
public byte ST2
{
get { return _sT2; }
set { _sT2 = value; }
}
/// <summary>
/// Actual total data length in bytes
/// If this is greater than the sector size specified by N, then multiple copies
/// of the sector data are present (representing weak/random copy protection data)
/// </summary>
private int _totalDataLength;
public int TotalDataLength
{
get { return _totalDataLength; }
set { _totalDataLength = value; }
}
/// <summary>
/// The sector data entry point
/// If multiple sector data is found this should return a randomly chosen data for this sector
/// </summary>
public byte[] SectorData
{
get
{
// number of sector data copies found
int count = _sectorDatas.Count();
if (count <= 0)
{
// no sectors present
return new byte[0];
}
if (count == 1)
{
// only one copy of data found - return this
return _sectorDatas.First();
}
if (count > 1)
{
// there is more than one copy of sector data stored
// return at random to simulate weak/random copy protection sectors
Random rnd = new Random();
int pnt = rnd.Next(0, count - 1);
return _sectorDatas[pnt];
}
// probably shouldnt ever get this far
return null;
}
}
/// <summary>
/// Adds sector data based on the copy index
/// </summary>
/// <param name="position"></param>
public void AddSectorData(int position, byte[] data)
{
if (_sectorDatas.ElementAtOrDefault(position) == null)
{
// create byte arrays for uninstantiated indexes
for (int i = 0; i < position + 1; i++)
{
if (_sectorDatas.ElementAtOrDefault(i) == null)
{
_sectorDatas.Add(new byte[0]);
}
}
}
_sectorDatas[position] = data;
}
/// <summary>
/// Internal storage for sector data
/// </summary>
private List<byte[]> _sectorDatas = new List<byte[]>();
/// <summary>
/// Returns a CHRN object for this sector
/// </summary>
/// <returns></returns>
public CHRN GetCHRN()
{
return new CHRN
{
C = Track,
H = Side,
R = SectorID,
N = SectorSize,
Flag1 = ST1,
Flag2 = ST2,
DataBytes = SectorData
};
}
/// <summary>
/// State serialization
/// Should only be called for the ActiveSector object in the floppy drive
/// </summary>
/// <param name="ser"></param>
public void SyncState(Serializer ser)
{
ser.BeginSection("ActiveSector");
ser.Sync("IsValid", ref IsValid);
ser.Sync("_track", ref _track);
ser.Sync("_side", ref _side);
ser.Sync("_sectorID", ref _sectorID);
ser.Sync("_sectorSize", ref _sectorSize);
ser.Sync("_sT1", ref _sT1);
ser.Sync("_sT2", ref _sT2);
ser.Sync("_totalDataLength", ref _totalDataLength);
if (ser.IsReader)
{
ser.Sync("SecCopySize", ref SecCopySize);
byte[][] sds = new byte[SecCopySize][];
for (int i = 0; i < SecCopySize; i++)
{
ser.Sync("sec" + i, ref sds[i], false);
}
_sectorDatas = sds.ToList();
}
if (ser.IsWriter)
{
SecCopySize = _sectorDatas.Count();
ser.Sync("SecCopySize", ref SecCopySize);
byte[][] sds = _sectorDatas.ToArray();
for (int i = 0; i < SecCopySize; i++)
{
ser.Sync("sec" + i, ref sds[i], false);
}
}
ser.EndSection();
}
// Sector array size (for state serialization)
private int SecCopySize;
}
}

View File

@ -1,95 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
/// <summary>
/// Represents a disk track
/// </summary>
public class Track
{
/// <summary>
/// The track number
/// </summary>
public byte TrackNumber { get; set; }
/// <summary>
/// The side number
/// </summary>
public byte SideNumber { get; set; }
/// <summary>
/// Data rate defines the rate at which data was written to the track. This value applies to the entire track
/// </summary>
public byte DataRate { get; set; }
/// <summary>
/// Recording mode is used to define how the data was written. It defines the encoding used to write the data to the disc and the structure of the data on the
/// disc including the layout of the sectors. This value applies to the entire track.
/// </summary>
public byte RecordingMode { get; set; }
/// <summary>
/// Used to calculate the location of each sector's data. Therefore, The data allocated for each sector must be the same
/// </summary>
public int SectorSize { get; set; }
/// <summary>
/// Identifies the number of valid entries in the sector information list
/// </summary>
public byte SectorCount { get; set; }
/// <summary>
/// The length of GAP3 data
/// </summary>
public byte GAP3Length { get; set; }
/// <summary>
/// Byte used as filler
/// </summary>
public byte FillerByte { get; set; }
/// <summary>
/// List containing all the sectors for this track
/// </summary>
public List<Sector> Sectors = new List<Sector>();
/// <summary>
/// Defines the offset in the disk image file at which the track information block starts
/// </summary>
public int TrackStartOffset { get; set; }
/// <summary>
/// The actual length of the track (including info block) in the disk image file
/// </summary>
public int TrackByteLength { get; set; }
/// <summary>
/// Returns all sector data for this track in one byte array
/// </summary>
public byte[] AllSectorBytes
{
get
{
int byteSize = 0;
foreach (var s in Sectors)
{
byteSize += s.SectorData.Count();
}
byte[] all = new byte[byteSize];
int _pos = 0;
foreach (var s in Sectors)
{
foreach (var d in s.SectorData)
{
all[_pos] = d;
_pos++;
}
}
return all;
}
}
public byte[] ResultBytes { get; set; }
}
}