164 lines
5.1 KiB
C#
164 lines
5.1 KiB
C#
using System;
|
|
using System.Text;
|
|
using System.IO;
|
|
using System.Globalization;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace BizHawk.Emulation.DiscSystem
|
|
{
|
|
/// <summary>
|
|
/// A resource representing a disc opened and mounted through the MednaDisc component.
|
|
/// Does not attempt to virtually present the disc as a BizHawk disc - that will be the
|
|
/// responsibility of the user of this code
|
|
/// </summary>
|
|
public unsafe class MednaDisc : IDisposable
|
|
{
|
|
public MednaDisc(string pathToDisc)
|
|
{
|
|
if (!IsLibraryAvailable)
|
|
throw new InvalidOperationException("MednaDisc library is not available!");
|
|
|
|
handle = mednadisc_LoadCD(pathToDisc);
|
|
if (handle == IntPtr.Zero)
|
|
throw new InvalidOperationException("Failed to load MednaDisc: " + pathToDisc);
|
|
|
|
//read the mednafen toc
|
|
TOCTracks = new MednadiscTOCTrack[101];
|
|
fixed (MednadiscTOCTrack* _tracks = &TOCTracks[0])
|
|
fixed(MednadiscTOC* _toc = &TOC)
|
|
mednadisc_ReadTOC(handle, _toc, _tracks);
|
|
|
|
//leave the disc open until this is disposed so we can read sectors from it
|
|
}
|
|
|
|
IntPtr handle;
|
|
|
|
public MednadiscTOC TOC;
|
|
public MednadiscTOCTrack[] TOCTracks;
|
|
|
|
[ThreadStatic] static byte[] buf2442 = new byte[2448];
|
|
[ThreadStatic] static byte[] buf96 = new byte[96];
|
|
|
|
|
|
public void Read_2442(int LBA, byte[] buffer, int offset)
|
|
{
|
|
//read directly into the target buffer
|
|
fixed(byte* pBuffer = &buffer[0])
|
|
mednadisc_ReadSector(handle, LBA, pBuffer + offset);
|
|
}
|
|
|
|
//public void ReadSubcodeDeinterleaved(int LBA, byte[] buffer, int offset)
|
|
//{
|
|
// fixed (byte* pBuffer = buf2442)
|
|
// mednadisc_ReadSector(handle, LBA, pBuffer);
|
|
// SubcodeUtils.Deinterleave(buf2442, 2352, buffer, offset);
|
|
//}
|
|
|
|
//public void ReadSubcodeChannel(int LBA, int number, byte[] buffer, int offset)
|
|
//{
|
|
// fixed (byte* pBuffer = buf2442)
|
|
// mednadisc_ReadSector(handle, LBA, pBuffer);
|
|
// SubcodeUtils.Deinterleave(buf2442, 2352, buf96, 0);
|
|
// for (int i = 0; i < 12; i++)
|
|
// buffer[offset + i] = buf96[number * 12 + i];
|
|
//}
|
|
|
|
//public void Read_2352(int LBA, byte[] buffer, int offset)
|
|
//{
|
|
// fixed (byte* pBuffer = buf2442)
|
|
// mednadisc_ReadSector(handle, LBA, pBuffer);
|
|
// Buffer.BlockCopy(buf2442, 0, buffer, offset, 2352);
|
|
//}
|
|
|
|
//public void Read_2048(int LBA, byte[] buffer, int offset)
|
|
//{
|
|
// //this depends on CD-XA mode and such. so we need to read the mode bytes
|
|
// //HEY!!!!!! SHOULD THIS BE DONE BASED ON THE CLAIMED TRACK TYPE, OR ON WHATS IN THE SECTOR?
|
|
// //this is kind of a function of the CD reader.. it's not clear how this function should work.
|
|
// //YIKES!!!!!!!!!!!!!!
|
|
// //well, we need to scrutinize it for CCD files anyway, so...
|
|
// //this sucks.
|
|
|
|
// fixed (byte* pBuffer = buf2442)
|
|
// mednadisc_ReadSector(handle, LBA, pBuffer);
|
|
|
|
// byte mode = buf2442[15];
|
|
// if (mode == 1)
|
|
// Buffer.BlockCopy(buf2442, 16, buffer, offset, 2048);
|
|
// else
|
|
// Buffer.BlockCopy(buf2442, 24, buffer, offset, 2048); //PSX assumptions about CD-XA.. BAD BAD BAD
|
|
//}
|
|
|
|
static void CheckLibrary()
|
|
{
|
|
IntPtr lib = LoadLibrary("mednadisc.dll");
|
|
if (lib == IntPtr.Zero)
|
|
{
|
|
_IsLibraryAvailable = false;
|
|
return;
|
|
}
|
|
IntPtr addr = GetProcAddress(lib, "mednadisc_LoadCD");
|
|
FreeLibrary(lib);
|
|
if (addr == IntPtr.Zero)
|
|
{
|
|
_IsLibraryAvailable = false;
|
|
}
|
|
_IsLibraryAvailable = true;
|
|
}
|
|
|
|
static MednaDisc()
|
|
{
|
|
CheckLibrary();
|
|
}
|
|
|
|
static bool _IsLibraryAvailable;
|
|
public static bool IsLibraryAvailable { get { return _IsLibraryAvailable; } }
|
|
|
|
public void Dispose()
|
|
{
|
|
if(handle == IntPtr.Zero) return;
|
|
mednadisc_CloseCD(handle);
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct MednadiscTOC
|
|
{
|
|
public byte first_track;
|
|
public byte last_track;
|
|
public byte disc_type;
|
|
};
|
|
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
public struct MednadiscTOCTrack
|
|
{
|
|
[FieldOffset(0)] public byte adr;
|
|
[FieldOffset(1)] public byte control;
|
|
[FieldOffset(4)] public uint lba;
|
|
|
|
//can't be a bool due to marshalling...
|
|
[FieldOffset(8)] public byte _validByte;
|
|
|
|
public bool Valid { get { return _validByte != 0; } }
|
|
};
|
|
|
|
[DllImport("kernel32.dll")]
|
|
static extern IntPtr LoadLibrary(string dllToLoad);
|
|
[DllImport("kernel32.dll")]
|
|
static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
|
|
[DllImport("kernel32.dll")]
|
|
static extern bool FreeLibrary(IntPtr hModule);
|
|
|
|
[DllImport("mednadisc.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr mednadisc_LoadCD(string path);
|
|
|
|
[DllImport("mednadisc.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern int mednadisc_ReadSector(IntPtr disc, int lba, byte* buf2448);
|
|
|
|
[DllImport("mednadisc.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void mednadisc_CloseCD(IntPtr disc);
|
|
|
|
[DllImport("mednadisc.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void mednadisc_ReadTOC(IntPtr disc, MednadiscTOC* toc, MednadiscTOCTrack* tracks101);
|
|
}
|
|
} |