Fixup multisession handling with MDS and improve its track/sector size handling, also maybe fix it entirely? (not sure if this ever worked)
Move the various synths using the CUE SS_Base to a file, mostly just a nicer organizational change as MDS and CDI use one of these but not CUE Misc improvements elsewhere
This commit is contained in:
parent
1f3068fe77
commit
2012b083f6
|
@ -443,52 +443,6 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
return ret;
|
||||
}
|
||||
|
||||
private class SS_CDI_RawQ : SS_Base
|
||||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset, 2352);
|
||||
|
||||
if ((job.Parts & ESectorSynthPart.SubchannelP) != 0)
|
||||
{
|
||||
SynthUtils.SubP(job.DestBuffer2448, job.DestOffset + 2352, Pause);
|
||||
}
|
||||
|
||||
// Q is present in the blob and non-interleaved
|
||||
if ((job.Parts & ESectorSynthPart.SubchannelQ) != 0)
|
||||
{
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset + 2352 + 12, 12);
|
||||
}
|
||||
|
||||
//clear R-W if needed
|
||||
if ((job.Parts & ESectorSynthPart.Subchannel_RSTUVW) != 0)
|
||||
{
|
||||
Array.Clear(job.DestBuffer2448, job.DestOffset + 2352 + 12 + 12, 12 * 6);
|
||||
}
|
||||
|
||||
//subcode has been generated deinterleaved; we may still need to interleave it
|
||||
if ((job.Parts & ESectorSynthPart.SubcodeAny) != 0 && (job.Parts & ESectorSynthPart.SubcodeDeinterleave) == 0)
|
||||
{
|
||||
SynthUtils.InterleaveSubcodeInplace(job.DestBuffer2448, job.DestOffset + 2352);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SS_CDI_RawPQRSTUVW : SS_Base
|
||||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
// all subcode is present and interleaved, just read it all
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset, 2448);
|
||||
|
||||
// deinterleave it if needed
|
||||
if ((job.Parts & ESectorSynthPart.SubcodeDeinterleave) != 0)
|
||||
{
|
||||
SynthUtils.DeinterleaveSubcodeInplace(job.DestBuffer2448, job.DestOffset + 2352);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="CDIParseException">file <paramref name="cdiPath"/> not found</exception>
|
||||
public static Disc LoadCDIToDisc(string cdiPath, DiscMountPolicy IN_DiscMountPolicy)
|
||||
{
|
||||
|
@ -559,8 +513,8 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
0 => new SS_Mode1_2048(),
|
||||
1 => new SS_Mode2_2336(),
|
||||
2 => new SS_2352(),
|
||||
3 => new SS_CDI_RawQ(),
|
||||
4 => new SS_CDI_RawPQRSTUVW(),
|
||||
3 => new SS_2364_DeinterleavedQ(),
|
||||
4 => new SS_2448_Interleaved(),
|
||||
_ => throw new InvalidOperationException()
|
||||
};
|
||||
synth.Blob = cdiBlob;
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.DiscSystem.CUE
|
||||
{
|
||||
// extra synths using SS_Base, not used by CUEs but used for other formats
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mode2 Form1 2048-byte sector
|
||||
/// Only used by MDS
|
||||
/// </summary>
|
||||
internal class SS_Mode2_Form1_2048 : SS_Base
|
||||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
var ecm = (job.Parts & ESectorSynthPart.ECMAny) != 0;
|
||||
if (ecm)
|
||||
{
|
||||
// ecm needs these parts for synth
|
||||
job.Parts |= ESectorSynthPart.User2048;
|
||||
job.Parts |= ESectorSynthPart.Header16;
|
||||
}
|
||||
|
||||
//read the sector user data
|
||||
if ((job.Parts & ESectorSynthPart.User2048) != 0)
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset + 24, 2048);
|
||||
|
||||
if ((job.Parts & ESectorSynthPart.Header16) != 0)
|
||||
SynthUtils.SectorHeader(job.DestBuffer2448, job.DestOffset + 0, job.LBA, 2);
|
||||
|
||||
if (ecm)
|
||||
SynthUtils.ECM_Mode2_Form1(job.DestBuffer2448, job.DestOffset);
|
||||
|
||||
SynthSubchannelAsNeed(job);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mode2 Form1 2324-byte sector
|
||||
/// Only used by MDS
|
||||
/// </summary>
|
||||
internal class SS_Mode2_Form2_2324 : SS_Base
|
||||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
//read the sector userdata (note: ECC data is now userdata in this regard)
|
||||
if ((job.Parts & ESectorSynthPart.User2336) != 0)
|
||||
{
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset + 24, 2324);
|
||||
// only needs userdata for synth
|
||||
SynthUtils.ECM_Mode2_Form2(job.DestBuffer2448, job.DestOffset);
|
||||
}
|
||||
|
||||
if ((job.Parts & ESectorSynthPart.Header16) != 0)
|
||||
SynthUtils.SectorHeader(job.DestBuffer2448, job.DestOffset + 0, job.LBA, 2);
|
||||
|
||||
SynthSubchannelAsNeed(job);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mode2 Form1 2328-byte sector
|
||||
/// Only used by MDS
|
||||
/// </summary>
|
||||
internal class SS_Mode2_Form2_2328 : SS_Base
|
||||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
//read the sector userdata (note: ECC data is now userdata in this regard)
|
||||
if ((job.Parts & ESectorSynthPart.User2336) != 0)
|
||||
{
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset + 24, 2328);
|
||||
// only subheader needs to be synthed
|
||||
SynthUtils.SectorSubHeader(job.DestBuffer2448, job.DestOffset + 16, 2);
|
||||
}
|
||||
|
||||
if ((job.Parts & ESectorSynthPart.Header16) != 0)
|
||||
SynthUtils.SectorHeader(job.DestBuffer2448, job.DestOffset + 0, job.LBA, 2);
|
||||
|
||||
SynthSubchannelAsNeed(job);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a full 2448-byte sector with interleaved subcode
|
||||
/// Only used by MDS and CDI
|
||||
/// </summary>
|
||||
internal class SS_2448_Interleaved : SS_Base
|
||||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
// all subcode is present and interleaved, just read it all
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset, 2448);
|
||||
|
||||
// deinterleave it if needed
|
||||
if ((job.Parts & ESectorSynthPart.SubcodeDeinterleave) != 0)
|
||||
SynthUtils.DeinterleaveSubcodeInplace(job.DestBuffer2448, job.DestOffset + 2352);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 2364-byte (2352 + 12) sector with deinterleaved Q subcode
|
||||
/// Only used by CDI
|
||||
/// </summary>
|
||||
internal class SS_2364_DeinterleavedQ : SS_Base
|
||||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
if ((job.Parts & ESectorSynthPart.User2352) != 0)
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset, 2352);
|
||||
|
||||
if ((job.Parts & ESectorSynthPart.SubchannelP) != 0)
|
||||
SynthUtils.SubP(job.DestBuffer2448, job.DestOffset + 2352, Pause);
|
||||
|
||||
// Q is present in the blob and non-interleaved
|
||||
if ((job.Parts & ESectorSynthPart.SubchannelQ) != 0)
|
||||
Blob.Read(BlobOffset + 2352, job.DestBuffer2448, job.DestOffset + 2352 + 12, 12);
|
||||
|
||||
// clear R-W if needed
|
||||
if ((job.Parts & ESectorSynthPart.Subchannel_RSTUVW) != 0)
|
||||
Array.Clear(job.DestBuffer2448, job.DestOffset + 2352 + 12 + 12, 12 * 6);
|
||||
|
||||
// subcode has been generated deinterleaved; we may still need to interleave it
|
||||
if ((job.Parts & ESectorSynthPart.SubcodeAny) != 0 && (job.Parts & ESectorSynthPart.SubcodeDeinterleave) == 0)
|
||||
SynthUtils.InterleaveSubcodeInplace(job.DestBuffer2448, job.DestOffset + 2352);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,11 +39,10 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
|||
}
|
||||
|
||||
//subcode has been generated deinterleaved; we may still need to interleave it
|
||||
if((job.Parts & ESectorSynthPart.SubcodeAny) != 0)
|
||||
if ((job.Parts & (ESectorSynthPart.SubcodeDeinterleave)) == 0)
|
||||
{
|
||||
SynthUtils.InterleaveSubcodeInplace(job.DestBuffer2448, job.DestOffset + 2352);
|
||||
}
|
||||
if ((job.Parts & ESectorSynthPart.SubcodeAny) != 0 && (job.Parts & ESectorSynthPart.SubcodeDeinterleave) == 0)
|
||||
{
|
||||
SynthUtils.InterleaveSubcodeInplace(job.DestBuffer2448, job.DestOffset + 2352);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,15 +53,23 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
|||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
var ecm = (job.Parts & ESectorSynthPart.ECMAny) != 0;
|
||||
if (ecm)
|
||||
{
|
||||
// ecm needs these parts for synth
|
||||
job.Parts |= ESectorSynthPart.User2048;
|
||||
job.Parts |= ESectorSynthPart.Header16;
|
||||
}
|
||||
|
||||
//read the sector user data
|
||||
if((job.Parts & ESectorSynthPart.User2048) != 0)
|
||||
if ((job.Parts & ESectorSynthPart.User2048) != 0)
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset + 16, 2048);
|
||||
|
||||
if ((job.Parts & ESectorSynthPart.Header16) != 0)
|
||||
SynthUtils.SectorHeader(job.DestBuffer2448, job.DestOffset + 0, job.LBA, 1);
|
||||
|
||||
if ((job.Parts & ESectorSynthPart.ECMAny) != 0)
|
||||
SynthUtils.ECM_Mode1(job.DestBuffer2448, job.DestOffset + 0, job.LBA);
|
||||
if (ecm)
|
||||
SynthUtils.ECM_Mode1(job.DestBuffer2448, job.DestOffset + 0);
|
||||
|
||||
SynthSubchannelAsNeed(job);
|
||||
}
|
||||
|
@ -75,8 +82,9 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
|||
{
|
||||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
//read the sector user data
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset + 16, 2336);
|
||||
//read the sector sector user data + ECM data
|
||||
if ((job.Parts & ESectorSynthPart.User2336) != 0)
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset + 16, 2336);
|
||||
|
||||
if ((job.Parts & ESectorSynthPart.Header16) != 0)
|
||||
SynthUtils.SectorHeader(job.DestBuffer2448, job.DestOffset + 0, job.LBA, 2);
|
||||
|
@ -94,7 +102,8 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
|||
public override void Synth(SectorSynthJob job)
|
||||
{
|
||||
//read the sector user data
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset, 2352);
|
||||
if ((job.Parts & ESectorSynthPart.User2352) != 0)
|
||||
Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset, 2352);
|
||||
|
||||
//if subcode is needed, synthesize it
|
||||
SynthSubchannelAsNeed(job);
|
||||
|
@ -159,7 +168,7 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
|||
case 1:
|
||||
{
|
||||
if ((job.Parts & ESectorSynthPart.ECMAny) != 0)
|
||||
SynthUtils.ECM_Mode1(job.DestBuffer2448, job.DestOffset + 0, job.LBA);
|
||||
SynthUtils.ECM_Mode1(job.DestBuffer2448, job.DestOffset + 0);
|
||||
break;
|
||||
}
|
||||
case 2 when form == 2:
|
||||
|
@ -170,6 +179,4 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
|||
SynthSubchannelAsNeed(job);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -154,9 +154,9 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
public class ATrack
|
||||
{
|
||||
/// <summary>
|
||||
/// The specified data mode
|
||||
/// The specified data mode (only lower 3 bits are actually meaningful)
|
||||
/// 0x00 - None (no data)
|
||||
/// 0x02 - DVD
|
||||
/// 0x02 - DVD (when header specifies DVD, Mode1 otherwise)
|
||||
/// 0xA9 - Audio
|
||||
/// 0xAA - Mode1
|
||||
/// 0xAB - Mode2
|
||||
|
@ -271,6 +271,19 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
public int PSec;
|
||||
public int PFrame;
|
||||
|
||||
/// <summary>
|
||||
/// Lower 3 bits of ATrack Mode
|
||||
/// Upper 5 bits are meaningless (see mirage_parser_mds_convert_track_mode)
|
||||
/// 0x0 - None or Mode2 (Depends on sector size)
|
||||
/// 0x1 - Audio
|
||||
/// 0x2 - DVD or Mode1 (Depends on medium)
|
||||
/// 0x3 - Mode2
|
||||
/// 0x4 - Mode2 Form1
|
||||
/// 0x5 - Mode2 Form2
|
||||
/// 0x6 - UNKNOWN
|
||||
/// 0x7 - Mode2
|
||||
/// </summary>
|
||||
public int TrackMode;
|
||||
|
||||
public int SectorSize;
|
||||
public long TrackOffset;
|
||||
|
@ -313,6 +326,12 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
throw new MDSParseException($"MDS Parse Error: Only MDS version 1.x is supported!\nDetected version: {aFile.Header.Version[0]}.{aFile.Header.Version[1]}");
|
||||
}
|
||||
|
||||
isDvd = aFile.Header.Medium is 0x10 or 0x12;
|
||||
if (isDvd)
|
||||
{
|
||||
throw new MDSParseException("DVD Detected. Not currently supported!");
|
||||
}
|
||||
|
||||
// parse sessions
|
||||
var aSessions = new Dictionary<int, ASession>();
|
||||
|
||||
|
@ -377,12 +396,6 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
track.Files = bc.ToInt32(trackHeader.Skip(48).Take(4).ToArray());
|
||||
track.FooterOffset = bc.ToInt32(trackHeader.Skip(52).Take(4).ToArray());
|
||||
|
||||
if (track.Mode == 0x02)
|
||||
{
|
||||
isDvd = true;
|
||||
throw new MDSParseException("DVD Detected. Not currently supported!");
|
||||
}
|
||||
|
||||
// check for track extra block - this can probably be handled in a separate loop,
|
||||
// but I'll just store the current stream position then seek forward to the extra block for this track
|
||||
var currPos = stream.Position;
|
||||
|
@ -484,8 +497,15 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
|
||||
stream.Position = currPos;
|
||||
|
||||
var point = track.Point;
|
||||
// each session has its own 0xA0/0xA1/0xA3 track
|
||||
// so this can't be used directly as a key
|
||||
if (point is 0xA0 or 0xA1 or 0xA2)
|
||||
{
|
||||
point |= session.SessionNumber << 8;
|
||||
}
|
||||
|
||||
aTracks.Add(track.Point, track);
|
||||
aTracks.Add(point, track);
|
||||
aFile.Tracks.Add(track);
|
||||
|
||||
if (footerOffset == 0)
|
||||
|
@ -521,32 +541,57 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
|
||||
// now build the TOC object
|
||||
foreach (var se in aFile.ParsedSession)
|
||||
foreach (var t in aTracks.Values
|
||||
.Where(a => se.StartTrack <= a.TrackNo && a.TrackNo <= se.EndTrack)
|
||||
.OrderBy(a => a.TrackNo))
|
||||
{
|
||||
ATOCEntry CreateTOCEntryFromTrack(ATrack track)
|
||||
{
|
||||
aFile.TOCEntries.Add(new(t.Point)
|
||||
return new(track.Point)
|
||||
{
|
||||
ADR_Control = t.ADR_Control,
|
||||
AFrame = t.AFrame,
|
||||
AMin = t.AMin,
|
||||
ASec = t.ASec,
|
||||
BlobIndex = t.BlobIndex,
|
||||
EntryNum = t.TrackNo,
|
||||
ExtraBlock = t.ExtraBlock,
|
||||
ImageFileNamePaths = t.ImageFileNamePaths,
|
||||
PFrame = t.PFrame,
|
||||
PLBA = Convert.ToInt32(t.PLBA),
|
||||
PMin = t.PMin,
|
||||
Point = t.Point,
|
||||
PSec = t.PSec,
|
||||
SectorSize = t.SectorSize,
|
||||
ADR_Control = track.ADR_Control,
|
||||
AFrame = track.AFrame,
|
||||
AMin = track.AMin,
|
||||
ASec = track.ASec,
|
||||
BlobIndex = track.BlobIndex,
|
||||
EntryNum = track.TrackNo,
|
||||
ExtraBlock = track.ExtraBlock,
|
||||
ImageFileNamePaths = track.ImageFileNamePaths,
|
||||
PFrame = track.PFrame,
|
||||
PLBA = Convert.ToInt32(track.PLBA),
|
||||
PMin = track.PMin,
|
||||
Point = track.Point,
|
||||
PSec = track.PSec,
|
||||
TrackMode = track.Mode & 0x7,
|
||||
SectorSize = track.SectorSize,
|
||||
Session = se.SessionSequence,
|
||||
TrackOffset = Convert.ToInt64(t.StartOffset),
|
||||
Zero = t.Zero
|
||||
});
|
||||
TrackOffset = Convert.ToInt64(track.StartOffset),
|
||||
Zero = track.Zero
|
||||
};
|
||||
}
|
||||
|
||||
void AddAXTrack(int x)
|
||||
{
|
||||
if (aTracks.TryGetValue(se.SessionSequence << 8 | 0xA0 | x, out var axTrack))
|
||||
{
|
||||
aFile.TOCEntries.Add(CreateTOCEntryFromTrack(axTrack));
|
||||
}
|
||||
}
|
||||
|
||||
// add in the 0xA0/0xA1/0xA2 tracks
|
||||
AddAXTrack(0);
|
||||
AddAXTrack(1);
|
||||
AddAXTrack(2);
|
||||
|
||||
// add in the rest of the tracks
|
||||
foreach (var t in aTracks
|
||||
.Where(a => se.StartTrack <= a.Key && a.Key <= se.EndTrack)
|
||||
.OrderBy(a => a.Key)
|
||||
.Select(a => a.Value))
|
||||
{
|
||||
aFile.TOCEntries.Add(CreateTOCEntryFromTrack(t));
|
||||
}
|
||||
|
||||
// TODO: first session might have 0xB0/0xC0 tracks... not sure how to handle these
|
||||
}
|
||||
|
||||
return aFile;
|
||||
}
|
||||
|
||||
|
@ -714,6 +759,32 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
var currBlobIndex = 0;
|
||||
foreach (var session in mdsf.ParsedSession)
|
||||
{
|
||||
// leadin track
|
||||
// we create this only for session 2+, not session 1
|
||||
var leadinSize = session.SessionSequence == 1 ? 0 : 4500;
|
||||
for (var i = 0; i < leadinSize; i++)
|
||||
{
|
||||
// this is most certainly wrong
|
||||
// nothing relies on the exact contents for now (only multisession core is VirtualJaguar which doesn't touch leadin)
|
||||
// just needs sectors to be present due to track info LBAs of session 2+ accounting for this being present
|
||||
var pregapTrackType = CUE.CueTrackType.Audio;
|
||||
if (tocSynth.Result.TOCItems[1].IsData)
|
||||
{
|
||||
pregapTrackType = tocSynth.Result.SessionFormat switch
|
||||
{
|
||||
SessionFormat.Type20_CDXA => CUE.CueTrackType.Mode2_2352,
|
||||
SessionFormat.Type10_CDI => CUE.CueTrackType.CDI_2352,
|
||||
SessionFormat.Type00_CDROM_CDDA => CUE.CueTrackType.Mode1_2352,
|
||||
_ => pregapTrackType
|
||||
};
|
||||
}
|
||||
disc._Sectors.Add(new CUE.SS_Gap()
|
||||
{
|
||||
Policy = IN_DiscMountPolicy,
|
||||
TrackType = pregapTrackType
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = session.StartTrack; i <= session.EndTrack; i++)
|
||||
{
|
||||
var relMSF = -1;
|
||||
|
@ -800,8 +871,6 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
var currBlobOffset = track.TrackOffset;
|
||||
for (var sector = session.StartSector; sector <= session.EndSector; sector++)
|
||||
{
|
||||
CUE.SS_Base sBase;
|
||||
|
||||
// get the current blob from the BlobIndex
|
||||
var currBlob = (Blob_RawFile) BlobIndex[currBlobIndex];
|
||||
var currBlobLength = currBlob.Length;
|
||||
|
@ -809,33 +878,29 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
currBlobIndex++;
|
||||
var mdfBlob = (IBlob) disc.DisposableResources[currBlobIndex];
|
||||
|
||||
//int userSector = 2048;
|
||||
switch (track.SectorSize)
|
||||
CUE.SS_Base sBase = track.SectorSize switch
|
||||
{
|
||||
case 2448:
|
||||
sBase = new CUE.SS_2352()
|
||||
{
|
||||
Policy = IN_DiscMountPolicy
|
||||
};
|
||||
//userSector = 2352;
|
||||
break;
|
||||
case 2048:
|
||||
default:
|
||||
sBase = new CUE.SS_Mode1_2048()
|
||||
{
|
||||
Policy = IN_DiscMountPolicy
|
||||
};
|
||||
//userSector = 2048;
|
||||
break;
|
||||
|
||||
//throw new Exception($"Not supported: Sector Size {track.SectorSize}");
|
||||
}
|
||||
2352 when track.TrackMode is 1 => new CUE.SS_2352(),
|
||||
2048 when track.TrackMode is 2 => new CUE.SS_Mode1_2048(),
|
||||
2336 when track.TrackMode is 0 or 3 or 7 => new CUE.SS_Mode2_2336(),
|
||||
2048 when track.TrackMode is 4 => new CUE.SS_Mode2_Form1_2048(),
|
||||
2324 when track.TrackMode is 5 => new CUE.SS_Mode2_Form2_2324(),
|
||||
2328 when track.TrackMode is 5 => new CUE.SS_Mode2_Form2_2328(),
|
||||
// best guesses
|
||||
2048 => new CUE.SS_Mode1_2048(),
|
||||
2336 => new CUE.SS_Mode2_2336(),
|
||||
2352 => new CUE.SS_2352(),
|
||||
2448 => new CUE.SS_2448_Interleaved(),
|
||||
_ => throw new InvalidOperationException($"Not supported: Sector Size {track.SectorSize}, Track Mode {track.TrackMode}")
|
||||
};
|
||||
|
||||
sBase.Policy = IN_DiscMountPolicy;
|
||||
|
||||
// configure blob
|
||||
sBase.Blob = mdfBlob;
|
||||
sBase.BlobOffset = currBlobOffset;
|
||||
|
||||
currBlobOffset += track.SectorSize; // userSector;
|
||||
currBlobOffset += track.SectorSize;
|
||||
|
||||
// add subchannel data
|
||||
relMSF++;
|
||||
|
@ -873,6 +938,18 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
disc._Sectors.Add(sBase);
|
||||
}
|
||||
}
|
||||
|
||||
// leadout track
|
||||
// first leadout is 6750 sectors, later ones are 2250 sectors
|
||||
var leadoutSize = session.SessionSequence == 1 ? 6750 : 2250;
|
||||
for (var i = 0; i < leadoutSize; i++)
|
||||
{
|
||||
disc._Sectors.Add(new SS_Leadout
|
||||
{
|
||||
SessionNumber = session.SessionSequence,
|
||||
Policy = IN_DiscMountPolicy
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return disc;
|
||||
|
|
|
@ -29,11 +29,8 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
Result.TOCItems[0].Control = 0;
|
||||
Result.TOCItems[0].Exists = false;
|
||||
|
||||
//just in case this doesn't get set...
|
||||
Result.FirstRecordedTrackNumber = 0;
|
||||
Result.LastRecordedTrackNumber = 0;
|
||||
|
||||
var maxFoundTrack = 0;
|
||||
var minFoundTrack = 1;
|
||||
var maxFoundTrack = 1;
|
||||
|
||||
foreach (var te in Entries)
|
||||
{
|
||||
|
@ -50,6 +47,7 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
case 255:
|
||||
throw new InvalidOperationException("point == 255");
|
||||
case <= 99:
|
||||
minFoundTrack = Math.Min(minFoundTrack, point);
|
||||
maxFoundTrack = Math.Max(maxFoundTrack, point);
|
||||
Result.TOCItems[point].LBA = q.AP_Timestamp - 150; //RawTOCEntries contained an absolute time
|
||||
Result.TOCItems[point].Control = q.CONTROL;
|
||||
|
@ -96,8 +94,7 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
}
|
||||
|
||||
//this is speculative:
|
||||
//well, nothing to be done here..
|
||||
// if (ret.FirstRecordedTrackNumber == -1) { }
|
||||
if (Result.FirstRecordedTrackNumber == -1) { Result.FirstRecordedTrackNumber = minFoundTrack; }
|
||||
if (Result.LastRecordedTrackNumber == -1) { Result.LastRecordedTrackNumber = maxFoundTrack; }
|
||||
if (Result.SessionFormat == SessionFormat.None) Result.SessionFormat = SessionFormat.Type00_CDROM_CDDA;
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
/// <summary>
|
||||
/// The complete sector userdata (2352 bytes) is required
|
||||
/// </summary>
|
||||
UserComplete = 15,
|
||||
UserComplete = (Header16 | User2048 | ECM288Complete),
|
||||
|
||||
/// <summary>
|
||||
/// An alias for UserComplete
|
||||
|
|
|
@ -71,6 +71,30 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
buffer16[offset + 15] = mode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synthesizes a Mode2 sector subheader
|
||||
/// </summary>
|
||||
public static void SectorSubHeader(byte[] buffer8, int offset, byte form)
|
||||
{
|
||||
// see mirage_sector_generate_subheader
|
||||
for (var i = 0; i < 8; i++) buffer8[offset + i] = 0;
|
||||
if (form == 2)
|
||||
{
|
||||
// these are just 0 in form 1
|
||||
buffer8[offset + 2] = 0x20;
|
||||
buffer8[offset + 5] = 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synthesizes the EDC checksum for a Mode 1 data sector (and puts it in place)
|
||||
/// </summary>
|
||||
public static void EDC_Mode1(byte[] buf2352, int offset)
|
||||
{
|
||||
var edc = ECM.EDC_Calc(buf2352, offset, 2064);
|
||||
ECM.PokeUint(buf2352, offset + 2064, edc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synthesizes the EDC checksum for a Mode 2 Form 1 data sector (and puts it in place)
|
||||
/// </summary>
|
||||
|
@ -92,13 +116,12 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
|
||||
/// <summary>
|
||||
/// Synthesizes the complete ECM data (EDC + ECC) for a Mode 1 data sector (and puts it in place)
|
||||
/// Make sure everything else in the sector userdata is done before calling this
|
||||
/// Make sure everything else in the sector header and userdata is done before calling this
|
||||
/// </summary>
|
||||
public static void ECM_Mode1(byte[] buf2352, int offset, int LBA)
|
||||
public static void ECM_Mode1(byte[] buf2352, int offset)
|
||||
{
|
||||
//EDC
|
||||
var edc = ECM.EDC_Calc(buf2352, offset, 2064);
|
||||
ECM.PokeUint(buf2352, offset + 2064, edc);
|
||||
EDC_Mode1(buf2352, offset);
|
||||
|
||||
//reserved, zero
|
||||
for (var i = 0; i < 8; i++) buf2352[offset + 2068 + i] = 0;
|
||||
|
@ -107,6 +130,37 @@ namespace BizHawk.Emulation.DiscSystem
|
|||
ECM.ECC_Populate(buf2352, offset, buf2352, offset, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synthesizes the complete ECM data (Subheader + EDC + ECC) for a Mode 2 Form 1 data sector (and puts it in place)
|
||||
/// Make sure everything else in the sector header and userdata is done before calling this
|
||||
/// </summary>
|
||||
public static void ECM_Mode2_Form1(byte[] buf2352, int offset)
|
||||
{
|
||||
//Subheader
|
||||
SectorSubHeader(buf2352, offset + 16, 1);
|
||||
|
||||
//EDC
|
||||
EDC_Mode2_Form1(buf2352, offset);
|
||||
|
||||
//ECC
|
||||
ECM.ECC_Populate(buf2352, offset, buf2352, offset, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synthesizes the complete ECM data (Subheader + EDC) for a Mode 2 Form 2 data sector (and puts it in place)
|
||||
/// Make sure everything else in the userdata is done before calling this
|
||||
/// </summary>
|
||||
public static void ECM_Mode2_Form2(byte[] buf2352, int offset)
|
||||
{
|
||||
//Subheader
|
||||
SectorSubHeader(buf2352, offset + 16, 2);
|
||||
|
||||
//EDC
|
||||
EDC_Mode2_Form2(buf2352, offset);
|
||||
|
||||
//note that Mode 2 Form 2 does not have ECC
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the useful (but unrealistic) deinterleaved subchannel data into the useless (but realistic) interleaved format.
|
||||
/// in_buf and out_buf should not overlap
|
||||
|
|
Loading…
Reference in New Issue