using System;
using System.Text;
using System.Collections.Generic;
namespace BizHawk.Emulation.DiscSystem
{
///
/// Contains structural information for the disc broken down into c# data structures for easy interrogation.
/// This represents a best-effort interpretation of the raw disc image.
/// You cannot assume a disc can be round-tripped into its original format through this (especially if it came from a format more detailed)
/// TODO - index 0s arent populated
/// IDEA: Make this be generated by a module which is aware of the 'firmware' being emulated, so firmware-specific rules can be applied.
///
public class DiscStructure
{
///
/// Right now support for anything other than 1 session is totally not working
///
public List Sessions = new List();
///
/// List of Points described by the TOC.
/// TODO - this is kind of garbage.
/// TODO - rename this
/// TODO - generate it during loading of ccd/cue
/// TODO - is this 98% redundant with the Tracks list? I think so. Maybe it can encode more detail, but the DiscStructure is lossy anyway
/// Really, what it is, is a series of points where the tno/index change. Kind of an agenda.
/// Maybe I should rename it something different, or at least comment it
/// Or, you could look at this as a kind of compressed disc map
/// NOTE: While this class is actually pretty useless for robust stuff, this list of TOCPoints could be considered robust once fully evaluated
///
public List Points;
///
/// How many sectors in the disc, including the 150 lead-in sectors, up to the end of the last track (before the lead-out track)
/// TODO - does anyone ever need this as the ABA Count? Rename it LBACount or ABACount
///
public int LengthInSectors;
///
/// Length (including lead-in) of the disc as a timestamp
/// TODO - does anyone ever need this as the ABA Count? Rename it LBACount or ABACount
///
public Timestamp FriendlyLength { get { return new Timestamp(LengthInSectors); } }
///
/// How many bytes of data in the disc (including lead-in). Disc sectors are really 2352 bytes each, so this is LengthInSectors * 2352
///
public long BinarySize
{
get { return LengthInSectors * 2352; }
}
///
/// Synthesizes the DiscStructure from RawTOCEntriesJob
/// TODO - move to attic, not being used
/// WOULD BE NICE TO USE FOR CUE
///
public class SynthesizeFromRawTOCEntriesJob
{
public IEnumerable Entries;
public DiscStructure Result;
public void Run()
{
Result = new DiscStructure();
var session = new Session();
Result.Sessions.Add(session);
//TODO - are these necessarily in order?
foreach (var te in Entries)
{
int pt = te.QData.q_index.DecimalValue;
int lba = te.QData.Timestamp.Sector;
var bcd2 = new BCD2 { BCDValue = (byte)pt };
if (bcd2.DecimalValue > 99) //A0 A1 A2 leadout and crap
continue;
var track = new Track { Start_ABA = lba, Number = pt };
track.Indexes.Add(new Index()); //dummy index 0
track.Indexes.Add(new Index() { Number = 1, LBA = lba });
session.Tracks.Add(track);
}
}
}
///
/// seeks the point immediately before (or equal to) this LBA
///
public TOCPoint SeekPoint(int lba)
{
int aba = lba + 150;
for(int i=0;i aba)
return Points[i - 1];
}
return Points[Points.Count - 1];
}
///
/// Uhm... I'm back to thinking this is a good idea. It's a pretty lean log of the shape of the disc and a good thing to generate a DiscStructure from (and maybe avoid using the DiscStructure altogether)
/// Rename it to DiscMapEntry?
///
public class TOCPoint
{
public int Num;
public int ABA, TrackNum, IndexNum;
public Track Track;
public int ADR; //meh...
public EControlQ Control;
public int LBA
{
get { return ABA - 150; }
}
}
///
/// Generates the Points list from the current logical TOC
///
public void Synthesize_TOCPointsFromSessions()
{
Points = new List();
int num = 0;
foreach (var ses in Sessions)
{
for(int t=0;t 150)
{
int weirdPregapSize = distance - 150;
//need a new point. fix the old one
tp.ADR = Points[Points.Count - 1].ADR;
tp.Control = Points[Points.Count - 1].Control;
Points.Add(tp);
aba += weirdPregapSize;
repeat = true;
goto REPEAT;
}
}
Points.Add(tp);
}
}
var tpLeadout = new TOCPoint();
var lastTrack = ses.Tracks[ses.Tracks.Count - 1];
tpLeadout.Num = num++;
tpLeadout.ABA = lastTrack.Indexes[1].aba + lastTrack.LengthInSectors;
tpLeadout.IndexNum = 0;
tpLeadout.TrackNum = 100;
tpLeadout.Track = null; //no leadout track.. now... or ever?
Points.Add(tpLeadout);
}
}
public class Session
{
public int num;
///
/// All the tracks in the session.. but... Tracks[0] should be "Track 1". So beware of this.
/// SO SUCKY!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/// We might should keep this organized as a dictionary as well.
///
public List