using System; using System.Collections.Generic; using System.Runtime.InteropServices; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi { class mupen64plusVideoApi { IntPtr GfxDll; /// /// Fills a provided buffer with the mupen64plus framebuffer /// /// The buffer to fill /// A pointer to a variable to fill with the width of the framebuffer /// A pointer to a variable to fill with the height of the framebuffer /// Which buffer to read: 0 = front, 1 = back [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void ReadScreen2(int[] framebuffer, ref int width, ref int height, int buffer); ReadScreen2 GFXReadScreen2; /// /// Gets the width and height of the mupen64plus framebuffer /// /// Use IntPtr.Zero /// A pointer to a variable to fill with the width of the framebuffer /// A pointer to a variable to fill with the height of the framebuffer /// Which buffer to read: 0 = front, 1 = back [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void ReadScreen2Res(IntPtr dummy, ref int width, ref int height, int buffer); ReadScreen2Res GFXReadScreen2Res; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate Int32 GetScreenTextureID(); GetScreenTextureID GFXGetScreenTextureID; public mupen64plusVideoApi(mupen64plusApi core, VideoPluginSettings settings) { string videoplugin; switch (settings.Plugin) { default: case PluginType.Rice: videoplugin = "mupen64plus-video-rice.dll"; break; case PluginType.Glide: videoplugin = "mupen64plus-video-glide64.dll"; break; case PluginType.GlideMk2: videoplugin = "mupen64plus-video-glide64mk2.dll"; break; case PluginType.GLideN64: videoplugin = "mupen64plus-video-GLideN64.dll"; break; } GfxDll = core.AttachPlugin(mupen64plusApi.m64p_plugin_type.M64PLUGIN_GFX, videoplugin); GFXReadScreen2 = mupen64plusApi.GetTypedDelegate(GfxDll, "ReadScreen2"); GFXReadScreen2Res = mupen64plusApi.GetTypedDelegate(GfxDll, "ReadScreen2"); var funcPtr = OSTailoredCode.LinkedLibManager.GetProcAddrOrNull(GfxDll, "GetScreenTextureID"); if (funcPtr != null) GFXGetScreenTextureID = (GetScreenTextureID) Marshal.GetDelegateForFunctionPointer(funcPtr.Value, typeof(GetScreenTextureID)); } public void GetScreenDimensions(ref int width, ref int height) { GFXReadScreen2Res(IntPtr.Zero, ref width, ref height, 0); } private int[] m64pBuffer = new int[0]; /// /// This function copies the frame buffer from mupen64plus /// public void Getm64pFrameBuffer(int[] buffer, ref int width, ref int height) { if (m64pBuffer.Length != width * height) m64pBuffer = new int[width * height]; // Actually get the frame buffer GFXReadScreen2(m64pBuffer, ref width, ref height, 0); // vflip int fromindex = width * (height - 1) * 4; int toindex = 0; for (int j = 0; j < height; j++) { Buffer.BlockCopy(m64pBuffer, fromindex, buffer, toindex, width * 4); fromindex -= width * 4; toindex += width * 4; } // opaque unsafe { fixed (int* ptr = &buffer[0]) { int l = buffer.Length; for (int i = 0; i < l; i++) { ptr[i] |= unchecked((int)0xff000000); } } } } } public class VideoPluginSettings { public PluginType Plugin; //public Dictionary IntParameters = new Dictionary(); //public Dictionary StringParameters = new Dictionary(); public Dictionary Parameters = new Dictionary(); public int Height; public int Width; public VideoPluginSettings(PluginType Plugin, int Width, int Height) { this.Plugin = Plugin; this.Width = Width; this.Height = Height; } } }