disc: add some subcode infrastructure

This commit is contained in:
zeromus 2011-05-14 21:56:54 +00:00
parent 87cd0730e6
commit 1800fcb965
5 changed files with 171 additions and 21 deletions

View File

@ -163,10 +163,12 @@
<Compile Include="Database\Database.cs" />
<Compile Include="Disc\CCD_format.cs" />
<Compile Include="Disc\CUE_format.cs" />
<Compile Include="Disc\Disc.API.cs" />
<Compile Include="Disc\Disc.cs" />
<Compile Include="Disc\DiscTOC.cs" />
<Compile Include="Disc\ECM.cs" />
<Compile Include="Disc\FFmpeg.cs" />
<Compile Include="Disc\Subcode.cs" />
<Compile Include="Disc\TOC_format.cs" />
<Compile Include="Interfaces\Base Implementations\Game.cs" />
<Compile Include="Interfaces\Base Implementations\IPS.cs" />

View File

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

View File

@ -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();

View File

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

View File

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