public void Run() { using (var fs = File.OpenRead(IN_Path)) { BinaryReader br = new BinaryReader(fs); string sig = br.ReadStringFixedAscii(4); if (sig != "SBI\0") throw new SBIParseException("Missing magic number"); SubQPatchData ret = new SubQPatchData(); List<short> bytes = new List<short>(); //read records until done for (; ; ) { //graceful end if (fs.Position == fs.Length) break; if (fs.Position + 4 > fs.Length) throw new SBIParseException("Broken record"); var m = BCD2.BCDToInt(br.ReadByte()); var s = BCD2.BCDToInt(br.ReadByte()); var f = BCD2.BCDToInt(br.ReadByte()); var ts = new Timestamp(m, s, f); ret.ABAs.Add(ts.Sector); int type = br.ReadByte(); switch (type) { case 1: //Q0..Q9 if (fs.Position + 10 > fs.Length) throw new SBIParseException("Broken record"); for (int i = 0; i <= 9; i++) bytes.Add(br.ReadByte()); for (int i = 10; i <= 11; i++) bytes.Add(-1); break; case 2: //Q3..Q5 if (fs.Position + 3 > fs.Length) throw new SBIParseException("Broken record"); for (int i = 0; i <= 2; i++) bytes.Add(-1); for (int i = 3; i <= 5; i++) bytes.Add(br.ReadByte()); for (int i = 6; i <= 11; i++) bytes.Add(-1); break; case 3: //Q7..Q9 if (fs.Position + 3 > fs.Length) throw new SBIParseException("Broken record"); for (int i = 0; i <= 6; i++) bytes.Add(-1); for (int i = 7; i <= 9; i++) bytes.Add(br.ReadByte()); for (int i = 10; i <= 11; i++) bytes.Add(-1); break; default: throw new SBIParseException("Broken record"); } } ret.subq = bytes.ToArray(); OUT_Data = ret; } }
/// <summary> /// applies an SBI file to the disc /// </summary> public void Run(Disc disc, SBI.SubQPatchData sbi, bool asMednafen) { //TODO - could implement as a blob, to avoid allocating so many byte buffers //save this, it's small, and we'll want it for disc processing a/b checks disc.Memos["sbi"] = sbi; DiscSectorReader dsr = new DiscSectorReader(disc); int n = sbi.ABAs.Count; int b = 0; for (int i = 0; i < n; i++) { int lba = sbi.ABAs[i] - 150; //create a synthesizer which can return the patched data var ss_patchq = new SS_PatchQ() { Original = disc._Sectors[lba + 150] }; byte[] subQbuf = ss_patchq.Buffer_SubQ; //read the old subcode dsr.ReadLBA_SubQ(lba, subQbuf, 0); //insert patch disc._Sectors[lba + 150] = ss_patchq; //apply SBI patch for (int j = 0; j < 12; j++) { short patch = sbi.subq[b++]; if (patch == -1) { continue; } else { subQbuf[j] = (byte)patch; } } //Apply mednafen hacks //The reasoning here is that we know we expect these sectors to have a wrong checksum. therefore, generate a checksum, and make it wrong //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_SynthChecksum(subQbuf, 0); subQbuf[10] ^= 0xFF; subQbuf[11] ^= 0xFF; } } }
/// <exception cref="SBIParseException">file at <see cref="IN_Path"/> does not contain valid header or contains misformatted record</exception> public override void Run() { using var fs = File.OpenRead(IN_Path); BinaryReader br = new BinaryReader(fs); string sig = br.ReadStringFixedAscii(4); if (sig != "SBI\0") { throw new SBIParseException("Missing magic number"); } SubQPatchData ret = new SubQPatchData(); List <short> bytes = new List <short>(); //read records until done for (; ;) { //graceful end if (fs.Position == fs.Length) { break; } if (fs.Position + 4 > fs.Length) { throw new SBIParseException("Broken record"); } var m = BCD2.BCDToInt(br.ReadByte()); var s = BCD2.BCDToInt(br.ReadByte()); var f = BCD2.BCDToInt(br.ReadByte()); var ts = new Timestamp(m, s, f); ret.ABAs.Add(ts.Sector); int type = br.ReadByte(); switch (type) { case 1: //Q0..Q9 if (fs.Position + 10 > fs.Length) { throw new SBIParseException("Broken record"); } for (int i = 0; i <= 9; i++) { bytes.Add(br.ReadByte()); } for (int i = 10; i <= 11; i++) { bytes.Add(-1); } break; case 2: //Q3..Q5 if (fs.Position + 3 > fs.Length) { throw new SBIParseException("Broken record"); } for (int i = 0; i <= 2; i++) { bytes.Add(-1); } for (int i = 3; i <= 5; i++) { bytes.Add(br.ReadByte()); } for (int i = 6; i <= 11; i++) { bytes.Add(-1); } break; case 3: //Q7..Q9 if (fs.Position + 3 > fs.Length) { throw new SBIParseException("Broken record"); } for (int i = 0; i <= 6; i++) { bytes.Add(-1); } for (int i = 7; i <= 9; i++) { bytes.Add(br.ReadByte()); } for (int i = 10; i <= 11; i++) { bytes.Add(-1); } break; default: throw new SBIParseException("Broken record"); } } ret.subq = bytes.ToArray(); OUT_Data = ret; }