Refactored some N64 code
This commit is contained in:
parent
6f05084b2c
commit
b79bcaf2d0
|
@ -225,7 +225,9 @@
|
||||||
<Compile Include="Consoles\Nintendo\GBA\Meteor.cs" />
|
<Compile Include="Consoles\Nintendo\GBA\Meteor.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\N64\mupen64plusApi.cs" />
|
<Compile Include="Consoles\Nintendo\N64\mupen64plusApi.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\N64\N64.cs" />
|
<Compile Include="Consoles\Nintendo\N64\N64.cs" />
|
||||||
|
<Compile Include="Consoles\Nintendo\N64\N64Audio.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\N64\N64SyncSettings.cs" />
|
<Compile Include="Consoles\Nintendo\N64\N64SyncSettings.cs" />
|
||||||
|
<Compile Include="Consoles\Nintendo\N64\N64VideoProvider.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\NES\APU.cs" />
|
<Compile Include="Consoles\Nintendo\NES\APU.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\NES\BoardSystem.cs" />
|
<Compile Include="Consoles\Nintendo\NES\BoardSystem.cs" />
|
||||||
<Compile Include="Consoles\Nintendo\NES\Boards\AVE-NINA.cs" />
|
<Compile Include="Consoles\Nintendo\NES\Boards\AVE-NINA.cs" />
|
||||||
|
|
|
@ -10,7 +10,7 @@ using BizHawk.Emulation.Cores.Consoles.Nintendo.N64;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Nintendo.N64
|
namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
{
|
{
|
||||||
public class N64 : IEmulator, IVideoProvider
|
public class N64 : IEmulator
|
||||||
{
|
{
|
||||||
public List<KeyValuePair<string, int>> GetCpuFlagsAndRegisters()
|
public List<KeyValuePair<string, int>> GetCpuFlagsAndRegisters()
|
||||||
{
|
{
|
||||||
|
@ -64,24 +64,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
public string BoardName { get { return null; } }
|
public string BoardName { get { return null; } }
|
||||||
|
|
||||||
public CoreComm CoreComm { get; private set; }
|
public CoreComm CoreComm { get; private set; }
|
||||||
public byte[] rom;
|
|
||||||
public GameInfo game;
|
|
||||||
|
|
||||||
public IVideoProvider VideoProvider { get { return this; } }
|
private N64VideoProvider videoProvider;
|
||||||
public int[] frameBuffer;// = new int[800 * 600];
|
public IVideoProvider VideoProvider { get { return videoProvider; } }
|
||||||
public int[] GetVideoBuffer() { return frameBuffer; }
|
|
||||||
public int VirtualWidth { get; set; }
|
|
||||||
public int BufferWidth { get; set; }
|
|
||||||
public int BufferHeight { get; set; }
|
|
||||||
public int BackgroundColor { get { return 0; } }
|
|
||||||
|
|
||||||
private DisplayType _display_type = DisplayType.NTSC;
|
private DisplayType _display_type = DisplayType.NTSC;
|
||||||
public DisplayType DisplayType { get { return _display_type; } }
|
public DisplayType DisplayType { get { return _display_type; } }
|
||||||
|
|
||||||
public SpeexResampler resampler;
|
private N64Audio audioProvider;
|
||||||
|
|
||||||
public ISoundProvider SoundProvider { get { return null; } }
|
public ISoundProvider SoundProvider { get { return null; } }
|
||||||
public ISyncSoundProvider SyncSoundProvider { get { return resampler; } }
|
public ISyncSoundProvider SyncSoundProvider { get { return audioProvider.Resampler; } }
|
||||||
public bool StartAsyncSound() { return false; }
|
public bool StartAsyncSound() { return false; }
|
||||||
public void EndAsyncSound() { }
|
public void EndAsyncSound() { }
|
||||||
|
|
||||||
|
@ -118,18 +110,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public int Frame { get; set; }
|
public int Frame { get; private set; }
|
||||||
public int LagCount { get; set; }
|
public int LagCount { get; set; }
|
||||||
public bool IsLagFrame { get; set; }
|
public bool IsLagFrame { get; private set; }
|
||||||
public void ResetCounters()
|
public void ResetCounters()
|
||||||
{
|
{
|
||||||
Frame = 0;
|
Frame = 0;
|
||||||
LagCount = 0;
|
LagCount = 0;
|
||||||
IsLagFrame = false;
|
IsLagFrame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FrameAdvance(bool render, bool rendersound)
|
public void FrameAdvance(bool render, bool rendersound)
|
||||||
{
|
{
|
||||||
RefreshMemoryCallbacks();
|
audioProvider.RenderSound = rendersound;
|
||||||
|
|
||||||
if (Controller["Reset"])
|
if (Controller["Reset"])
|
||||||
{
|
{
|
||||||
|
@ -142,10 +135,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
|
|
||||||
IsLagFrame = true;
|
IsLagFrame = true;
|
||||||
api.frame_advance();
|
api.frame_advance();
|
||||||
|
|
||||||
if (IsLagFrame) LagCount++;
|
if (IsLagFrame) LagCount++;
|
||||||
Frame++;
|
Frame++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Translates controller inputs from EmuHawk and
|
||||||
|
/// shoves them into mupen64plus
|
||||||
|
/// </summary>
|
||||||
public void setControllers()
|
public void setControllers()
|
||||||
{
|
{
|
||||||
CoreComm.InputCallback.Call();
|
CoreComm.InputCallback.Call();
|
||||||
|
@ -171,6 +169,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read all buttons from a controller and translate them
|
||||||
|
/// into a form the N64 understands
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="num">Number of controller to translate</param>
|
||||||
|
/// <returns>Bitlist of pressed buttons</returns>
|
||||||
public int ReadController(int num)
|
public int ReadController(int num)
|
||||||
{
|
{
|
||||||
int buttons = 0;
|
int buttons = 0;
|
||||||
|
@ -193,7 +197,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DeterministicEmulation { get; set; }
|
public bool DeterministicEmulation { get { return false; } }
|
||||||
|
|
||||||
public byte[] ReadSaveRam()
|
public byte[] ReadSaveRam()
|
||||||
{
|
{
|
||||||
|
@ -212,12 +216,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
|
|
||||||
public bool SaveRamModified { get { return true; } set { } }
|
public bool SaveRamModified { get { return true; } set { } }
|
||||||
|
|
||||||
void SyncState(Serializer ser)
|
|
||||||
{
|
|
||||||
ser.BeginSection("N64");
|
|
||||||
ser.EndSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
// these next 5 functions are all exact copy paste from gambatte.
|
// these next 5 functions are all exact copy paste from gambatte.
|
||||||
// if something's wrong here, it's probably wrong there too
|
// if something's wrong here, it's probably wrong there too
|
||||||
|
|
||||||
|
@ -321,11 +319,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
// we RefreshMemoryCallbacks() after the triggers in case the trigger turns itself off at that point
|
// we RefreshMemoryCallbacks() after the triggers in case the trigger turns itself off at that point
|
||||||
|
|
||||||
if (mcs.HasReads)
|
if (mcs.HasReads)
|
||||||
readcb = delegate(uint addr) { mcs.CallRead(addr); RefreshMemoryCallbacks(); };
|
readcb = delegate(uint addr) { mcs.CallRead(addr); };
|
||||||
else
|
else
|
||||||
readcb = null;
|
readcb = null;
|
||||||
if (mcs.HasWrites)
|
if (mcs.HasWrites)
|
||||||
writecb = delegate(uint addr) { mcs.CallWrite(addr); RefreshMemoryCallbacks(); };
|
writecb = delegate(uint addr) { mcs.CallWrite(addr); };
|
||||||
else
|
else
|
||||||
writecb = null;
|
writecb = null;
|
||||||
|
|
||||||
|
@ -394,11 +392,21 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
videoProvider.Dispose();
|
||||||
|
audioProvider.Dispose();
|
||||||
api.Dispose();
|
api.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
mupen64plusApi api;
|
// mupen64plus DLL Api
|
||||||
|
private mupen64plusApi api;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create mupen64plus Emulator
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="comm">Core communication object</param>
|
||||||
|
/// <param name="game">Game information of game to load</param>
|
||||||
|
/// <param name="rom">Rom that should be loaded</param>
|
||||||
|
/// <param name="SyncSettings">N64SyncSettings object</param>
|
||||||
public N64(CoreComm comm, GameInfo game, byte[] rom, object SyncSettings)
|
public N64(CoreComm comm, GameInfo game, byte[] rom, object SyncSettings)
|
||||||
{
|
{
|
||||||
int SaveType = 0;
|
int SaveType = 0;
|
||||||
|
@ -406,8 +414,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
SaveType = 1;
|
SaveType = 1;
|
||||||
|
|
||||||
CoreComm = comm;
|
CoreComm = comm;
|
||||||
this.rom = rom;
|
|
||||||
this.game = game;
|
|
||||||
|
|
||||||
this.SyncSettings = (N64SyncSettings)SyncSettings ?? new N64SyncSettings();
|
this.SyncSettings = (N64SyncSettings)SyncSettings ?? new N64SyncSettings();
|
||||||
|
|
||||||
|
@ -439,7 +445,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
api = new mupen64plusApi(this, rom, this.SyncSettings.GetVPS(game), SaveType);
|
api = new mupen64plusApi(this, rom, this.SyncSettings.GetVPS(game), SaveType);
|
||||||
api.SetM64PInputCallback(new mupen64plusApi.InputCallback(setControllers));
|
api.SetM64PInputCallback(new mupen64plusApi.InputCallback(setControllers));
|
||||||
|
|
||||||
|
audioProvider = new N64Audio(api);
|
||||||
|
videoProvider = new N64VideoProvider(api);
|
||||||
|
api.FrameFinished += videoProvider.DoVideoFrame;
|
||||||
|
api.VInterrupt += audioProvider.DoAudioFrame;
|
||||||
|
|
||||||
InitMemoryDomains();
|
InitMemoryDomains();
|
||||||
|
RefreshMemoryCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
N64SyncSettings SyncSettings;
|
N64SyncSettings SyncSettings;
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
|
{
|
||||||
|
class N64Audio : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// mupen64 DLL Api
|
||||||
|
/// </summary>
|
||||||
|
private mupen64plusApi api;
|
||||||
|
/// <summary>
|
||||||
|
/// Buffer for audio data
|
||||||
|
/// </summary>
|
||||||
|
private short[] audioBuffer = new short[0];
|
||||||
|
private uint _samplingRate = 0;
|
||||||
|
/// <summary>
|
||||||
|
/// Currently active sampling rate
|
||||||
|
/// </summary>
|
||||||
|
public uint SamplingRate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _samplingRate;
|
||||||
|
}
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
_samplingRate = value;
|
||||||
|
Resampler.ChangeRate(_samplingRate, 44100, _samplingRate, 44100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Resampler for audio output
|
||||||
|
/// </summary>
|
||||||
|
public SpeexResampler Resampler { get; private set; }
|
||||||
|
public bool RenderSound { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a N64 Audio subsystem
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">Mupen64 api which is used for fetching sound</param>
|
||||||
|
public N64Audio(mupen64plusApi api)
|
||||||
|
{
|
||||||
|
this.api = api;
|
||||||
|
_samplingRate = api.GetSamplingRate();
|
||||||
|
Resampler = new SpeexResampler(6, SamplingRate, 44100,
|
||||||
|
SamplingRate, 44100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches the audio buffer from mupen64plus and pushes it into the
|
||||||
|
/// Resampler for audio output
|
||||||
|
/// </summary>
|
||||||
|
public void DoAudioFrame()
|
||||||
|
{
|
||||||
|
uint m64pSamplingRate = api.GetSamplingRate();
|
||||||
|
if (m64pSamplingRate != SamplingRate)
|
||||||
|
SamplingRate = m64pSamplingRate;
|
||||||
|
|
||||||
|
int audioBufferSize = api.GetAudioBufferSize();
|
||||||
|
if (audioBuffer.Length < audioBufferSize)
|
||||||
|
audioBuffer = new short[audioBufferSize];
|
||||||
|
|
||||||
|
if (audioBufferSize > 0)
|
||||||
|
{
|
||||||
|
api.GetAudioBuffer(audioBuffer);
|
||||||
|
if (RenderSound)
|
||||||
|
Resampler.EnqueueSamples(audioBuffer, audioBufferSize / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if(Resampler != null)
|
||||||
|
Resampler.Dispose();
|
||||||
|
Resampler = null;
|
||||||
|
// Api is disposed by N64
|
||||||
|
api = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
|
{
|
||||||
|
class N64VideoProvider : IVideoProvider, IDisposable
|
||||||
|
{
|
||||||
|
private int[] frameBuffer;
|
||||||
|
private mupen64plusApi api;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates N64 Video system with mupen64plus backend
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">mupen64plus DLL that is used</param>
|
||||||
|
public N64VideoProvider(mupen64plusApi api)
|
||||||
|
{
|
||||||
|
this.api = api;
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
api.GetScreenDimensions(ref width, ref height);
|
||||||
|
SetBufferSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] GetVideoBuffer()
|
||||||
|
{
|
||||||
|
return frameBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int VirtualWidth { get { return BufferWidth; } }
|
||||||
|
public int BufferWidth { get; private set; }
|
||||||
|
public int BufferHeight { get; private set; }
|
||||||
|
public int BackgroundColor { get { return 0; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches current frame buffer from mupen64
|
||||||
|
/// </summary>
|
||||||
|
public void DoVideoFrame()
|
||||||
|
{
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
api.GetScreenDimensions(ref width, ref height);
|
||||||
|
if (width != BufferWidth || height != BufferHeight)
|
||||||
|
{
|
||||||
|
SetBufferSize(width, height);
|
||||||
|
}
|
||||||
|
api.Getm64pFrameBuffer(frameBuffer, ref width, ref height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a new width and height for frame buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="width">New width in pixels</param>
|
||||||
|
/// <param name="height">New height in pixels</param>
|
||||||
|
private void SetBufferSize(int width, int height)
|
||||||
|
{
|
||||||
|
BufferHeight = height;
|
||||||
|
BufferWidth = width;
|
||||||
|
frameBuffer = new int[width * height];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// api is disposed by N64
|
||||||
|
api = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,14 +12,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
{
|
{
|
||||||
public class mupen64plusApi : IDisposable
|
public class mupen64plusApi : IDisposable
|
||||||
{
|
{
|
||||||
|
// Only left in because api needs to know the number of frames passed
|
||||||
|
// because of a bug
|
||||||
private readonly N64 bizhawkCore;
|
private readonly N64 bizhawkCore;
|
||||||
static mupen64plusApi AttachedCore = null;
|
static mupen64plusApi AttachedCore = null;
|
||||||
|
|
||||||
bool disposed = false;
|
bool disposed = false;
|
||||||
|
|
||||||
uint m64pSamplingRate;
|
|
||||||
short[] m64pAudioBuffer = new short[2];
|
|
||||||
|
|
||||||
Thread m64pEmulator;
|
Thread m64pEmulator;
|
||||||
|
|
||||||
AutoResetEvent m64pFrameComplete = new AutoResetEvent(false);
|
AutoResetEvent m64pFrameComplete = new AutoResetEvent(false);
|
||||||
|
@ -439,12 +438,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
|
|
||||||
public mupen64plusApi(N64 bizhawkCore, byte[] rom, VideoPluginSettings video_settings, int SaveType)
|
public mupen64plusApi(N64 bizhawkCore, byte[] rom, VideoPluginSettings video_settings, int SaveType)
|
||||||
{
|
{
|
||||||
|
// There can only be one core (otherwise breaks mupen64plus)
|
||||||
if (AttachedCore != null)
|
if (AttachedCore != null)
|
||||||
{
|
{
|
||||||
AttachedCore.Dispose();
|
AttachedCore.Dispose();
|
||||||
AttachedCore = null;
|
AttachedCore = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bizhawkCore = bizhawkCore;
|
this.bizhawkCore = bizhawkCore;
|
||||||
|
|
||||||
string VidDllName;
|
string VidDllName;
|
||||||
|
@ -485,7 +484,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
connectFunctionPointers();
|
connectFunctionPointers();
|
||||||
|
|
||||||
// Start up the core
|
// Start up the core
|
||||||
m64p_error result = m64pCoreStartup(0x20001, "", "", "Core", (IntPtr foo, int level, string Message) => { }, "", IntPtr.Zero);
|
m64p_error result = m64pCoreStartup(0x20001, "", "", "Core",
|
||||||
|
(IntPtr foo, int level, string Message) => { },
|
||||||
|
"", IntPtr.Zero);
|
||||||
|
|
||||||
// Set the savetype if needed
|
// Set the savetype if needed
|
||||||
if (SaveType != 0)
|
if (SaveType != 0)
|
||||||
|
@ -498,9 +499,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
// Pass the rom to the core
|
// Pass the rom to the core
|
||||||
result = m64pCoreDoCommandByteArray(m64p_command.M64CMD_ROM_OPEN, rom.Length, rom);
|
result = m64pCoreDoCommandByteArray(m64p_command.M64CMD_ROM_OPEN, rom.Length, rom);
|
||||||
|
|
||||||
// Resize the video to the size in bizhawk's settings
|
|
||||||
SetVideoSize(video_settings.Width, video_settings.Height);
|
|
||||||
|
|
||||||
// Open the general video settings section in the config system
|
// Open the general video settings section in the config system
|
||||||
IntPtr video_section = IntPtr.Zero;
|
IntPtr video_section = IntPtr.Zero;
|
||||||
m64pConfigOpenSection("Video-General", ref video_section);
|
m64pConfigOpenSection("Video-General", ref video_section);
|
||||||
|
@ -511,6 +509,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
|
|
||||||
set_video_parameters(video_settings);
|
set_video_parameters(video_settings);
|
||||||
|
|
||||||
|
// Order of plugin loading is important, do not change!
|
||||||
// Set up and connect the graphics plugin
|
// Set up and connect the graphics plugin
|
||||||
result = GfxPluginStartup(CoreDll, "Video", (IntPtr foo, int level, string Message) => { });
|
result = GfxPluginStartup(CoreDll, "Video", (IntPtr foo, int level, string Message) => { });
|
||||||
result = m64pCoreAttachPlugin(m64p_plugin_type.M64PLUGIN_GFX, GfxDll);
|
result = m64pCoreAttachPlugin(m64p_plugin_type.M64PLUGIN_GFX, GfxDll);
|
||||||
|
@ -520,23 +519,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
result = m64pCoreAttachPlugin(m64p_plugin_type.M64PLUGIN_AUDIO, AudDll);
|
result = m64pCoreAttachPlugin(m64p_plugin_type.M64PLUGIN_AUDIO, AudDll);
|
||||||
|
|
||||||
// Set up our input plugin
|
// Set up our input plugin
|
||||||
result = AudPluginStartup(CoreDll, "Input", (IntPtr foo, int level, string Message) => { });
|
result = AudPluginStartup(CoreDll, "Input",
|
||||||
|
(IntPtr foo, int level, string Message) => { });
|
||||||
result = m64pCoreAttachPlugin(m64p_plugin_type.M64PLUGIN_INPUT, InpDll);
|
result = m64pCoreAttachPlugin(m64p_plugin_type.M64PLUGIN_INPUT, InpDll);
|
||||||
|
|
||||||
// Set up and connect the RSP plugin
|
// Set up and connect the RSP plugin
|
||||||
result = RspPluginStartup(CoreDll, "RSP", (IntPtr foo, int level, string Message) => { });
|
result = RspPluginStartup(CoreDll, "RSP", (IntPtr foo, int level, string Message) => { });
|
||||||
result = m64pCoreAttachPlugin(m64p_plugin_type.M64PLUGIN_RSP, RspDll);
|
result = m64pCoreAttachPlugin(m64p_plugin_type.M64PLUGIN_RSP, RspDll);
|
||||||
|
|
||||||
// Set up the frame callback function
|
|
||||||
m64pFrameCallback = new FrameCallback(Getm64pFrameBuffer);
|
|
||||||
result = m64pCoreDoCommandFrameCallback(m64p_command.M64CMD_SET_FRAME_CALLBACK, 0, m64pFrameCallback);
|
|
||||||
|
|
||||||
// Set up the VI callback function
|
|
||||||
m64pVICallback = new VICallback(VI);
|
|
||||||
result = m64pCoreDoCommandVICallback(m64p_command.M64CMD_SET_VI_CALLBACK, 0, m64pVICallback);
|
|
||||||
|
|
||||||
InitSaveram();
|
InitSaveram();
|
||||||
|
|
||||||
|
// Initialize event invoker
|
||||||
|
m64pFrameCallback = new FrameCallback(FireFrameFinishedEvent);
|
||||||
|
result = m64pCoreDoCommandFrameCallback(m64p_command.M64CMD_SET_FRAME_CALLBACK, 0, m64pFrameCallback);
|
||||||
|
m64pVICallback = new VICallback(FireVIEvent);
|
||||||
|
result = m64pCoreDoCommandVICallback(m64p_command.M64CMD_SET_VI_CALLBACK, 0, m64pVICallback);
|
||||||
|
|
||||||
// Start the emulator in another thread
|
// Start the emulator in another thread
|
||||||
m64pEmulator = new Thread(ExecuteEmulator);
|
m64pEmulator = new Thread(ExecuteEmulator);
|
||||||
m64pEmulator.Start();
|
m64pEmulator.Start();
|
||||||
|
@ -544,14 +542,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
// Wait for the core to boot up
|
// Wait for the core to boot up
|
||||||
m64pStartupComplete.WaitOne();
|
m64pStartupComplete.WaitOne();
|
||||||
|
|
||||||
// Set up the resampler
|
|
||||||
m64pSamplingRate = (uint)AudGetAudioRate();
|
|
||||||
bizhawkCore.resampler = new SpeexResampler(6, m64pSamplingRate, 44100, m64pSamplingRate, 44100, null, null);
|
|
||||||
|
|
||||||
AttachedCore = this;
|
AttachedCore = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile bool emulator_running = false;
|
volatile bool emulator_running = false;
|
||||||
|
/// <summary>
|
||||||
|
/// Starts execution of mupen64plus
|
||||||
|
/// Does not return until the emulator stops
|
||||||
|
/// </summary>
|
||||||
public void ExecuteEmulator()
|
public void ExecuteEmulator()
|
||||||
{
|
{
|
||||||
emulator_running = true;
|
emulator_running = true;
|
||||||
|
@ -611,16 +609,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
RspPluginShutdown = (PluginShutdown)Marshal.GetDelegateForFunctionPointer(GetProcAddress(RspDll, "PluginShutdown"), typeof(PluginShutdown));
|
RspPluginShutdown = (PluginShutdown)Marshal.GetDelegateForFunctionPointer(GetProcAddress(RspDll, "PluginShutdown"), typeof(PluginShutdown));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVideoSize(int vidX, int vidY)
|
/// <summary>
|
||||||
{
|
/// Puts plugin settings of EmuHawk into mupen64plus
|
||||||
bizhawkCore.VirtualWidth = vidX;
|
/// </summary>
|
||||||
bizhawkCore.BufferWidth = vidX;
|
/// <param name="video_settings">Settings to put into mupen64plus</param>
|
||||||
bizhawkCore.BufferHeight = vidY;
|
|
||||||
|
|
||||||
bizhawkCore.frameBuffer = new int[vidX * vidY];
|
|
||||||
m64p_FrameBuffer = new int[vidX * vidY];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set_video_parameters(VideoPluginSettings video_settings)
|
public void set_video_parameters(VideoPluginSettings video_settings)
|
||||||
{
|
{
|
||||||
IntPtr video_plugin_section = IntPtr.Zero;
|
IntPtr video_plugin_section = IntPtr.Zero;
|
||||||
|
@ -656,45 +648,34 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int[] m64pBuffer = new int[0];
|
||||||
int[] m64p_FrameBuffer;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This function will be used as the frame callback. It pulls the framebuffer from mupen64plus
|
/// This function copies the frame buffer from mupen64plus
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Getm64pFrameBuffer()
|
public void Getm64pFrameBuffer(int[] buffer, ref int width, ref int height)
|
||||||
{
|
{
|
||||||
int width = 0;
|
if(m64pBuffer.Length != width * height)
|
||||||
int height = 0;
|
m64pBuffer = new int[width * height];
|
||||||
|
|
||||||
// Get the size of the frame buffer
|
|
||||||
GFXReadScreen2Res(IntPtr.Zero, ref width, ref height, 0);
|
|
||||||
|
|
||||||
// If it's not the same size as the current one, change the sizes
|
|
||||||
if (width != bizhawkCore.BufferWidth || height != bizhawkCore.BufferHeight)
|
|
||||||
{
|
|
||||||
SetVideoSize(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually get the frame buffer
|
// Actually get the frame buffer
|
||||||
GFXReadScreen2(m64p_FrameBuffer, ref width, ref height, 0);
|
GFXReadScreen2(m64pBuffer, ref width, ref height, 0);
|
||||||
|
|
||||||
// vflip
|
// vflip
|
||||||
int fromindex = bizhawkCore.BufferWidth * (bizhawkCore.BufferHeight - 1) * 4;
|
int fromindex = width * (height - 1) * 4;
|
||||||
int toindex = 0;
|
int toindex = 0;
|
||||||
for (int j = 0; j < bizhawkCore.BufferHeight; j++)
|
|
||||||
|
for (int j = 0; j < height; j++)
|
||||||
{
|
{
|
||||||
Buffer.BlockCopy(m64p_FrameBuffer, fromindex, bizhawkCore.frameBuffer, toindex, bizhawkCore.BufferWidth * 4);
|
Buffer.BlockCopy(m64pBuffer, fromindex, buffer, toindex, width * 4);
|
||||||
fromindex -= bizhawkCore.BufferWidth * 4;
|
fromindex -= width * 4;
|
||||||
toindex += bizhawkCore.BufferWidth * 4;
|
toindex += width * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// opaque
|
// opaque
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
fixed (int* ptr = &bizhawkCore.frameBuffer[0])
|
fixed (int* ptr = &buffer[0])
|
||||||
{
|
{
|
||||||
int l = bizhawkCore.frameBuffer.Length;
|
int l = buffer.Length;
|
||||||
for (int i = 0; i < l; i++)
|
for (int i = 0; i < l; i++)
|
||||||
{
|
{
|
||||||
ptr[i] |= unchecked((int)0xff000000);
|
ptr[i] |= unchecked((int)0xff000000);
|
||||||
|
@ -703,32 +684,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This function will be used as the VI callback. It checks the audio rate and updates the resampler if necessary.
|
|
||||||
/// It then polls the audio buffer for samples. It then marks the frame as complete.
|
|
||||||
/// </summary>
|
|
||||||
public void VI()
|
|
||||||
{
|
|
||||||
uint s = (uint)AudGetAudioRate();
|
|
||||||
if (s != m64pSamplingRate)
|
|
||||||
{
|
|
||||||
m64pSamplingRate = s;
|
|
||||||
bizhawkCore.resampler.ChangeRate(s, 44100, s, 44100);
|
|
||||||
//Console.WriteLine("N64 ARate Change {0}", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
int m64pAudioBufferSize = AudGetBufferSize();
|
|
||||||
if (m64pAudioBuffer.Length < m64pAudioBufferSize)
|
|
||||||
m64pAudioBuffer = new short[m64pAudioBufferSize];
|
|
||||||
|
|
||||||
if (m64pAudioBufferSize > 0)
|
|
||||||
{
|
|
||||||
AudReadAudioBuffer(m64pAudioBuffer);
|
|
||||||
bizhawkCore.resampler.EnqueueSamples(m64pAudioBuffer, m64pAudioBufferSize / 2);
|
|
||||||
}
|
|
||||||
m64pFrameComplete.Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int get_memory_size(N64_MEMORY id)
|
public int get_memory_size(N64_MEMORY id)
|
||||||
{
|
{
|
||||||
return m64pMemGetSize(id);
|
return m64pMemGetSize(id);
|
||||||
|
@ -777,6 +732,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
// When using the dynamic recompiler if a state is loaded too early some pointers are not set up yet, so mupen
|
// When using the dynamic recompiler if a state is loaded too early some pointers are not set up yet, so mupen
|
||||||
// tries to access null pointers and the emulator crashes. It seems like it takes 2 frames to fully set up the recompiler,
|
// tries to access null pointers and the emulator crashes. It seems like it takes 2 frames to fully set up the recompiler,
|
||||||
// so if two frames haven't been run yet, run them, then load the state.
|
// so if two frames haven't been run yet, run them, then load the state.
|
||||||
|
|
||||||
if (bizhawkCore.Frame < 2)
|
if (bizhawkCore.Frame < 2)
|
||||||
{
|
{
|
||||||
frame_advance();
|
frame_advance();
|
||||||
|
@ -851,9 +807,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
// Backup the saveram in case bizhawk wants to get at is after we've freed the libraries
|
// Backup the saveram in case bizhawk wants to get at is after we've freed the libraries
|
||||||
saveram_backup = SaveSaveram();
|
saveram_backup = SaveSaveram();
|
||||||
|
|
||||||
bizhawkCore.resampler.Dispose();
|
|
||||||
bizhawkCore.resampler = null;
|
|
||||||
|
|
||||||
m64pCoreDetachPlugin(m64p_plugin_type.M64PLUGIN_GFX);
|
m64pCoreDetachPlugin(m64p_plugin_type.M64PLUGIN_GFX);
|
||||||
m64pCoreDetachPlugin(m64p_plugin_type.M64PLUGIN_AUDIO);
|
m64pCoreDetachPlugin(m64p_plugin_type.M64PLUGIN_AUDIO);
|
||||||
m64pCoreDetachPlugin(m64p_plugin_type.M64PLUGIN_INPUT);
|
m64pCoreDetachPlugin(m64p_plugin_type.M64PLUGIN_INPUT);
|
||||||
|
@ -878,6 +831,49 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||||
disposed = true;
|
disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GetScreenDimensions(ref int width, ref int height)
|
||||||
|
{
|
||||||
|
GFXReadScreen2Res(IntPtr.Zero, ref width, ref height, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint GetSamplingRate()
|
||||||
|
{
|
||||||
|
return (uint)AudGetAudioRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetAudioBufferSize()
|
||||||
|
{
|
||||||
|
return AudGetBufferSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetAudioBuffer(short[] buffer)
|
||||||
|
{
|
||||||
|
AudReadAudioBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action FrameFinished;
|
||||||
|
public event Action VInterrupt;
|
||||||
|
|
||||||
|
private void FireFrameFinishedEvent()
|
||||||
|
{
|
||||||
|
// Execute Frame Callback functions
|
||||||
|
if (FrameFinished != null)
|
||||||
|
FrameFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireVIEvent()
|
||||||
|
{
|
||||||
|
// Execute VI Callback functions
|
||||||
|
if (VInterrupt != null)
|
||||||
|
VInterrupt();
|
||||||
|
m64pFrameComplete.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CompletedFrameCallback()
|
||||||
|
{
|
||||||
|
m64pFrameComplete.Set();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VideoPluginSettings
|
public class VideoPluginSettings
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /y $(OutDir)mupen64plus.dll $(TargetDir)..\..\..\..\..\output\dll\</Command>
|
<Command>xcopy /y "$(OutDir)mupen64plus.dll" "$(TargetDir)..\..\..\..\..\output\dll\"</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue