pizza: use waterboxcore
This commit is contained in:
parent
5c71fc2e34
commit
278b29a840
|
@ -1,4 +1,5 @@
|
|||
using BizHawk.Common.BizInvoke;
|
||||
using BizHawk.Emulation.Cores.Waterbox;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -8,11 +9,10 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
|
||||
{
|
||||
public abstract class LibPizza
|
||||
public abstract class LibPizza : LibWaterboxCore
|
||||
{
|
||||
private const CallingConvention CC = CallingConvention.Cdecl;
|
||||
[Flags]
|
||||
public enum Buttons : ushort
|
||||
public enum Buttons : int
|
||||
{
|
||||
A = 0x01,
|
||||
B = 0x02,
|
||||
|
@ -24,20 +24,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
|
|||
DOWN = 0x80
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FrameInfo
|
||||
public new class FrameInfo : LibWaterboxCore.FrameInfo
|
||||
{
|
||||
public IntPtr VideoBuffer;
|
||||
public IntPtr SoundBuffer;
|
||||
public int Clocks;
|
||||
public int Samples;
|
||||
public Buttons Keys;
|
||||
}
|
||||
|
||||
[BizImport(CC)]
|
||||
public abstract bool Init(byte[] rom, int romlen);
|
||||
[BizImport(CC)]
|
||||
public abstract void FrameAdvance([In,Out] FrameInfo frame);
|
||||
[BizImport(CC)]
|
||||
public abstract bool IsCGB();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,33 +12,42 @@ 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, ISoundProvider
|
||||
public class Pizza : WaterboxCore, IGameboyCommon
|
||||
{
|
||||
private LibPizza _pizza;
|
||||
private PeRunner _exe;
|
||||
private bool _disposed;
|
||||
|
||||
[CoreConstructor("GB")]
|
||||
public Pizza(byte[] rom, CoreComm comm)
|
||||
:base(comm, new Configuration
|
||||
{
|
||||
DefaultWidth = 160,
|
||||
DefaultHeight = 144,
|
||||
MaxWidth = 160,
|
||||
MaxHeight = 144,
|
||||
MaxSamples = 1024,
|
||||
SystemId = "GB",
|
||||
DefaultFpsNumerator = TICKSPERSECOND,
|
||||
DefaultFpsDenominator = TICKSPERFRAME
|
||||
})
|
||||
{
|
||||
CoreComm = comm;
|
||||
ServiceProvider = new BasicServiceProvider(this);
|
||||
ControllerDefinition = BizHawk.Emulation.Cores.Nintendo.Gameboy.Gameboy.GbController;
|
||||
|
||||
_exe = new PeRunner(new PeRunnerOptions
|
||||
_pizza = PreInit<LibPizza>(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, CallingConventionAdapters.Waterbox);
|
||||
|
||||
if (!_pizza.Init(rom, rom.Length))
|
||||
{
|
||||
throw new InvalidOperationException("Core rejected the rom!");
|
||||
}
|
||||
|
||||
PostInit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -56,8 +65,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
|
|||
/// </summary>
|
||||
private const int TICKSPERSECOND_SGB = 2147727;
|
||||
|
||||
private int _tickOverflow = 0;
|
||||
|
||||
private static LibPizza.Buttons GetButtons(IController c)
|
||||
{
|
||||
LibPizza.Buttons b = 0;
|
||||
|
@ -80,108 +87,23 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy
|
|||
return b;
|
||||
}
|
||||
|
||||
public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true)
|
||||
LibPizza.FrameInfo _tmp; // TODO: clean this up so it's not so hacky
|
||||
|
||||
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
|
||||
{
|
||||
fixed (int* vp = _videoBuffer)
|
||||
fixed (short* sp = _soundBuffer)
|
||||
return _tmp = new LibPizza.FrameInfo
|
||||
{
|
||||
var targetClocks = TICKSPERFRAME - _tickOverflow;
|
||||
|
||||
var frame = new LibPizza.FrameInfo
|
||||
{
|
||||
VideoBuffer = (IntPtr)vp,
|
||||
SoundBuffer = (IntPtr)sp,
|
||||
Clocks = targetClocks,
|
||||
Keys = GetButtons(controller)
|
||||
};
|
||||
|
||||
_pizza.FrameAdvance(frame);
|
||||
_tickOverflow = frame.Clocks - targetClocks;
|
||||
_numSamples = frame.Samples;
|
||||
Frame++;
|
||||
}
|
||||
Keys = GetButtons(controller)
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
protected override void FrameAdvancePost()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_exe.Dispose();
|
||||
_exe = null;
|
||||
_pizza = null;
|
||||
_disposed = true;
|
||||
}
|
||||
Console.WriteLine(_tmp.Cycles);
|
||||
_tmp = null;
|
||||
}
|
||||
|
||||
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 ISoundProvider
|
||||
|
||||
private short[] _soundBuffer = new short[2048];
|
||||
private int _numSamples;
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = _soundBuffer;
|
||||
nsamp = _numSamples;
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CanProvideAsync => false;
|
||||
|
||||
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
|
||||
|
||||
#endregion
|
||||
|
||||
#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
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/* button states */
|
||||
static uint16_t input_keys;
|
||||
static uint8_t input_keys;
|
||||
|
||||
void input_set_keys(uint16_t keys)
|
||||
void input_set_keys(uint8_t keys)
|
||||
{
|
||||
// 7......0
|
||||
// DULRSsBA
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
|
||||
/* prototypes */
|
||||
uint8_t input_get_keys(uint8_t line);
|
||||
void input_set_keys(uint16_t keys);
|
||||
void input_set_keys(uint8_t keys);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <emulibc.h>
|
||||
#include "../emulibc/emulibc.h"
|
||||
#include "../emulibc/waterboxcore.h"
|
||||
#include <string.h>
|
||||
|
||||
#define EXPORT ECL_EXPORT
|
||||
|
@ -79,23 +80,34 @@ EXPORT int Init(const void *rom, int romlen)
|
|||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t* vbuff;
|
||||
int16_t* sbuff;
|
||||
int32_t clocks; // desired(in) actual(out) time to run; 2MHZ
|
||||
int32_t samples; // actual number of samples produced
|
||||
uint16_t keys; // keypad input
|
||||
} frameinfo_t;
|
||||
uint32_t* VideoBuffer;
|
||||
int16_t* SoundBuffer;
|
||||
int64_t Cycles;
|
||||
int32_t Width;
|
||||
int32_t Height;
|
||||
int32_t Samples;
|
||||
int32_t Lagged;
|
||||
uint32_t Keys;
|
||||
} MyFrameInfo;
|
||||
|
||||
static uint32_t* current_vbuff;
|
||||
static uint64_t overflow;
|
||||
|
||||
EXPORT void FrameAdvance(frameinfo_t* frame)
|
||||
EXPORT void FrameAdvance(MyFrameInfo* frame)
|
||||
{
|
||||
input_set_keys(frame->keys);
|
||||
input_set_keys(frame->Keys);
|
||||
current_vbuff = frame->VideoBuffer;
|
||||
|
||||
uint64_t current = cycles.sampleclock;
|
||||
current_vbuff = frame->vbuff;
|
||||
gameboy_run(current + frame->clocks);
|
||||
frame->clocks = cycles.sampleclock - current;
|
||||
frame->samples = sound_output_read(frame->sbuff);
|
||||
uint64_t target = current + 35112 - overflow;
|
||||
gameboy_run(target);
|
||||
uint64_t elapsed = cycles.sampleclock - current;
|
||||
frame->Cycles = elapsed;
|
||||
overflow = cycles.sampleclock - target;
|
||||
|
||||
frame->Samples = sound_output_read(frame->SoundBuffer);
|
||||
frame->Width = 160;
|
||||
frame->Height = 144;
|
||||
current_vbuff = NULL;
|
||||
}
|
||||
|
||||
|
@ -104,6 +116,19 @@ EXPORT int IsCGB(void)
|
|||
return global_cgb;
|
||||
}
|
||||
|
||||
EXPORT void SetInputCallback(void (*callback)(void))
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
EXPORT void GetMemoryAreas(MemoryArea* m)
|
||||
{
|
||||
m[0].Data = mmu.memory;
|
||||
m[0].Name = "Fake System Bus";
|
||||
m[0].Size = 0x10000;
|
||||
m[0].Flags = MEMORYAREA_FLAGS_PRIMARY | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1;
|
||||
}
|
||||
|
||||
void frame_cb()
|
||||
{
|
||||
memcpy(current_vbuff, gpu.frame_buffer, sizeof(gpu.frame_buffer));
|
||||
|
|
Loading…
Reference in New Issue