psx - support SBI files
This commit is contained in:
parent
c55a35610c
commit
132b1dc281
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue