Gambatte core: Add RTC divisor offset support.
This commit is contained in:
parent
1c0f8ff36b
commit
a93916e24c
|
@ -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)]
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
Loading…
Reference in New Issue