Skip to content

Commit

Permalink
Merge pull request #1582 from MrWint/update-gambatte-speedrun
Browse files Browse the repository at this point in the history
Update Gambatte core
  • Loading branch information
alyosha-tas committed Jun 2, 2019
2 parents e60896c + a93916e commit 50a0b36
Show file tree
Hide file tree
Showing 76 changed files with 8,569 additions and 9,217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,9 @@ public void StoreSaveRam(byte[] data)
break;
default:
throw new ArgumentException("Size of saveram data does not match expected!");
case 44:
data = FixRTC(data, 44);
break;
case 40:
data = FixRTC(data, 40);
break;
}

LibGambatte.gambatte_loadsavedata(GambatteState, data);
}

private byte[] FixRTC(byte[] data, int offset)
{
// length - offset is the start of the VBA-only data; so
// length - offset - 4 is the start of the RTC block
int idx = data.Length - offset - 4;

byte[] ret = new byte[idx + 4];
Buffer.BlockCopy(data, 0, ret, 0, idx);
data[idx] = (byte)zerotime;
data[idx + 1] = (byte)(zerotime >> 8);
data[idx + 2] = (byte)(zerotime >> 16);
data[idx + 3] = (byte)(zerotime >> 24);

return ret;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,10 @@ public enum ConsoleModeType
[DefaultValue(false)]
public bool RealTimeRTC { get; set; }

[DisplayName("RTC Initial Time")]
[Description("Set the initial RTC time in terms of elapsed seconds. Only used when RealTimeRTC is false.")]
[DisplayName("RTC Divisor Offset")]
[Description("CPU clock frequency relative to real time clock. Base value is 2^22 Hz. Used in cycle-based RTC to sync on real hardware to account for RTC imperfections.")]
[DefaultValue(0)]
public int RTCInitialTime
{
get { return _RTCInitialTime; }
set { _RTCInitialTime = Math.Max(0, Math.Min(1024 * 24 * 60 * 60, value)); }
}

[JsonIgnore]
private int _RTCInitialTime;
public int RTCDivisorOffset { get; set; }

[DisplayName("Equal Length Frames")]
[Description("When false, emulation frames sync to vblank. Only useful for high level TASing.")]
Expand All @@ -141,11 +134,6 @@ public bool EqualLengthFrames
[DeepEqualsIgnore]
private bool _equalLengthFrames;

[DisplayName("Initial DIV offset")]
[Description("Internal. Probably doesn't work. Leave this set to 0. Accepts values from 0 to 65532 in steps of 4")]
[DefaultValue(0)]
public int InitialDiv { get; set; }

public GambatteSyncSettings()
{
SettingsUtil.SetDefaultValues(this);
Expand All @@ -160,11 +148,6 @@ public static bool NeedsReboot(GambatteSyncSettings x, GambatteSyncSettings y)
{
return !DeepEquality.DeepEquals(x, y);
}

public uint GetInitialDivInternal()
{
return (uint)(InitialDiv & 0xfffc);
}
}
}
}
92 changes: 14 additions & 78 deletions BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,6 @@ public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, objec
{
_syncSettings = (GambatteSyncSettings)syncSettings ?? new GambatteSyncSettings();

// copy over non-loadflag syncsettings now; they won't take effect if changed later
zerotime = (uint)_syncSettings.RTCInitialTime;

real_rtc_time = !DeterministicEmulation && _syncSettings.RealTimeRTC;

DivInternal = _syncSettings.GetInitialDivInternal();

LibGambatte.LoadFlags flags = 0;

switch (_syncSettings.ConsoleMode)
Expand All @@ -90,33 +83,26 @@ public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, objec
flags |= LibGambatte.LoadFlags.MULTICART_COMPAT;
}

if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, GetCurrentTime(), flags, DivInternal) != 0)
if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, flags) != 0)
{
throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_load)}() returned non-zero (is this not a gb or gbc rom?)");
}

