From 132b1dc281cd0680eda10b54eafc8bf9578febd1 Mon Sep 17 00:00:00 2001 From: zeromus Date: Mon, 5 Jan 2015 23:01:23 +0000 Subject: [PATCH] psx - support SBI files --- .../BizHawk.Emulation.DiscSystem.csproj | 1 + BizHawk.Emulation.DiscSystem/Disc.cs | 54 ++++++++- BizHawk.Emulation.DiscSystem/SBI_format.cs | 104 ++++++++++++++++++ BizHawk.Emulation.DiscSystem/Subcode.cs | 14 ++- 4 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 BizHawk.Emulation.DiscSystem/SBI_format.cs diff --git a/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj b/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj index 6017f778f6..af11ed18f6 100644 --- a/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj +++ b/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj @@ -74,6 +74,7 @@ + diff --git a/BizHawk.Emulation.DiscSystem/Disc.cs b/BizHawk.Emulation.DiscSystem/Disc.cs index 371f6d557d..ddc5557304 100644 --- a/BizHawk.Emulation.DiscSystem/Disc.cs +++ b/BizHawk.Emulation.DiscSystem/Disc.cs @@ -66,6 +66,11 @@ namespace BizHawk.Emulation.DiscSystem { public partial class Disc : IDisposable { + /// + /// Free-form optional memos about the disc + /// + public Dictionary Memos = new Dictionary(); + /// /// The raw TOC entries found in the lead-in track. /// @@ -204,9 +209,19 @@ FILE ""xarp.barp.marp.farp"" BINARY { var ret = new Disc(); ret.FromCuePathInternal(cuePath, prefs); + ret.Structure.Synthesize_TOCPointsFromSessions(); ret.Synthesize_SubcodeFromStructure(); ret.Synthesize_TOCRawFromStructure(); + + //try loading SBI. make sure its done after the subcode is synthesized! + string sbiPath = Path.ChangeExtension(cuePath, "sbi"); + if (File.Exists(sbiPath) && SBI_Format.QuickCheckISSBI(sbiPath)) + { + var sbi = new SBI_Format().LoadSBIPath(sbiPath); + ret.ApplySBI(sbi); + } + return ret; } @@ -251,6 +266,33 @@ FILE ""xarp.barp.marp.farp"" BINARY TOCRaw.LeadoutTimestamp = new Timestamp(lastEnd); } + /// + /// applies an SBI file to the disc + /// + public void ApplySBI(SBI_Format.SBIFile sbi) + { + //save this, it's small, and we'll want it for disc processing a/b checks + Memos["sbi"] = sbi; + + int n = sbi.ABAs.Count; + byte[] subcode = new byte[96]; + int b=0; + for (int i = 0; i < n; i++) + { + int aba = sbi.ABAs[i]; + var oldSubcode = this.Sectors[aba].SubcodeSector; + oldSubcode.ReadSubcodeDeinterleaved(subcode, 0); + for (int j = 0; j < 12; j++) + { + short patch = sbi.subq[b++]; + if (patch == -1) continue; + else subcode[12 + j] = (byte)patch; + } + var bss = new BufferedSubcodeSector(); + Sectors[aba].SubcodeSector = BufferedSubcodeSector.CloneFromBytesDeinterleaved(subcode); + } + } + /// /// Creates the subcode (really, just subchannel Q) for this disc from its current TOC. /// Depends on the TOCPoints existing in the structure @@ -283,10 +325,6 @@ FILE ""xarp.barp.marp.farp"" BINARY } var dp = Structure.Points[dpIndex]; - if (aba == 4903 + 150) - { - int zzz = 9; - } var se = Sectors[aba]; @@ -366,8 +404,14 @@ FILE ""xarp.barp.marp.farp"" BINARY return new BCD2 {DecimalValue = d}; } + public static int BCDToInt(byte n) + { + var bcd = new BCD2(); + bcd.BCDValue = n; + return bcd.DecimalValue; + } - static byte IntToBCD(int n) + public static byte IntToBCD(int n) { int ones; int tens = Math.DivRem(n, 10, out ones); diff --git a/BizHawk.Emulation.DiscSystem/SBI_format.cs b/BizHawk.Emulation.DiscSystem/SBI_format.cs new file mode 100644 index 0000000000..7f31b45765 --- /dev/null +++ b/BizHawk.Emulation.DiscSystem/SBI_format.cs @@ -0,0 +1,104 @@ +using System; +using System.Text; +using System.IO; +using System.Collections.Generic; + +using BizHawk.Common.IOExtensions; + +namespace BizHawk.Emulation.DiscSystem +{ + public class SBI_Format + { + public class SBIParseException : Exception + { + public SBIParseException(string message) : base(message) { } + } + + public class SBIFile + { + /// + /// a list of patched ABAs + /// + public List ABAs = new List(); + + /// + /// 12 values (Q subchannel data) for every patched ABA; -1 means unpatched + /// + public short[] subq; + } + + /// + /// Does a cursory check to see if the file looks like an SBI + /// + public static bool QuickCheckISSBI(string path) + { + using (var fs = File.OpenRead(path)) + { + BinaryReader br = new BinaryReader(fs); + string sig = br.ReadStringFixedAscii(4); + if (sig != "SBI\0") + return false; + } + return true; + } + + /// + /// Loads an SBI file from the specified path + /// + public SBIFile LoadSBIPath(string path) + { + using(var fs = File.OpenRead(path)) + { + BinaryReader br = new BinaryReader(fs); + string sig = br.ReadStringFixedAscii(4); + if (sig != "SBI\0") + throw new SBIParseException("Missing magic number"); + + SBIFile ret = new SBIFile(); + List bytes = new List(); + + //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(); + return ret; + + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.DiscSystem/Subcode.cs b/BizHawk.Emulation.DiscSystem/Subcode.cs index 7488b40da8..ec69b3eeba 100644 --- a/BizHawk.Emulation.DiscSystem/Subcode.cs +++ b/BizHawk.Emulation.DiscSystem/Subcode.cs @@ -108,7 +108,19 @@ namespace BizHawk.Emulation.DiscSystem Buffer.BlockCopy(SubcodeDeinterleaved, number * 12, buffer, offset, 12); } - public byte[] SubcodeDeinterleaved = new byte[96]; + 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