GBS support using SameBoy
This commit is contained in:
parent
0c6f0523a0
commit
9528a2030f
Binary file not shown.
Binary file not shown.
|
@ -10,6 +10,7 @@ using BizHawk.Common.StringExtensions;
|
|||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores;
|
||||
using BizHawk.Emulation.Cores.Libretro;
|
||||
using BizHawk.Emulation.Cores.Nintendo.Sameboy;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SNES;
|
||||
using BizHawk.Emulation.Cores.Sony.PSX;
|
||||
using BizHawk.Emulation.Cores.Arcades.MAME;
|
||||
|
@ -493,6 +494,19 @@ namespace BizHawk.Client.Common
|
|||
nextEmulator = MakeCoreFromCoreInventory(cip, forcedCoreName);
|
||||
}
|
||||
|
||||
private void LoadGBS(string path, CoreComm nextComm, HawkFile file, out IEmulator nextEmulator, out RomGame rom, out GameInfo game)
|
||||
{
|
||||
rom = new RomGame(file);
|
||||
rom.GameInfo.System = VSystemID.Raw.GB;
|
||||
game = rom.GameInfo;
|
||||
nextEmulator = new Sameboy(
|
||||
nextComm,
|
||||
rom.FileData,
|
||||
GetCoreSettings<Sameboy, Sameboy.SameboySettings>(),
|
||||
GetCoreSyncSettings<Sameboy, Sameboy.SameboySyncSettings>()
|
||||
);
|
||||
}
|
||||
|
||||
private void LoadPSF(string path, CoreComm nextComm, HawkFile file, out IEmulator nextEmulator, out RomGame rom, out GameInfo game)
|
||||
{
|
||||
// TODO: Why does the PSF loader need CbDeflater provided? Surely this is a matter internal to it.
|
||||
|
@ -679,6 +693,9 @@ namespace BizHawk.Client.Common
|
|||
if (!LoadXML(path, nextComm, file, forcedCoreName, out nextEmulator, out rom, out game))
|
||||
return false;
|
||||
break;
|
||||
case ".gbs":
|
||||
LoadGBS(path, nextComm, file, out nextEmulator, out rom, out game);
|
||||
break;
|
||||
case ".psf":
|
||||
case ".minipsf":
|
||||
LoadPSF(path, nextComm, file, out nextEmulator, out rom, out game);
|
||||
|
|
|
@ -47,6 +47,25 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
[BizImport(cc)]
|
||||
public abstract void sameboy_destroy(IntPtr core);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct GBSInfo
|
||||
{
|
||||
public byte TrackCount;
|
||||
public byte FirstTrack;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 33)]
|
||||
public byte[] Title;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 33)]
|
||||
public byte[] Author;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 33)]
|
||||
public byte[] Copyright;
|
||||
}
|
||||
|
||||
[BizImport(cc, Compatibility = true)]
|
||||
public abstract bool sameboy_loadgbs(IntPtr core, byte[] gbs, int gbslen, ref GBSInfo gbsInfo);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void sameboy_switchgbstrack(IntPtr core, int track);
|
||||
|
||||
[UnmanagedFunctionPointer(cc)]
|
||||
public delegate void InputCallback();
|
||||
|
||||
|
|
|
@ -15,6 +15,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
|
||||
private static readonly IReadOnlyList<string> GB_BUTTON_ORDER_IN_BITMASK = new[] { "Start", "Select", "B", "A", "Down", "Up", "Left", "Right", };
|
||||
|
||||
private readonly int _firstTrack;
|
||||
private readonly int _lastTrack;
|
||||
private int _curTrack = 0;
|
||||
private bool _switchingTrack = false;
|
||||
|
||||
private LibSameboy.Buttons FrameAdvancePrep(IController controller)
|
||||
{
|
||||
_controller = controller;
|
||||
|
@ -31,6 +36,33 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
LibSameboy.sameboy_reset(SameboyState);
|
||||
}
|
||||
|
||||
var prevTrack = controller.IsPressed("Previous Track");
|
||||
var nextTrack = controller.IsPressed("Next Track");
|
||||
|
||||
if (!_switchingTrack)
|
||||
{
|
||||
if (prevTrack)
|
||||
{
|
||||
if (_curTrack != _firstTrack)
|
||||
{
|
||||
_curTrack--;
|
||||
LibSameboy.sameboy_switchgbstrack(SameboyState, _curTrack);
|
||||
Comm.Notify($"Switching to Track {_curTrack}");
|
||||
}
|
||||
}
|
||||
else if (nextTrack)
|
||||
{
|
||||
if (_curTrack != _lastTrack)
|
||||
{
|
||||
_curTrack++;
|
||||
LibSameboy.sameboy_switchgbstrack(SameboyState, _curTrack);
|
||||
Comm.Notify($"Switching to Track {_curTrack}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_switchingTrack = prevTrack || nextTrack;
|
||||
|
||||
IsLagFrame = true;
|
||||
|
||||
LibSameboy.sameboy_settracecallback(SameboyState, Tracer.IsEnabled() ? _tracecb : null);
|
||||
|
|
|
@ -27,6 +27,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
writer.Write(theta_prev);
|
||||
writer.Write(phi_prev);
|
||||
writer.Write(phi_prev_2);
|
||||
writer.Write(_curTrack);
|
||||
writer.Write(_switchingTrack);
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader reader)
|
||||
|
@ -55,6 +57,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
theta_prev = reader.ReadDouble();
|
||||
phi_prev = reader.ReadDouble();
|
||||
phi_prev_2 = reader.ReadDouble();
|
||||
_curTrack = reader.ReadInt32();
|
||||
_switchingTrack = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
public void DebugSameBoyState()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using BizHawk.BizInvoke;
|
||||
using BizHawk.Common;
|
||||
|
@ -29,6 +30,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
|
||||
private readonly Gameboy.GBDisassembler _disassembler;
|
||||
|
||||
private readonly CoreComm Comm;
|
||||
|
||||
private IntPtr SameboyState { get; set; } = IntPtr.Zero;
|
||||
|
||||
public bool IsCgb { get; set; }
|
||||
|
@ -41,14 +44,68 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
|
||||
private readonly LibSameboy.RumbleCallback _rumblecb;
|
||||
|
||||
public Sameboy(CoreComm comm, byte[] gbs, SameboySettings settings, SameboySyncSettings syncSettings)
|
||||
: this(comm, GameInfo.NullInstance, null, settings, syncSettings, false)
|
||||
{
|
||||
var gbsInfo = new LibSameboy.GBSInfo
|
||||
{
|
||||
TrackCount = 0,
|
||||
FirstTrack = 0,
|
||||
Title = new byte[33],
|
||||
Author = new byte[33],
|
||||
Copyright = new byte[33],
|
||||
};
|
||||
|
||||
if (!LibSameboy.sameboy_loadgbs(SameboyState, gbs, gbs.Length, ref gbsInfo))
|
||||
{
|
||||
throw new InvalidOperationException("Core rejected the GBS!");
|
||||
}
|
||||
|
||||
RomDetails = $"Track Count: {gbsInfo.TrackCount}\r\n" +
|
||||
$"First Track: {gbsInfo.FirstTrack}\r\n" +
|
||||
$"Title: {Encoding.UTF8.GetString(gbsInfo.Title).Trim()}\r\n" +
|
||||
$"Author: {Encoding.UTF8.GetString(gbsInfo.Author).Trim()}\r\n" +
|
||||
$"Copyright: {Encoding.UTF8.GetString(gbsInfo.Copyright).Trim()}";
|
||||
|
||||
_firstTrack = gbsInfo.FirstTrack;
|
||||
_lastTrack = gbsInfo.FirstTrack + gbsInfo.TrackCount - 1;
|
||||
|
||||
_curTrack = _firstTrack;
|
||||
LibSameboy.sameboy_switchgbstrack(SameboyState, _curTrack);
|
||||
|
||||
BoardName = "GBS";
|
||||
ControllerDefinition = new ControllerDefinition("GBS Controller")
|
||||
{
|
||||
BoolButtons = { "Previous Track", "Next Track" }
|
||||
}.MakeImmutable();
|
||||
|
||||
Comm = comm;
|
||||
|
||||
_stateBuf = new byte[LibSameboy.sameboy_statelen(SameboyState)];
|
||||
}
|
||||
|
||||
[CoreConstructor(VSystemID.Raw.GB)]
|
||||
[CoreConstructor(VSystemID.Raw.GBC)]
|
||||
public Sameboy(CoreComm comm, GameInfo game, byte[] file, SameboySettings settings, SameboySyncSettings syncSettings, bool deterministic)
|
||||
public Sameboy(CoreLoadParameters<SameboySettings, SameboySyncSettings> lp)
|
||||
: this(lp.Comm, lp.Game, lp.Roms[0].FileData, lp.Settings, lp.SyncSettings, lp.DeterministicEmulationRequested)
|
||||
{
|
||||
var file = lp.Roms[0].FileData;
|
||||
|
||||
RomDetails = $"{lp.Game.Name}\r\n{SHA1Checksum.ComputePrefixedHex(file)}\r\n{MD5Checksum.ComputePrefixedHex(file)}\r\n";
|
||||
|
||||
BoardName = MapperName(file);
|
||||
_hasAcc = BoardName is "MBC7 ROM+ACCEL+EEPROM";
|
||||
ControllerDefinition = Gameboy.Gameboy.CreateControllerDefinition(sgb: false, sub: false, tilt: _hasAcc, rumble: true, remote: false);
|
||||
|
||||
_stateBuf = new byte[LibSameboy.sameboy_statelen(SameboyState)];
|
||||
}
|
||||
|
||||
private Sameboy(CoreComm comm, GameInfo game, byte[] file, SameboySettings settings, SameboySyncSettings syncSettings, bool deterministic)
|
||||
{
|
||||
_serviceProvider = new BasicServiceProvider(this);
|
||||
|
||||
_settings = settings ?? new SameboySettings();
|
||||
_syncSettings = syncSettings ?? new SameboySyncSettings();
|
||||
_settings = settings ?? new();
|
||||
_syncSettings = syncSettings ?? new();
|
||||
|
||||
var model = _syncSettings.ConsoleMode;
|
||||
if (model is SameboySyncSettings.GBModel.Auto)
|
||||
|
@ -86,7 +143,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
DeterministicEmulation = true;
|
||||
}
|
||||
|
||||
SameboyState = LibSameboy.sameboy_create(file, file.Length, bios, bios.Length, model, realtime, _syncSettings.NoJoypadBounce);
|
||||
SameboyState = LibSameboy.sameboy_create(file, file?.Length ?? 0, bios, bios.Length, model, realtime, _syncSettings.NoJoypadBounce);
|
||||
|
||||
InitMemoryDomains();
|
||||
InitMemoryCallbacks();
|
||||
|
@ -111,14 +168,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy
|
|||
|
||||
PutSettings(_settings);
|
||||
|
||||
_stateBuf = new byte[LibSameboy.sameboy_statelen(SameboyState)];
|
||||
|
||||
RomDetails = $"{game.Name}\r\n{SHA1Checksum.ComputePrefixedHex(file)}\r\n{MD5Checksum.ComputePrefixedHex(file)}\r\n";
|
||||
BoardName = MapperName(file);
|
||||
|
||||
_hasAcc = BoardName is "MBC7 ROM+ACCEL+EEPROM";
|
||||
ControllerDefinition = Gameboy.Gameboy.CreateControllerDefinition(sgb: false, sub: false, tilt: _hasAcc, rumble: true, remote: false);
|
||||
|
||||
LibSameboy.sameboy_setrtcdivisoroffset(SameboyState, _syncSettings.RTCDivisorOffset);
|
||||
CycleCount = 0;
|
||||
}
|
||||
|
|
|
@ -143,7 +143,11 @@ EXPORT biz_t* sameboy_create(u8* romdata, u32 romlen, u8* biosdata, u32 bioslen,
|
|||
biz_t* biz = calloc(1, sizeof (biz_t));
|
||||
GB_random_seed(0);
|
||||
GB_init(&biz->gb, model);
|
||||
GB_load_rom_from_buffer(&biz->gb, romdata, romlen);
|
||||
// this will be NULL if a GBS is going to be loaded later
|
||||
if (romdata)
|
||||
{
|
||||
GB_load_rom_from_buffer(&biz->gb, romdata, romlen);
|
||||
}
|
||||
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_rumble_mode(&biz->gb, GB_RUMBLE_ALL_GAMES);
|
||||
|
@ -171,6 +175,16 @@ EXPORT void sameboy_destroy(biz_t* biz)
|
|||
free(biz);
|
||||
}
|
||||
|
||||
EXPORT bool sameboy_loadgbs(biz_t* biz, u8* gbs, u32 gbslen, GB_gbs_info_t* gbsinfo)
|
||||
{
|
||||
return GB_load_gbs_from_buffer(&biz->gb, gbs, gbslen, gbsinfo) == 0;
|
||||
}
|
||||
|
||||
EXPORT void sameboy_switchgbstrack(biz_t* biz, u32 track)
|
||||
{
|
||||
GB_gbs_switch_track(&biz->gb, track);
|
||||
}
|
||||
|
||||
EXPORT void sameboy_setinputcallback(biz_t* biz, input_callback_t callback)
|
||||
{
|
||||
biz->input_cb = callback;
|
||||
|
|
Loading…
Reference in New Issue