byte[] Bios;
if ((flags & LibGambatte.LoadFlags.FORCE_DMG) == LibGambatte.LoadFlags.FORCE_DMG)
{
byte[] Bios = comm.CoreFileProvider.GetFirmware("GB", "World", true, "BIOS Not Found, Cannot Load");

Bios = comm.CoreFileProvider.GetFirmware("GB", "World", true, "BIOS Not Found, Cannot Load");
IsCgb = false;

if (LibGambatte.gambatte_loaddmgbios(GambatteState, Bios) != 0)
{
throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loaddmgbios)}() returned non-zero (bios error)");
}
}
else
{
byte[] Bios = comm.CoreFileProvider.GetFirmware("GBC", "World", true, "BIOS Not Found, Cannot Load");

Bios = comm.CoreFileProvider.GetFirmware("GBC", "World", true, "BIOS Not Found, Cannot Load");
IsCgb = true;

if (LibGambatte.gambatte_loadgbcbios(GambatteState, Bios) != 0)
{
throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadgbcbios)}() returned non-zero (bios error)");
}
}
if (LibGambatte.gambatte_loadbios(GambatteState, Bios, (uint)Bios.Length) != 0)
{
throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbios)}() returned non-zero (bios error)");
}

// set real default colors (before anyone mucks with them at all)
PutSettings((GambatteSettings)settings ?? new GambatteSettings());
Expand All @@ -140,8 +126,11 @@ public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, objec
string romname = System.Text.Encoding.ASCII.GetString(buff);
Console.WriteLine("Core reported rom name: {0}", romname);

TimeCallback = new LibGambatte.RTCCallback(GetCurrentTime);
LibGambatte.gambatte_setrtccallback(GambatteState, TimeCallback);
if (!DeterministicEmulation && _syncSettings.RealTimeRTC)
{
LibGambatte.gambatte_settimemode(GambatteState, false);
}
LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset);

_cdCallback = new LibGambatte.CDCallback(CDCallbackProc);

Expand Down Expand Up @@ -174,59 +163,6 @@ public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, objec
/// </summary>
private LibGambatte.Buttons CurrentButtons = 0;

private uint DivInternal = 0;

#region RTC

/// <summary>
/// RTC time when emulation begins.
/// </summary>
private readonly uint zerotime = 0;

/// <summary>
/// if true, RTC will run off of real elapsed time
/// </summary>
private bool real_rtc_time = false;

private LibGambatte.RTCCallback TimeCallback;

private static long GetUnixNow()
{
// because internally the RTC works off of relative time, we don't need to base
// this off of any particular canonical epoch.
return DateTime.UtcNow.Ticks / 10000000L - 60000000000L;
}

private uint GetCurrentTime()
{
if (real_rtc_time)
{
return (uint)GetUnixNow();
}

ulong fn = (ulong)Frame;

// as we're exactly tracking cpu cycles, this can be pretty accurate
fn *= 4389;
fn /= 262144;
fn += zerotime;
return (uint)fn;
}

private uint GetInitialTime()
{
if (real_rtc_time)
{
return (uint)GetUnixNow();
}

// setting the initial boot time to 0 will cause our zerotime
// to function as an initial offset, which is what we want
return 0;
}

#endregion

#region ALL SAVESTATEABLE STATE GOES HERE

/// <summary>
Expand Down Expand Up @@ -327,7 +263,7 @@ internal void FrameAdvancePrep(IController controller)

if (controller.IsPressed("Power"))
{
LibGambatte.gambatte_reset(GambatteState, GetCurrentTime(), DivInternal);
LibGambatte.gambatte_reset(GambatteState);
}

if (Tracer.Enabled)
Expand Down
49 changes: 21 additions & 28 deletions BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,29 +53,20 @@ public enum CDLog_Flags : int
/// <param name="core">opaque state pointer</param>
/// <param name="romdata">the rom data, can be disposed of once this function returns</param>
/// <param name="length">length of romdata in bytes</param>
/// <param name="now">RTC time when the rom is loaded</param>
/// <param name="flags">ORed combination of LoadFlags.</param>
/// <returns>0 on success, negative value on failure.</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gambatte_load(IntPtr core, byte[] romdata, uint length, long now, LoadFlags flags, uint div);
public static extern int gambatte_load(IntPtr core, byte[] romdata, uint length, LoadFlags flags);

