diff --git a/BizHawk.Emulation.DiscSystem/API/Disc.API.cs b/BizHawk.Emulation.DiscSystem/API/Disc.API.cs index da1e5532c2..ba56d63283 100644 --- a/BizHawk.Emulation.DiscSystem/API/Disc.API.cs +++ b/BizHawk.Emulation.DiscSystem/API/Disc.API.cs @@ -25,16 +25,6 @@ namespace BizHawk.Emulation.DiscSystem sealed public partial class Disc { - /// - /// Returns a SectorEntry from which you can retrieve various interesting pieces of information about the sector. - /// The SectorEntry's interface is not likely to be stable, though, but it may be more convenient. - /// - public SectorEntry ReadLBA_SectorEntry(int lba) - { - return Sectors[lba + 150]; - } - - /// /// Main API to determine how many LBAs are available on the disc. /// This counts from LBA 0 to the final sector available. diff --git a/BizHawk.Emulation.DiscSystem/API/DiscSectorReader.cs b/BizHawk.Emulation.DiscSystem/API/DiscSectorReader.cs index bf19a92c05..893e10b397 100644 --- a/BizHawk.Emulation.DiscSystem/API/DiscSectorReader.cs +++ b/BizHawk.Emulation.DiscSystem/API/DiscSectorReader.cs @@ -94,7 +94,7 @@ namespace BizHawk.Emulation.DiscSystem job.Parts = ESectorSynthPart.User2352; job.Disc = disc; - sector.SectorSynth.Synth(job); + sector.Synth(job); Buffer.BlockCopy(buf2442, 0, buffer, offset, 2352); @@ -116,7 +116,7 @@ namespace BizHawk.Emulation.DiscSystem if (Policy.DeinterleavedSubcode) job.Parts |= ESectorSynthPart.SubcodeDeinterleave; - sector.SectorSynth.Synth(job); + sector.Synth(job); //we went straight to the caller's buffer, so no need to copy return 2442; @@ -133,7 +133,7 @@ namespace BizHawk.Emulation.DiscSystem job.DestOffset = 0; job.Parts = ESectorSynthPart.User2048; - sector.SectorSynth.Synth(job); + sector.Synth(job); Buffer.BlockCopy(buf2442, 16, buffer, offset, 2048); return 2048; @@ -150,7 +150,7 @@ namespace BizHawk.Emulation.DiscSystem job.DestOffset = 0; job.Parts = ESectorSynthPart.User2336; - sector.SectorSynth.Synth(job); + sector.Synth(job); Buffer.BlockCopy(buf2442, 24, buffer, offset, 2048); return 2048; @@ -170,7 +170,7 @@ namespace BizHawk.Emulation.DiscSystem job.DestOffset = 0; job.Parts = ESectorSynthPart.SubchannelQ | ESectorSynthPart.SubcodeDeinterleave; - sector.SectorSynth.Synth(job); + sector.Synth(job); Buffer.BlockCopy(buf2442, 2352 + 12, buffer, offset, 12); return 12; @@ -201,7 +201,7 @@ namespace BizHawk.Emulation.DiscSystem job.DestOffset = 0; job.Parts = ESectorSynthPart.Header16 | ESectorSynthPart.User2048 | ESectorSynthPart.EDC12; - sector.SectorSynth.Synth(job); + sector.Synth(job); //now the inspection, based on the mode byte mode = buf2442[15]; @@ -276,7 +276,7 @@ namespace BizHawk.Emulation.DiscSystem job.Parts = ESectorSynthPart.Header16; job.Disc = disc; - sector.SectorSynth.Synth(job); + sector.Synth(job); return buf2442[15]; } diff --git a/BizHawk.Emulation.DiscSystem/CCD_format.cs b/BizHawk.Emulation.DiscSystem/CCD_format.cs index 6b21ce11bc..6a475fedaa 100644 --- a/BizHawk.Emulation.DiscSystem/CCD_format.cs +++ b/BizHawk.Emulation.DiscSystem/CCD_format.cs @@ -470,7 +470,7 @@ namespace BizHawk.Emulation.DiscSystem //subcode comes to us deinterleved; we may still need to interleave it if ((job.Parts & (ESectorSynthPart.SubcodeDeinterleave)) == 0) { - SubcodeUtils.InterleaveInplace(job.DestBuffer2448, job.DestOffset + 2352); + SynthUtils.InterleaveSubcodeInplace(job.DestBuffer2448, job.DestOffset + 2352); } } } @@ -501,7 +501,6 @@ namespace BizHawk.Emulation.DiscSystem //generate DiscTOCRaw items from the ones specified in the CCD file //TODO - range validate these (too many truncations to byte) disc.RawTOCEntries = new List(); - BufferedSubcodeSector bss = new BufferedSubcodeSector(); //TODO - its hacky that we need this.. foreach (var entry in ccdf.TOCEntries) { BCD2 tno, ino; @@ -530,82 +529,27 @@ namespace BizHawk.Emulation.DiscSystem ap_min = BCD2.FromDecimal(entry.PMin), ap_sec = BCD2.FromDecimal(entry.PSec), ap_frame = BCD2.FromDecimal(entry.PFrame), + q_crc = 0, //meainingless }; - //CRC cant be calculated til we've got all the fields setup - q.q_crc = bss.Synthesize_SubchannelQ(ref q, true); - disc.RawTOCEntries.Add(new RawTOCEntry { QData = q }); } - - //disc.Structure = new DiscStructure(); - //var ses = new DiscStructure.Session(); - //disc.Structure.Sessions.Add(ses); - - //for(int i=1;i<=99;i++) - //{ - // if(!ccdf.TracksByNumber.ContainsKey(i)) - // continue; - // var ccdt = ccdf.TracksByNumber[i]; - - // DiscStructure.Track track = new DiscStructure.Track() { Number = i }; - // ses.Tracks.Add(track); - - // //if index 0 is missing, add it - // if (!ccdt.Indexes.ContainsKey(0)) - // track.Indexes.Add(new DiscStructure.Index { Number = 0, LBA = ccdt.Indexes[1] }); - // for(int j=1;j<=99;j++) - // if (ccdt.Indexes.ContainsKey(j)) - // track.Indexes.Add(new DiscStructure.Index { Number = j, LBA = ccdt.Indexes[j] }); - - // //TODO - this should only be used in case the .sub needs reconstructing - // //determination should be done from heuristics. - // //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 ( - // switch (ccdt.Mode) - // { - // case 0: - // track.TrackType = DiscStructure.ETrackType.Audio; //for CCD, this means audio, apparently. - // break; - // case 1: - // case 2: - // track.TrackType = DiscStructure.ETrackType.Data; - // break; - // default: - // throw new InvalidOperationException("Unsupported CCD mode"); - // } - //} - - //add sectors for the "mandatory track 1 pregap", which isn't stored in the CCD file - //THIS IS JUNK. MORE CORRECTLY SYNTHESIZE IT + //add sectors for the mandatory track 1 pregap, which isn't stored in the CCD file + //TODO - 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++) { - var se = new SectorEntry(leadin_sector_zero); - disc.Sectors.Add(se); - se.SubcodeSector = leadin_subcode_zero; + //TODO - YIKES! + disc.Sectors.Add(null); } //build the sectors: - //set up as many sectors as we have img/sub for, even if the TOC doesnt reference them (TOC is unreliable, although the tracks should have covered it all) + //set up as many sectors as we have img/sub for, even if the TOC doesnt reference them + //(TOC is unreliable, although the tracks should have covered it all) for (int i = 0; i < loadResults.NumImgSectors; i++) { - var isec = new Sector_RawBlob(); - isec.Offset = ((long)i) * 2352; - isec.Blob = imgBlob; - - var se = new SectorEntry(isec); - disc.Sectors.Add(se); - - var scsec = new BlobSubcodeSectorPreDeinterleaved(); - scsec.Offset = ((long)i) * 96; - scsec.Blob = subBlob; - se.SubcodeSector = scsec; - se.SectorSynth = synth; + disc.Sectors.Add(synth); } return disc; diff --git a/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs b/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs index 73b3bc322c..78f02ea644 100644 --- a/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs +++ b/BizHawk.Emulation.DiscSystem/CUE/CUE_Load.cs @@ -331,10 +331,7 @@ namespace BizHawk.Emulation.DiscSystem if (curr_index == 0) ss.Pause = true; - //make the SectorEntry (some temporary bullshit here) - var se = new SectorEntry(null); - se.SectorSynth = ss; - OUT_Disc.Sectors.Add(se); + OUT_Disc.Sectors.Add(ss); relMSF++; if (cct.IsFinalInFile) @@ -360,7 +357,6 @@ namespace BizHawk.Emulation.DiscSystem int specifiedPostgapLength = cct.PostgapLength.Sector; for (int s = 0; s < specifiedPostgapLength; s++) { - var se= new SectorEntry(null); var ss = new SS_Gap(); ss.TrackType = cct.TrackType; //TODO - old track type in some < -150 cases? @@ -376,8 +372,7 @@ namespace BizHawk.Emulation.DiscSystem //always paused--is this good enough? ss.Pause = true; - se.SectorSynth = ss; - OUT_Disc.Sectors.Add(se); + OUT_Disc.Sectors.Add(ss); relMSF++; } diff --git a/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs b/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs index 1c1b18e792..0e0c8aa7da 100644 --- a/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs +++ b/BizHawk.Emulation.DiscSystem/CUE/CUE_Synths.cs @@ -31,11 +31,10 @@ namespace BizHawk.Emulation.DiscSystem } //synth Q if needed + //TODO - why not already have it serialized? Into a disc resource, even. 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); + SynthUtils.SubQ_Serialize(job.DestBuffer2448, job.DestOffset + 2352 + 12, ref sq); } //clear R-W if needed @@ -47,7 +46,7 @@ namespace BizHawk.Emulation.DiscSystem //subcode has been generated deinterleaved; we may still need to interleave it if ((job.Parts & (ESectorSynthPart.SubcodeDeinterleave)) == 0) { - SubcodeUtils.InterleaveInplace(job.DestBuffer2448, job.DestOffset + 2352); + SynthUtils.InterleaveSubcodeInplace(job.DestBuffer2448, job.DestOffset + 2352); } } } diff --git a/BizHawk.Emulation.DiscSystem/Disc.cs b/BizHawk.Emulation.DiscSystem/Disc.cs index 30c75fb6e5..ee9258100c 100644 --- a/BizHawk.Emulation.DiscSystem/Disc.cs +++ b/BizHawk.Emulation.DiscSystem/Disc.cs @@ -118,7 +118,7 @@ namespace BizHawk.Emulation.DiscSystem /// /// The sectors on the disc /// - public List Sectors = new List(); + internal List Sectors = new List(); internal SectorSynthParams SynthParams = new SectorSynthParams(); @@ -137,6 +137,7 @@ namespace BizHawk.Emulation.DiscSystem /// /// generates lead-out sectors according to very crude approximations + /// TODO - this isnt being used right now /// public class SynthesizeLeadoutJob { @@ -159,8 +160,8 @@ namespace BizHawk.Emulation.DiscSystem for (int i = 0; i < Length; i++) { - var se = new SectorEntry(sz); - Disc.Sectors.Add(se); + //var se = new SectorEntry(sz); + //Disc.Sectors.Add(se); SubchannelQ sq = new SubchannelQ(); int track_relative_msf = i; @@ -179,9 +180,7 @@ namespace BizHawk.Emulation.DiscSystem byte ADR = 1; sq.SetStatus(ADR, leadoutFlags); - var subcode = new BufferedSubcodeSector(); - subcode.Synthesize_SubchannelQ(ref sq, true); - se.SubcodeSector = subcode; + //TODO - actually stash the subQ } } } @@ -233,14 +232,14 @@ namespace BizHawk.Emulation.DiscSystem int lba = sbi.ABAs[i] - 150; //create a synthesizer which can return the patched data - var ss_patchq = new SS_PatchQ() { Original = this.Sectors[lba+150].SectorSynth }; + var ss_patchq = new SS_PatchQ() { Original = this.Sectors[lba+150] }; byte[] subQbuf = ss_patchq.Buffer_SubQ; //read the old subcode dsr.ReadLBA_SubQ(lba, subQbuf, 0); //insert patch - Sectors[lba + 150].SectorSynth = ss_patchq; + Sectors[lba + 150] = ss_patchq; //apply SBI patch for (int j = 0; j < 12; j++) @@ -255,7 +254,7 @@ namespace BizHawk.Emulation.DiscSystem //However, this seems senseless to me. The whole point of the SBI data is that it stores the patches needed to generate an acceptable subQ, right? if (asMednafen) { - SynthUtils.SubQ_Checksum(subQbuf, 0); + SynthUtils.SubQ_SynthChecksum(subQbuf, 0); subQbuf[10] ^= 0xFF; subQbuf[11] ^= 0xFF; } @@ -422,73 +421,199 @@ namespace BizHawk.Emulation.DiscSystem static class SynthUtils { - /// - /// Calculates the checksum of the provided Q subchannel + /// Calculates the checksum of the provided Q subchannel buffer and emplaces it /// - /// 12 byte Q subchannel: input and output buffer for operation + /// 12 byte Q subchannel buffer: input and output buffer for operation /// location within buffer of Q subchannel - public static void SubQ_Checksum(byte[] buffer, int offset) + public static ushort SubQ_SynthChecksum(byte[] buf12, int offset) { - ushort crc16 = CRC16_CCITT.Calculate(buffer, offset, 10); + ushort crc16 = CRC16_CCITT.Calculate(buf12, offset, 10); //CRC is stored inverted and big endian - buffer[offset + 10] = (byte)(~(crc16 >> 8)); - buffer[offset + 11] = (byte)(~(crc16)); + buf12[offset + 10] = (byte)(~(crc16 >> 8)); + buf12[offset + 11] = (byte)(~(crc16)); + + return crc16; } - public static void SubP(byte[] buffer, int offset, bool pause) + /// + /// Caclulates the checksum of the provided Q subchannel buffer + /// + public static ushort SubQ_CalcChecksum(byte[] buf12, int offset) + { + return CRC16_CCITT.Calculate(buf12, offset, 10); + } + + /// + /// Serializes the provided SubchannelQ structure into a buffer + /// Returns the crc, calculated or otherwise. + /// + public static ushort SubQ_Serialize(byte[] buf12, int offset, ref SubchannelQ sq) + { + buf12[offset + 0] = sq.q_status; + buf12[offset + 1] = sq.q_tno.BCDValue; + buf12[offset + 2] = sq.q_index.BCDValue; + buf12[offset + 3] = sq.min.BCDValue; + buf12[offset + 4] = sq.sec.BCDValue; + buf12[offset + 5] = sq.frame.BCDValue; + buf12[offset + 6] = sq.zero; + buf12[offset + 7] = sq.ap_min.BCDValue; + buf12[offset + 8] = sq.ap_sec.BCDValue; + buf12[offset + 9] = sq.ap_frame.BCDValue; + + return SubQ_SynthChecksum(buf12, offset); + } + + /// + /// Synthesizes the typical subP data into the provided buffer depending on the indicated pause flag + /// + public static void SubP(byte[] buffer12, int offset, bool pause) { byte val = (byte)(pause ? 0xFF : 0x00); for (int i = 0; i < 12; i++) - buffer[offset + i] = val; + buffer12[offset + i] = val; } - public static void SectorHeader(byte[] buffer, int offset, int LBA, byte mode) + /// + /// Synthesizes a data sector header + /// + public static void SectorHeader(byte[] buffer16, int offset, int LBA, byte mode) { - buffer[offset + 0] = 0x00; - for (int i = 1; i < 11; i++) buffer[offset + i] = 0xFF; - buffer[offset + 11] = 0x00; + buffer16[offset + 0] = 0x00; + for (int i = 1; i < 11; i++) buffer16[offset + i] = 0xFF; + buffer16[offset + 11] = 0x00; Timestamp ts = new Timestamp(LBA + 150); - buffer[offset + 12] = BCD2.IntToBCD(ts.MIN); - buffer[offset + 13] = BCD2.IntToBCD(ts.SEC); - buffer[offset + 14] = BCD2.IntToBCD(ts.FRAC); - buffer[offset + 15] = mode; + buffer16[offset + 12] = BCD2.IntToBCD(ts.MIN); + buffer16[offset + 13] = BCD2.IntToBCD(ts.SEC); + buffer16[offset + 14] = BCD2.IntToBCD(ts.FRAC); + buffer16[offset + 15] = mode; } - public static void EDC_Mode2_Form1(byte[] buffer, int offset) + /// + /// Synthesizes the EDC checksum for a Mode 2 Form 1 data sector (and puts it in place) + /// + public static void EDC_Mode2_Form1(byte[] buf2352, int offset) { - uint edc = ECM.EDC_Calc(buffer, offset + 16, 2048 + 8); - ECM.PokeUint(buffer, offset + 2072, edc); + uint edc = ECM.EDC_Calc(buf2352, offset + 16, 2048 + 8); + ECM.PokeUint(buf2352, offset + 2072, edc); } - public static void EDC_Mode2_Form2(byte[] buffer, int offset) + /// + /// Synthesizes the EDC checksum for a Mode 2 Form 2 data sector (and puts it in place) + /// + public static void EDC_Mode2_Form2(byte[] buf2352, int offset) { - uint edc = ECM.EDC_Calc(buffer, offset + 16, 2324 + 8); - ECM.PokeUint(buffer, offset + 2348, edc); + uint edc = ECM.EDC_Calc(buf2352, offset + 16, 2324 + 8); + ECM.PokeUint(buf2352, offset + 2348, edc); } /// + /// 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 /// - public static void ECM_Mode1(byte[] buffer, int offset, int LBA) + public static void ECM_Mode1(byte[] buf2352, int offset, int LBA) { //EDC - uint edc = ECM.EDC_Calc(buffer, offset, 2064); - ECM.PokeUint(buffer, offset + 2064, edc); + uint edc = ECM.EDC_Calc(buf2352, offset, 2064); + ECM.PokeUint(buf2352, offset + 2064, edc); //reserved, zero - for (int i = 0; i < 8; i++) buffer[offset + 2068 + i] = 0; + for (int i = 0; i < 8; i++) buf2352[offset + 2068 + i] = 0; //ECC - ECM.ECC_Populate(buffer, offset, buffer, offset, false); + ECM.ECC_Populate(buf2352, offset, buf2352, offset, false); + } + + /// + /// Converts the useful (but unrealistic) deinterleaved subchannel data into the useless (but realistic) interleaved format. + /// in_buf and out_buf should not overlap + /// + public static void InterleaveSubcode(byte[] in_buf, int in_buf_index, byte[] out_buf, int out_buf_index) + { + for (int d = 0; d < 12; d++) + { + for (int bitpoodle = 0; bitpoodle < 8; bitpoodle++) + { + int rawb = 0; + + for (int ch = 0; ch < 8; ch++) + { + rawb |= ((in_buf[ch * 12 + d + in_buf_index] >> (7 - bitpoodle)) & 1) << (7 - ch); + } + out_buf[(d << 3) + bitpoodle + out_buf_index] = (byte)rawb; + } + } + } + + /// + /// Converts the useless (but realistic) interleaved subchannel data into a useful (but unrealistic) deinterleaved format. + /// in_buf and out_buf should not overlap + /// + public static void DeinterleaveSubcode(byte[] in_buf, int in_buf_index, byte[] out_buf, int out_buf_index) + { + for (int i = 0; i < 96; i++) + out_buf[i] = 0; + + for (int ch = 0; ch < 8; ch++) + { + for (int i = 0; i < 96; i++) + { + out_buf[(ch * 12) + (i >> 3) + out_buf_index] |= (byte)(((in_buf[i + in_buf_index] >> (7 - ch)) & 0x1) << (7 - (i & 0x7))); + } + } + } + + /// + /// Converts the useful (but unrealistic) deinterleaved data into the useless (but realistic) interleaved subchannel format. + /// + public unsafe static void InterleaveSubcodeInplace(byte[] buf, int buf_index) + { + byte* out_buf = stackalloc byte[96]; + + for (int i = 0; i < 96; i++) + out_buf[i] = 0; + + for (int d = 0; d < 12; d++) + { + for (int bitpoodle = 0; bitpoodle < 8; bitpoodle++) + { + int rawb = 0; + + for (int ch = 0; ch < 8; ch++) + { + rawb |= ((buf[ch * 12 + d + buf_index] >> (7 - bitpoodle)) & 1) << (7 - ch); + } + out_buf[(d << 3) + bitpoodle] = (byte)rawb; + } + } + + for (int i = 0; i < 96; i++) + buf[i + buf_index] = out_buf[i]; + } + + /// + /// Converts the useless (but realistic) interleaved subchannel data into a useful (but unrealistic) deinterleaved format. + /// + public unsafe static void DeinterleaveSubcodeInplace(byte[] buf, int buf_index) + { + byte* out_buf = stackalloc byte[96]; + + for (int i = 0; i < 96; i++) + out_buf[i] = 0; + + for (int ch = 0; ch < 8; ch++) + { + for (int i = 0; i < 96; i++) + { + out_buf[(ch * 12) + (i >> 3)] |= (byte)(((buf[i + buf_index] >> (7 - ch)) & 0x1) << (7 - (i & 0x7))); + } + } + + for (int i = 0; i < 96; i++) + buf[i + buf_index] = out_buf[i]; } } - //not being used yet - class DiscPreferences - { - - } } \ No newline at end of file diff --git a/BizHawk.Emulation.DiscSystem/DiscTypes.cs b/BizHawk.Emulation.DiscSystem/DiscTypes.cs index 49ae05f19d..9d502a58ad 100644 --- a/BizHawk.Emulation.DiscSystem/DiscTypes.cs +++ b/BizHawk.Emulation.DiscSystem/DiscTypes.cs @@ -19,29 +19,4 @@ namespace BizHawk.Emulation.DiscSystem { BizHawk, MednaDisc, LibMirage } - - - - /// - /// Main unit of organization for reading data from the disc. Represents one physical disc sector. - /// - public class SectorEntry - { - public SectorEntry(ISector sec) { Sector = sec; } - - internal ISectorSynthJob2448 SectorSynth; - - /// - /// Access the --whatsitcalled-- normal data for the sector with this - /// - public ISector Sector; - - /// - /// Access the subcode data for the sector - /// - public ISubcodeSector SubcodeSector; - - //todo - add a PARAMETER fields to this (a long, maybe) so that the ISector can use them (so that each ISector doesnt have to be constructed also) - //also then, maybe this could be a struct - } } \ No newline at end of file diff --git a/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.MednaDisc.cs b/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.MednaDisc.cs index 85f0a6d109..2a2a57b243 100644 --- a/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.MednaDisc.cs +++ b/BizHawk.Emulation.DiscSystem/Jobs/DiscMountJob.MednaDisc.cs @@ -18,7 +18,7 @@ namespace BizHawk.Emulation.DiscSystem //we may still need to deinterleave it if subcode was requested and it needs deinterleaving if ((job.Parts & (ESectorSynthPart.SubcodeDeinterleave | ESectorSynthPart.SubcodeAny)) != 0) { - SubcodeUtils.DeinterleaveInplace(job.DestBuffer2448, 2352); + SynthUtils.DeinterleaveSubcodeInplace(job.DestBuffer2448, 2352); } } } @@ -26,6 +26,7 @@ namespace BizHawk.Emulation.DiscSystem void RunMednaDisc() { var disc = new Disc(); + OUT_Disc = disc; //create a MednaDisc and give it to the disc for ownership var md = new MednaDisc(IN_FromPath); @@ -43,27 +44,17 @@ namespace BizHawk.Emulation.DiscSystem //make sector interfaces: var pregap_sector_zero = new Sector_Zero(); - var pregap_subcode_zero = new ZeroSubcodeSector(); for (int i = 0; i < 150; i++) { - var se = new SectorEntry(pregap_sector_zero); - se.SectorSynth = synth; - disc.Sectors.Add(se); - se.SubcodeSector = pregap_subcode_zero; + disc.Sectors.Add(synth); } //2. actual sectors for (int i = 0; i < nSectors; i++) { - //var sectorInterface = new MednaDiscSectorInterface() { LBA = i, md = md }; - var se = new SectorEntry(null); - //se.SubcodeSector = new MednaDiscSubcodeSectorInterface() { LBA = i, md = md }; - se.SectorSynth = synth; - disc.Sectors.Add(se); + disc.Sectors.Add(synth); } - BufferedSubcodeSector bss = new BufferedSubcodeSector(); //TODO - its hacky that we need this.. - //ADR (q-Mode) is necessarily 0x01 for a RawTOCEntry const int kADR = 1; const int kUnknownControl = 0; @@ -96,15 +87,13 @@ namespace BizHawk.Emulation.DiscSystem ap_min = BCD2.FromDecimal(m_ts.MIN), ap_sec = BCD2.FromDecimal(m_ts.SEC), ap_frame = BCD2.FromDecimal(m_ts.FRAC), + q_crc = 0 //meaningless }; //a special fixup: mednafen's entry 100 is the lead-out track if (i == 100) q.q_index.BCDValue = 0xA2; - //CRC cant be calculated til we've got all the fields setup - q.q_crc = bss.Synthesize_SubchannelQ(ref q, true); - disc.RawTOCEntries.Add(new RawTOCEntry { QData = q }); } @@ -121,8 +110,8 @@ namespace BizHawk.Emulation.DiscSystem ap_min = BCD2.FromDecimal(md.TOC.first_track), ap_sec = BCD2.FromDecimal(0), ap_frame = BCD2.FromDecimal(0), + q_crc = 0, //meaningless }; - qA1.q_crc = bss.Synthesize_SubchannelQ(ref qA1, true); disc.RawTOCEntries.Add(new RawTOCEntry { QData = qA1 }); var qA2 = new SubchannelQ { @@ -136,44 +125,10 @@ namespace BizHawk.Emulation.DiscSystem ap_min = BCD2.FromDecimal(md.TOC.last_track), ap_sec = BCD2.FromDecimal(0), ap_frame = BCD2.FromDecimal(0), + q_crc = 0, //meaningless }; - qA2.q_crc = bss.Synthesize_SubchannelQ(ref qA2, true); disc.RawTOCEntries.Add(new RawTOCEntry { QData = qA2 }); - //generate the toc from the entries. still not sure we're liking this idea - var tocSynth = new DiscTOCRaw.SynthesizeFromRawTOCEntriesJob() { Entries = disc.RawTOCEntries }; - tocSynth.Run(); - disc.TOCRaw = tocSynth.Result; - - //DO THIS IN A MORE UNIFORM WAY PLEASE - //setup the DiscStructure - //disc.Structure = new DiscStructure(); - //var ses = new DiscStructure.Session(); - //disc.Structure.Sessions.Add(ses); - //for (int i = 1; i < 100; i++) - //{ - // var m_te = md.TOCTracks[i]; - // if (!m_te.Valid) continue; - - // DiscStructure.Track track = new DiscStructure.Track() { Number = i }; - // ses.Tracks.Add(track); - // if ((m_te.control & (int)EControlQ.DATA) == 0) - // track.IsData = false; - // else - // track.IsData = true; - - // track.Start_LBA = (int)m_te.lba; - // track. - - // //from mednafen, we couldnt build the index 0, and that's OK, since that's not really a sensible thing in CD terms anyway. - // //I need to refactor this thing to oblivion - // //track.Indexes.Add(new DiscStructure.Index { Number = 0, LBA = (int)m_te.lba }); //<-- not accurate, but due for deletion - // //track.Indexes.Add(new DiscStructure.Index { Number = 1, LBA = (int)m_te.lba }); - //} - - //NOT FULLY COMPLETE - - OUT_Disc = disc; } } } \ No newline at end of file diff --git a/BizHawk.Emulation.DiscSystem/Jobs/Synthesize_A0A1A2_Job.cs b/BizHawk.Emulation.DiscSystem/Jobs/Synthesize_A0A1A2_Job.cs index 0a038cfb53..275d81c5a5 100644 --- a/BizHawk.Emulation.DiscSystem/Jobs/Synthesize_A0A1A2_Job.cs +++ b/BizHawk.Emulation.DiscSystem/Jobs/Synthesize_A0A1A2_Job.cs @@ -41,8 +41,6 @@ namespace BizHawk.Emulation.DiscSystem { 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; diff --git a/BizHawk.Emulation.DiscSystem/Subcode.cs b/BizHawk.Emulation.DiscSystem/Subcode.cs index 45ba1bebb5..c138ac5be7 100644 --- a/BizHawk.Emulation.DiscSystem/Subcode.cs +++ b/BizHawk.Emulation.DiscSystem/Subcode.cs @@ -17,224 +17,6 @@ namespace BizHawk.Emulation.DiscSystem { - //YET ANOTHER BAD IDEA - public interface ISubcodeSector - { - /// - /// reads 96 bytes of subcode data (deinterleaved) for this sector into the supplied buffer - /// - void ReadSubcodeDeinterleaved(byte[] buffer, int offset); - - /// - /// Reads just one of the channels. p=0, q=1, etc. - /// - void ReadSubcodeChannel(int number, byte[] buffer, int offset); - } - - public static class SubcodeUtils - { - /// - /// Converts the useful (but unrealistic) deinterleaved data into the useless (but realistic) interleaved subchannel format. - /// in_buf and out_buf should not overlap - /// - public static void Interleave(byte[] in_buf, int in_buf_index, byte[] out_buf, int out_buf_index) - { - for (int d = 0; d < 12; d++) - { - for (int bitpoodle = 0; bitpoodle < 8; bitpoodle++) - { - int rawb = 0; - - for (int ch = 0; ch < 8; ch++) - { - rawb |= ((in_buf[ch * 12 + d + in_buf_index] >> (7 - bitpoodle)) & 1) << (7 - ch); - } - out_buf[(d << 3) + bitpoodle + out_buf_index] = (byte)rawb; - } - } - } - - /// - /// Converts the useless (but realistic) interleaved subchannel data into a useful (but unrealistic) deinterleaved format. - /// in_buf and out_buf should not overlap - /// - public static void Deinterleave(byte[] in_buf, int in_buf_index, byte[] out_buf, int out_buf_index) - { - for (int i = 0; i < 96; i++) - out_buf[i] = 0; - - for (int ch = 0; ch < 8; ch++) - { - for (int i = 0; i < 96; i++) - { - out_buf[(ch * 12) + (i >> 3) + out_buf_index] |= (byte)(((in_buf[i + in_buf_index] >> (7 - ch)) & 0x1) << (7 - (i & 0x7))); - } - } - } - - /// - /// Converts the useful (but unrealistic) deinterleaved data into the useless (but realistic) interleaved subchannel format. - /// - public unsafe static void InterleaveInplace(byte[] buf, int buf_index) - { - byte* out_buf = stackalloc byte[96]; - - for (int i = 0; i < 96; i++) - out_buf[i] = 0; - - for (int d = 0; d < 12; d++) - { - for (int bitpoodle = 0; bitpoodle < 8; bitpoodle++) - { - int rawb = 0; - - for (int ch = 0; ch < 8; ch++) - { - rawb |= ((buf[ch * 12 + d + buf_index] >> (7 - bitpoodle)) & 1) << (7 - ch); - } - out_buf[(d << 3) + bitpoodle] = (byte)rawb; - } - } - - for (int i = 0; i < 96; i++) - buf[i + buf_index] = out_buf[i]; - } - - /// - /// Converts the useless (but realistic) interleaved subchannel data into a useful (but unrealistic) deinterleaved format. - /// - public unsafe static void DeinterleaveInplace(byte[] buf, int buf_index) - { - byte* out_buf = stackalloc byte[96]; - - for (int i = 0; i < 96; i++) - out_buf[i] = 0; - - for (int ch = 0; ch < 8; ch++) - { - for (int i = 0; i < 96; i++) - { - out_buf[(ch * 12) + (i >> 3)] |= (byte)(((buf[i + buf_index] >> (7 - ch)) & 0x1) << (7 - (i & 0x7))); - } - } - - for (int i = 0; i < 96; i++) - buf[i + buf_index] = out_buf[i]; - } - } - - - /// - /// Reads subcode from an internally-managed buffer - /// - class BufferedSubcodeSector : ISubcodeSector - { - public void Synthesize_SubchannelP(bool pause) - { - byte val = pause ? (byte)0xFF : (byte)0x00; - for (int i = 0; i < 12; i++) - SubcodeDeinterleaved[i] = val; - } - - /// - /// Fills this subcode buffer with subchannel Q data. calculates the required CRC, as well. - /// Returns the crc, calculated or otherwise. - /// - public ushort Synthesize_SubchannelQ(ref SubchannelQ sq, bool calculateCRC) - { - int offset = 12; //Q subchannel begins after P, 12 bytes in - SubcodeDeinterleaved[offset + 0] = sq.q_status; - SubcodeDeinterleaved[offset + 1] = sq.q_tno.BCDValue; - SubcodeDeinterleaved[offset + 2] = sq.q_index.BCDValue; - SubcodeDeinterleaved[offset + 3] = sq.min.BCDValue; - SubcodeDeinterleaved[offset + 4] = sq.sec.BCDValue; - SubcodeDeinterleaved[offset + 5] = sq.frame.BCDValue; - SubcodeDeinterleaved[offset + 6] = sq.zero; - SubcodeDeinterleaved[offset + 7] = sq.ap_min.BCDValue; - SubcodeDeinterleaved[offset + 8] = sq.ap_sec.BCDValue; - SubcodeDeinterleaved[offset + 9] = sq.ap_frame.BCDValue; - - ushort crc16; - if (calculateCRC) - crc16 = CRC16_CCITT.Calculate(SubcodeDeinterleaved, offset, 10); - else crc16 = sq.q_crc; - - //CRC is stored inverted and big endian - SubcodeDeinterleaved[offset + 10] = (byte)(~(crc16 >> 8)); - SubcodeDeinterleaved[offset + 11] = (byte)(~(crc16)); - - return crc16; - } - - public void Synthesize_SunchannelQ_Checksum() - { - int offset = 12; //Q subchannel begins after P, 12 bytes in - - ushort crc16 = CRC16_CCITT.Calculate(SubcodeDeinterleaved, offset, 10); - - //CRC is stored inverted and big endian - SubcodeDeinterleaved[offset + 10] = (byte)(~(crc16 >> 8)); - SubcodeDeinterleaved[offset + 11] = (byte)(~(crc16)); - } - - public void ReadSubcodeDeinterleaved(byte[] buffer, int offset) - { - Buffer.BlockCopy(SubcodeDeinterleaved, 0, buffer, offset, 96); - } - - public void ReadSubcodeChannel(int number, byte[] buffer, int offset) - { - Buffer.BlockCopy(SubcodeDeinterleaved, number * 12, buffer, offset, 12); - } - - public BufferedSubcodeSector() - { - SubcodeDeinterleaved = new byte[96]; - } - - public static BufferedSubcodeSector CloneFromBytesDeinterleaved(byte[] buffer) - { - var ret = new BufferedSubcodeSector(); - Buffer.BlockCopy(buffer, 0, ret.SubcodeDeinterleaved, 0, 96); - return ret; - } - - public byte[] SubcodeDeinterleaved; - } - - public class ZeroSubcodeSector : ISubcodeSector - { - public void ReadSubcodeDeinterleaved(byte[] buffer, int offset) - { - for (int i = 0; i < 96; i++) buffer[i + offset] = 0; - } - - public void ReadSubcodeChannel(int number, byte[] buffer, int offset) - { - for (int i = 0; i < 12; i++) - buffer[i + offset] = 0; - } - } - - /// - /// Reads subcode data from a blob, assuming it was already stored in deinterleaved format - /// - public class BlobSubcodeSectorPreDeinterleaved : ISubcodeSector - { - public void ReadSubcodeDeinterleaved(byte[] buffer, int offset) - { - Blob.Read(Offset, buffer, offset, 96); - } - - public void ReadSubcodeChannel(int number, byte[] buffer, int offset) - { - Blob.Read(Offset + number * 12, buffer, offset, 12); - } - - public IBlob Blob; - public long Offset; - } - /// /// Control bit flags for the Q Subchannel. /// @@ -277,8 +59,8 @@ namespace BizHawk.Emulation.DiscSystem /// /// These are the initial set of timestamps. Meaning varies: /// check yellowbook 22.3.3 and 22.3.4 - /// normal track: relative timestamp /// leadin track: unknown + /// user information track: relative timestamp /// leadout: relative timestamp /// 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 @@ -293,17 +75,16 @@ namespace BizHawk.Emulation.DiscSystem /// /// These are the second set of timestamps. Meaning varies: /// check yellowbook 22.3.3 and 22.3.4 - /// normal track: absolute timestamp /// leadin track q-mode 1: TOC entry, absolute MSF of track + /// user information track: absolute timestamp /// leadout: absolute timestamp /// public BCD2 ap_min, ap_sec, ap_frame; /// - /// The CRC. This is the actual CRC value as would be calculated from our library (it is inverted and written big endian to the disc) - /// Don't assume this CRC is correct-- If this SubchannelQ was read from a dumped disc, the CRC might be wrong. - /// CCD doesnt specify this for TOC entries, so it will be wrong. It may or may not be right for data track sectors from a CCD file. - /// Or we may have computed this SubchannelQ data and generated the correct CRC at that time. + /// Don't assume this CRC is correct, in the case of some copy protections it is intended to be wrong. + /// Furthermore, it is meaningless (and in BizHawk, unpopulated) for a TOC Entry + /// (since an invalid CRC on a [theyre redundantly/duplicately stored] toc entry would cause it to get discarded in favor of another one with a correct CRC) /// public ushort q_crc; @@ -390,24 +171,4 @@ namespace BizHawk.Emulation.DiscSystem } } - public class SubcodeDataDecoder - { - /// - /// This seems to deinterleave Q from a subcode buffer? Not sure.. it isn't getting used anywhere right now, as you can see. - /// - public static void Unpack_Q(byte[] output, int out_ofs, byte[] input, int in_ofs) - { - for (int i = 0; i < 12; i++) - output[out_ofs + i] = 0; - for (int i = 0; i < 96; i++) - { - int bytenum = i >> 3; - int bitnum = i & 7; - bitnum = 7 - bitnum; - int bitval = (byte)((input[in_ofs + i] >> 6) & 1); - bitval <<= bitnum; - output[out_ofs + bytenum] |= (byte)bitval; - } - } - } }