get some of the disc api interop stuff checked in

This commit is contained in:
zeromus 2011-08-02 08:26:33 +00:00
parent 074edfdc67
commit 19d0cc627e
19 changed files with 327 additions and 82 deletions

View File

@ -1,10 +1,43 @@
using System;
using System.Collections.Generic;
//main apis for emulator core routine use
namespace BizHawk.Disc
{
public class DiscHopper
{
public Disc CurrentDisc;
public Queue<Disc> Queue = new Queue<Disc>();
public void Enqueue(Disc disc)
{
Queue.Enqueue(disc);
}
public void Next()
{
if (Queue.Count != 0) Queue.Dequeue();
}
public void Eject()
{
CurrentDisc = null;
}
public void Insert()
{
if (Queue.Count > 0)
CurrentDisc = Queue.Peek();
}
public void Clear()
{
CurrentDisc = null;
Queue.Clear();
}
}
public partial class Disc
{
//main API to read a 2352-byte LBA from a disc.

View File

@ -288,9 +288,10 @@ namespace BizHawk.Disc
blob.PhysicalPath = fiIso.FullName;
Blobs.Add(blob);
int num_lba = (int)(fiIso.Length / 2048);
//index.length_lba = num_lba;
track.length_lba = num_lba;
if (fiIso.Length % 2048 != 0)
throw new InvalidOperationException("invalid iso file (size not multiple of 2048)");
//TODO - handle this with Final Fantasy 9 cd1.iso
var ecmCacheBlob = new ECMCacheBlob(blob);
for (int i = 0; i < num_lba; i++)

View File

@ -14,7 +14,7 @@ namespace BizHawk.Disc
public int num;
public List<Track> Tracks = new List<Track>();
//the length of the track (should be the sum of all track lengths)
//the length of the session (should be the sum of all track lengths)
public int length_lba;
public Cue.CueTimestamp FriendlyLength { get { return new Cue.CueTimestamp(length_lba); } }
}

View File

@ -13,22 +13,99 @@ using System.Threading;
namespace BizHawk
{
/// <summary>
/// represents an external core's interface to a disc
/// </summary>
public class DiscInterface : ExternalCore
{
public DiscInterface(IExternalCoreAccessor accessor)
: base(accessor)
{
UnmanagedOpaque = QueryCoreCall<Func<IntPtr, IntPtr>>("DiscInterface.Construct")(ManagedOpaque);
SetFp("Dispose", new disposeDelegate(Dispose));
SetFp("GetNumSessions", new GetNumSessionsDelegate(GetNumSessions));
SetFp("GetNumTracks", new GetNumTracksDelegate(GetNumTracks));
SetFp("GetTrack", new GetTrackDelegate(GetTrack));
}
bool disposed = false;
public override void Dispose()
{
if (disposed) return;
disposed = true;
QueryCoreCall<Action>("DiscInterface.Delete")();
base.Dispose();
}
public Disc.DiscHopper DiscHopper;
void SetFp(string name, Delegate del)
{
QueryCoreCall<Action<string, IntPtr>>("DiscInterface.Set_fp")(name, ExportDelegate(del));
}
struct TrackInfo
{
public Disc.ETrackType TrackType;
public int length_lba;
public int start_lba;
}
int GetNumSessions()
{
return DiscHopper.CurrentDisc.ReadTOC().Sessions.Count;
}
int GetNumTracks(int session)
{
return DiscHopper.CurrentDisc.ReadTOC().Sessions[session].Tracks.Count;
}
TrackInfo GetTrack(int session, int track)
{
var ti = new TrackInfo();
var toc_track = DiscHopper.CurrentDisc.ReadTOC().Sessions[session].Tracks[track];
ti.TrackType = toc_track.TrackType;
ti.length_lba = toc_track.length_lba;
return ti;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void disposeDelegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int GetNumSessionsDelegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int GetNumTracksDelegate(int session);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate TrackInfo GetTrackDelegate(int session, int track);
}
public class EmuFile : ExternalCore
{
public EmuFile(IExternalCoreAccessor accessor)
: base(accessor)
{
UnmanagedOpaque = QueryCoreCall<Func<IntPtr, IntPtr>>("EmuFile.Construct")(ManagedOpaque);
QueryCoreCall<Action<string, IntPtr>>("EmuFile.Set_fp")("fgetc", ExportDelegate(new fgetcDelegate(fgetc)));
QueryCoreCall<Action<string, IntPtr>>("EmuFile.Set_fp")("fread", ExportDelegate(new freadDelegate(fread)));
QueryCoreCall<Action<string, IntPtr>>("EmuFile.Set_fp")("fwrite", ExportDelegate(new fwriteDelegate(fwrite)));
QueryCoreCall<Action<string, IntPtr>>("EmuFile.Set_fp")("fseek", ExportDelegate(new fseekDelegate(fseek)));
QueryCoreCall<Action<string, IntPtr>>("EmuFile.Set_fp")("ftell", ExportDelegate(new ftellDelegate(ftell)));
QueryCoreCall<Action<string, IntPtr>>("EmuFile.Set_fp")("size", ExportDelegate(new sizeDelegate(size)));
QueryCoreCall<Action<string, IntPtr>>("EmuFile.Set_fp")("size", ExportDelegate(new sizeDelegate(size)));
SetFp("fgetc", new fgetcDelegate(fgetc));
SetFp("fread", new freadDelegate(fread));
SetFp("fwrite", new fwriteDelegate(fwrite));
SetFp("fseek", new fseekDelegate(fseek));
SetFp("ftell", new ftellDelegate(ftell));
SetFp("size", new sizeDelegate(size));
SetFp("dispose", new disposeDelegate(Dispose));
}
void SetFp(string name, Delegate del)
{
QueryCoreCall<Action<string, IntPtr>>("EmuFile.Set_fp")(name, ExportDelegate(del));
}
public Stream BaseStream { get; set; }
@ -54,6 +131,7 @@ namespace BizHawk
{
return BaseStream.ReadByte();
}
IntPtr fread(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
byte[] ptr,
@ -65,12 +143,14 @@ namespace BizHawk
int ret = BaseStream.Read(ptr, 0, (int)len);
return new IntPtr(ret);
}
IntPtr fseek(IntPtr offset, IntPtr origin)
{
SeekOrigin so = (SeekOrigin)origin.ToInt32();
long loffset = offset.ToInt64();
return new IntPtr(BaseStream.Seek(loffset, so));
}
IntPtr ftell() { return new IntPtr(BaseStream.Position); }
IntPtr size() { return new IntPtr(BaseStream.Length); }
@ -89,6 +169,8 @@ namespace BizHawk
delegate int fgetcDelegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void disposeDelegate();
//TODO - for more speed fread and fwrite might appreciate taking pointers
//(although, we'll have to convert it to an array to deal with an underlying stream anyway -- or will we?
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate IntPtr freadDelegate(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]

View File

@ -13,6 +13,7 @@ using System.Collections.Generic;
namespace BizHawk
{
/// <summary>
/// universal interface to a shared library
@ -62,14 +63,16 @@ namespace BizHawk
if (register)
{
mCoreRegistry[core.ManagedOpaque] = core;
}
else
{
//delete
mCoreRegistry.Remove(core.ManagedOpaque);
}
}
StaticCoreCommon scc;
Dictionary<IntPtr, ExternalCore> mCoreRegistry = new Dictionary<IntPtr, ExternalCore>();
public void Dispose()
{
@ -95,7 +98,10 @@ namespace BizHawk
{
return scc.ClientSignal(type, obj, param, value);
}
else return IntPtr.Zero;
else
{
return mCoreRegistry[obj].ClientSignal(type, obj, param, value);
}
}
public IntPtr Signal(string type, IntPtr obj, string param, IntPtr value)
@ -112,17 +118,18 @@ namespace BizHawk
public IntPtr ManagedOpaque;
public IntPtr UnmanagedOpaque;
static int _ManagedOpaque_Counter = 1;
private static object oLock = new object();
protected IExternalCoreAccessor mAccessor;
public ExternalCore(IExternalCoreAccessor accessor)
{
mAccessor = accessor;
mAccessor.RegisterCore(this,true);
lock (this)
lock (oLock)
{
ManagedOpaque = new IntPtr(_ManagedOpaque_Counter);
_ManagedOpaque_Counter++;
}
mAccessor.RegisterCore(this, true);
}
public virtual void Dispose()
@ -136,8 +143,13 @@ namespace BizHawk
/// <summary>
/// cores call into the client from here. this system is not fully baked yet, though
/// </summary>
virtual public IntPtr ClientSignal(string type, IntPtr obj, string param, IntPtr value)
public virtual IntPtr ClientSignal(string type, IntPtr obj, string param, IntPtr value)
{
//if (type == "FACTORY")
//{
// return new DiscInterface(mAccessor).UnmanagedOpaque;
//}
//else return IntPtr.Zero;
return IntPtr.Zero;
}
@ -230,6 +242,11 @@ namespace BizHawk
mAccessor.Signal("SET_CLIENT_SIGNAL", IntPtr.Zero, null, ExportDelegate(ClientSignal));
}
public override IntPtr ClientSignal(string type, IntPtr obj, string param, IntPtr value)
{
return IntPtr.Zero;
}
}

View File

@ -19,6 +19,8 @@ namespace BizHawk
CoreOutputComm = new CoreOutputComm();
CoreInputComm = new CoreInputComm();
mDiscInterface = new DiscInterface(mAccessor);
UnmanagedOpaque = QueryCoreCall<Func<IntPtr,IntPtr>>("PsxCore.Construct")(ManagedOpaque);
QueryCoreCall(out cGetResolution, "PsxCore.GetResolution");
@ -26,6 +28,21 @@ namespace BizHawk
QueryCoreCall(out cFrameAdvance, "PsxCore.FrameAdvance");
}
DiscInterface mDiscInterface;
public void SetDiscHopper(Disc.DiscHopper hopper)
{
mDiscInterface.DiscHopper = hopper;
}
public override IntPtr ClientSignal(string type, IntPtr obj, string param, IntPtr value)
{
if (param == "GetDiscInterface")
{
return mDiscInterface.UnmanagedOpaque;
}
return base.ClientSignal(type, obj, param, value);
}
Func<System.Drawing.Size> cGetResolution;
Action cFrameAdvance;
Action<IntPtr> cUpdateVideoBuffer;

View File

@ -74,6 +74,9 @@ namespace BizHawk.MultiClient
return mg.GetControllersAsMnemonic();
}
public static Disc.DiscHopper DiscHopper = new BizHawk.Disc.DiscHopper();
public static CoreAccessor PsxCoreLibrary = new CoreAccessor(new Win32LibAccessor("PsxHawk.Core.dll"));
}

