pizza: use waterboxcore

This commit is contained in:
nattthebear 2017-06-18 16:05:33 -04:00
parent 5c71fc2e34
commit 278b29a840
5 changed files with 71 additions and 131 deletions

View File

@ -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();
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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));