cleanup CUE toc handling a bit
This commit is contained in:
parent
fda3ec03ed
commit
4b8d3cfa79
|
@ -137,7 +137,9 @@
|
|||
<Compile Include="Computers\AppleII\AppleII.IMemoryDomains.cs">
|
||||
<DependentUpon>AppleII.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Computers\AppleII\AppleII.ISettable.cs" />
|
||||
<Compile Include="Computers\AppleII\AppleII.ISettable.cs">
|
||||
<DependentUpon>AppleII.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Computers\AppleII\AppleII.IStatable.cs">
|
||||
<DependentUpon>AppleII.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
<Compile Include="Jobs\DiscMountJob.MednaDisc.cs" />
|
||||
<Compile Include="Jobs\LoadSBIJob.cs" />
|
||||
<Compile Include="Jobs\LoggedJob.cs" />
|
||||
<Compile Include="Jobs\Synthesize_A0A1A2_Job.cs" />
|
||||
<Compile Include="M3U_file.cs" />
|
||||
<Compile Include="MednaDiscAPI.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -560,7 +560,7 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
//if we keep this, it should just be as a memo that later heuristics can use. For example: 'use guidance from original disc image'
|
||||
track.ModeHeuristic = ccdt.Mode;
|
||||
|
||||
//TODO - this should be deleted anyway (
|
||||
//TODO - this should be deleted anyway (
|
||||
switch (ccdt.Mode)
|
||||
{
|
||||
case 0:
|
||||
|
|
|
@ -162,8 +162,11 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
{
|
||||
var ext = Path.GetExtension(fi.FullName).ToLowerInvariant();
|
||||
|
||||
//SBI and CUE are always bad choices
|
||||
if (ext == ".cue" || ext == ".sbi")
|
||||
//some choices are always bad: (we're looking for things like .bin and .wav)
|
||||
//it's a little unclear whether we should go for a whitelist or a blacklist here.
|
||||
//there's similar numbers of cases either way.
|
||||
//perhaps we could code both (and prefer choices from the whitelist)
|
||||
if (ext == ".cue" || ext == ".sbi" || ext == ".ccd" || ext == ".sub")
|
||||
continue;
|
||||
|
||||
|
||||
|
@ -230,7 +233,7 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
//TODO - once we reorganize the file ID stuff, do legit checks here (this is completely redundant with the fileID system
|
||||
//TODO - decode vs stream vs unpossible policies in input policies object (including ffmpeg availability-checking callback (results can be cached))
|
||||
string blobPathExt = Path.GetExtension(choice).ToUpperInvariant();
|
||||
if (blobPathExt == ".BIN") cfi.Type = AnalyzeCueJob.CueFileType.BIN;
|
||||
if (blobPathExt == ".BIN" || blobPathExt == ".IMG") cfi.Type = AnalyzeCueJob.CueFileType.BIN;
|
||||
else if (blobPathExt == ".ISO") cfi.Type = AnalyzeCueJob.CueFileType.BIN;
|
||||
else if (blobPathExt == ".WAV")
|
||||
{
|
||||
|
|
|
@ -345,9 +345,10 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
SubchannelQ priorSubchannelQ = new SubchannelQ();
|
||||
int LBA = 0;
|
||||
List<IDisposable> resources = disc.DisposableResources;
|
||||
var TOCInfo = new Synthesize_A0A1A2_Job { FirstRecordedTrackNumber = -1, LastRecordedTrackNumber = -1, LeadoutLBA = -1};
|
||||
//lets start with this. we'll change it if we ever find a track of a different format (this is based on mednafen's behaviour)
|
||||
TOCInfo.Session1Format = DiscTOCRaw.SessionFormat.Type00_CDROM_CDDA;
|
||||
|
||||
//lets start with session type CDDA. we'll change it if we ever find a track of a different format (this is based on mednafen's behaviour)
|
||||
var TOCMiscInfo = new Synthesize_A0A1A2_Job { IN_FirstRecordedTrackNumber = -1, IN_LastRecordedTrackNumber = -1, IN_LeadoutTimestamp = new Timestamp(0) };
|
||||
TOCMiscInfo.IN_Session1Format = DiscTOCRaw.SessionFormat.Type00_CDROM_CDDA;
|
||||
|
||||
//a little subroutine to wrap a sector if the blob is out of space
|
||||
Func<int,Sector_RawBlob> eatBlobAndWrap = (required) =>
|
||||
|
@ -384,7 +385,7 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
sq.sec = BCD2.FromDecimal(0);
|
||||
sq.frame = BCD2.FromDecimal(0);
|
||||
|
||||
sq.AP_Timestamp = new Timestamp(LBA); //off by 150?
|
||||
sq.AP_Timestamp = new Timestamp(LBA + 150); //its supposed to be an absolute timestamp
|
||||
|
||||
disc.RawTOCEntries.Add(new RawTOCEntry { QData = sq });
|
||||
};
|
||||
|
@ -768,21 +769,21 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
disc.Structure.Sessions[0].Tracks.Add(st);
|
||||
|
||||
//maintain some memos
|
||||
if (TOCInfo.FirstRecordedTrackNumber == -1)
|
||||
TOCInfo.FirstRecordedTrackNumber = track_num;
|
||||
TOCInfo.LastRecordedTrackNumber = track_num;
|
||||
if (TOCMiscInfo.IN_FirstRecordedTrackNumber == -1)
|
||||
TOCMiscInfo.IN_FirstRecordedTrackNumber = track_num;
|
||||
TOCMiscInfo.IN_LastRecordedTrackNumber = track_num;
|
||||
//update the disc type... do we need to do any double checks here to check for regressions? doubt it.
|
||||
if (TOCInfo.Session1Format == DiscTOCRaw.SessionFormat.Type00_CDROM_CDDA)
|
||||
if (TOCMiscInfo.IN_Session1Format == DiscTOCRaw.SessionFormat.Type00_CDROM_CDDA)
|
||||
{
|
||||
switch (track_currentCommand.Type)
|
||||
{
|
||||
case CueFile.TrackType.Mode2_2336:
|
||||
case CueFile.TrackType.Mode2_2352:
|
||||
TOCInfo.Session1Format = DiscTOCRaw.SessionFormat.Type20_CDXA;
|
||||
TOCMiscInfo.IN_Session1Format = DiscTOCRaw.SessionFormat.Type20_CDXA;
|
||||
break;
|
||||
case CueFile.TrackType.CDI_2336:
|
||||
case CueFile.TrackType.CDI_2352:
|
||||
TOCInfo.Session1Format = DiscTOCRaw.SessionFormat.Type10_CDI;
|
||||
TOCMiscInfo.IN_Session1Format = DiscTOCRaw.SessionFormat.Type10_CDI;
|
||||
break;
|
||||
default:
|
||||
//no changes here
|
||||
|
@ -863,8 +864,8 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
disc.Structure.LengthInSectors = disc.Sectors.Count;
|
||||
|
||||
//add RawTOCEntries A0 A1 A2 to round out the TOC
|
||||
TOCInfo.LeadoutLBA = LBA;
|
||||
TOCInfo.Run(disc.RawTOCEntries);
|
||||
TOCMiscInfo.IN_LeadoutTimestamp = new Timestamp(LBA + 150);
|
||||
TOCMiscInfo.Run(disc.RawTOCEntries);
|
||||
|
||||
//generate the TOCRaw from the RawTocEntries
|
||||
var tocSynth = new DiscTOCRaw.SynthesizeFromRawTOCEntriesJob() { Entries = disc.RawTOCEntries };
|
||||
|
|
|
@ -5,11 +5,14 @@ using System.IO;
|
|||
using System.Collections.Generic;
|
||||
|
||||
//ARCHITECTURE NOTE:
|
||||
//no provisions are made for caching synthesized data for later accelerated use.
|
||||
//in the worst case that might result in synthesizing an entire disc in memory.
|
||||
//instead, users should be advised to `hawk` the disc first for most rapid access
|
||||
//this will result in a completely flattened CCD where everything comes right off the hard drive
|
||||
//This might be an unwise decision for disc ID and miscellaneous purposes but it's best for gaming and stream-converting (hawking and hashing)
|
||||
//No provisions are made for caching synthesized data for later accelerated use.
|
||||
//This is because, in the worst case that might result in synthesizing an entire disc in memory.
|
||||
//Instead, users should be advised to `hawk` the disc first for most rapid access so that synthesis won't be necessary and speed will be maximized.
|
||||
//This will result in a completely flattened CCD where everything comes right off the hard drive
|
||||
//Our choice here might be an unwise decision for disc ID and miscellaneous purposes but it's best for gaming and stream-converting (hawking and hashing)
|
||||
|
||||
//https://books.google.com/books?id=caF_AAAAQBAJ&lpg=PA124&ots=OA9Ttj9CHZ&dq=disc%20TOC%20point%20A2&pg=PA124
|
||||
|
||||
|
||||
//http://www.staff.uni-mainz.de/tacke/scsi/SCSI2-14.html
|
||||
|
||||
|
|
|
@ -20,60 +20,7 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
BizHawk, MednaDisc, LibMirage
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synthesizes RawTCOEntry A0 A1 A2 from the provided information
|
||||
/// TODO - dont these need to have timestamps too?
|
||||
/// </summary>
|
||||
public class Synthesize_A0A1A2_Job
|
||||
{
|
||||
//heres a thing
|
||||
//https://books.google.com/books?id=caF_AAAAQBAJ&lpg=PA124&ots=OA9Ttj9CHZ&dq=disc%20TOC%20point%20A2&pg=PA124
|
||||
|
||||
public int FirstRecordedTrackNumber;
|
||||
public int LastRecordedTrackNumber;
|
||||
public int LeadoutLBA;
|
||||
|
||||
/// <summary>
|
||||
/// TODO - this hasnt been set for CCD, has it?
|
||||
/// </summary>
|
||||
public DiscTOCRaw.SessionFormat Session1Format;
|
||||
|
||||
/// <summary>
|
||||
/// Appends the new entries to the provided list
|
||||
/// </summary>
|
||||
public void Run(List<RawTOCEntry> entries)
|
||||
{
|
||||
SubchannelQ sq = new SubchannelQ();
|
||||
|
||||
//first recorded track number:
|
||||
sq.q_index.DecimalValue = 0xA0;
|
||||
sq.ap_min.DecimalValue = FirstRecordedTrackNumber;
|
||||
switch(Session1Format)
|
||||
{
|
||||
case DiscTOCRaw.SessionFormat.Type00_CDROM_CDDA: sq.ap_sec.DecimalValue = 0x00; break;
|
||||
case DiscTOCRaw.SessionFormat.Type10_CDI: sq.ap_sec.DecimalValue = 0x10; break;
|
||||
case DiscTOCRaw.SessionFormat.Type20_CDXA: sq.ap_sec.DecimalValue = 0x20; break;
|
||||
default: throw new InvalidOperationException("Invalid Session1Format");
|
||||
}
|
||||
sq.ap_frame.DecimalValue = 0;
|
||||
|
||||
entries.Add(new RawTOCEntry { QData = sq });
|
||||
|
||||
//last recorded track number:
|
||||
sq.q_index.DecimalValue = 0xA1;
|
||||
sq.ap_min.DecimalValue = LastRecordedTrackNumber;
|
||||
sq.ap_sec.DecimalValue = 0;
|
||||
sq.ap_frame.DecimalValue = 0;
|
||||
|
||||
entries.Add(new RawTOCEntry { QData = sq });
|
||||
|
||||
//leadout:
|
||||
sq.q_index.DecimalValue = 0xA2;
|
||||
sq.AP_Timestamp = new Timestamp(LeadoutLBA);
|
||||
|
||||
entries.Add(new RawTOCEntry { QData = sq });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Main unit of organization for reading data from the disc. Represents one physical disc sector.
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
//TODO - generate correct Q subchannel CRC
|
||||
|
||||
namespace BizHawk.Emulation.DiscSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Synthesizes RawTCOEntry A0 A1 A2 from the provided information.
|
||||
/// This might be reused by formats other than CUE later, so it isn't directly associated with that
|
||||
/// </summary>
|
||||
public class Synthesize_A0A1A2_Job
|
||||
{
|
||||
/// <summary>
|
||||
/// "First Recorded Track Number" value for TOC (usually 1)
|
||||
/// </summary>
|
||||
public int IN_FirstRecordedTrackNumber;
|
||||
|
||||
/// <summary>
|
||||
/// "Last Recorded Track Number" value for TOC
|
||||
/// </summary>
|
||||
public int IN_LastRecordedTrackNumber;
|
||||
|
||||
/// <summary>
|
||||
/// The absolute timestamp of the lead-out track
|
||||
/// </summary>
|
||||
public Timestamp IN_LeadoutTimestamp;
|
||||
|
||||
/// <summary>
|
||||
/// The session format for this TOC
|
||||
/// </summary>
|
||||
public DiscTOCRaw.SessionFormat IN_Session1Format;
|
||||
|
||||
/// <summary>
|
||||
/// Appends the new entries to the provided list
|
||||
/// </summary>
|
||||
public void Run(List<RawTOCEntry> entries)
|
||||
{
|
||||
SubchannelQ sq = new SubchannelQ();
|
||||
|
||||
BufferedSubcodeSector bss = new BufferedSubcodeSector(); //TODO - its hacky that we need this.. (NOT USED YET)
|
||||
|
||||
//ADR (q-Mode) is necessarily 0x01 for a RawTOCEntry
|
||||
const int kADR = 1;
|
||||
const int kUnknownControl = 0;
|
||||
|
||||
sq.SetStatus(kADR, (EControlQ)kUnknownControl);
|
||||
|
||||
//first recorded track number:
|
||||
sq.q_index.BCDValue = 0xA0;
|
||||
sq.ap_min.DecimalValue = IN_FirstRecordedTrackNumber;
|
||||
switch(IN_Session1Format)
|
||||
{
|
||||
//TODO these probably shouldn't be decimal values
|
||||
case DiscTOCRaw.SessionFormat.Type00_CDROM_CDDA: sq.ap_sec.DecimalValue = 0x00; break;
|
||||
case DiscTOCRaw.SessionFormat.Type10_CDI: sq.ap_sec.DecimalValue = 0x10; break;
|
||||
case DiscTOCRaw.SessionFormat.Type20_CDXA: sq.ap_sec.DecimalValue = 0x20; break;
|
||||
default: throw new InvalidOperationException("Invalid Session1Format");
|
||||
}
|
||||
sq.ap_frame.DecimalValue = 0;
|
||||
|
||||
entries.Add(new RawTOCEntry { QData = sq });
|
||||
|
||||
//last recorded track number:
|
||||
sq.q_index.BCDValue = 0xA1;
|
||||
sq.ap_min.DecimalValue = IN_LastRecordedTrackNumber;
|
||||
sq.ap_sec.DecimalValue = 0;
|
||||
sq.ap_frame.DecimalValue = 0;
|
||||
|
||||
entries.Add(new RawTOCEntry { QData = sq });
|
||||
|
||||
//leadout:
|
||||
sq.q_index.BCDValue = 0xA2;
|
||||
sq.AP_Timestamp = IN_LeadoutTimestamp;
|
||||
|
||||
|
||||
entries.Add(new RawTOCEntry { QData = sq });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -249,44 +249,6 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
_4CH = 8, //Four channel audio
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the q-mode 1 Q subchannel data. These contain TOC entries.
|
||||
/// design of this struct is from [IEC10149].
|
||||
/// Nothing in here is BCD
|
||||
/// </summary>
|
||||
public class Q_Mode_1
|
||||
{
|
||||
/// <summary>
|
||||
/// Supposed to be zero, because it was in the lead-in track, but you never know
|
||||
/// </summary>
|
||||
public byte TNO;
|
||||
|
||||
/// <summary>
|
||||
/// The track number (or a special A0 A1 A2 value) of the track being described
|
||||
/// </summary>
|
||||
public byte POINTER;
|
||||
|
||||
/// <summary>
|
||||
/// Supposedly the timestamp within the lead-in track. but it's useless
|
||||
/// </summary>
|
||||
public byte MIN, SEC, FRAC;
|
||||
|
||||
/// <summary>
|
||||
/// Supposed to be zero
|
||||
/// </summary>
|
||||
public byte ZERO;
|
||||
|
||||
/// <summary>
|
||||
/// A track number of the first (for A0) or final (A1) information track; or the _absolute_ time position of an information track
|
||||
/// </summary>
|
||||
public byte P_MIN;
|
||||
|
||||
/// <summary>
|
||||
/// ZERO for an A0 or A1 entry (where P_MIN was the track number); or the _absolute_ time position of an information track
|
||||
/// </summary>
|
||||
public byte P_SEC, P_FRAC;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Why did I make this a struct? I thought there might be a shitton of these and I was trying to cut down on object creation churn during disc-loading.
|
||||
/// But I ended up mostly just having a shitton of byte[] for each buffer (I could improve that later to possibly reference a blob on top of a memorystream)
|
||||
|
@ -296,18 +258,18 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
{
|
||||
/// <summary>
|
||||
/// ADR and CONTROL
|
||||
/// TODO - make BCD2?
|
||||
/// TODO - make BCD2? PROBABLY NOT. I DONT KNOW.
|
||||
/// </summary>
|
||||
public byte q_status;
|
||||
|
||||
/// <summary>
|
||||
/// normal track: BCD indications of the current track number
|
||||
/// normal track: BCD indication of the current track number
|
||||
/// leadin track: should be 0
|
||||
/// </summary>
|
||||
public BCD2 q_tno;
|
||||
|
||||
/// <summary>
|
||||
/// normal track: BCD indications of the current index
|
||||
/// normal track: BCD indication of the current index
|
||||
/// leadin track: 'POINT' field used to ID the TOC entry #
|
||||
/// </summary>
|
||||
public BCD2 q_index;
|
||||
|
@ -318,7 +280,7 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
/// normal track: relative timestamp
|
||||
/// leadin track: unknown
|
||||
/// leadout: relative timestamp
|
||||
/// TODO - why are these BCD2? having things in BCD2 is freaking annoying, I should only make them BCD2 when serializing
|
||||
/// TODO - why are these BCD2? having things in BCD2 is freaking annoying, I should only make them BCD2 when serializing into a subchannel Q buffer
|
||||
/// EDIT - elsewhere I rambled "why not BCD2?". geh. need to make a final organized approach
|
||||
/// </summary>
|
||||
public BCD2 min, sec, frame;
|
||||
|
@ -345,7 +307,6 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
/// </summary>
|
||||
public ushort q_crc;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the initial set of timestamps (min,sec,frac) as a convenient Timestamp
|
||||
/// </summary>
|
||||
|
@ -360,19 +321,19 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// sets the status byte from the provided adr and control values
|
||||
/// sets the status byte from the provided adr/qmode and control values
|
||||
/// </summary>
|
||||
public void SetStatus(byte adr, EControlQ control)
|
||||
public void SetStatus(byte adr_or_qmode, EControlQ control)
|
||||
{
|
||||
q_status = ComputeStatus(adr, control);
|
||||
q_status = ComputeStatus(adr_or_qmode, control);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// computes a status byte from the provided adr and control values
|
||||
/// computes a status byte from the provided adr/qmode and control values
|
||||
/// </summary>
|
||||
public static byte ComputeStatus(int adr, EControlQ control)
|
||||
public static byte ComputeStatus(int adr_or_qmode, EControlQ control)
|
||||
{
|
||||
return (byte)(adr | (((int)control) << 4));
|
||||
return (byte)(adr_or_qmode | (((int)control) << 4));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
Loading…
Reference in New Issue