From d698bb80592ec166a2ebd750f79deaac02f5db95 Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 28 Jun 2015 03:51:45 -0500 Subject: [PATCH] work on bringing back cue loading --- .../API/DiscSectorReader.cs | 17 ++++ .../BizHawk.Emulation.DiscSystem.csproj | 1 + .../Blobs/Blob_ZeroPadAdapter.cs | 67 ++------------- BizHawk.Emulation.DiscSystem/CCD_format.cs | 12 ++- BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs | 59 +++++++------ .../CUE/CUE_Synths.cs | 84 +++++++++++++++++++ .../SectorInterfaces.cs | 17 +++- 7 files changed, 164 insertions(+), 93 deletions(-) create mode 100644 BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs diff --git a/BizHawk.Emulation.DiscSystem/API/DiscSectorReader.cs b/BizHawk.Emulation.DiscSystem/API/DiscSectorReader.cs index 5896851ba9..064fe25d99 100644 --- a/BizHawk.Emulation.DiscSystem/API/DiscSectorReader.cs +++ b/BizHawk.Emulation.DiscSystem/API/DiscSectorReader.cs @@ -46,6 +46,13 @@ namespace BizHawk.Emulation.DiscSystem /// How about .sub files? Can't remember right now. /// public bool DeinterleavedSubcode = true; + + /// + /// Indicates whether the output buffer should be cleared before returning any data. + /// This will involve clearing sections you didn't ask for, and clearing sections about to be filled with data from the disc. + /// It is a waste of performance, but it will ensure reliability. + /// + public bool DeterministicClearBuffer = true; } @@ -71,6 +78,11 @@ namespace BizHawk.Emulation.DiscSystem job.Disc = disc; } + void PrepareBuffer(byte[] buffer, int offset, int size) + { + if (Policy.DeterministicClearBuffer) Array.Clear(buffer, offset, size); + } + //todo - methods to read only subcode /// @@ -80,6 +92,7 @@ namespace BizHawk.Emulation.DiscSystem { var sector = disc.Sectors[lba + 150]; + PrepareBuffer(buffer, offset, 2352); PrepareJob(lba); job.DestBuffer2448 = buf2442; job.DestOffset = 0; @@ -100,6 +113,7 @@ namespace BizHawk.Emulation.DiscSystem { var sector = disc.Sectors[lba + 150]; + PrepareBuffer(buffer, offset, 2352); PrepareJob(lba); job.DestBuffer2448 = buffer; //go straight to the caller's buffer job.DestOffset = offset; //go straight to the caller's buffer @@ -118,6 +132,7 @@ namespace BizHawk.Emulation.DiscSystem //we can read the 2048 bytes directly var sector = disc.Sectors[lba + 150]; + PrepareBuffer(buffer, offset, 2352); PrepareJob(lba); job.DestBuffer2448 = buf2442; job.DestOffset = 0; @@ -134,6 +149,7 @@ namespace BizHawk.Emulation.DiscSystem //we can read the 2048 bytes directly but we have to get them from the mode 2 data var sector = disc.Sectors[lba + 150]; + PrepareBuffer(buffer, offset, 2352); PrepareJob(lba); job.DestBuffer2448 = buf2442; job.DestOffset = 0; @@ -160,6 +176,7 @@ namespace BizHawk.Emulation.DiscSystem //in no case do we need the ECC so build special flags here var sector = disc.Sectors[lba + 150]; + PrepareBuffer(buffer, offset, 2352); PrepareJob(lba); job.DestBuffer2448 = buf2442; job.DestOffset = 0; diff --git a/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj b/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj index 5de64f69f4..0ba54147c1 100644 --- a/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj +++ b/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj @@ -75,6 +75,7 @@ + diff --git a/BizHawk.Emulation.DiscSystem/Blobs/Blob_ZeroPadAdapter.cs b/BizHawk.Emulation.DiscSystem/Blobs/Blob_ZeroPadAdapter.cs index 9c1a5a4bfd..ca2cd1c362 100644 --- a/BizHawk.Emulation.DiscSystem/Blobs/Blob_ZeroPadAdapter.cs +++ b/BizHawk.Emulation.DiscSystem/Blobs/Blob_ZeroPadAdapter.cs @@ -1,6 +1,8 @@ using System; using System.IO; +//I have an ff9 disc which is truncated + namespace BizHawk.Emulation.DiscSystem { public partial class Disc : IDisposable @@ -13,10 +15,13 @@ namespace BizHawk.Emulation.DiscSystem public static Blob_ZeroPadBuffer MakeBufferFrom(IBlob baseBlob, long start, int bufferLength) { var ret = new Blob_ZeroPadBuffer(); + //allocate the entire buffer we'll need, and it will already be zero-padded ret.buffer = new byte[bufferLength]; + //read as much as is left baseBlob.Read(start, ret.buffer, 0, bufferLength); + //if any less got read, well, there were already zeroes there return ret; } @@ -39,66 +44,6 @@ namespace BizHawk.Emulation.DiscSystem } } - public sealed class Blob_ZeroPadAdapter : IBlob - { - public Blob_ZeroPadAdapter(IBlob baseBlob, long padFrom, long padLen) - { - this.baseBlob = baseBlob; - this.padFrom = padFrom; - this.padLen = padLen; - } - - public int Read(long byte_pos, byte[] buffer, int offset, int count) - { - //I have an ff9 disc which can demo this - throw new NotImplementedException("Blob_ZeroPadAdapter hasnt been tested yet! please report this!"); - - //something about this seems unnecessarily complex, but... i dunno. - /* - //figure out how much remains until the zero-padding begins - long remain = byte_pos - padFrom; - int todo; - if (remain < count) - todo = (int)remain; - else todo = count; - - //read up until the zero-padding - int totalRead = 0; - int readed = baseBlob.Read(byte_pos, buffer, offset, todo); - totalRead += readed; - offset += todo; - - //if we didnt read enough, we certainly shouldnt try to read any more - if (readed < todo) - return readed; - - //if that was all we needed, then we're done - count -= todo; - if (count == 0) - return totalRead; - - //if we need more, it must come from zero-padding - remain = padLen; - if (remain < count) - todo = (int)remain; - else todo = count; - - Array.Clear(buffer, offset, todo); - totalRead += todo; - - return totalRead; - */ - } - - public void Dispose() - { - baseBlob.Dispose(); - } - - private readonly IBlob baseBlob; - private long padFrom; - private long padLen; - } - + } } \ No newline at end of file diff --git a/BizHawk.Emulation.DiscSystem/CCD_format.cs b/BizHawk.Emulation.DiscSystem/CCD_format.cs index 51da7f1d50..0deac090cf 100644 --- a/BizHawk.Emulation.DiscSystem/CCD_format.cs +++ b/BizHawk.Emulation.DiscSystem/CCD_format.cs @@ -449,14 +449,17 @@ namespace BizHawk.Emulation.DiscSystem var subBlob = job.Disc.DisposableResources[1] as Disc.Blob_RawFile; //Read_2442(job.LBA, job.DestBuffer2448, job.DestOffset); - //read the IMG data - long ofs = job.LBA * 2352; - imgBlob.Read(ofs, job.DestBuffer2448, 0, 2352); + //read the IMG data if needed + if ((job.Parts & ESectorSynthPart.UserAny) != 0) + { + long ofs = job.LBA * 2352; + imgBlob.Read(ofs, job.DestBuffer2448, 0, 2352); + } //if subcode is needed, read it if ((job.Parts & (ESectorSynthPart.SubcodeAny)) != 0) { - ofs = job.LBA * 96; + long ofs = job.LBA * 96; subBlob.Read(ofs, job.DestBuffer2448, 2352, 96); //sub data comes to us deinterleved; we may still need to interleave it @@ -576,6 +579,7 @@ namespace BizHawk.Emulation.DiscSystem } //add sectors for the "mandatory track 1 pregap", which isn't stored in the CCD file + //THIS IS JUNK. MORE CORRECTLY SYNTHESIZE IT var leadin_sector_zero = new Sector_Zero(); var leadin_subcode_zero = new ZeroSubcodeSector(); for (int i = 0; i < 150; i++) diff --git a/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs b/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs index 80d04e4987..d3fc01cd82 100644 --- a/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs +++ b/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs @@ -302,9 +302,8 @@ namespace BizHawk.Emulation.DiscSystem var zero_sector = new Sector_Zero(); var zero_subSector = new ZeroSubcodeSector(); - //generate lead-in gap - //TODO - shouldnt this have proper subcode? dunno - //mednafen will probably be testing this in the next release + //add sectors for the "mandatory track 1 pregap", which isn't stored in the CCD file + //THIS IS JUNK. MORE CORRECTLY SYNTHESIZE IT for(int i=0;i<150;i++) { var se_leadin = new SectorEntry(zero_sector); @@ -351,17 +350,16 @@ namespace BizHawk.Emulation.DiscSystem TOCMiscInfo.IN_Session1Format = DiscTOCRaw.SessionFormat.Type00_CDROM_CDDA; //a little subroutine to wrap a sector if the blob is out of space - Func eatBlobAndWrap = (required) => + Func> eatBlobAndWrap = (required) => { IBlob blob = file_blob; - var ret = new Sector_RawBlob { Blob = file_blob, Offset = file_ofs }; + var ret = new Tuple(file_blob, file_ofs); if (file_ofs + required > file_len) { job.Warn("Zero-padding mis-sized file: " + Path.GetFileName(file_command.Path)); blob = Disc.Blob_ZeroPadBuffer.MakeBufferFrom(file_blob,file_ofs,required); resources.Add(blob); - ret.Blob = blob; - ret.Offset = 0; + ret = new Tuple(blob,0); } file_ofs += required; return ret; @@ -395,6 +393,7 @@ namespace BizHawk.Emulation.DiscSystem Action writeSector = (SectorWriteType type) => { ISector siface = null; + SS_Base ss = null; if (type == SectorWriteType.Normal) { @@ -406,22 +405,32 @@ namespace BizHawk.Emulation.DiscSystem case CueFile.TrackType.CDI_2352: case CueFile.TrackType.Mode1_2352: - case CueFile.TrackType.Mode2_2352: - case CueFile.TrackType.Audio: - //these cases are all 2352 bytes. - //in all these cases, either no ECM is present or ECM is provided. so we just emit a Sector_RawBlob - siface = eatBlobAndWrap(2352); break; + case CueFile.TrackType.Mode2_2352: + { + var t = eatBlobAndWrap(2352); + ss = new SS_2352() { Blob = t.Item1, BlobOffset = t.Item2 }; + break; + } + + case CueFile.TrackType.Audio: + { + var t = eatBlobAndWrap(2352); + ss = new SS_2352() { Blob = t.Item1, BlobOffset = t.Item2 }; + break; + } + case CueFile.TrackType.Mode1_2048: { //2048 bytes are present. ECM needs to be generated to create a full raw sector - var raw = eatBlobAndWrap(2048); - siface = new Sector_Mode1_2048(LBA + 150) //pass the ABA I guess - { - Blob = new ECMCacheBlob(raw.Blob), //archaic - Offset = raw.Offset - }; + //var raw = eatBlobAndWrap(2048); + //siface = new Sector_Mode1_2048(LBA + 150) //pass the ABA I guess + //{ + // Blob = new ECMCacheBlob(raw.Blob), //archaic + // Offset = raw.Offset + //}; + //TODO break; } @@ -433,13 +442,13 @@ namespace BizHawk.Emulation.DiscSystem } else if (type == SectorWriteType.Postgap) { - //TODO - does subchannel need to get written differently? - siface = zero_sector; + //TODO + //siface = zero_sector; + throw new InvalidOperationException("cue postgap broken right now"); } else if (type == SectorWriteType.Pregap) { - //TODO - does subchannel need to get written differently? - siface = zero_sector; + ss = new SS_Pregap(); } //make the subcode @@ -483,7 +492,6 @@ namespace BizHawk.Emulation.DiscSystem //second interval: at least 150 sectors coded as user data track. //so... we ASSUME the 150 sector pregap is more important. so if thats all there is, theres no 75 sector pregap like the old track //if theres a longer pregap, then we generate weird old track pregap to contain the rest. - //TODO - GENERATE P SUBCHANNEL if (track_relative_msf > 150) { //only if we're burning a data track now @@ -501,8 +509,9 @@ namespace BizHawk.Emulation.DiscSystem priorSubchannelQ = sq; //now we have the ISector and subcode; make the SectorEntry - var se = new SectorEntry(siface); - se.SubcodeSector = subcode; + var se = new SectorEntry(null); + se.SectorSynth = ss; + ss.sq = sq; disc.Sectors.Add(se); LBA++; file_ownmsf++; diff --git a/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs b/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs new file mode 100644 index 0000000000..0dcb4dd240 --- /dev/null +++ b/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs @@ -0,0 +1,84 @@ +using System; +using System.IO; +using System.Collections.Generic; + +namespace BizHawk.Emulation.DiscSystem +{ + partial class CUE_Format2 + { + abstract class SS_Base : ISectorSynthJob2448 + { + public SubchannelQ sq; + + public abstract void Synth(SectorSynthJob job); + } + + class SS_Mode1_2048 : SS_Base + { + public override void Synth(SectorSynthJob job) + { + } + } + + + static class SubSynth + { + public static void P(byte[] buffer, int offset, bool pause) + { + byte val = (byte)(pause?0xFF:0x00); + for (int i = 0; i < 12; i++) + buffer[offset + i] = val; + } + } + + /// + /// Represents a pregap sector + /// + class SS_Pregap : SS_Base + { + public override void Synth(SectorSynthJob job) + { + if ((job.Parts & ESectorSynthPart.SubchannelP) != 0) + { + SubSynth.P(job.DestBuffer2448, job.DestOffset + 2352, false); //for now.... + } + + if ((job.Parts & ESectorSynthPart.SubchannelQ) != 0) + { + var subcode = new BufferedSubcodeSector(); + subcode.Synthesize_SubchannelQ(ref sq, true); + Buffer.BlockCopy(subcode.SubcodeDeinterleaved, 12, job.DestBuffer2448, job.DestOffset + 2352 + 12, 12); + } + } + } + + /// + /// Represents a Mode1 or Mode2 2352-byte sector + /// + class SS_2352 : SS_Base + { + public IBlob Blob; + public long BlobOffset; + public override void Synth(SectorSynthJob job) + { + //read the sector user data + Blob.Read(BlobOffset, job.DestBuffer2448, job.DestOffset, 2352); + + //if subcode is needed, synthesize it + + if ((job.Parts & ESectorSynthPart.SubchannelP) != 0) + { + SubSynth.P(job.DestBuffer2448, job.DestOffset + 2352, false); //for now.... + } + + if ((job.Parts & ESectorSynthPart.SubchannelQ) != 0) + { + var subcode = new BufferedSubcodeSector(); + subcode.Synthesize_SubchannelQ(ref sq, true); + Buffer.BlockCopy(subcode.SubcodeDeinterleaved, 12, job.DestBuffer2448, job.DestOffset + 2352 + 12, 12); + } + } + } + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.DiscSystem/SectorInterfaces.cs b/BizHawk.Emulation.DiscSystem/SectorInterfaces.cs index 507df7761e..876c4b030d 100644 --- a/BizHawk.Emulation.DiscSystem/SectorInterfaces.cs +++ b/BizHawk.Emulation.DiscSystem/SectorInterfaces.cs @@ -53,9 +53,20 @@ namespace BizHawk.Emulation.DiscSystem User2336 = (User2048|ECC276|EDC12), /// - /// The entirety of the sector userdata is required + /// The complete sector userdata (2352 bytes) is required /// - User2352 = 15, + UserComplete = 15, + + /// + /// An alias for UserComplete + /// + UserAny = UserComplete, + + /// + /// An alias for UserComplete + /// + User2352 = UserComplete, + /// /// SubP is required @@ -134,7 +145,7 @@ namespace BizHawk.Emulation.DiscSystem /// /// this ISector is dumb and only knows how to drag chunks off a source blob - /// TODO - actually make it that way! + /// TODO - garbage, delete me /// public class Sector_RawBlob : ISector {