View File

@ -848,12 +848,10 @@ namespace BizHawk.MultiClient
nextEmulator = psx;
game = new RomGame();
var disc = Disc.Disc.FromIsoPath(path);
//Global.DiscHopper.Clear();
//Global.DiscHopper.Enqueue(disc);
//Global.DiscHopper.Insert();
//set disc
//psx.
Global.DiscHopper.Clear();
Global.DiscHopper.Enqueue(disc);
Global.DiscHopper.Insert();
psx.SetDiscHopper(Global.DiscHopper);
}
}
else

View File

@ -48,6 +48,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
CallingConvention="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@ -110,6 +111,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CallingConvention="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@ -151,6 +153,14 @@
RelativePath=".\core.h"
>
</File>
<File
RelativePath=".\DiscInterface.cpp"
>
</File>
<File
RelativePath=".\DiscInterface.h"
>
</File>
<File
RelativePath=".\emufile.cpp"
>

View File

@ -0,0 +1,11 @@
#include "DiscInterface.h"
static FunctionRecord records[] = {
REG("DiscInterface.Construct", &DiscInterface::Construct),
REG("DiscInterface.Set_fp", &DiscInterface::Set_fp),
};
void* DiscInterface::Construct(void* ManagedOpaque)
{
return new DiscInterface(ManagedOpaque);
}

