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); + // } + // } + //} } }