disc: add some subcode infrastructure
This commit is contained in:
parent
87cd0730e6
commit
1800fcb965
|
@ -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" />
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue