Gambatte core: Add RTC divisor offset support.

This commit is contained in:
MrWint 2019-06-02 13:24:54 +02:00
parent 1c0f8ff36b
commit a93916e24c
12 changed files with 37 additions and 4 deletions

View File

@ -116,6 +116,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
[DefaultValue(false)]
public bool RealTimeRTC { get; set; }
[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 RTCDivisorOffset { get; set; }
[DisplayName("Equal Length Frames")]
[Description("When false, emulation frames sync to vblank. Only useful for high level TASing.")]
[DefaultValue(false)]

View File

@ -130,6 +130,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
LibGambatte.gambatte_settimemode(GambatteState, false);
}
LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset);
_cdCallback = new LibGambatte.CDCallback(CDCallbackProc);

View File

@ -280,6 +280,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gambatte_settimemode(IntPtr core, bool useCycles);
/// <summary>
/// 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="rtcDivisorOffset">CPU frequency adjustment</param>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
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.
/// </summary>

View File

@ -130,6 +130,9 @@ public:
/** Use cycle-based RTC instead of real-time. */
void setTimeMode(bool useCycles);
/** adjust the assumed clock speed of the CPU compared to the RTC */
void setRtcDivisorOffset(long const rtcDivisorOffset);
/** Returns true if the currently loaded ROM image is treated as having CGB support. */
bool isCgb() const;

View File

@ -72,6 +72,10 @@ GBEXPORT void gambatte_settimemode(GB *g, bool useCycles) {
g->setTimeMode(useCycles);
}
GBEXPORT void gambatte_setrtcdivisoroffset(GB *g, int rtcDivisorOffset) {
g->setRtcDivisorOffset(rtcDivisorOffset);
}
GBEXPORT void gambatte_reset(GB *g) {
g->reset();
}

View File

@ -91,6 +91,7 @@ public:
mem_.setCgbPalette(lut);
}
void setTimeMode(bool useCycles) { mem_.setTimeMode(useCycles, cycleCounter_); }
void setRtcDivisorOffset(long const rtcDivisorOffset) { mem_.setRtcDivisorOffset(rtcDivisorOffset); }
void setBios(char const *buffer, std::size_t size) { mem_.setBios(buffer, size); }
bool gbIsCgb() { return mem_.gbIsCgb(); }

View File

@ -134,6 +134,10 @@ void GB::setTimeMode(bool useCycles) {
p_->cpu.setTimeMode(useCycles);
}
void GB::setRtcDivisorOffset(long const rtcDivisorOffset) {
p_->cpu.setRtcDivisorOffset(rtcDivisorOffset);
}
LoadRes GB::load(char const *romfiledata, unsigned romfilelength, unsigned const flags) {
LoadRes const loadres = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT);

View File

@ -71,6 +71,7 @@ public:
void resetCc(unsigned long const oldCc, unsigned long const newCc) { time_.resetCc(oldCc, newCc); }
void speedChange(unsigned long const cc) { time_.speedChange(cc); }
void setTimeMode(bool useCycles, unsigned long const cc) { time_.setTimeMode(useCycles, cc); }
void setRtcDivisorOffset(long const rtcDivisorOffset) { time_.setRtcDivisorOffset(rtcDivisorOffset); }
void rtcWrite(unsigned data, unsigned long const cc) { rtc_.write(data, cc); }
unsigned char rtcRead() const { return *rtc_.activeData(); }
void loadSavedata(char const *data, unsigned long cycleCounter);

View File

@ -34,6 +34,7 @@ static timeval operator-(timeval l, timeval r) {
Time::Time()
: useCycles_(true)
, rtcDivisor_(0x400000)
{
}
@ -108,9 +109,9 @@ void Time::setTimeMode(bool useCycles, unsigned long const cc) {
void Time::update(unsigned long const cc) {
if (useCycles_) {
std::uint32_t diff = (cc - lastCycles_) / (0x400000 << ds_);
std::uint32_t diff = (cc - lastCycles_) / (rtcDivisor_ << ds_);
seconds_ += diff;
lastCycles_ += diff * (0x400000 << ds_);
lastCycles_ += diff * (rtcDivisor_ << ds_);
} else {
std::uint32_t diff = (now() - lastTime_).tv_sec;
seconds_ += diff;
@ -121,13 +122,13 @@ void Time::update(unsigned long const cc) {
void Time::cyclesFromTime(unsigned long const cc) {
update(cc);
timeval diff = now() - lastTime_;
lastCycles_ = cc - diff.tv_usec * ((0x400000 << ds_) / 1000000.0f);
lastCycles_ = cc - diff.tv_usec * ((rtcDivisor_ << ds_) / 1000000.0f);
}
void Time::timeFromCycles(unsigned long const cc) {
update(cc);
unsigned long diff = cc - lastCycles_;
timeval usec = { 0, (long)(diff / ((0x400000 << ds_) / 1000000.0f)) };
timeval usec = { 0, (long)(diff / ((rtcDivisor_ << ds_) / 1000000.0f)) };
lastTime_ = now() - usec;
}

View File

@ -57,12 +57,14 @@ public:
timeval baseTime(unsigned long cycleCounter);
void setBaseTime(timeval baseTime, unsigned long cycleCounter);
void setTimeMode(bool useCycles, unsigned long cycleCounter);
void setRtcDivisorOffset(long const rtcDivisorOffset) { rtcDivisor_ = 0x400000L + rtcDivisorOffset; }
private:
std::uint32_t seconds_;
timeval lastTime_;
unsigned long lastCycles_;
bool useCycles_;
unsigned long rtcDivisor_;
bool ds_;
void update(unsigned long cycleCounter);

View File

@ -266,6 +266,7 @@ public:
void setTimeMode(bool useCycles, unsigned long const cc) {
cart_.setTimeMode(useCycles, cc);
}
void setRtcDivisorOffset(long const rtcDivisorOffset) { cart_.setRtcDivisorOffset(rtcDivisorOffset); }
int linkStatus(int which);

Binary file not shown.