/// <summary>
/// Load GB BIOS image.
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="biosdata">the bios data, can be disposed of once this function returns</param>
/// <returns>0 on success, negative value on failure.</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gambatte_loaddmgbios(IntPtr core, byte[] biosdata);

/// <summary>
/// Load GBC BIOS image.
/// Load GB(C) BIOS image.
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="biosdata">the bios data, can be disposed of once this function returns</param>
/// <param name="length">length of romdata in bytes</param>
/// <returns>0 on success, negative value on failure.</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gambatte_loadgbcbios(IntPtr core, byte[] biosdata);
public static extern int gambatte_loadbios(IntPtr core, byte[] biosdata, uint length);

/// <summary>
/// Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer,
Expand Down Expand Up @@ -122,9 +113,8 @@ public enum CDLog_Flags : int
/// Equivalent to reloading a ROM image, or turning a Game Boy Color off and on again.
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="now">RTC time when the reset occurs</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_reset(IntPtr core, long now, uint div);
public static extern void gambatte_reset(IntPtr core);

/// <summary>
/// palette type for gambatte_setdmgpalettecolor
Expand Down Expand Up @@ -267,35 +257,38 @@ public enum Buttons: uint
/// <param name="sl">0-153 inclusive</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_setscanlinecallback(IntPtr core, ScanlineCallback callback, int sl);

/// <summary>
/// type of the RTC callback
/// type of the link data sent callback
/// </summary>
/// <returns>what time is it, unixy</returns>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint RTCCallback();
public delegate void LinkCallback();

/// <summary>
/// sets RTC callback. probably mandatory.
/// sets the Link data sent callback.
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="callback">the callback</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_setrtccallback(IntPtr core, RTCCallback callback);
public static extern void gambatte_setlinkcallback(IntPtr core, LinkCallback callback);

/// <summary>
/// type of the link data sent callback
/// Changes between cycle-based and real-time RTC. Defaults to cycle-based.
/// </summary>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LinkCallback();
/// <param name="core">opaque state pointer</param>
/// <param name="useCycles">use cycle-based RTC</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_settimemode(IntPtr core, bool useCycles);

/// <summary>
/// sets the Link data sent callback.
/// Adjusts the CPU clock frequency relative to real time. Base value is 2^22 Hz.
/// This is used to account for drift in the RTC when syncing cycle-based RTC to real hardware.
/// RTCs in carts are not perfectly accurate, and the value will differ from cart to cart.
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="callback">the callback</param>
/// <param name="rtcDivisorOffset">CPU frequency adjustment</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_setlinkcallback(IntPtr core, LinkCallback callback);
public static extern void gambatte_setrtcdivisoroffset(IntPtr core, int rtcDivisorOffset);

/// <summary>
/// Returns true if the currently loaded ROM image is treated as having CGB support.
Expand Down
4 changes: 2 additions & 2 deletions libgambatte/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ SRCS = \
src/cpu.cpp \
src/gambatte.cpp \
src/initstate.cpp \
src/interrupter.cpp \
src/interruptrequester.cpp \
src/memory.cpp \
src/mem/cartridge.cpp \
src/mem/memptrs.cpp \
src/mem/rtc.cpp \
src/mem/time.cpp \
src/newstate.cpp \
src/sound.cpp \
src/sound/channel1.cpp \
Expand Down Expand Up @@ -61,6 +61,6 @@ $(TARGET) : $(OBJS)
clean:
$(RM) $(OBJS)
$(RM) $(TARGET)

install:
$(CP) $(TARGET) $(DEST_$(ARCH))
Loading

0 comments on commit 50a0b36

Please sign in to comment.