unmanaged core experiment
This commit is contained in:
parent
c30529685d
commit
8a1e0c2b09
|
@ -190,6 +190,9 @@
|
|||
<Compile Include="Disc\FFmpeg.cs" />
|
||||
<Compile Include="Disc\Subcode.cs" />
|
||||
<Compile Include="Disc\TOC_format.cs" />
|
||||
<Compile Include="ExternalCores\EmuFile.cs" />
|
||||
<Compile Include="ExternalCores\ExternalCore.cs" />
|
||||
<Compile Include="ExternalCores\PsxCore.cs" />
|
||||
<Compile Include="Interfaces\Base Implementations\Game.cs" />
|
||||
<Compile Include="Interfaces\Base Implementations\IPS.cs" />
|
||||
<Compile Include="Interfaces\Base Implementations\Movies.cs" />
|
||||
|
@ -241,6 +244,7 @@
|
|||
<Content Include="Consoles\Nintendo\Docs\test_status.txt" />
|
||||
<Content Include="Consoles\PC Engine\Compat.txt" />
|
||||
<Content Include="Consoles\Sega\SMS\Compat.txt" />
|
||||
<Content Include="ExternalCores\Snippets.txt" />
|
||||
<Content Include="Notes.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
using System;
|
||||
using System.Security;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Reflection.Emit;
|
||||
using System.Threading;
|
||||
|
||||
namespace BizHawk
|
||||
{
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
public Stream BaseStream { get; set; }
|
||||
|
||||
//do we want to have a finalizer? not sure.
|
||||
bool disposed = false;
|
||||
public override void Dispose()
|
||||
{
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
|
||||
//we will call Delete in the c++ side, which will delete the object, and cause Dispose() to get called.
|
||||
//but, Dispose() can never be called again due to setting the flag above
|
||||
QueryCoreCall<Action>("EmuFile.Delete")();
|
||||
|
||||
//do we always want to do this? not sure. but usually.
|
||||
BaseStream.Dispose();
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
int fgetc()
|
||||
{
|
||||
return BaseStream.ReadByte();
|
||||
}
|
||||
IntPtr fread(
|
||||
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
|
||||
byte[] ptr,
|
||||
IntPtr bytes)
|
||||
{
|
||||
long len = bytes.ToInt64();
|
||||
if (len >= int.MaxValue || len < 0) throw new ArgumentException();
|
||||
|
||||
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); }
|
||||
|
||||
void fwrite(
|
||||
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
|
||||
byte[] ptr,
|
||||
IntPtr bytes)
|
||||
{
|
||||
long len = bytes.ToInt64();
|
||||
if (len >= int.MaxValue || len < 0) throw new ArgumentException();
|
||||
|
||||
BaseStream.Write(ptr, 0, (int)len);
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate int fgetcDelegate();
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate void disposeDelegate();
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate IntPtr freadDelegate(
|
||||
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
|
||||
byte[] ptr,
|
||||
IntPtr bytes);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate void fwriteDelegate(
|
||||
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
|
||||
byte[] ptr,
|
||||
IntPtr bytes);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate IntPtr fseekDelegate(IntPtr offset, IntPtr origin);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate IntPtr ftellDelegate();
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate IntPtr sizeDelegate();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
using System;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// universal interface to a shared library
|
||||
/// </summary>
|
||||
public interface ILibAccessor : IDisposable
|
||||
{
|
||||
IntPtr GetProcAddress(string name);
|
||||
bool IsOpen { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// universal access to an external emulator core
|
||||
/// </summary>
|
||||
public interface IExternalCoreAccessor : IDisposable
|
||||
{
|
||||
IntPtr Signal(string type, IntPtr obj, string param, IntPtr value);
|
||||
bool IsOpen { get; }
|
||||
void RegisterCore(ExternalCore core, bool register);
|
||||
}
|
||||
|
||||
|
||||
public class CoreAccessor : IExternalCoreAccessor
|
||||
{
|
||||
ILibAccessor mLibAccessor;
|
||||
public CoreAccessor(ILibAccessor accessor)
|
||||
{
|
||||
mLibAccessor = accessor;
|
||||
if (accessor.IsOpen)
|
||||
{
|
||||
mSignal = (SignalCallbackDelegate)Marshal.GetDelegateForFunctionPointer(accessor.GetProcAddress("Core_signal"), typeof(SignalCallbackDelegate));
|
||||
IsOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterCore(ExternalCore core, bool register)
|
||||
{
|
||||
if (core is StaticCoreCommon) return;
|
||||
|
||||
//defer initialization until the core is needed, to avoid pointless costs for cores the user isnt using
|
||||
if (!IsInitialized)
|
||||
{
|
||||
IsInitialized = true;
|
||||
scc = new StaticCoreCommon(this);
|
||||
scc.RegisterClientSignal(new SignalCallbackDelegate(ClientSignal));
|
||||
scc.Initialize();
|
||||
}
|
||||
|
||||
if (register)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//delete
|
||||
}
|
||||
}
|
||||
|
||||
StaticCoreCommon scc;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (mLibAccessor == null) return;
|
||||
scc.Dispose();
|
||||
mLibAccessor.Dispose();
|
||||
mLibAccessor = null;
|
||||
IsOpen = false;
|
||||
}
|
||||
|
||||
public bool IsOpen { get; private set; }
|
||||
bool IsInitialized;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate IntPtr SignalCallbackDelegate(string type, IntPtr obj, string param, IntPtr value);
|
||||
SignalCallbackDelegate mSignal;
|
||||
|
||||
//external cores call into the client from here
|
||||
public IntPtr ClientSignal(string type, IntPtr obj, string param, IntPtr value)
|
||||
{
|
||||
//static calls
|
||||
if (obj == IntPtr.Zero)
|
||||
{
|
||||
return scc.ClientSignal(type, obj, param, value);
|
||||
}
|
||||
else return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public IntPtr Signal(string type, IntPtr obj, string param, IntPtr value)
|
||||
{
|
||||
if (!IsOpen) throw new InvalidOperationException("core accessor is open");
|
||||
return mSignal(type, obj, param, value);
|
||||
}
|
||||
}
|
||||
|
||||
//todo - make abstract
|
||||
public class ExternalCore : IDisposable
|
||||
{
|
||||
//rename to managed and unmanaged
|
||||
public IntPtr ManagedOpaque;
|
||||
public IntPtr UnmanagedOpaque;
|
||||
static int _ManagedOpaque_Counter = 1;
|
||||
|
||||
protected IExternalCoreAccessor mAccessor;
|
||||
public ExternalCore(IExternalCoreAccessor accessor)
|
||||
{
|
||||
mAccessor = accessor;
|
||||
mAccessor.RegisterCore(this,true);
|
||||
lock (this)
|
||||
{
|
||||
ManagedOpaque = new IntPtr(_ManagedOpaque_Counter);
|
||||
_ManagedOpaque_Counter++;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
mAccessor.RegisterCore(this, false);
|
||||
|
||||
//universal delete mechanism?
|
||||
//probably not.
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// merely emits an integer of the current system int size to an ILGenerator
|
||||
/// </summary>
|
||||
static void EmitIntPtr(ILGenerator gen, IntPtr val)
|
||||
{
|
||||
if (IntPtr.Size == 4) gen.Emit(OpCodes.Ldc_I4, val.ToInt32());
|
||||
else gen.Emit(OpCodes.Ldc_I8, val.ToInt64());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// retrieves a function pointer from the core and returns it as the specified delegate type
|
||||
/// </summary>
|
||||
protected void QueryCoreCall<T>(out T del, string name)
|
||||
{
|
||||
del = QueryCoreCall<T>(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// retrieves a function pointer from the core and returns it as the specified delegate type
|
||||
/// </summary>
|
||||
protected T QueryCoreCall<T>(string name)
|
||||
{
|
||||
MethodInfo mi = typeof(T).GetMethod("Invoke");
|
||||
ParameterInfo[] pis = mi.GetParameters();
|
||||
Type[] unmanagedParamTypes = new Type[pis.Length + 1];
|
||||
Type[] managedParamTypes = new Type[pis.Length];
|
||||
unmanagedParamTypes[0] = typeof(int);
|
||||
for (int i = 0; i < pis.Length; i++)
|
||||
{
|
||||
unmanagedParamTypes[i + 1] = pis[i].ParameterType;
|
||||
managedParamTypes[i] = pis[i].ParameterType;
|
||||
}
|
||||
|
||||
IntPtr fptr = mAccessor.Signal("QUERY_FUNCTION", IntPtr.Zero, name, IntPtr.Zero);
|
||||
if (fptr == IntPtr.Zero)
|
||||
throw new InvalidOperationException("external core was missing requested function: " + name);
|
||||
|
||||
DynamicMethod dm = new DynamicMethod("", mi.ReturnType, managedParamTypes, GetType().Module);
|
||||
ILGenerator gen = dm.GetILGenerator();
|
||||
EmitIntPtr(gen, UnmanagedOpaque);
|
||||
for (int i = 0; i < pis.Length; i++) gen.Emit(OpCodes.Ldarg, i);
|
||||
EmitIntPtr(gen, fptr);
|
||||
gen.EmitCalli(OpCodes.Calli, CallingConvention.ThisCall, mi.ReturnType, unmanagedParamTypes);
|
||||
gen.Emit(OpCodes.Ret);
|
||||
|
||||
Delegate d = dm.CreateDelegate(typeof(T));
|
||||
return (T)(object)d;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// exports a delegate as an IntPtr for use in unmanaged code and manages its life cycle to keep it from getting freed
|
||||
/// </summary>
|
||||
protected IntPtr ExportDelegate(Delegate d)
|
||||
{
|
||||
IntPtr retPtr = Marshal.GetFunctionPointerForDelegate(d);
|
||||
listLiveDelegates.Add(d);
|
||||
return retPtr;
|
||||
}
|
||||
|
||||
//need to hold on to these callbacks to make sure they dont get GCed while unmanaged code has a pointer to them
|
||||
List<Delegate> listLiveDelegates = new List<Delegate>();
|
||||
}
|
||||
|
||||
|
||||
public class StaticCoreCommon : ExternalCore
|
||||
{
|
||||
//keep in mind that we may need to make the console thread safe if we ever do any zany multithreaded things
|
||||
|
||||
public StaticCoreCommon(IExternalCoreAccessor accessor)
|
||||
: base(accessor)
|
||||
{
|
||||
}
|
||||
|
||||
EmuFile Console;
|
||||
public void Initialize()
|
||||
{
|
||||
Console = new EmuFile(mAccessor);
|
||||
if (Log.HACK_LOG_STREAM != null)
|
||||
Console.BaseStream = Log.HACK_LOG_STREAM;
|
||||
else
|
||||
Console.BaseStream = System.Console.OpenStandardOutput();
|
||||
mAccessor.Signal("SET_CONSOLE", IntPtr.Zero, null, Console.UnmanagedOpaque);
|
||||
}
|
||||
|
||||
public void RegisterClientSignal(CoreAccessor.SignalCallbackDelegate ClientSignal)
|
||||
{
|
||||
mAccessor.Signal("SET_CLIENT_SIGNAL", IntPtr.Zero, null, ExportDelegate(ClientSignal));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk
|
||||
{
|
||||
|
||||
public class PsxCore : ExternalCore, IEmulator, IVideoProvider, ISoundProvider
|
||||
{
|
||||
public PsxCore(IExternalCoreAccessor accessor)
|
||||
: base(accessor)
|
||||
{
|
||||
var domains = new List<MemoryDomain>(1);
|
||||
memoryDomains = domains.AsReadOnly();
|
||||
CoreOutputComm = new CoreOutputComm();
|
||||
CoreInputComm = new CoreInputComm();
|
||||
|
||||
UnmanagedOpaque = QueryCoreCall<Func<IntPtr,IntPtr>>("PsxCore.Construct")(ManagedOpaque);
|
||||
|
||||
QueryCoreCall(out cGetResolution, "PsxCore.GetResolution");
|
||||
QueryCoreCall(out cUpdateVideoBuffer, "PsxCore.UpdateVideoBuffer");
|
||||
QueryCoreCall(out cFrameAdvance, "PsxCore.FrameAdvance");
|
||||
}
|
||||
|
||||
Func<System.Drawing.Size> cGetResolution;
|
||||
Action cFrameAdvance;
|
||||
Action<IntPtr> cUpdateVideoBuffer;
|
||||
|
||||
//video provider
|
||||
int[] videoBuffer = new int[256 * 256];
|
||||
public int[] GetVideoBuffer() { return videoBuffer; }
|
||||
public int BufferWidth { get { return 256; } }
|
||||
public int BufferHeight { get { return 192; } }
|
||||
public int BackgroundColor { get { return 0; } }
|
||||
|
||||
|
||||
|
||||
public string SystemId { get { return "PSX"; } }
|
||||
public static readonly ControllerDefinition NullController = new ControllerDefinition { Name = "Null Controller" };
|
||||
|
||||
private Random rand = new Random();
|
||||
public CoreInputComm CoreInputComm { get; set; }
|
||||
public CoreOutputComm CoreOutputComm { get; private set; }
|
||||
public IVideoProvider VideoProvider { get { return this; } }
|
||||
public ISoundProvider SoundProvider { get { return this; } }
|
||||
public void LoadGame(IGame game) { }
|
||||
public unsafe void FrameAdvance(bool render)
|
||||
{
|
||||
//if (render == false) return;
|
||||
cFrameAdvance();
|
||||
fixed (int* vidbuf = &videoBuffer[0])
|
||||
cUpdateVideoBuffer(new IntPtr(vidbuf));
|
||||
}
|
||||
public ControllerDefinition ControllerDefinition { get { return NullController; } }
|
||||
public IController Controller { get; set; }
|
||||
|
||||
public int Frame { get; set; }
|
||||
public int LagCount { get { return 0; } set { return; } }
|
||||
public bool IsLagFrame { get { return false; } }
|
||||
|
||||
public byte[] SaveRam { get { return new byte[0]; } }
|
||||
public bool DeterministicEmulation { get; set; }
|
||||
public bool SaveRamModified { get; set; }
|
||||
public void SaveStateText(TextWriter writer) { }
|
||||
public void LoadStateText(TextReader reader) { }
|
||||
public void SaveStateBinary(BinaryWriter writer) { }
|
||||
public void LoadStateBinary(BinaryReader reader) { }
|
||||
public byte[] SaveStateBinary() { return new byte[1]; }
|
||||
public void GetSamples(short[] samples) { }
|
||||
public void DiscardSamples() { }
|
||||
private IList<MemoryDomain> memoryDomains;
|
||||
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
|
||||
public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
////////////////////////////
|
||||
//we can't use these because we need more clever control over the delegate type (marshalling attributes, for one thing)
|
||||
|
||||
Delegate MyMakeDelegate(string methodName)
|
||||
{
|
||||
MethodInfo mi = GetType().GetMethod(methodName,BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
var parameters = mi.GetParameters()
|
||||
.Select(p => p.ParameterType)
|
||||
.ToArray();
|
||||
|
||||
Type t = DelegateCreator.MakeNewCustomDelegate(mi.ReturnType, parameters);
|
||||
return Delegate.CreateDelegate(t, this, mi);
|
||||
}
|
||||
|
||||
|
||||
static class DelegateCreator
|
||||
{
|
||||
public static Type MakeNewCustomDelegate(Type ret_type, Type[] argtypes)
|
||||
{
|
||||
var _DelegateCtorSignature = new Type[] { typeof(object), typeof(IntPtr) };
|
||||
Type returnType = ret_type;
|
||||
Type[] parameterTypes = argtypes;
|
||||
TypeBuilder builder = DefineDelegateType("Delegate" + argtypes.Length);
|
||||
builder.DefineConstructor(MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, CallingConventions.Standard, _DelegateCtorSignature).SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
|
||||
builder.DefineMethod("Invoke", MethodAttributes.VtableLayoutMask | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public, returnType, parameterTypes).SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
|
||||
|
||||
//[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
//builder.SetCustomAttribute(new CustomAttributeBuilder(new ConstructorInfo(
|
||||
ConstructorInfo ci = typeof(UnmanagedFunctionPointerAttribute).GetConstructor(new[] { typeof(CallingConvention) });
|
||||
CustomAttributeBuilder cab = new CustomAttributeBuilder(ci, new object[] { CallingConvention.ThisCall });
|
||||
builder.SetCustomAttribute(cab);
|
||||
|
||||
return builder.CreateType();
|
||||
}
|
||||
|
||||
internal static TypeBuilder DefineDelegateType(string name)
|
||||
{
|
||||
return DefineType(name, typeof(MulticastDelegate), TypeAttributes.AutoClass | TypeAttributes.Sealed | TypeAttributes.Public);
|
||||
}
|
||||
|
||||
static int _index;
|
||||
private static TypeBuilder DefineType(string name, Type parent, TypeAttributes attr)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(name);
|
||||
int num = Interlocked.Increment(ref _index);
|
||||
builder.Append("$");
|
||||
builder.Append(num);
|
||||
builder.Replace('+', '_').Replace('[', '_').Replace(']', '_').Replace('*', '_').Replace('&', '_').Replace(',', '_').Replace('\\', '_');
|
||||
name = builder.ToString();
|
||||
return _myModule.DefineType(name, attr, parent);
|
||||
}
|
||||
|
||||
static AssemblyBuilder _myAssembly;
|
||||
static ModuleBuilder _myModule;
|
||||
static void InitializeAssemblyGen()
|
||||
{
|
||||
AssemblyName name = new AssemblyName("Snippets");
|
||||
CustomAttributeBuilder[] assemblyAttributes = new CustomAttributeBuilder[] { new CustomAttributeBuilder(typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes), new object[0]) };
|
||||
_myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run, assemblyAttributes);
|
||||
_myModule = _myAssembly.DefineDynamicModule(name.Name, false);
|
||||
_myAssembly.DefineVersionInfoResource();
|
||||
}
|
||||
static DelegateCreator()
|
||||
{
|
||||
InitializeAssemblyGen();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////
|
||||
these are members of external core. theyre deprecated.
|
||||
|
||||
|
||||
public IntPtr Signal(string param, IntPtr value)
|
||||
{
|
||||
return mAccessor.Signal(null, IntPtr.Zero, param, value);
|
||||
}
|
||||
|
||||
public IntPtr Signal(string param)
|
||||
{
|
||||
return mAccessor.Signal(null, IntPtr.Zero, param, IntPtr.Zero);
|
||||
}
|
||||
|
||||
public IntPtr Signal(string type, IntPtr obj, string param, Delegate value)
|
||||
{
|
||||
liveDelegates[value.Target ?? ostatic][param] = value;
|
||||
return mAccessor.Signal(type, obj, param, Marshal.GetFunctionPointerForDelegate(value));
|
||||
}
|
||||
|
||||
public IntPtr Signal(string param, Delegate value)
|
||||
{
|
||||
return Signal(null, IntPtr.Zero, param, value);
|
||||
}
|
||||
|
||||
public IntPtr Signal(string param, int value)
|
||||
{
|
||||
return mAccessor.Signal(null, IntPtr.Zero, param, new IntPtr(value));
|
||||
}
|
||||
|
||||
public IntPtr Signal(string type, IntPtr obj, string param, IntPtr value)
|
||||
{
|
||||
return mAccessor.Signal(type, obj, param, value);
|
||||
}
|
|
@ -128,6 +128,7 @@
|
|||
<Compile Include="config\SoundConfig.Designer.cs">
|
||||
<DependentUpon>SoundConfig.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ExternalCoreSupport.cs" />
|
||||
<Compile Include="Gameboy\Debugger.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
@ -667,4 +668,8 @@
|
|||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -56,5 +56,8 @@ namespace BizHawk.MultiClient
|
|||
|
||||
//TODO - wtf is this being used for
|
||||
public static bool MovieMode;
|
||||
|
||||
public static CoreAccessor PsxCoreLibrary = new CoreAccessor(new Win32LibAccessor("PsxHawk.Core.dll"));
|
||||
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
@ -74,6 +75,7 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
|
||||
UpdateStatusSlots();
|
||||
|
||||
//in order to allow late construction of this database, we hook up a delegate here to dearchive the data and provide it on demand
|
||||
//we could background thread this later instead if we wanted to be real clever
|
||||
NES.BootGodDB.GetDatabaseBytes = () =>
|
||||
|
@ -819,70 +821,83 @@ namespace BizHawk.MultiClient
|
|||
else return false;
|
||||
}
|
||||
|
||||
var game = new RomGame(file);
|
||||
IEmulator nextEmulator = null;
|
||||
RomGame game = null;
|
||||
|
||||
switch (game.System)
|
||||
if (Path.GetExtension(path).ToLower() == ".iso")
|
||||
{
|
||||
case "SG":
|
||||
case "SMS":
|
||||
nextEmulator = new SMS();
|
||||
if (Global.Config.SmsEnableFM) game.AddOptions("UseFM");
|
||||
if (Global.Config.SmsAllowOverlock) game.AddOptions("AllowOverclock");
|
||||
if (Global.Config.SmsForceStereoSeparation) game.AddOptions("ForceStereo");
|
||||
break;
|
||||
case "GG":
|
||||
nextEmulator = new SMS { IsGameGear = true };
|
||||
if (Global.Config.SmsAllowOverlock) game.AddOptions("AllowOverclock");
|
||||
break;
|
||||
case "PCE":
|
||||
nextEmulator = new PCEngine(NecSystemType.TurboGrafx);
|
||||
break;
|
||||
case "SGX":
|
||||
nextEmulator = new PCEngine(NecSystemType.SuperGrafx);
|
||||
break;
|
||||
case "GEN":
|
||||
nextEmulator = new Genesis(true);//TODO
|
||||
break;
|
||||
case "TI83":
|
||||
nextEmulator = new TI83();
|
||||
if (Global.Config.TI83autoloadKeyPad)
|
||||
LoadTI83KeyPad();
|
||||
break;
|
||||
case "NES":
|
||||
{
|
||||
NES nes = new NES();
|
||||
nextEmulator = nes;
|
||||
if (Global.Config.NESAutoLoadPalette && Global.Config.NESPaletteFile.Length > 0 && HawkFile.ExistsAt(Global.Config.NESPaletteFile))
|
||||
if (Global.PsxCoreLibrary.IsOpen)
|
||||
{
|
||||
nextEmulator = new PsxCore(Global.PsxCoreLibrary);
|
||||
game = new RomGame();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
game = new RomGame(file);
|
||||
|
||||
switch (game.System)
|
||||
{
|
||||
case "SG":
|
||||
case "SMS":
|
||||
nextEmulator = new SMS();
|
||||
if (Global.Config.SmsEnableFM) game.AddOptions("UseFM");
|
||||
if (Global.Config.SmsAllowOverlock) game.AddOptions("AllowOverclock");
|
||||
if (Global.Config.SmsForceStereoSeparation) game.AddOptions("ForceStereo");
|
||||
break;
|
||||
case "GG":
|
||||
nextEmulator = new SMS { IsGameGear = true };
|
||||
if (Global.Config.SmsAllowOverlock) game.AddOptions("AllowOverclock");
|
||||
break;
|
||||
case "PCE":
|
||||
nextEmulator = new PCEngine(NecSystemType.TurboGrafx);
|
||||
break;
|
||||
case "SGX":
|
||||
nextEmulator = new PCEngine(NecSystemType.SuperGrafx);
|
||||
break;
|
||||
case "GEN":
|
||||
nextEmulator = new Genesis(true);//TODO
|
||||
break;
|
||||
case "TI83":
|
||||
nextEmulator = new TI83();
|
||||
if (Global.Config.TI83autoloadKeyPad)
|
||||
LoadTI83KeyPad();
|
||||
break;
|
||||
case "NES":
|
||||
{
|
||||
nes.SetPalette(NES.Palettes.Load_FCEUX_Palette(HawkFile.ReadAllBytes(Global.Config.NESPaletteFile)));
|
||||
NES nes = new NES();
|
||||
nextEmulator = nes;
|
||||
if (Global.Config.NESAutoLoadPalette && Global.Config.NESPaletteFile.Length > 0 && HawkFile.ExistsAt(Global.Config.NESPaletteFile))
|
||||
{
|
||||
nes.SetPalette(NES.Palettes.Load_FCEUX_Palette(HawkFile.ReadAllBytes(Global.Config.NESPaletteFile)));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "GB":
|
||||
nextEmulator = new Gameboy();
|
||||
break;
|
||||
break;
|
||||
case "GB":
|
||||
nextEmulator = new Gameboy();
|
||||
break;
|
||||
}
|
||||
|
||||
if (nextEmulator == null) throw new Exception();
|
||||
|
||||
try
|
||||
{
|
||||
nextEmulator.CoreInputComm = Global.CoreInputComm;
|
||||
|
||||
//this is a bit hacky, but many cores do not take responsibility for setting this, so we need to set it for them.
|
||||
nextEmulator.CoreOutputComm.RomStatus = game.Status;
|
||||
|
||||
nextEmulator.LoadGame(game);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Exception during loadgame:\n\n" + ex.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextEmulator == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (nextEmulator == null) throw new Exception();
|
||||
|
||||
try
|
||||
{
|
||||
nextEmulator.CoreInputComm = Global.CoreInputComm;
|
||||
|
||||
//this is a bit hacky, but many cores do not take responsibility for setting this, so we need to set it for them.
|
||||
nextEmulator.CoreOutputComm.RomStatus = game.Status;
|
||||
|
||||
nextEmulator.LoadGame(game);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Exception during loadgame:\n\n" + ex.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseGame();
|
||||
Global.Emulator.Dispose();
|
||||
|
@ -1916,11 +1931,38 @@ namespace BizHawk.MultiClient
|
|||
typeof(ToolStrip).InvokeMember("ProcessMnemonicInternal", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance, null, menuStrip1, new object[] { c });
|
||||
}
|
||||
|
||||
string FormatFilter(params string[] args)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (args.Length % 2 != 0) throw new ArgumentException();
|
||||
int num = args.Length / 2;
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
sb.AppendFormat("{0} ({1})|{1}", args[i * 2], args[i * 2 + 1]);
|
||||
if (i != num - 1) sb.Append('|');
|
||||
}
|
||||
string str = sb.ToString().Replace("%ARCH%", "*.zip;*.rar;*.7z");
|
||||
str = str.Replace(";", "; ");
|
||||
return str;
|
||||
}
|
||||
|
||||
private void OpenROM()
|
||||
{
|
||||
var ofd = new OpenFileDialog();
|
||||
ofd.InitialDirectory = PathManager.GetRomsPath(Global.Emulator.SystemId);
|
||||
ofd.Filter = "Rom Files|*.NES;*.SMS;*.GG;*.SG;*.PCE;*.SGX;*.GB;*.BIN;*.SMD;*.ROM;*.ZIP;*.7z|NES|*.NES|Master System|*.SMS;*.GG;*.SG;*.ZIP;*.7z|PC Engine|*.PCE;*.SGX;*.ZIP;*.7z|Gameboy|*.GB;*.ZIP;*.7z|TI-83|*.rom|Archive Files|*.zip;*.7z|Savestate|*.state|All Files|*.*";
|
||||
//"Rom Files|*.NES;*.SMS;*.GG;*.SG;*.PCE;*.SGX;*.GB;*.BIN;*.SMD;*.ROM;*.ZIP;*.7z|NES (*.NES)|*.NES|Master System|*.SMS;*.GG;*.SG;*.ZIP;*.7z|PC Engine|*.PCE;*.SGX;*.ZIP;*.7z|Gameboy|*.GB;*.ZIP;*.7z|TI-83|*.rom|Archive Files|*.zip;*.7z|Savestate|*.state|All Files|*.*";
|
||||
ofd.Filter = FormatFilter(
|
||||
"Rom Files", "*.nes;*.sms;*.gg;*.sg;*.pce;*.sgx;*.gb;*.bin;*.smd;*.rom;*.iso;%ARCH%",
|
||||
"Disc Images", "*.iso",
|
||||
"NES", "*.nes;%ARCH%",
|
||||
"Master System", "*.sms;*.gg;*.sg;%ARCH%",
|
||||
"PC Engine", "*.pce;*.sgx;%ARCH%",
|
||||
"Gameboy", "*.gb;%ARCH%",
|
||||
"TI-83", "*.rom;%ARCH%",
|
||||
"Archive Files", "%ARCH%",
|
||||
"Savestate", "*.state",
|
||||
"All Files", "*.*");
|
||||
|
||||
ofd.RestoreDirectory = false;
|
||||
|
||||
Global.Sound.StopSound();
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace BizHawk.MultiClient
|
|||
private List<string> options;
|
||||
private const int BankSize = 4096;
|
||||
|
||||
public RomGame() { }
|
||||
|
||||
public RomGame(HawkFile file) : this(file, null) { }
|
||||
|
||||
public RomGame(HawkFile file, string patch)
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="BizHawk.UnmanagedCore"
|
||||
ProjectGUID="{1CE74E20-B345-4126-AACB-A21FA23149DE}"
|
||||
RootNamespace="BizHawkUnmanagedCore"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\core.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\core.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\emufile.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\emufile.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\emufile_hawk.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\emufile_hawk.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\types.h"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
|
@ -0,0 +1,91 @@
|
|||
#include <string>
|
||||
#include "core.h"
|
||||
#include "emufile.h"
|
||||
#include "emufile_hawk.h"
|
||||
|
||||
|
||||
//TODO
|
||||
class DISC_INTERFACE
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
//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;
|
||||
EMUFILE_HAWK* con = NULL;
|
||||
|
||||
static void* (*ClientSignal_cb)(const char*,void*,const char*,void*);
|
||||
void* ClientSignal(const char* type, void* obj, const char* _param, void* value)
|
||||
{
|
||||
return ClientSignal_cb(type,obj,_param,value);
|
||||
}
|
||||
|
||||
|
||||
//core objects function pointers get registered here
|
||||
class FunctionRegistry
|
||||
{
|
||||
private:
|
||||
|
||||
typedef std::map<std::string, void*> TFunctionMap;
|
||||
TFunctionMap map;
|
||||
|
||||
public:
|
||||
static FunctionRegistry& Instance() {
|
||||
static FunctionRegistry inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
void Register(const char* _name, void* _funcptr)
|
||||
{
|
||||
map[_name] = _funcptr;
|
||||
}
|
||||
|
||||
void* Lookup(const char* name)
|
||||
{
|
||||
TFunctionMap::iterator it(map.find(name));
|
||||
if(it == map.end()) return NULL;
|
||||
else return it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
FunctionRegistry() {}
|
||||
};
|
||||
|
||||
void _registerFunction(const char* _name, void* _funcptr)
|
||||
{
|
||||
FunctionRegistry::Instance().Register(_name,_funcptr);
|
||||
}
|
||||
|
||||
//maybe youll need this some day... but probably not.
|
||||
//#pragma comment(linker, "/include:_Core_signal")
|
||||
extern "C" __declspec(dllexport) void* Core_signal(const char* type, void* obj, const char* param, void* value)
|
||||
{
|
||||
//use this to log signals
|
||||
if(con) con->fprintf("core signal: %s : %s\n",type?type:"n/a",param?param:"n/a");
|
||||
|
||||
if(!strcmp(type,"SET_CLIENT_SIGNAL"))
|
||||
{
|
||||
ClientSignal_cb = (void *(*)(const char*,void*,const char*,void*))value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!strcmp(type,"SET_CONSOLE"))
|
||||
{
|
||||
con = (EMUFILE_HAWK*)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//query a function pointer for later blazing fast reuse
|
||||
if(!strcmp(type,"QUERY_FUNCTION"))
|
||||
return FunctionRegistry::Instance().Lookup(param);
|
||||
|
||||
//TODO - custom core static operations?
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef _CORE_H_
|
||||
#define _CORE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#ifndef CTASSERT
|
||||
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1];
|
||||
#endif
|
||||
|
||||
//use this to send a signal to the client.
|
||||
//it may not be completely fully-baked yet though
|
||||
void* ClientSignal(const char* type, void* obj, const char* _param, void* value);
|
||||
|
||||
class EMUFILE_HAWK;
|
||||
|
||||
//use this to print output to the client
|
||||
extern EMUFILE_HAWK* con;
|
||||
|
||||
|
||||
//this is supposedly illegal. but i say its perfectly legal, as long as im not using virtual functions. so stuff it.
|
||||
//well, since we're doing it illegally, we need to resist the urge to generalize the function pointer system (to emufile and disc)
|
||||
//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)
|
||||
template<typename T> void* MP(const T& a)
|
||||
{
|
||||
union U{
|
||||
void* vp;
|
||||
T t;
|
||||
} u;
|
||||
u.t = a;
|
||||
return u.vp;
|
||||
CTASSERT(sizeof(U)==4||(sizeof(U)==8&&sizeof(void*)==8));
|
||||
}
|
||||
|
||||
//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
|
||||
{
|
||||
private:
|
||||
template<typename T> T MPX(void* a)
|
||||
{
|
||||
union U{
|
||||
void* vp;
|
||||
T t;
|
||||
} u;
|
||||
u.vp = a;
|
||||
return u.t;
|
||||
CTASSERT(sizeof(U)==4||(sizeof(U)==8&&sizeof(void*)==8));
|
||||
}
|
||||
public:
|
||||
T func;
|
||||
void set(void* val) { func = MPX<T>(val); }
|
||||
};
|
||||
|
||||
//nothing important
|
||||
void _registerFunction(const char* _name, void* _funcptr);
|
||||
struct FunctionRecord
|
||||
{
|
||||
FunctionRecord(const char* _name, void* _funcptr)
|
||||
{
|
||||
_registerFunction(_name,_funcptr);
|
||||
}
|
||||
};
|
||||
|
||||
//register a core object member function. put it in a global static array
|
||||
template<typename T> FunctionRecord FUNC(const char* name, const T& a)
|
||||
{
|
||||
return FunctionRecord(name,MP(a));
|
||||
}
|
||||
|
||||
#endif //_CORE_H_
|
|
@ -0,0 +1,28 @@
|
|||
#include "types.h"
|
||||
#include "emufile.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
bool EMUFILE::readAllBytes(std::vector<u8>* dstbuf, const std::string& fname)
|
||||
{
|
||||
EMUFILE_FILE file(fname.c_str(),"rb");
|
||||
if(file.fail()) return false;
|
||||
int size = file.size();
|
||||
dstbuf->resize(size);
|
||||
file.fread(&dstbuf->at(0),size);
|
||||
return true;
|
||||
}
|
||||
|
||||
EMUFILE* EMUFILE::memwrap(EMUFILE* fp)
|
||||
{
|
||||
EMUFILE_FILE* file;
|
||||
EMUFILE_MEMORY* mem;
|
||||
file = dynamic_cast<EMUFILE_FILE*>(fp);
|
||||
mem = dynamic_cast<EMUFILE_MEMORY*>(fp);
|
||||
if(mem) return mem;
|
||||
mem = new EMUFILE_MEMORY(file->size());
|
||||
if(file->size()==0) return mem;
|
||||
file->fread(mem->buf(),file->size());
|
||||
delete file;
|
||||
return mem;
|
||||
}
|
|
@ -0,0 +1,299 @@
|
|||
/* 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
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
|
||||
//should be changed to #ifdef FCEUX but too much work
|
||||
#ifndef DESMUME
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef char s8;
|
||||
typedef short s16;
|
||||
typedef int s32;
|
||||
#endif
|
||||
|
||||
#ifdef _XBOX
|
||||
#undef min;
|
||||
#undef max;
|
||||
#endif
|
||||
|
||||
class EMUFILE {
|
||||
protected:
|
||||
bool failbit;
|
||||
|
||||
public:
|
||||
EMUFILE()
|
||||
: failbit(false)
|
||||
{}
|
||||
|
||||
|
||||
//takes control of the provided EMUFILE and returns a new EMUFILE which is guranteed to be in memory
|
||||
static EMUFILE* memwrap(EMUFILE* fp);
|
||||
|
||||
virtual ~EMUFILE() {}
|
||||
|
||||
static bool readAllBytes(std::vector<u8>* buf, const std::string& fname);
|
||||
|
||||
bool fail() { return failbit; }
|
||||
|
||||
bool eof() { return size()==ftell(); }
|
||||
|
||||
size_t fread(const void *ptr, size_t bytes){
|
||||
return _fread(ptr,bytes);
|
||||
}
|
||||
|
||||
void unget() { fseek(-1,SEEK_CUR); }
|
||||
|
||||
//virtuals
|
||||
public:
|
||||
|
||||
virtual FILE *get_fp() = 0;
|
||||
|
||||
virtual int fprintf(const char *format, ...) = 0;
|
||||
|
||||
virtual int fgetc() = 0;
|
||||
virtual int fputc(int c) = 0;
|
||||
|
||||
virtual size_t _fread(const void *ptr, size_t bytes) = 0;
|
||||
|
||||
//removing these return values for now so we can find any code that might be using them and make sure
|
||||
//they handle the return values correctly
|
||||
|
||||
virtual void fwrite(const void *ptr, size_t bytes) = 0;
|
||||
|
||||
virtual int fseek(int offset, int origin) = 0;
|
||||
|
||||
virtual int ftell() = 0;
|
||||
virtual int size() = 0;
|
||||
};
|
||||
|
||||
//todo - handle read-only specially?
|
||||
class EMUFILE_MEMORY : public EMUFILE {
|
||||
protected:
|
||||
std::vector<u8> *vec;
|
||||
bool ownvec;
|
||||
s32 pos, len;
|
||||
|
||||
void reserve(u32 amt) {
|
||||
if(vec->size() < amt)
|
||||
vec->resize(amt);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
EMUFILE_MEMORY(std::vector<u8> *underlying) : vec(underlying), ownvec(false), pos(0), len(underlying->size()) { }
|
||||
EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) {
|
||||
vec->resize(preallocate);
|
||||
len = preallocate;
|
||||
}
|
||||
EMUFILE_MEMORY() : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { vec->reserve(1024); }
|
||||
EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(size) {
|
||||
vec->resize(size);
|
||||
if(size != 0)
|
||||
memcpy(&vec[0],buf,size);
|
||||
}
|
||||
|
||||
~EMUFILE_MEMORY() {
|
||||
if(ownvec) delete vec;
|
||||
}
|
||||
|
||||
u8* buf() { return &(*vec)[0]; }
|
||||
|
||||
std::vector<u8>* get_vec() { return vec; };
|
||||
|
||||
virtual FILE *get_fp() { return NULL; }
|
||||
|
||||
virtual int fprintf(const char *format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
|
||||
//we dont generate straight into the buffer because it will null terminate (one more byte than we want)
|
||||
int amt = vsnprintf(0,0,format,argptr);
|
||||
char* tempbuf = new char[amt+1];
|
||||
vsprintf(tempbuf,format,argptr);
|
||||
fwrite(tempbuf,amt);
|
||||
delete[] tempbuf;
|
||||
va_end(argptr);
|
||||
return amt;
|
||||
};
|
||||
|
||||
virtual int fgetc() {
|
||||
u8 temp;
|
||||
|
||||
//need an optimized codepath
|
||||
//if(_fread(&temp,1) != 1)
|
||||
// return EOF;
|
||||
//else return temp;
|
||||
u32 remain = len-pos;
|
||||
if(remain<1) {
|
||||
failbit = true;
|
||||
return -1;
|
||||
}
|
||||
temp = buf()[pos];
|
||||
pos++;
|
||||
return temp;
|
||||
}
|
||||
virtual int fputc(int c) {
|
||||
u8 temp = (u8)c;
|
||||
//TODO
|
||||
//if(fwrite(&temp,1)!=1) return EOF;
|
||||
fwrite(&temp,1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t _fread(const void *ptr, size_t bytes){
|
||||
u32 remain = len-pos;
|
||||
u32 todo = std::min<u32>(remain,(u32)bytes);
|
||||
memcpy((void*)ptr,buf()+pos,todo);
|
||||
pos += todo;
|
||||
if(todo<bytes)
|
||||
failbit = true;
|
||||
return todo;
|
||||
}
|
||||
|
||||
//removing these return values for now so we can find any code that might be using them and make sure
|
||||
//they handle the return values correctly
|
||||
|
||||
virtual void fwrite(const void *ptr, size_t bytes){
|
||||
reserve(pos+bytes);
|
||||
memcpy(buf()+pos,ptr,bytes);
|
||||
pos += bytes;
|
||||
len = std::max(pos,len);
|
||||
}
|
||||
|
||||
virtual int fseek(int offset, int origin){
|
||||
//work differently for read-only...?
|
||||
switch(origin) {
|
||||
case SEEK_SET:
|
||||
pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
pos += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
pos = size()+offset;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
reserve(pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int ftell() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
void trim()
|
||||
{
|
||||
vec->resize(len);
|
||||
}
|
||||
|
||||
virtual int size() { return (int)len; }
|
||||
};
|
||||
|
||||
class EMUFILE_FILE : public EMUFILE {
|
||||
protected:
|
||||
FILE* fp;
|
||||
|
||||
private:
|
||||
void open(const char* fname, const char* mode)
|
||||
{
|
||||
fp = fopen(fname,mode);
|
||||
if(!fp)
|
||||
failbit = true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
EMUFILE_FILE(const std::string& fname, const char* mode) { open(fname.c_str(),mode); }
|
||||
EMUFILE_FILE(const char* fname, const char* mode) { open(fname,mode); }
|
||||
|
||||
virtual ~EMUFILE_FILE() {
|
||||
if(NULL != fp)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
virtual FILE *get_fp() {
|
||||
return fp;
|
||||
}
|
||||
|
||||
bool is_open() { return fp != NULL; }
|
||||
|
||||
virtual int fprintf(const char *format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
int ret = ::vfprintf(fp, format, argptr);
|
||||
va_end(argptr);
|
||||
return ret;
|
||||
};
|
||||
|
||||
virtual int fgetc() {
|
||||
return ::fgetc(fp);
|
||||
}
|
||||
virtual int fputc(int c) {
|
||||
return ::fputc(c, fp);
|
||||
}
|
||||
|
||||
virtual size_t _fread(const void *ptr, size_t bytes){
|
||||
size_t ret = ::fread((void*)ptr, 1, bytes, fp);
|
||||
if(ret < bytes)
|
||||
failbit = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//removing these return values for now so we can find any code that might be using them and make sure
|
||||
//they handle the return values correctly
|
||||
|
||||
virtual void fwrite(const void *ptr, size_t bytes){
|
||||
size_t ret = ::fwrite((void*)ptr, 1, bytes, fp);
|
||||
if(ret < bytes)
|
||||
failbit = true;
|
||||
}
|
||||
|
||||
virtual int fseek(int offset, int origin){
|
||||
return ::fseek(fp, offset, origin);
|
||||
}
|
||||
|
||||
virtual int ftell() {
|
||||
return (u32)::ftell(fp);
|
||||
}
|
||||
|
||||
virtual int size() {
|
||||
int oldpos = ftell();
|
||||
fseek(0,SEEK_END);
|
||||
int len = ftell();
|
||||
fseek(oldpos,SEEK_SET);
|
||||
return len;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
#include "emufile_hawk.h"
|
||||
#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),
|
||||
};
|
||||
|
||||
|
||||
int EMUFILE_HAWK::fprintf(const char *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
|
||||
//could use a small static buf here optionally for quickness's sake but we may regret it if we multithread later
|
||||
|
||||
int amt = vsnprintf(0,0,format,argptr);
|
||||
char* tempbuf = new char[amt+1];
|
||||
vsprintf(tempbuf,format,argptr);
|
||||
fwrite(tempbuf,amt);
|
||||
delete[] tempbuf;
|
||||
va_end(argptr);
|
||||
return amt;
|
||||
}
|
||||
|
||||
|
||||
void* EMUFILE_HAWK::Construct(void* ManagedOpaque)
|
||||
{
|
||||
return new EMUFILE_HAWK(ManagedOpaque);
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef _EMUFILE_HAWK_H_
|
||||
#define _EMUFILE_HAWK_H_
|
||||
|
||||
#include "emufile.h"
|
||||
#include "core.h"
|
||||
|
||||
class EMUFILE_HAWK : public EMUFILE
|
||||
{
|
||||
void* ManagedOpaque;
|
||||
|
||||
|
||||
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;
|
||||
} _;
|
||||
|
||||
public:
|
||||
~EMUFILE_HAWK()
|
||||
{
|
||||
_.dispose.func();
|
||||
}
|
||||
EMUFILE_HAWK(void* _ManagedOpaque)
|
||||
: ManagedOpaque(_ManagedOpaque)
|
||||
{
|
||||
}
|
||||
|
||||
void* Construct(void* ManagedOpaque);
|
||||
|
||||
void Delete()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void Set_fp(const char* param, void* value)
|
||||
{
|
||||
if(!strcmp(param,"fgetc")) _.fgetc.set(value);
|
||||
if(!strcmp(param,"fread")) _.fread.set(value);
|
||||
if(!strcmp(param,"fwrite")) _.fwrite.set(value);
|
||||
if(!strcmp(param,"fseek")) _.fseek.set(value);
|
||||
if(!strcmp(param,"ftell")) _.ftell.set(value);
|
||||
if(!strcmp(param,"size")) _.size.set(value);
|
||||
if(!strcmp(param,"dispose")) _.dispose.set(value);
|
||||
}
|
||||
|
||||
virtual int fgetc() { return _.fgetc.func(); }
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
#endif //_EMUFILE_HAWK_H_
|
|
@ -0,0 +1,8 @@
|
|||
typedef unsigned char u8;
|
||||
typedef char s8;
|
||||
typedef unsigned short u16;
|
||||
typedef short s16;
|
||||
typedef unsigned int u32;
|
||||
typedef int s32;
|
||||
typedef unsigned __int64 u64;
|
||||
typedef __int64 s64;
|
58
BizHawk.sln
58
BizHawk.sln
|
@ -6,31 +6,89 @@ EndProject
|
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Util", "BizHawk.Util\BizHawk.Util.csproj", "{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.MultiClient", "BizHawk.MultiClient\BizHawk.MultiClient.csproj", "{DD448B37-BA3F-4544-9754-5406E8094723}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25} = {7B67D95B-29E0-4F9D-9767-42C35CEC3F25}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscoHawk", "DiscoHawk\DiscoHawk.csproj", "{C4366030-6D03-424B-AE53-F4F43BB217C3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PsxHawk.Core", "PsxHawk.Core\PsxHawk.Core.vcproj", "{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE} = {1CE74E20-B345-4126-AACB-A21FA23149DE}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BizHawk.UnmanagedCore", "BizHawk.UnmanagedCore\BizHawk.UnmanagedCore.vcproj", "{1CE74E20-B345-4126-AACB-A21FA23149DE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{EE135301-08B3-4EFC-A61C-1C53E1C65CB9}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{DD448B37-BA3F-4544-9754-5406E8094723}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{C4366030-6D03-424B-AE53-F4F43BB217C3}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}.Release|Win32.Build.0 = Release|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{1CE74E20-B345-4126-AACB-A21FA23149DE}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#include "PsxCore.h"
|
||||
#include "core.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "emufile_hawk.h"
|
||||
|
||||
|
||||
static FunctionRecord records[] = {
|
||||
FUNC("PsxCore.Construct", &PsxCore::Construct),
|
||||
FUNC("PsxCore.GetResolution", &PsxCore::GetResolution),
|
||||
FUNC("PsxCore.FrameAdvance", &PsxCore::FrameAdvance),
|
||||
FUNC("PsxCore.UpdateVideoBuffer", &PsxCore::UpdateVideoBuffer)
|
||||
};
|
||||
|
||||
|
||||
PsxCore::Size PsxCore::GetResolution()
|
||||
{
|
||||
con->fprintf("in PsxCore::GetResolution\n");
|
||||
Size size = {256,256};
|
||||
return size;
|
||||
}
|
||||
|
||||
int videoBuffer[256*256];
|
||||
|
||||
void PsxCore::FrameAdvance()
|
||||
{
|
||||
for(int i=0;i<256*256;i++)
|
||||
{
|
||||
videoBuffer[i] = rand() | (rand()<<15) | 0xFF000000;
|
||||
}
|
||||
}
|
||||
|
||||
void PsxCore::UpdateVideoBuffer(void* target)
|
||||
{
|
||||
int* dest = (int*)target;
|
||||
int* src = (int*)videoBuffer;
|
||||
for(int i=0;i<256*256;i++)
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef _PSXCORE_H_
|
||||
#define _PSXCORE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class PsxCore
|
||||
{
|
||||
public:
|
||||
PsxCore(void* _opaque)
|
||||
: opaque(_opaque)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void* opaque;
|
||||
|
||||
public:
|
||||
void* Construct(void* ManagedOpaque)
|
||||
{
|
||||
return new PsxCore(ManagedOpaque);
|
||||
}
|
||||
|
||||
struct Size
|
||||
{
|
||||
int width,height;
|
||||
};
|
||||
|
||||
Size GetResolution();
|
||||
void FrameAdvance();
|
||||
void UpdateVideoBuffer(void* target);
|
||||
};
|
||||
|
||||
#endif //_PSXCORE_H_
|
|
@ -0,0 +1,184 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="PsxHawk.Core"
|
||||
ProjectGUID="{7B67D95B-29E0-4F9D-9767-42C35CEC3F25}"
|
||||
RootNamespace="PsxHawkCore"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\BizHawk.UnmanagedCore"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PSXHAWKCORE_EXPORTS;_CRT_SECURE_NO_WARNINGS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
GenerateMapFile="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy $(TargetPath) $(SolutionDir)\BizHawk.MultiClient\output"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="..\BizHawk.UnmanagedCore"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PSXHAWKCORE_EXPORTS;_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="copy $(TargetPath) $(SolutionDir)\BizHawk.MultiClient\output"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\PsxCore.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PsxCore.h"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
Loading…
Reference in New Issue