psx - support SBI files

This commit is contained in:
zeromus 2015-01-05 23:01:23 +00:00
parent c55a35610c
commit 132b1dc281
4 changed files with 167 additions and 6 deletions

View File

@ -74,6 +74,7 @@
<Compile Include="GPL_ECM.cs" />
<Compile Include="M3U_file.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SBI_format.cs" />
<Compile Include="SectorInterfaces.cs" />
<Compile Include="Subcode.cs" />
<Compile Include="TOC\DiscStructure.cs" />

View File

@ -66,6 +66,11 @@ namespace BizHawk.Emulation.DiscSystem
{
public partial class Disc : IDisposable
{
/// <summary>
/// Free-form optional memos about the disc
/// </summary>
public Dictionary<string, object> Memos = new Dictionary<string, object>();
/// <summary>
/// The raw TOC entries found in the lead-in track.
/// </summary>
@ -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);
}
/// <summary>
/// applies an SBI file to the disc
/// </summary>
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);
}
}
/// <summary>
/// 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);

View File

@ -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
{
/// <summary>
/// a list of patched ABAs
/// </summary>
public List<int> ABAs = new List<int>();
/// <summary>
/// 12 values (Q subchannel data) for every patched ABA; -1 means unpatched
/// </summary>
public short[] subq;
}
/// <summary>
/// Does a cursory check to see if the file looks like an SBI
/// </summary>
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;
}
/// <summary>
/// Loads an SBI file from the specified path
/// </summary>
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<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();
return ret;
}
}
}
}

View File

@ -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