View File

@ -0,0 +1,61 @@
#ifndef _DISCINTERFACE_H_
#define _DISCINTERFACE_H_
#include "DiscInterface.h"
#include "core.h"
class DiscInterface
{
void* ManagedOpaque;
public:
enum ETrackType : int
{
ETrackType_Mode1_2352,
ETrackType_Mode1_2048,
ETrackType_Mode2_2352,
ETrackType_Audio
};
struct TrackInfo
{
ETrackType TrackType;
int length_lba;
int start_lba;
};
FUNC<void()> Dispose;
FUNC<int()> GetNumSessions;
FUNC<int(int)> GetNumTracks;
FUNC<TrackInfo(int,int)> GetTrack;
~DiscInterface()
{
Dispose.func();
}
DiscInterface(void* _ManagedOpaque)
: ManagedOpaque(_ManagedOpaque)
{
}
void* Construct(void* ManagedOpaque);
void Delete()
{
delete this;
}
void Set_fp(const char* param, void* value)
{
if(!strcmp(param,"GetNumSessions")) GetNumSessions.set(value);
if(!strcmp(param,"GetNumTracks")) GetNumTracks.set(value);
if(!strcmp(param,"GetTrack")) GetTrack.set(value);
if(!strcmp(param,"Dispose")) Dispose.set(value);
}
};
#endif //_DISCINTERFACE_H_

View File

