diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index b5710082a9..9920c794a0 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -163,10 +163,12 @@
+
+
diff --git a/BizHawk.Emulation/Disc/Disc.API.cs b/BizHawk.Emulation/Disc/Disc.API.cs
new file mode 100644
index 0000000000..3e3ab77c9f
--- /dev/null
+++ b/BizHawk.Emulation/Disc/Disc.API.cs
@@ -0,0 +1,35 @@
+using System;
+
+//main apis for emulator core routine use
+
+namespace BizHawk.Disc
+{
+
+ public partial class Disc
+ {
+ //main API to read a 2352-byte LBA from a disc.
+ //this starts at the beginning of the disc (at the lead-in)
+ //so add 150 to get to a FAD-address in the user data area
+ public void ReadLBA(int lba, byte[] buffer, int offset)
+ {
+ if (lba < 150)
+ {
+ //lead-in area not supported yet
+ //in the future it will return something to mate with the
+ //subchannel data which we will load or calculate from the TOC
+ return;
+ }
+
+ Sectors[lba - 150].Sector.Read(buffer, offset);
+ }
+
+ //main API to determine how many LBA sectors are available
+ public int LBACount { get { return Sectors.Count + 150; } }
+
+ //main api for reading the TOC from a disc
+ public DiscTOC ReadTOC()
+ {
+ return TOC;
+ }
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Disc/Disc.cs b/BizHawk.Emulation/Disc/Disc.cs
index e9fdd3813c..c91f89f8fd 100644
--- a/BizHawk.Emulation/Disc/Disc.cs
+++ b/BizHawk.Emulation/Disc/Disc.cs
@@ -283,27 +283,6 @@ namespace BizHawk.Disc
}
}
- //main api for reading a 2352-byte LBA from a disc.
- //this starts at the beginning of the disc (at the lead-in)
- //so add 150 to get to a FAD-address in the user data area
- public void ReadLBA(int lba, byte[] buffer, int offset)
- {
- if (lba < 150) {
- //lead-in area not supported yet
- //in the future it will return something to mate with the
- //subchannel data which we will load or calculate from the TOC
- return;
- }
-
- Sectors[lba-150].Sector.Read(buffer, offset);
- }
-
- //main api for reading the TOC from a disc
- public DiscTOC ReadTOC()
- {
- return TOC;
- }
-
public static Disc FromCuePath(string cuePath)
{
var ret = new Disc();
diff --git a/BizHawk.Emulation/Disc/Subcode.cs b/BizHawk.Emulation/Disc/Subcode.cs
new file mode 100644
index 0000000000..159e4a20f3
--- /dev/null
+++ b/BizHawk.Emulation/Disc/Subcode.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.IO;
+using System.Collections.Generic;
+
+//a decent little subcode reference
+//http://www.jbum.com/cdg_revealed.html
+
+namespace BizHawk.Disc
+{
+ public class SubcodeStream
+ {
+ Stream source;
+ long offset;
+ public SubcodeStream(Stream source, long offset)
+ {
+ this.source = source;
+ this.offset = offset;
+ cached_decoder = new SubcodePacketDecoder(cached_buffer, 0);
+ }
+ int channel = 0;
+ public char Channel
+ {
+ get { return (char)((7 - channel) + 'p'); }
+ set { channel = SubcodePacketDecoder.NormalizeChannel(value); }
+ }
+
+ long Position { get; set; }
+
+ int cached_addr = -1;
+ SubcodePacketDecoder cached_decoder = null;
+ byte[] cached_buffer = new byte[24];
+ public int ReadByte()
+ {
+ int subcode_addr = (int)Position;
+ int subcode_byte = subcode_addr & 1;
+ subcode_addr /= 2;
+ subcode_addr *= 24;
+ if (subcode_addr != cached_addr)
+ {
+ cached_decoder.Reset();
+ source.Position = offset + subcode_addr;
+ if (source.Read(cached_buffer, 0, 24) != 24)
+ return -1;
+ cached_addr = subcode_addr;
+ }
+ Position = Position + 1;
+ ushort val = cached_decoder.ReadChannel(channel);
+ val >>= (8 * subcode_byte);
+ val &= 0xFF;
+ return (int)val;
+ }
+ }
+
+ class SubcodePacketDecoder
+ {
+ internal static int NormalizeChannel(char channel)
+ {
+ int channum;
+ if (channel >= 'P' && channel <= 'W') channum = channel - 'P';
+ else if (channel >= 'p' && channel <= 'w') channum = (channel - 'p');
+ else throw new InvalidOperationException("invalid channel specified");
+ channum = 7 - channum;
+ return channum;
+ }
+
+ public void Reset()
+ {
+ cached = false;
+ }
+ byte[] buffer;
+ int offset;
+ public SubcodePacketDecoder(byte[] buffer, int offset)
+ {
+ this.buffer = buffer;
+ this.offset = offset;
+ }
+ byte command { get { return buffer[offset + 0]; } set { buffer[offset + 0] = value; } }
+ byte instruction { get { return buffer[offset + 1]; } set { buffer[offset + 1] = value; } }
+
+ public int parityQ_offset { get { return offset + 2; } }
+ public int data_offset { get { return offset + 4; } }
+ public int parityP_offset { get { return offset + 20; } }
+
+ public byte ReadData(int index)
+ {
+ return buffer[data_offset + index];
+ }
+
+ public ushort ReadChannel(char channel)
+ {
+ return ReadChannel(NormalizeChannel(channel));
+ }
+
+ bool cached;
+ ushort[] decoded_channels = new ushort[8];
+ public ushort ReadChannel(int channum)
+ {
+ if (!cached)
+ {
+ decoded_channels = new ushort[8];
+ for (int i = 0; i < 8; i++)
+ decoded_channels[i] = DecodeChannel(i);
+ }
+ return decoded_channels[channum];
+ }
+
+ ushort DecodeChannel(int channum)
+ {
+ int ret = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ ret |= ((ReadData(i) >> channum) & 1) << i;
+ }
+ return (ushort)ret;
+ }
+ }
+}
diff --git a/DiscoHawk/DiscoHawk.cs b/DiscoHawk/DiscoHawk.cs
index 8237006ba5..cb0d449129 100644
--- a/DiscoHawk/DiscoHawk.cs
+++ b/DiscoHawk/DiscoHawk.cs
@@ -22,6 +22,21 @@ namespace BizHawk
//Console.WriteLine(disc.ReadTOC().DebugPrint());
//disc.DumpBin_2352("d:\\test.2352");
+ //test reading the subcode data. unfortunately we don't have lead-in subcode so we have no TOC
+ //using (FileStream fs = File.OpenRead("c:\\bof4.sub"))
+ //{
+ // Disc.SubcodeStream stream = new Disc.SubcodeStream(fs, 0);
+ // stream.Channel = 'q';
+ // using (FileStream fsOut = File.OpenWrite("c:\\bof4.sub.q"))
+ // {
+ // for (; ; )
+ // {
+ // int ret = stream.ReadByte();
+ // if (ret == -1) break;
+ // fsOut.WriteByte((byte)ret);
+ // }
+ // }
+ //}
}
}