BizHawk/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Pizza.cs

151 lines
4.0 KiB
C#

using BizHawk.Common;
using BizHawk.Common.BizInvoke;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Waterbox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
{
[CoreAttributes("Pizza Boy", "Davide Berra", true, false, "c7bc6ee376028b3766de8d7a02e60ab794841f45",
"https://github.com/davideberra/emu-pizza/", false)]
public class Pizza : IEmulator, IInputPollable, IVideoProvider, IGameboyCommon
{
private LibPizza _pizza;
private PeRunner _exe;
private bool _disposed;
[CoreConstructor("GB")]
public Pizza(byte[] rom, CoreComm comm)
{
CoreComm = comm;
ServiceProvider = new BasicServiceProvider(this);
_exe = new PeRunner(new PeRunnerOptions
{
Filename = "pizza.wbx",
Path = comm.CoreFileProvider.DllPath(),
SbrkHeapSizeKB = 2 * 1024,
InvisibleHeapSizeKB = 16 * 1024,
SealedHeapSizeKB = 16 * 1024,
PlainHeapSizeKB = 16 * 1024,
MmapHeapSizeKB = 32 * 1024
});
_pizza = BizInvoker.GetInvoker<LibPizza>(_exe, _exe);
if (!_pizza.Init(rom, rom.Length))
{
throw new InvalidOperationException("Core rejected the rom!");
}
}
/// <summary>
/// the nominal length of one frame
/// </summary>
private const int TICKSPERFRAME = 35112;
/// <summary>
/// number of ticks per second (GB, CGB)
/// </summary>
private const int TICKSPERSECOND = 2097152;
/// <summary>
/// number of ticks per second (SGB)
/// </summary>
private const int TICKSPERSECOND_SGB = 2147727;
private int _tickOverflow = 0;
private static LibPizza.Buttons GetButtons(IController c)
{
LibPizza.Buttons b = 0;
if (c.IsPressed("Up"))
b |= LibPizza.Buttons.UP;
if (c.IsPressed("Down"))
b |= LibPizza.Buttons.DOWN;
if (c.IsPressed("Left"))
b |= LibPizza.Buttons.LEFT;
if (c.IsPressed("Right"))
b |= LibPizza.Buttons.RIGHT;
if (c.IsPressed("A"))
b |= LibPizza.Buttons.A;
if (c.IsPressed("B"))
b |= LibPizza.Buttons.B;
if (c.IsPressed("Select"))
b |= LibPizza.Buttons.SELECT;
if (c.IsPressed("Start"))
b |= LibPizza.Buttons.START;
return b;
}
public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true)
{
fixed (int* vp = _videoBuffer)
{
var targetClocks = TICKSPERFRAME - _tickOverflow;
var frame = new LibPizza.FrameInfo
{
VideoBuffer = (IntPtr)vp,
Clocks = targetClocks,
Keys = GetButtons(controller)
};
_pizza.FrameAdvance(frame);
_tickOverflow = frame.Clocks - targetClocks;
Frame++;
}
}
public void Dispose()
{
if (!_disposed)
{
_exe.Dispose();
_exe = null;
_pizza = null;
_disposed = true;
}
}
public bool IsCGBMode() => _pizza.IsCGB();
public ControllerDefinition ControllerDefinition => BizHawk.Emulation.Cores.Nintendo.Gameboy.Gameboy.GbController;
public int Frame { get; private set; }
public int LagCount { get; set; }
public bool IsLagFrame { get; set; }
public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem();
public void ResetCounters()
{
Frame = 0;
}
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public string SystemId { get { return "GB"; } }
public bool DeterministicEmulation { get; private set; }
public CoreComm CoreComm { get; }
#region IVideoProvider
private int[] _videoBuffer = new int[160 * 144];
public int[] GetVideoBuffer()
{
return _videoBuffer;
}
public int VirtualWidth => 160;
public int VirtualHeight => 144;
public int BufferWidth => 160;
public int BufferHeight => 144;
public int VsyncNumerator { get; private set; } = TICKSPERSECOND;
public int VsyncDenominator { get; private set; } = TICKSPERFRAME;
public int BackgroundColor => unchecked((int)0xff000000);
#endregion
}
}