@ -2,13 +2,7 @@
#include "core.h"
#include "emufile.h"
#include "emufile_hawk.h"
//TODO
class DISC_INTERFACE
{
};
#include "DiscInterface.h"
//TODO - setup a null file to use as the default console, so we dont have to check whether its set to null everywhere
class EMUFILE_HAWK;
@ -84,7 +78,9 @@ extern "C" __declspec(dllexport) void* Core_signal(const char* type, void* obj,
//force a reference to our core types. a bit annoying but if its this easy i guess i dont mind
if(!strcmp(type,"IMPOSSIBLE"))
{
return new EMUFILE_HAWK(0);
con->fprintf("%x\n",((DiscInterface*)NULL)->Construct(NULL));
con->fprintf("%x\n",((EMUFILE_HAWK*)NULL)->Construct(NULL));
return 0;
}
return 0;

View File

@ -23,6 +23,7 @@ extern EMUFILE_HAWK* con;
//since we may need to change all these later to work un-generalized
//but seriously. before doing that, i would rather return sizeof(functionpointer) bytes as a token to the managed code and pass that back in
//(MP stands for MEMBER POINTER)
//we could also try using the FastDelegate. really, we probably should.
template<typename T> void* MP(const T& a)
{
union U{
@ -35,7 +36,7 @@ template<typename T> void* MP(const T& a)
}
//this is a function pointer which can be assigned without having to type the function protoype again to cast it.
template<typename T> class FP
template<typename T> class __FP
{
private:
template<typename T> T MPX(void* a)
@ -48,12 +49,39 @@ private:
return u.t;
CTASSERT(sizeof(U)==4||(sizeof(U)==8&&sizeof(void*)==8));
}
//protected:
public:
T func;
void set(void* val) { func = MPX<T>(val); }
};
//nothing important
//----------------
//these templates help us call a function pointer directly with () instead of fp.func()
template<typename R=void> struct FUNC0 : public __FP<R(*)()> { public:
R operator()() { return func(); }
};
template<typename A1, typename R=void> struct FUNC1 : public __FP<R(*)(A1)> { public:
R operator()(A1 a1) { return func(a1); }
};
template<typename A1, typename A2, typename R=void> struct FUNC2 : public __FP<R(*)(A1,A2)> { public:
R operator()(A1 a1, A2 a2) { return func(a1,a2); }
};
template<typename A1, typename A2, typename A3, typename R=void> struct FUNC3 : public __FP<R(*)(A1,A2,A3)> { public:
R operator()(A1 a1, A2 a2, A3 a3) { return func(a1,a2,a3); }
};
template<typename A1, typename A2, typename A3, typename A4, typename R=void> struct FUNC4 : public __FP<R(*)(A1,A2,A3,A4)> { public:
R operator()(A1 a1, A2 a2, A3 a3, A4 a4) { return func(a1,a2,a3,a4); }
};
template<typename Signature> class FUNC;
template<typename R> class FUNC<R()> : public FUNC0<R> {};
template<typename A1, typename R> class FUNC<R(A1)> : public FUNC1<A1,R> {};
template<typename A1, typename A2, typename R> class FUNC<R(A1,A2)> : public FUNC2<A1,A2,R> {};
template<typename A1, typename A2, typename A3, typename R> class FUNC<R(A1,A2,A3)> : public FUNC3<A1,A2,A3,R> {};
template<typename A1, typename A2, typename A3, typename A4, typename R> class FUNC<R(A1,A2,A3,A4)> : public FUNC4<A1,A2,A3,A4,R> {};
//----------------
void _registerFunction(const char* _name, void* _funcptr);
struct FunctionRecord
{
@ -64,7 +92,7 @@ struct FunctionRecord
};
//register a core object member function. put it in a global static array
template<typename T> FunctionRecord FUNC(const char* name, const T& a)
template<typename T> FunctionRecord REG(const char* name, const T& a)
{
return FunctionRecord(name,MP(a));
}

View File

@ -1,22 +1,3 @@
/* Copyright (C) 2009 DeSmuME team
*
* This file is part of DeSmuME
*
* DeSmuME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DeSmuME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DeSmuME; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef EMUFILE_H
#define EMUFILE_H

View File

@ -2,9 +2,9 @@
#include "core.h"
static FunctionRecord records[] = {
FUNC("EmuFile.Construct", &EMUFILE_HAWK::Construct),
FUNC("EmuFile.Set_fp", &EMUFILE_HAWK::Set_fp),
FUNC("EmuFile.Delete", &EMUFILE_HAWK::Delete),
REG("EmuFile.Construct", &EMUFILE_HAWK::Construct),
REG("EmuFile.Set_fp", &EMUFILE_HAWK::Set_fp),
REG("EmuFile.Delete", &EMUFILE_HAWK::Delete),
};
@ -24,7 +24,6 @@ int EMUFILE_HAWK::fprintf(const char *format, ...)
return amt;
}
void* EMUFILE_HAWK::Construct(void* ManagedOpaque)
{
return new EMUFILE_HAWK(ManagedOpaque);

View File

@ -10,22 +10,23 @@ class EMUFILE_HAWK : public EMUFILE
struct {
FP<int(*)()> fgetc;
FP<size_t(*)(const void* ptr, size_t bytes)> fread;
FP<void(*)(const void* ptr, size_t bytes)> fwrite;
FP<int(*)(int offset, int origin)> fseek;
FP<int(*)()> ftell;
FP<int(*)()> size;
FP<void(*)()> dispose;
FUNC<int()> fgetc;
FUNC<int(const void* ptr, size_t bytes)> fread;
FUNC<void(const void* ptr, size_t bytes)> fwrite;
FUNC<int(int offset, int origin)> fseek;
FUNC<int()> ftell;
FUNC<int()> size;
FUNC<void()> dispose;
} _;
public:
~EMUFILE_HAWK()
{
_.dispose.func();
_.dispose();
}
EMUFILE_HAWK(void* _ManagedOpaque)
: ManagedOpaque(_ManagedOpaque)
EMUFILE_HAWK(void* _ManagedOpaque)
: ManagedOpaque(_ManagedOpaque)
{
}
@ -47,18 +48,15 @@ public:
if(!strcmp(param,"dispose")) _.dispose.set(value);
}
virtual int fgetc() { return _.fgetc.func(); }
virtual int fgetc() { return _.fgetc(); }
virtual FILE *get_fp() { return NULL; }
virtual int fputc(int c) { return -1; }
virtual int fprintf(const char *format, ...);
virtual size_t _fread(const void *ptr, size_t bytes) { return _.fread.func(ptr,bytes); }
virtual void fwrite(const void *ptr, size_t bytes) { return _.fwrite.func(ptr,bytes); }
virtual int fseek(int offset, int origin) { return _.fseek.func(offset,origin); }
virtual int ftell() { return _.ftell.func(); }
virtual int size() { return _.size.func(); }
void* signal(const char* _param, void* value);
virtual size_t _fread(const void *ptr, size_t bytes) { return _.fread(ptr,bytes); }
virtual void fwrite(const void *ptr, size_t bytes) { return _.fwrite(ptr,bytes); }
virtual int fseek(int offset, int origin) { return _.fseek(offset,origin); }
virtual int ftell() { return _.ftell(); }
virtual int size() { return _.size(); }
};

View File

@ -3,15 +3,21 @@
#include <string.h>
#include <stdlib.h>
#include "emufile_hawk.h"
#include "DiscInterface.h"
static FunctionRecord records[] = {
FUNC("PsxCore.Construct", &PsxCore::Construct),
FUNC("PsxCore.GetResolution", &PsxCore::GetResolution),
FUNC("PsxCore.FrameAdvance", &PsxCore::FrameAdvance),
FUNC("PsxCore.UpdateVideoBuffer", &PsxCore::UpdateVideoBuffer)
REG("PsxCore.Construct", &PsxCore::Construct),
REG("PsxCore.GetResolution", &PsxCore::GetResolution),
REG("PsxCore.FrameAdvance", &PsxCore::FrameAdvance),
REG("PsxCore.UpdateVideoBuffer", &PsxCore::UpdateVideoBuffer)
};
PsxCore::PsxCore(void* _opaque)
: opaque(_opaque)
{
discInterface = (DiscInterface*)ClientSignal(NULL,opaque,"GetDiscInterface",NULL);
}
PsxCore::Size PsxCore::GetResolution()
{
@ -28,6 +34,8 @@ void PsxCore::FrameAdvance()
{
videoBuffer[i] = rand() | (rand()<<15) | 0xFF000000;
}
DiscInterface::TrackInfo ti = discInterface->GetTrack(0,0);
con->fprintf("lba len: %d\n",ti.length_lba);
}
void PsxCore::UpdateVideoBuffer(void* target)

View File

@ -3,16 +3,16 @@
#include <stdio.h>
class DiscInterface;
class PsxCore
{
public:
PsxCore(void* _opaque)
: opaque(_opaque)
{
}
PsxCore(void* _opaque);
private:
void* opaque;
DiscInterface* discInterface;
public:
void* Construct(void* ManagedOpaque)

View File

@ -49,6 +49,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
CallingConvention="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@ -124,6 +125,7 @@
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CallingConvention="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"