From 7739b9dc802fad94a70ca66bf288880900e06411 Mon Sep 17 00:00:00 2001 From: nattthebear Date: Sun, 21 May 2017 17:43:43 -0400 Subject: [PATCH] rough in some snes9x stuff. not working yet --- BizHawk.Common/BizInvoke/BizInvoker.cs | 12 +++ .../Consoles/Nintendo/SNES9X/LibSnes9x.cs | 44 +++++++++-- .../Consoles/Nintendo/SNES9X/Snes9x.cs | 76 +++++++++++++++++-- waterbox/emulibc/emulibc.h | 8 ++ waterbox/gpgx/Makefile | 2 +- waterbox/snes9x | 2 +- 6 files changed, 128 insertions(+), 16 deletions(-) diff --git a/BizHawk.Common/BizInvoke/BizInvoker.cs b/BizHawk.Common/BizInvoke/BizInvoker.cs index 91ce7f292b..35ad6fa66a 100644 --- a/BizHawk.Common/BizInvoke/BizInvoker.cs +++ b/BizHawk.Common/BizInvoke/BizInvoker.cs @@ -474,6 +474,18 @@ namespace BizHawk.Common.BizInvoke return typeof(IntPtr); } + if (type.IsClass) + { + // non ref of class can just be passed as pointer + var loc = il.DeclareLocal(type, true); + il.Emit(OpCodes.Ldarg, (short)idx); + il.Emit(OpCodes.Dup); + il.Emit(OpCodes.Stloc, loc); + il.Emit(OpCodes.Conv_I); + + return typeof(IntPtr); + } + if (type.IsPrimitive || type.IsEnum) { il.Emit(OpCodes.Ldarg, (short)idx); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/LibSnes9x.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/LibSnes9x.cs index 6146d1e4d5..26470559f0 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/LibSnes9x.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/LibSnes9x.cs @@ -3,18 +3,48 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; +using BizHawk.Common.BizInvoke; namespace BizHawk.Emulation.Cores.Nintendo.SNES9X { - public class LibSnes9x + public abstract class LibSnes9x { - const string DllName = "libbizsnes.dll"; + [StructLayout(LayoutKind.Sequential)] + public class memory_area + { + public IntPtr ptr; + public int size; + }; + + [StructLayout(LayoutKind.Sequential)] + public class frame_info + { + public IntPtr ptr; + public int pitch; + public int width; + public int height; + }; + + const CallingConvention CC = CallingConvention.Cdecl; - [DllImport(DllName, CallingConvention = CC)] - public static extern bool debug_init(byte[] data, int length); - - [DllImport(DllName, CallingConvention = CC)] - public static extern void debug_advance(int[] data); + [BizImport(CC)] + public abstract void biz_set_sound_channels(int channels); + [BizImport(CC)] + public abstract void biz_set_layers(int layers); + [BizImport(CC)] + public abstract void biz_soft_reset(); + [BizImport(CC)] + public abstract void biz_set_port_devices(uint left, uint right); + [BizImport(CC)] + public abstract bool biz_load_rom(byte[] data, int size); + [BizImport(CC)] + public abstract bool biz_init(); + [BizImport(CC)] + public abstract void biz_run([In, Out] frame_info frame); + [BizImport(CC)] + public abstract bool biz_is_ntsc(); + [BizImport(CC, Compatibility = true)] + public abstract void biz_get_memory_area(int which, [In, Out] memory_area mem); } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs index cee9f05fcc..dd1ddbe7fc 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs @@ -1,20 +1,44 @@ using System; using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Waterbox; +using BizHawk.Common.BizInvoke; namespace BizHawk.Emulation.Cores.Nintendo.SNES9X { - [CoreAttributes("Snes9x", "FIXME", true, false, "5e0319ab3ef9611250efb18255186d0dc0d7e125", "https://github.com/snes9xgit/snes9x", true)] + [CoreAttributes("Snes9x", "FIXME", true, false, "5e0319ab3ef9611250efb18255186d0dc0d7e125", "https://github.com/snes9xgit/snes9x", false)] [ServiceNotApplicable(typeof(IDriveLight))] public class Snes9x : IEmulator, IVideoProvider, ISoundProvider { + private LibSnes9x _core; + private PeRunner _exe; + + [CoreConstructor("SNES")] public Snes9x(CoreComm comm, byte[] rom) { - if (!LibSnes9x.debug_init(rom, rom.Length)) - throw new Exception(); - ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; + + _exe = new PeRunner(comm.CoreFileProvider.DllPath(), "snes9x.exe", 20 * 1024 * 1024, 65536, 65536); + try + { + _core = BizInvoker.GetInvoker(_exe, _exe); + //Console.WriteLine(_exe.Resolve("biz_init")); + //System.Diagnostics.Debugger.Break(); + if (!_core.biz_init()) + { + throw new InvalidOperationException("Init() failed"); + } + if (!_core.biz_load_rom(rom, rom.Length)) + { + throw new InvalidOperationException("LoadRom() failed"); + } + } + catch + { + Dispose(); + throw; + } } #region controller @@ -26,8 +50,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X #endregion + private bool _disposed = false; + public void Dispose() { + if (!_disposed) + { + _exe.Dispose(); + _exe = null; + _disposed = true; + } } public IEmulatorServiceProvider ServiceProvider { get; private set; } @@ -35,8 +67,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X public void FrameAdvance(IController controller, bool render, bool rendersound = true) { Frame++; + LibSnes9x.frame_info frame = new LibSnes9x.frame_info(); - LibSnes9x.debug_advance(_vbuff); + _core.biz_run(frame); + Blit(frame); } public int Frame { get; private set; } @@ -52,13 +86,41 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X #region IVideoProvider + private unsafe void Blit(LibSnes9x.frame_info frame) + { + BufferWidth = frame.width; + BufferHeight = frame.height; + + int vinc = frame.pitch - frame.width; + + ushort* src = (ushort*)frame.ptr; + fixed (int* _dst = _vbuff) + { + byte* dst = (byte*)_dst; + + for (int j = 0; j < frame.height; j++) + { + for (int i = 0; i < frame.width; i++) + { + var c = *src++; + + *dst++ = (byte)(c << 3 & 0xf8 | c >> 2 & 7); + *dst++ = (byte)(c >> 3 & 0xfa | c >> 9 & 3); + *dst++ = (byte)(c >> 8 & 0xf8 | c >> 13 & 7); + *dst++ = 0xff; + } + src += vinc; + } + } + } + private int[] _vbuff = new int[512 * 480]; public int[] GetVideoBuffer() { return _vbuff; } public int VirtualWidth { get { return (int)(BufferWidth * 1.146); ; } } public int VirtualHeight { get { return BufferHeight; } } - public int BufferWidth { get { return 256; } } - public int BufferHeight { get { return 224; } } + public int BufferWidth { get; private set; } = 256; + public int BufferHeight { get; private set; } = 224; public int BackgroundColor { get { return unchecked((int)0xff000000); } } public int VsyncNumerator diff --git a/waterbox/emulibc/emulibc.h b/waterbox/emulibc/emulibc.h index 5982849229..898d0d5b35 100644 --- a/waterbox/emulibc/emulibc.h +++ b/waterbox/emulibc/emulibc.h @@ -3,6 +3,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + // mark an entry point or callback pointer #define ECL_ENTRY // mark a visible symbol @@ -22,4 +26,8 @@ void *alloc_invisible(size_t size); // send a debug string somewhere, bypassing stdio void _debug_puts(const char *); +#ifdef __cplusplus +} +#endif + #endif diff --git a/waterbox/gpgx/Makefile b/waterbox/gpgx/Makefile index 06855b1617..70a5f04d7b 100644 --- a/waterbox/gpgx/Makefile +++ b/waterbox/gpgx/Makefile @@ -6,7 +6,7 @@ CCFLAGS:=-Icore -Iutil -Icore/m68k -Icore/z80 -Icore/input_hw \ -Wall -Werror=pointer-to-int-cast -Werror=int-to-pointer-cast -Werror=implicit-function-declaration \ -std=c99 -fomit-frame-pointer -fvisibility=hidden \ -DLSB_FIRST -DUSE_32BPP_RENDERING -DINLINE=static\ __inline__ \ - -O2#-mcmodel=large + -O3#-mcmodel=large TARGET = gpgx.exe diff --git a/waterbox/snes9x b/waterbox/snes9x index 737caf908b..3a358804d3 160000 --- a/waterbox/snes9x +++ b/waterbox/snes9x @@ -1 +1 @@ -Subproject commit 737caf908be47b868bf58080f87ce9f3592fce07 +Subproject commit 3a358804d34b9ed5b4bedd9266bcebf255d72cfe