wire up sameboy's rumble

This commit is contained in:
CasualPokePlayer 2022-07-25 00:10:46 -07:00
parent ea5e8b70d3
commit d84da4ec4b
9 changed files with 50 additions and 12 deletions

Binary file not shown.

Binary file not shown.

View File

@ -182,7 +182,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
_cdCallback = new LibGambatte.CDCallback(CDCallbackProc); _cdCallback = new LibGambatte.CDCallback(CDCallbackProc);
ControllerDefinition = CreateControllerDefinition(sgb: IsSgb, sub: _syncSettings.FrameLength is GambatteSyncSettings.FrameLengthType.UserDefinedFrames, tilt: false); ControllerDefinition = CreateControllerDefinition(sgb: IsSgb, sub: _syncSettings.FrameLength is GambatteSyncSettings.FrameLengthType.UserDefinedFrames, tilt: false, rumble: false);
NewSaveCoreSetBuff(); NewSaveCoreSetBuff();
} }
@ -247,7 +247,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
public long CycleCount => (long)_cycleCount; public long CycleCount => (long)_cycleCount;
public double ClockRate => TICKSPERSECOND; public double ClockRate => TICKSPERSECOND;
public static ControllerDefinition CreateControllerDefinition(bool sgb, bool sub, bool tilt) public static ControllerDefinition CreateControllerDefinition(bool sgb, bool sub, bool tilt, bool rumble)
{ {
var ret = new ControllerDefinition((sub ? "Subframe " : "") + "Gameboy Controller" + (tilt ? " + Tilt" : "")); var ret = new ControllerDefinition((sub ? "Subframe " : "") + "Gameboy Controller" + (tilt ? " + Tilt" : ""));
if (sub) if (sub)
@ -258,6 +258,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{ {
ret.AddXYPair($"Tilt {{0}}", AxisPairOrientation.RightAndUp, (-90).RangeTo(90), 0); ret.AddXYPair($"Tilt {{0}}", AxisPairOrientation.RightAndUp, (-90).RangeTo(90), 0);
} }
if (rumble)
{
ret.HapticsChannels.Add("Rumble");
}
if (sgb) if (sgb)
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)

View File

@ -49,7 +49,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
_linkedCores[i] = new Gameboy(lp.Comm, lp.Roms[i].Game, lp.Roms[i].RomData, _settings._linkedSettings[i], _syncSettings._linkedSyncSettings[i], lp.DeterministicEmulationRequested); _linkedCores[i] = new Gameboy(lp.Comm, lp.Roms[i].Game, lp.Roms[i].RomData, _settings._linkedSettings[i], _syncSettings._linkedSyncSettings[i], lp.DeterministicEmulationRequested);
_linkedCores[i].ConnectInputCallbackSystem(_inputCallbacks); _linkedCores[i].ConnectInputCallbackSystem(_inputCallbacks);
_linkedCores[i].ConnectMemoryCallbackSystem(_memoryCallbacks, i); _linkedCores[i].ConnectMemoryCallbackSystem(_memoryCallbacks, i);
_linkedConts[i] = new SaveController(Gameboy.CreateControllerDefinition(sgb: false, sub: false, tilt: false)); _linkedConts[i] = new SaveController(Gameboy.CreateControllerDefinition(sgb: false, sub: false, tilt: false, rumble: false));
_linkedBlips[i] = new BlipBuffer(1024); _linkedBlips[i] = new BlipBuffer(1024);
_linkedBlips[i].SetRates(2097152 * 2, 44100); _linkedBlips[i].SetRates(2097152 * 2, 44100);
_linkedOverflow[i] = 0; _linkedOverflow[i] = 0;

View File

@ -53,6 +53,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
[BizImport(cc)] [BizImport(cc)]
public abstract void sameboy_setinputcallback(IntPtr core, InputCallback callback); public abstract void sameboy_setinputcallback(IntPtr core, InputCallback callback);
[UnmanagedFunctionPointer(cc)]
public delegate void RumbleCallback(int amplitude);
[BizImport(cc)]
public abstract void sameboy_setrumblecallback(IntPtr core, RumbleCallback callback);
[BizImport(cc)] [BizImport(cc)]
public abstract void sameboy_frameadvance(IntPtr core, Buttons buttons, ushort x, ushort y, short[] soundbuf, ref int nsamps, int[] videobuf, bool render, bool border); public abstract void sameboy_frameadvance(IntPtr core, Buttons buttons, ushort x, ushort y, short[] soundbuf, ref int nsamps, int[] videobuf, bool render, bool border);
@ -81,7 +87,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
public abstract int sameboy_statelen(IntPtr core); public abstract int sameboy_statelen(IntPtr core);
[BizImport(cc)] [BizImport(cc)]
public abstract bool sameboy_getmemoryarea(IntPtr core, MemoryAreas which, ref IntPtr data, ref int length); public abstract bool sameboy_getmemoryarea(IntPtr core, MemoryAreas which, ref IntPtr data, ref long length);
[BizImport(cc)] [BizImport(cc)]
public abstract byte sameboy_cpuread(IntPtr core, ushort addr); public abstract byte sameboy_cpuread(IntPtr core, ushort addr);

View File

@ -11,10 +11,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
public ControllerDefinition ControllerDefinition { get; } public ControllerDefinition ControllerDefinition { get; }
private IController _controller = NullController.Instance;
private static readonly IReadOnlyList<string> GB_BUTTON_ORDER_IN_BITMASK = new[] { "Start", "Select", "B", "A", "Down", "Up", "Left", "Right", }; private static readonly IReadOnlyList<string> GB_BUTTON_ORDER_IN_BITMASK = new[] { "Start", "Select", "B", "A", "Down", "Up", "Left", "Right", };
private LibSameboy.Buttons FrameAdvancePrep(IController controller) private LibSameboy.Buttons FrameAdvancePrep(IController controller)
{ {
_controller = controller;
uint b = 0; uint b = 0;
for (var i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
{ {

View File

@ -7,14 +7,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
{ {
public partial class Sameboy public partial class Sameboy
{ {
private readonly List<MemoryDomain> _memoryDomains = new List<MemoryDomain>(); private readonly List<MemoryDomain> _memoryDomains = new();
private IMemoryDomains MemoryDomains { get; set; } private IMemoryDomains MemoryDomains { get; set; }
private void CreateMemoryDomain(LibSameboy.MemoryAreas which, string name) private void CreateMemoryDomain(LibSameboy.MemoryAreas which, string name)
{ {
IntPtr data = IntPtr.Zero; IntPtr data = IntPtr.Zero;
int length = 0; long length = 0;
if (!LibSameboy.sameboy_getmemoryarea(SameboyState, which, ref data, ref length)) if (!LibSameboy.sameboy_getmemoryarea(SameboyState, which, ref data, ref length))
{ {

View File

@ -39,6 +39,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
private readonly LibSameboy.InputCallback _inputcb; private readonly LibSameboy.InputCallback _inputcb;
private readonly LibSameboy.RumbleCallback _rumblecb;
[CoreConstructor(VSystemID.Raw.GB)] [CoreConstructor(VSystemID.Raw.GB)]
[CoreConstructor(VSystemID.Raw.GBC)] [CoreConstructor(VSystemID.Raw.GBC)]
public Sameboy(CoreComm comm, GameInfo game, byte[] file, SameboySettings settings, SameboySyncSettings syncSettings, bool deterministic) public Sameboy(CoreComm comm, GameInfo game, byte[] file, SameboySettings settings, SameboySyncSettings syncSettings, bool deterministic)
@ -90,10 +92,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
InitMemoryCallbacks(); InitMemoryCallbacks();
_inputcb = InputCallback; _inputcb = InputCallback;
LibSameboy.sameboy_setinputcallback(SameboyState, _inputcb); _rumblecb = RumbleCallback;
_tracecb = MakeTrace; _tracecb = MakeTrace;
LibSameboy.sameboy_settracecallback(SameboyState, null);
LibSameboy.sameboy_setinputcallback(SameboyState, _inputcb);
LibSameboy.sameboy_setrumblecallback(SameboyState, _rumblecb);
LibSameboy.sameboy_settracecallback(SameboyState, null);
LibSameboy.sameboy_setscanlinecallback(SameboyState, null, 0); LibSameboy.sameboy_setscanlinecallback(SameboyState, null, 0);
LibSameboy.sameboy_setprintercallback(SameboyState, null); LibSameboy.sameboy_setprintercallback(SameboyState, null);
@ -112,7 +117,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
BoardName = MapperName(file); BoardName = MapperName(file);
_hasAcc = BoardName is "MBC7 ROM+ACCEL+EEPROM"; _hasAcc = BoardName is "MBC7 ROM+ACCEL+EEPROM";
ControllerDefinition = Gameboy.Gameboy.CreateControllerDefinition(sgb: false, sub: false, tilt: _hasAcc); ControllerDefinition = Gameboy.Gameboy.CreateControllerDefinition(sgb: false, sub: false, tilt: _hasAcc, rumble: true);
LibSameboy.sameboy_setrtcdivisoroffset(SameboyState, _syncSettings.RTCDivisorOffset); LibSameboy.sameboy_setrtcdivisoroffset(SameboyState, _syncSettings.RTCDivisorOffset);
CycleCount = 0; CycleCount = 0;
@ -140,6 +145,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
_inputCallbacks.Call(); _inputCallbacks.Call();
} }
private void RumbleCallback(int amplitude)
{
_controller.SetHapticChannelStrength("Rumble", amplitude);
}
public bool LinkConnected public bool LinkConnected
{ {
get => _printercb != null; get => _printercb != null;
@ -187,7 +197,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
var _bgpal = IntPtr.Zero; var _bgpal = IntPtr.Zero;
var _sppal = IntPtr.Zero; var _sppal = IntPtr.Zero;
var _oam = IntPtr.Zero; var _oam = IntPtr.Zero;
int unused = 0; long unused = 0;
if (!LibSameboy.sameboy_getmemoryarea(SameboyState, LibSameboy.MemoryAreas.VRAM, ref _vram, ref unused) if (!LibSameboy.sameboy_getmemoryarea(SameboyState, LibSameboy.MemoryAreas.VRAM, ref _vram, ref unused)
|| !LibSameboy.sameboy_getmemoryarea(SameboyState, LibSameboy.MemoryAreas.BGPRGB, ref _bgpal, ref unused) || !LibSameboy.sameboy_getmemoryarea(SameboyState, LibSameboy.MemoryAreas.BGPRGB, ref _bgpal, ref unused)
|| !LibSameboy.sameboy_getmemoryarea(SameboyState, LibSameboy.MemoryAreas.OBPRGB, ref _sppal, ref unused) || !LibSameboy.sameboy_getmemoryarea(SameboyState, LibSameboy.MemoryAreas.OBPRGB, ref _sppal, ref unused)

View File

@ -19,6 +19,7 @@ typedef uint32_t u32;
typedef uint64_t u64; typedef uint64_t u64;
typedef void (*input_callback_t)(void); typedef void (*input_callback_t)(void);
typedef void (*rumble_callback_t)(u32);
typedef void (*trace_callback_t)(u16); typedef void (*trace_callback_t)(u16);
typedef void (*memory_callback_t)(u16); typedef void (*memory_callback_t)(u16);
typedef void (*printer_callback_t)(u32*, u8, u8, u8, u8); typedef void (*printer_callback_t)(u32*, u8, u8, u8, u8);
@ -36,6 +37,7 @@ typedef struct
u32 obj_pal[0x20]; u32 obj_pal[0x20];
GB_palette_t custom_pal; GB_palette_t custom_pal;
input_callback_t input_cb; input_callback_t input_cb;
rumble_callback_t rumble_cb;
trace_callback_t trace_cb; trace_callback_t trace_cb;
memory_callback_t read_cb; memory_callback_t read_cb;
memory_callback_t write_cb; memory_callback_t write_cb;
@ -77,17 +79,22 @@ static u32 rgb_cb(GB_gameboy_t *gb, u8 r, u8 g, u8 b)
return (0xFF << 24) | (r << 16) | (g << 8) | b; return (0xFF << 24) | (r << 16) | (g << 8) | b;
} }
static void vblank_cb(GB_gameboy_t *gb, GB_vblank_type_t type) static void vblank_cb(GB_gameboy_t* gb, GB_vblank_type_t type)
{ {
((biz_t*)gb)->vblank_occured = true; ((biz_t*)gb)->vblank_occured = true;
} }
static u8 camera_pixel_cb(GB_gameboy_t *gb, u8 x, u8 y) static u8 camera_pixel_cb(GB_gameboy_t* gb, u8 x, u8 y)
{ {
// stub for now (also needed for determinism) // stub for now (also needed for determinism)
return 0; return 0;
} }
static void RumbleCallbackRelay(GB_gameboy_t* gb, double rumble_amplitude)
{
((biz_t*)gb)->rumble_cb(INT32_MAX * rumble_amplitude);
}
static u8 ReadCallbackRelay(GB_gameboy_t* gb, u16 addr, u8 data) static u8 ReadCallbackRelay(GB_gameboy_t* gb, u16 addr, u8 data)
{ {
((biz_t*)gb)->read_cb(addr); ((biz_t*)gb)->read_cb(addr);
@ -135,6 +142,8 @@ EXPORT biz_t* sameboy_create(u8* romdata, u32 romlen, u8* biosdata, u32 bioslen,
GB_load_rom_from_buffer(&biz->gb, romdata, romlen); GB_load_rom_from_buffer(&biz->gb, romdata, romlen);
GB_load_boot_rom_from_buffer(&biz->gb, biosdata, bioslen); GB_load_boot_rom_from_buffer(&biz->gb, biosdata, bioslen);
GB_set_sample_rate(&biz->gb, GB_get_clock_rate(&biz->gb) / 2 / 8); GB_set_sample_rate(&biz->gb, GB_get_clock_rate(&biz->gb) / 2 / 8);
GB_set_rumble_mode(&biz->gb, GB_RUMBLE_ALL_GAMES);
GB_set_rumble_callback(&biz->gb, RumbleCallbackRelay);
GB_apu_set_sample_callback(&biz->gb, sample_cb); GB_apu_set_sample_callback(&biz->gb, sample_cb);
GB_set_rgb_encode_callback(&biz->gb, rgb_cb); GB_set_rgb_encode_callback(&biz->gb, rgb_cb);
GB_set_vblank_callback(&biz->gb, vblank_cb); GB_set_vblank_callback(&biz->gb, vblank_cb);
@ -163,6 +172,11 @@ EXPORT void sameboy_setinputcallback(biz_t* biz, input_callback_t callback)
biz->input_cb = callback; biz->input_cb = callback;
} }
EXPORT void sameboy_setrumblecallback(biz_t* biz, rumble_callback_t callback)
{
biz->rumble_cb = callback;
}
static double FromRawToG(u16 raw) static double FromRawToG(u16 raw)
{ {
return (raw - 0x81D0) / (0x70 * 1.0); return (raw - 0x81D0) / (0x70 * 1.0);