BizHawk/BizHawk.Emulation.DiscSystem/DiscStructure.cs

180 lines
5.8 KiB
C#

using System;
using System.Text;
using System.Collections.Generic;
namespace BizHawk.Emulation.DiscSystem
{
/// <summary>
/// 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.
/// NOTE: Since this ended up really just having the list of sessions.. maybe it isn't needed and can just float on up into Disc
/// </summary>
public class DiscStructure
{
/// <summary>
/// This is a 1-indexed list of sessions (session 1 is at [1])
/// Support for multiple sessions is thoroughly not working yet
/// </summary>
public List<Session> Sessions = new List<Session>();
public class Session
{
//Notable omission:
//Length of the session
//How should this be defined? It's even harder than determining a track length
/// <summary>
/// The LBA of the session's leadout. In other words, for all intents and purposes, the end of the session
/// </summary>
public int LeadoutLBA { get { return LeadoutTrack.LBA; } }
/// <summary>
/// The session number
/// </summary>
public int Number;
/// <summary>
/// The number of user information tracks in the session.
/// This excludes the lead-in and lead-out tracks
/// Use this instead of Tracks.Count
/// </summary>
public int InformationTrackCount { get { return Tracks.Count - 2; } }
/// <summary>
/// All the tracks in the session.. but... Tracks[0] is the lead-in track. Tracks[1] should be "Track 1". So beware of this.
/// For a disc with "3 tracks", Tracks.Count will be 5: it includes that lead-in track as well as the leadout track.
/// Perhaps we should turn this into a special collection type with no Count or Length, or a method to GetTrack()
/// </summary>
public List<Track> Tracks = new List<Track>();
/// <summary>
/// A reference to the first information track (Track 1)
/// The raw TOC may have specified something different; it's not clear how this discrepancy is handled.
/// </summary>
public Track FirstInformationTrack { get { return Tracks[1]; } }
/// <summary>
/// A reference to the last information track on the disc.
/// The raw TOC may have specified something different; it's not clear how this discrepancy is handled.
/// </summary>
public Track LastInformationTrack { get { return Tracks[InformationTrackCount]; } }
/// <summary>
/// A reference to the lead-out track.
/// Effectively, the end of the user area of the disc.
/// </summary>
public Track LeadoutTrack { get { return Tracks[Tracks.Count - 1]; } }
/// <summary>
/// A reference to the lead-in track
/// </summary>
public Track LeadinTrack { get { return Tracks[0]; } }
/// <summary>
/// Determines which track of the session is at the specified LBA.
/// </summary>
public Track SeekTrack(int lba)
{
var ses = this;
for (int i = 1; i < Tracks.Count; i++)
{
var track = ses.Tracks[i];
//funny logic here: if the current track's LBA is > the requested track number, it means the previous track is the one we wanted
if (track.LBA > lba)
return ses.Tracks[i - 1];
}
return ses.LeadoutTrack;
}
}
/// <summary>
/// The Type of a track as specified in the TOC Q-Subchannel data from the control flags.
/// Could also be 4-Channel Audio, but we'll handle that later if needed
/// </summary>
public enum ETrackType
{
/// <summary>
/// The track type isn't always known.. it can take this value til its populated
/// </summary>
Unknown,
/// <summary>
/// Data track( TOC Q control 0x04 flag set )
/// </summary>
Data,
/// <summary>
/// Audio track( TOC Q control 0x04 flag clear )
/// </summary>
Audio
}
/// <summary>
/// Information about a Track.
/// </summary>
public class Track
{
//Notable omission:
//a list of Indices. It's difficult to reliably construct it.
//Notably, mednafen can't readily produce it.
//Indices may need scanning sector by sector.
//It's unlikely that any software would be needing indices anyway.
//We should add another index scanning service if that's ever needed.
//(note: a CCD should contain indices, but it's not clear whether it's required. logically it shouldnt be)
//Notable omission:
//Length of the track.
//How should this be defined? Between which indices? It's really hard.
//These omissions could be handled by ReadStructure() policies which permit the scanning of the entire disc.
//After that, they could be cached in here.
/// <summary>
/// The number of the track (1-indexed)
/// </summary>
public int Number;
/// <summary>
/// The Mode of the track (0 is Audio, 1 and 2 are data)
/// This is heuristically determined.
/// Actual sector contents may vary
/// </summary>
public int Mode;
/// <summary>
/// Is this track a Data track?
/// </summary>
public bool IsData { get { return !IsAudio; } }
/// <summary>
/// Is this track an Audio track?
/// </summary>
public bool IsAudio { get { return Mode == 0; } }
/// <summary>
/// The 'control' properties of the track expected to be found in the track's subQ.
/// However, this is what's indicated by the disc TOC.
/// Actual sector contents may vary.
/// </summary>
public EControlQ Control;
/// <summary>
/// The starting LBA of the track (index 1).
/// </summary>
public int LBA;
/// <summary>
/// The next track in the session. null for the leadout track of a session.
/// </summary>
public Track NextTrack;
}
public class Index
{
public int Number;
public int LBA;
}
}
}