SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit e08df2a089c9fe3984ab52c8e86df9a16a591636 parent 807712b9c266e75a47e7ffb3f907758a9971b244 Author: Lior Halphon <LIJI32@gmail.com> Date: Thu, 25 Feb 2021 22:12:14 +0200 Add accurate RTC emulation mode Diffstat:
| M | Cocoa/Document.m | 14 | ++++++++++++++ |
| M | Cocoa/GBPreferencesWindow.h | 1 | + |
| M | Cocoa/GBPreferencesWindow.m | 21 | +++++++++++++++++++++ |
| M | Cocoa/Preferences.xib | 243 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
| M | Core/gb.c | 31 | ++++++++++++++++++++++--------- |
| M | Core/gb.h | 11 | +++++++++++ |
| M | Core/timing.c | 114 | +++++++++++++++++++++++++++++++++++++++++++++---------------------------------- |
| M | Core/timing.h | 1 | - |
8 files changed, 270 insertions(+), 166 deletions(-)
diff --git a/Cocoa/Document.m b/Cocoa/Document.m @@ -295,6 +295,7 @@ static void infraredStateChanged(GB_gameboy_t *gb, bool on) GB_set_camera_update_request_callback(&gb, cameraRequestUpdate); GB_set_highpass_filter_mode(&gb, (GB_highpass_mode_t) [[NSUserDefaults standardUserDefaults] integerForKey:@"GBHighpassFilter"]); GB_set_rewind_length(&gb, [[NSUserDefaults standardUserDefaults] integerForKey:@"GBRewindLength"]); + GB_set_rtc_mode(&gb, [[NSUserDefaults standardUserDefaults] integerForKey:@"GBRTCMode"]); GB_apu_set_sample_callback(&gb, audioCallback); GB_set_rumble_callback(&gb, rumbleCallback); GB_set_infrared_callback(&gb, infraredStateChanged); @@ -727,6 +728,12 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency) object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateRTCMode) + name:@"GBRTCModeChanged" + object:nil]; + + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dmgModelChanged) name:@"GBDMGModelChanged" object:nil]; @@ -1878,6 +1885,13 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency) }]; } +- (void) updateRTCMode +{ + if (GB_is_inited(&gb)) { + GB_set_rtc_mode(&gb, [[NSUserDefaults standardUserDefaults] integerForKey:@"GBRTCMode"]); + } +} + - (void)dmgModelChanged { modelsChanging = true; diff --git a/Cocoa/GBPreferencesWindow.h b/Cocoa/GBPreferencesWindow.h @@ -12,6 +12,7 @@ @property (nonatomic, strong) IBOutlet NSPopUpButton *colorPalettePopupButton; @property (nonatomic, strong) IBOutlet NSPopUpButton *displayBorderPopupButton; @property (nonatomic, strong) IBOutlet NSPopUpButton *rewindPopupButton; +@property (nonatomic, strong) IBOutlet NSPopUpButton *rtcPopupButton; @property (nonatomic, strong) IBOutlet NSButton *configureJoypadButton; @property (nonatomic, strong) IBOutlet NSButton *skipButton; @property (nonatomic, strong) IBOutlet NSMenuItem *bootROMsFolderItem; diff --git a/Cocoa/GBPreferencesWindow.m b/Cocoa/GBPreferencesWindow.m @@ -19,6 +19,7 @@ NSPopUpButton *_colorPalettePopupButton; NSPopUpButton *_displayBorderPopupButton; NSPopUpButton *_rewindPopupButton; + NSPopUpButton *_rtcPopupButton; NSButton *_aspectRatioCheckbox; NSButton *_analogControlsCheckbox; NSEventModifierFlags previousModifiers; @@ -181,6 +182,18 @@ return _rewindPopupButton; } +- (NSPopUpButton *)rtcPopupButton +{ + return _rtcPopupButton; +} + +- (void)setRtcPopupButton:(NSPopUpButton *)rtcPopupButton +{ + _rtcPopupButton = rtcPopupButton; + NSInteger mode = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBRTCMode"]; + [_rtcPopupButton selectItemAtIndex:mode]; +} + - (void)setHighpassFilterPopupButton:(NSPopUpButton *)highpassFilterPopupButton { _highpassFilterPopupButton = highpassFilterPopupButton; @@ -360,6 +373,14 @@ [[NSNotificationCenter defaultCenter] postNotificationName:@"GBRewindLengthChanged" object:nil]; } +- (IBAction)rtcModeChanged:(id)sender +{ + [[NSUserDefaults standardUserDefaults] setObject:@([sender indexOfSelectedItem]) + forKey:@"GBRTCMode"]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"GBRTCModeChanged" object:nil]; + +} + - (IBAction) configureJoypad:(id)sender { [self.configureJoypadButton setEnabled:NO]; diff --git a/Cocoa/Preferences.xib b/Cocoa/Preferences.xib @@ -77,6 +77,7 @@ <outlet property="playerListButton" destination="gWx-7h-0xq" id="zo6-82-JId"/> <outlet property="preferredJoypadButton" destination="0Az-0R-oNw" id="7JM-tw-BhK"/> <outlet property="rewindPopupButton" destination="7fg-Ww-JjR" id="Ka2-TP-B1x"/> + <outlet property="rtcPopupButton" destination="tFf-H1-XUL" id="zxb-4h-aqg"/> <outlet property="rumbleModePopupButton" destination="Ogs-xG-b4b" id="vuw-VN-MTp"/> <outlet property="sgbPopupButton" destination="dza-T7-RkX" id="B0o-Nb-pIH"/> <outlet property="skipButton" destination="d2I-jU-sLb" id="udX-8K-0sK"/> @@ -85,11 +86,11 @@ <point key="canvasLocation" x="183" y="354"/> </window> <customView id="sRK-wO-K6R"> - <rect key="frame" x="0.0" y="0.0" width="292" height="378"/> + <rect key="frame" x="0.0" y="0.0" width="292" height="375"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <subviews> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="T91-rh-rRp"> - <rect key="frame" x="18" y="341" width="256" height="17"/> + <rect key="frame" x="18" y="338" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Graphics filter:" id="pXg-WY-8Q5"> <font key="font" metaFont="system"/> @@ -98,7 +99,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6pP-kK-EEC"> - <rect key="frame" x="30" y="308" width="234" height="26"/> + <rect key="frame" x="30" y="305" width="234" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Nearest neighbor (Pixelated)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="neN-eo-LA7" id="I1w-05-lGl"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -135,7 +136,7 @@ </connections> </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wc3-2K-6CD"> - <rect key="frame" x="18" y="286" width="256" height="17"/> + <rect key="frame" x="18" y="283" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Color correction:" id="5Si-hz-EK3"> <font key="font" metaFont="system"/> @@ -144,7 +145,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VEz-N4-uP6"> - <rect key="frame" x="30" y="254" width="234" height="26"/> + <rect key="frame" x="30" y="250" width="234" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Disabled" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="D2J-wV-1vu" id="fNJ-Fi-yOm"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -166,7 +167,7 @@ </connections> </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="MLC-Rx-FgO"> - <rect key="frame" x="20" y="178" width="252" height="17"/> + <rect key="frame" x="18" y="174" width="252" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Frame blending" id="UCa-EO-tzh"> <font key="font" metaFont="system"/> @@ -175,7 +176,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lxk-db-Sxv"> - <rect key="frame" x="30" y="149" width="231" height="22"/> + <rect key="frame" x="30" y="145" width="234" height="22"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Disabled" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="iHP-Yz-fiH" id="aQ6-HN-7Aj"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -195,7 +196,7 @@ </connections> </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8fG-zm-hpr"> - <rect key="frame" x="18" y="122" width="252" height="17"/> + <rect key="frame" x="18" y="123" width="252" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Color palette for monochrome models:" id="LAN-8Y-T7H"> <font key="font" metaFont="system"/> @@ -204,7 +205,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Iwr-eI-SD1"> - <rect key="frame" x="30" y="93" width="234" height="22"/> + <rect key="frame" x="30" y="94" width="234" height="22"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Greyscale" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Ajr-5r-iIk" id="rEU-jh-m3j"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -225,7 +226,7 @@ </connections> </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3Kz-cf-5X6"> - <rect key="frame" x="18" y="71" width="248" height="17"/> + <rect key="frame" x="18" y="72" width="248" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Display border:" id="HZd-qi-yyk"> <font key="font" metaFont="system"/> @@ -234,7 +235,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="R9D-FV-bpd"> - <rect key="frame" x="30" y="39" width="234" height="25"/> + <rect key="frame" x="30" y="40" width="234" height="25"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Never" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="1" imageScaling="proportionallyDown" inset="2" selectedItem="heL-AV-0az" id="DY9-2D-h1L"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -253,19 +254,8 @@ <action selector="displayBorderChanged:" target="QvC-M9-y7g" id="GoA-BU-v3h"/> </connections> </popUpButton> - <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vfj-tg-7OP"> - <rect key="frame" x="18" y="18" width="256" height="18"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="check" title="Keep aspect ratio" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="lsj-rC-Eo6"> - <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> - <font key="font" metaFont="system"/> - </buttonCell> - <connections> - <action selector="changeAspectRatio:" target="QvC-M9-y7g" id="mQG-Ib-1jN"/> - </connections> - </button> <slider verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NuA-mL-AJZ"> - <rect key="frame" x="30" y="207" width="230" height="24"/> + <rect key="frame" x="30" y="198" width="234" height="24"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <sliderCell key="cell" continuous="YES" state="on" alignment="left" minValue="-256" maxValue="256" tickMarkPosition="below" numberOfTickMarks="3" sliderType="linear" id="KX7-G9-k0O"/> <connections> @@ -273,7 +263,7 @@ </connections> </slider> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cCm-Oa-FbN"> - <rect key="frame" x="18" y="232" width="252" height="17"/> + <rect key="frame" x="20" y="228" width="252" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Ambient light temperature:" id="Lso-GQ-pBl"> <font key="font" metaFont="system"/> @@ -281,39 +271,26 @@ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> </textFieldCell> </textField> + <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vfj-tg-7OP"> + <rect key="frame" x="18" y="18" width="256" height="18"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <buttonCell key="cell" type="check" title="Keep aspect ratio" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="lsj-rC-Eo6"> + <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> + <font key="font" metaFont="system"/> + </buttonCell> + <connections> + <action selector="changeAspectRatio:" target="QvC-M9-y7g" id="mQG-Ib-1jN"/> + </connections> + </button> </subviews> - <point key="canvasLocation" x="-176" y="667"/> + <point key="canvasLocation" x="-176" y="667.5"/> </customView> <customView id="ymk-46-SX7"> - <rect key="frame" x="0.0" y="0.0" width="292" height="320"/> + <rect key="frame" x="0.0" y="0.0" width="292" height="375"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <subviews> - <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7fg-Ww-JjR"> - <rect key="frame" x="30" y="193" width="234" height="26"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <popUpButtonCell key="cell" type="push" title="Disabled" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="lxQ-4n-kEv" id="lvb-QF-0Ht"> - <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="menu"/> - <menu key="menu" id="lbS-Lw-kQX"> - <items> - <menuItem title="Disabled" state="on" id="lxQ-4n-kEv"> - <modifierMask key="keyEquivalentModifierMask"/> - </menuItem> - <menuItem title="10 Seconds" tag="10" id="bPU-vT-d5z"/> - <menuItem title="30 Seconds" tag="30" id="aR8-IU-fFh"/> - <menuItem title="1 Minute" tag="60" id="E0R-mf-Hdl"/> - <menuItem title="2 Minutes" tag="120" id="zb2-uh-lvj"/> - <menuItem title="5 Minutes" tag="300" id="6Jj-EI-f6k"/> - <menuItem title="10 Minutes" tag="600" id="DOL-qL-Caz"/> - </items> - </menu> - </popUpButtonCell> - <connections> - <action selector="rewindLengthChanged:" target="QvC-M9-y7g" id="5NQ-1T-RNc"/> - </connections> - </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="w9w-yX-KxB"> - <rect key="frame" x="18" y="225" width="256" height="17"/> + <rect key="frame" x="18" y="283" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Rewinding duration:" id="JaO-5h-ugl"> <font key="font" metaFont="system"/> @@ -321,8 +298,17 @@ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> </textFieldCell> </textField> + <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="o3Z-34-FJk"> + <rect key="frame" x="18" y="228" width="252" height="17"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Real Time Clock emulation:" id="Qoi-ub-YtI"> + <font key="font" metaFont="system"/> + <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + </textField> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="MI2-ql-f6M"> - <rect key="frame" x="18" y="283" width="256" height="17"/> + <rect key="frame" x="18" y="338" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Boot ROMs location:" id="nj0-Cb-gEA"> <font key="font" metaFont="system"/> @@ -330,32 +316,8 @@ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> </textFieldCell> </textField> - <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wC4-aJ-mhQ"> - <rect key="frame" x="30" y="251" width="234" height="26"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <popUpButtonCell key="cell" type="push" title="Use built-in boot ROMs" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Tnm-SR-ZEm" id="T3Y-Ln-Onl"> - <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="menu"/> - <menu key="menu" id="edo-AN-gRh"> - <items> - <menuItem title="Use built-in boot ROMs" state="on" id="Tnm-SR-ZEm"> - <connections> - <action selector="useBuiltinBootROMs:" target="QvC-M9-y7g" id="Kmo-wz-ZtB"/> - </connections> - </menuItem> - <menuItem id="Dzv-Gc-zoL"/> - <menuItem isSeparatorItem="YES" id="BqG-uI-xqE"/> - <menuItem title="Other..." id="ikb-cd-hZe"> - <connections> - <action selector="selectOtherBootROMFolder:" target="QvC-M9-y7g" id="ofn-ll-0bo"/> - </connections> - </menuItem> - </items> - </menu> - </popUpButtonCell> - </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wg8-hJ-df9"> - <rect key="frame" x="18" y="157" width="256" height="17"/> + <rect key="frame" x="18" y="160" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Game Boy revision:" id="GIA-ep-SBi"> <font key="font" metaFont="system"/> @@ -364,7 +326,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LFw-Uk-cPR"> - <rect key="frame" x="30" y="125" width="234" height="26"/> + <rect key="frame" x="30" y="127" width="234" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="DMG-CPU B" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="2" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" selectedItem="aXT-sE-m5Z" id="FuX-Hc-uO7"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -383,7 +345,7 @@ </connections> </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="MAq-1X-Gpo"> - <rect key="frame" x="18" y="49" width="256" height="17"/> + <rect key="frame" x="16" y="50" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Game Boy Color revision:" id="edD-t7-vwk"> <font key="font" metaFont="system"/> @@ -392,7 +354,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dlD-sk-SHO"> - <rect key="frame" x="30" y="17" width="234" height="26"/> + <rect key="frame" x="28" y="17" width="234" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="CPU-CGB E" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="517" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" selectedItem="3lF-1Q-2SS" id="Edt-1S-dXz"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -413,7 +375,7 @@ </connections> </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tAa-0A-0fP"> - <rect key="frame" x="18" y="103" width="256" height="17"/> + <rect key="frame" x="18" y="105" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Super Game Boy model:" id="d0g-rk-FK0"> <font key="font" metaFont="system"/> @@ -422,11 +384,11 @@ </textFieldCell> </textField> <box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="mdm-eW-ia1"> - <rect key="frame" x="12" y="180" width="268" height="5"/> + <rect key="frame" x="12" y="183" width="268" height="5"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> </box> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dza-T7-RkX"> - <rect key="frame" x="30" y="71" width="234" height="26"/> + <rect key="frame" x="28" y="72" width="234" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Super Game Boy (NTSC)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="4" imageScaling="proportionallyDown" inset="2" autoenablesItems="NO" selectedItem="x5A-7f-ef9" id="2Mt-ci-bB0"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -443,15 +405,82 @@ <action selector="sgbModelChanged:" target="QvC-M9-y7g" id="ybk-EV-WPS"/> </connections> </popUpButton> + <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tFf-H1-XUL"> + <rect key="frame" x="30" y="199" width="234" height="22"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <popUpButtonCell key="cell" type="push" title="Sync to system clock" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="arp-Qi-Xix" id="uRs-Ag-Sbw"> + <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="menu"/> + <menu key="menu" id="yFf-TQ-bZc"> + <items> + <menuItem title="Sync to system clock" state="on" id="arp-Qi-Xix"> + <modifierMask key="keyEquivalentModifierMask"/> + </menuItem> + <menuItem title="Accurate" id="H7h-S9-hvM"/> + </items> + </menu> + </popUpButtonCell> + <connections> + <action selector="rtcModeChanged:" target="QvC-M9-y7g" id="3fA-mo-MB1"/> + </connections> + </popUpButton> + <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wC4-aJ-mhQ"> + <rect key="frame" x="30" y="305" width="234" height="26"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <popUpButtonCell key="cell" type="push" title="Use built-in boot ROMs" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Tnm-SR-ZEm" id="T3Y-Ln-Onl"> + <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="menu"/> + <menu key="menu" id="edo-AN-gRh"> + <items> + <menuItem title="Use built-in boot ROMs" state="on" id="Tnm-SR-ZEm"> + <connections> + <action selector="useBuiltinBootROMs:" target="QvC-M9-y7g" id="Kmo-wz-ZtB"/> + </connections> + </menuItem> + <menuItem id="Dzv-Gc-zoL"/> + <menuItem isSeparatorItem="YES" id="BqG-uI-xqE"/> + <menuItem title="Other..." id="ikb-cd-hZe"> + <connections> + <action selector="selectOtherBootROMFolder:" target="QvC-M9-y7g" id="ofn-ll-0bo"/> + </connections> + </menuItem> + </items> + </menu> + </popUpButtonCell> + </popUpButton> + <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7fg-Ww-JjR"> + <rect key="frame" x="30" y="250" width="234" height="26"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <popUpButtonCell key="cell" type="push" title="Disabled" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="lxQ-4n-kEv" id="lvb-QF-0Ht"> + <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="menu"/> + <menu key="menu" id="lbS-Lw-kQX"> + <items> + <menuItem title="Disabled" state="on" id="lxQ-4n-kEv"> + <modifierMask key="keyEquivalentModifierMask"/> + </menuItem> + <menuItem title="10 Seconds" tag="10" id="bPU-vT-d5z"/> + <menuItem title="30 Seconds" tag="30" id="aR8-IU-fFh"/> + <menuItem title="1 Minute" tag="60" id="E0R-mf-Hdl"/> + <menuItem title="2 Minutes" tag="120" id="zb2-uh-lvj"/> + <menuItem title="5 Minutes" tag="300" id="6Jj-EI-f6k"/> + <menuItem title="10 Minutes" tag="600" id="DOL-qL-Caz"/> + </items> + </menu> + </popUpButtonCell> + <connections> + <action selector="rewindLengthChanged:" target="QvC-M9-y7g" id="5NQ-1T-RNc"/> + </connections> + </popUpButton> </subviews> - <point key="canvasLocation" x="-176" y="848"/> + <point key="canvasLocation" x="-501" y="667.5"/> </customView> <customView id="Zn1-Y5-RbR"> - <rect key="frame" x="0.0" y="0.0" width="292" height="134"/> + <rect key="frame" x="0.0" y="0.0" width="292" height="135"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <subviews> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="T69-6N-dhT"> - <rect key="frame" x="30" y="65" width="233" height="26"/> + <rect key="frame" x="30" y="65" width="234" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Disabled (Keep DC offset)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Fgo-0S-zUG" id="om2-Bn-43B"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -471,7 +500,7 @@ </connections> </popUpButton> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="WU3-oV-KHO"> - <rect key="frame" x="18" y="97" width="256" height="17"/> + <rect key="frame" x="18" y="98" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="High-pass filter:" id="YLF-RL-b2D"> <font key="font" metaFont="system"/> @@ -489,7 +518,7 @@ </textFieldCell> </textField> <slider verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FpE-5i-j5L"> - <rect key="frame" x="30" y="18" width="232" height="19"/> + <rect key="frame" x="30" y="18" width="234" height="19"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <sliderCell key="cell" continuous="YES" state="on" alignment="left" maxValue="256" tickMarkPosition="below" sliderType="linear" id="Rbx-DU-xYf"/> <connections> @@ -497,14 +526,14 @@ </connections> </slider> </subviews> - <point key="canvasLocation" x="-176" y="914"/> + <point key="canvasLocation" x="-825" y="547.5"/> </customView> <customView id="8TU-6J-NCg"> <rect key="frame" x="0.0" y="0.0" width="292" height="467"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <subviews> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Utu-t4-cLx"> - <rect key="frame" x="10" y="430" width="122" height="17"/> + <rect key="frame" x="18" y="430" width="122" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Control settings for" id="YqW-Ds-VIC"> <font key="font" metaFont="system"/> @@ -522,14 +551,14 @@ </textFieldCell> </textField> <scrollView focusRingType="none" fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" verticalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="PBp-dj-EIa"> - <rect key="frame" x="32" y="208" width="240" height="211"/> + <rect key="frame" x="32" y="208" width="229" height="211"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <clipView key="contentView" focusRingType="none" ambiguous="YES" drawsBackground="NO" id="AMs-PO-nid"> - <rect key="frame" x="1" y="1" width="238" height="209"/> - <autoresizingMask key="autoresizingMask"/> + <rect key="frame" x="1" y="1" width="227" height="209"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" id="UDd-IJ-fxX"> - <rect key="frame" x="0.0" y="0.0" width="238" height="209"/> + <rect key="frame" x="0.0" y="0.0" width="227" height="209"/> <autoresizingMask key="autoresizingMask"/> <size key="intercellSpacing" width="3" height="2"/> <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> @@ -548,7 +577,7 @@ </textFieldCell> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> </tableColumn> - <tableColumn width="116" minWidth="40" maxWidth="1000" id="5VG-zV-WM6"> + <tableColumn width="105" minWidth="40" maxWidth="1000" id="5VG-zV-WM6"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> @@ -589,7 +618,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Az-0R-oNw"> - <rect key="frame" x="42" y="152" width="208" height="26"/> + <rect key="frame" x="42" y="150" width="222" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="None" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingMiddle" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="hy8-cr-RrE" id="uEC-vN-8Jq"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -609,7 +638,7 @@ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> </box> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ReM-uo-H0r"> - <rect key="frame" x="215" y="430" width="8" height="17"/> + <rect key="frame" x="227" y="431" width="8" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title=":" id="VhO-3T-glt"> <font key="font" metaFont="system"/> @@ -618,7 +647,7 @@ </textFieldCell> </textField> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gWx-7h-0xq"> - <rect key="frame" x="131" y="423" width="87" height="26"/> + <rect key="frame" x="140" y="425" width="87" height="26"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Player 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="TO3-R7-9HN" id="pbt-Lr-bU1"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -637,7 +666,7 @@ </connections> </popUpButton> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ogs-xG-b4b"> - <rect key="frame" x="30" y="58" width="245" height="22"/> + <rect key="frame" x="30" y="58" width="234" height="22"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <popUpButtonCell key="cell" type="push" title="Never" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="jki-7x-bnM" id="o9b-MH-8kd"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> @@ -665,26 +694,26 @@ <action selector="changeAnalogControls:" target="QvC-M9-y7g" id="1xR-gY-WKo"/> </connections> </button> - <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d2I-jU-sLb"> - <rect key="frame" x="206" y="13" width="72" height="32"/> + <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Qa7-Z7-yfO"> + <rect key="frame" x="26" y="13" width="169" height="32"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="push" title="Clear" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sug-xy-tbw"> + <buttonCell key="cell" type="push" title="Configure a Controller" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="GdK-tQ-Wim"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="system"/> </buttonCell> <connections> - <action selector="skipButton:" target="QvC-M9-y7g" id="aw8-sw-yJw"/> + <action selector="configureJoypad:" target="QvC-M9-y7g" id="IfY-Kc-PKU"/> </connections> </button> - <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Qa7-Z7-yfO"> - <rect key="frame" x="18" y="13" width="188" height="32"/> + <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d2I-jU-sLb"> + <rect key="frame" x="195" y="13" width="72" height="32"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="push" title="Configure a Controller" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="GdK-tQ-Wim"> + <buttonCell key="cell" type="push" title="Clear" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sug-xy-tbw"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="system"/> </buttonCell> <connections> - <action selector="configureJoypad:" target="QvC-M9-y7g" id="IfY-Kc-PKU"/> + <action selector="skipButton:" target="QvC-M9-y7g" id="aw8-sw-yJw"/> </connections> </button> </subviews> diff --git a/Core/gb.c b/Core/gb.c @@ -664,9 +664,9 @@ int GB_save_battery_to_buffer(GB_gameboy_t *gb, uint8_t *buffer, size_t size) rtc_save.vba64.rtc_latched.days = gb->rtc_latched.days; rtc_save.vba64.rtc_latched.high = gb->rtc_latched.high; #ifdef GB_BIG_ENDIAN - rtc_save.vba64.last_rtc_second = __builtin_bswap64(gb->last_rtc_second); + rtc_save.vba64.last_rtc_second = __builtin_bswap64(time(NULL)); #else - rtc_save.vba64.last_rtc_second = gb->last_rtc_second; + rtc_save.vba64.last_rtc_second = time(NULL); #endif memcpy(buffer + gb->mbc_ram_size, &rtc_save.vba64, sizeof(rtc_save.vba64)); } @@ -728,9 +728,9 @@ int GB_save_battery(GB_gameboy_t *gb, const char *path) rtc_save.vba64.rtc_latched.days = gb->rtc_latched.days; rtc_save.vba64.rtc_latched.high = gb->rtc_latched.high; #ifdef GB_BIG_ENDIAN - rtc_save.vba64.last_rtc_second = __builtin_bswap64(gb->last_rtc_second); + rtc_save.vba64.last_rtc_second = __builtin_bswap64(time(NULL)); #else - rtc_save.vba64.last_rtc_second = gb->last_rtc_second; + rtc_save.vba64.last_rtc_second = time(NULL); #endif if (fwrite(&rtc_save.vba64, 1, sizeof(rtc_save.vba64), f) != sizeof(rtc_save.vba64)) { fclose(f); @@ -976,7 +976,6 @@ uint8_t GB_run(GB_gameboy_t *gb) gb->cycles_since_run = 0; GB_cpu_run(gb); if (gb->vblank_just_occured) { - GB_rtc_run(gb); GB_debugger_handle_async_commands(gb); GB_rewind_push(gb); } @@ -1530,15 +1529,20 @@ void GB_set_clock_multiplier(GB_gameboy_t *gb, double multiplier) uint32_t GB_get_clock_rate(GB_gameboy_t *gb) { + return GB_get_unmultiplied_clock_rate(gb) * gb->clock_multiplier; +} + + +uint32_t GB_get_unmultiplied_clock_rate(GB_gameboy_t *gb) +{ if (gb->model & GB_MODEL_PAL_BIT) { - return SGB_PAL_FREQUENCY * gb->clock_multiplier; + return SGB_PAL_FREQUENCY; } if ((gb->model & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB) { - return SGB_NTSC_FREQUENCY * gb->clock_multiplier; + return SGB_NTSC_FREQUENCY; } - return CPU_FREQUENCY * gb->clock_multiplier; + return CPU_FREQUENCY; } - void GB_set_border_mode(GB_gameboy_t *gb, GB_border_mode_t border_mode) { if (gb->border_mode > GB_BORDER_ALWAYS) return; @@ -1623,3 +1627,12 @@ unsigned GB_time_to_alarm(GB_gameboy_t *gb) if (current_time > alarm_time) return 0; return alarm_time - current_time; } + +void GB_set_rtc_mode(GB_gameboy_t *gb, GB_rtc_mode_t mode) +{ + if (gb->rtc_mode != mode) { + gb->rtc_mode = mode; + gb->rtc_cycles = 0; + gb->last_rtc_second = time(NULL); + } +} diff --git a/Core/gb.h b/Core/gb.h @@ -254,6 +254,11 @@ typedef enum { GB_BOOT_ROM_AGB, } GB_boot_rom_t; +typedef enum { + GB_RTC_MODE_SYNC_TO_HOST, + GB_RTC_MODE_ACCURATE, +} GB_rtc_mode_t; + #ifdef GB_INTERNAL #define LCDC_PERIOD 70224 #define CPU_FREQUENCY 0x400000 @@ -481,6 +486,7 @@ struct GB_gameboy_internal_s { GB_rtc_time_t rtc_real, rtc_latched; uint64_t last_rtc_second; bool rtc_latch; + uint32_t rtc_cycles; ); /* Video Display */ @@ -588,6 +594,7 @@ struct GB_gameboy_internal_s { /* Timing */ uint64_t last_sync; uint64_t cycles_since_last_sync; // In 8MHz units + GB_rtc_mode_t rtc_mode; /* Audio */ GB_apu_output_t apu_output; @@ -798,6 +805,9 @@ void GB_disconnect_serial(GB_gameboy_t *gb); /* For cartridges with an alarm clock */ unsigned GB_time_to_alarm(GB_gameboy_t *gb); // 0 if no alarm +/* RTC emulation mode */ +void GB_set_rtc_mode(GB_gameboy_t *gb, GB_rtc_mode_t mode); + /* For integration with SFC/SNES emulators */ void GB_set_joyp_write_callback(GB_gameboy_t *gb, GB_joyp_write_callback_t callback); void GB_set_icd_pixel_callback(GB_gameboy_t *gb, GB_icd_pixel_callback_t callback); @@ -805,6 +815,7 @@ void GB_set_icd_hreset_callback(GB_gameboy_t *gb, GB_icd_hreset_callback_t callb void GB_set_icd_vreset_callback(GB_gameboy_t *gb, GB_icd_vreset_callback_t callback); uint32_t GB_get_clock_rate(GB_gameboy_t *gb); +uint32_t GB_get_unmultiplied_clock_rate(GB_gameboy_t *gb); void GB_set_clock_multiplier(GB_gameboy_t *gb, double multiplier); unsigned GB_get_screen_width(GB_gameboy_t *gb); diff --git a/Core/timing.c b/Core/timing.c @@ -240,6 +240,70 @@ static void advance_serial(GB_gameboy_t *gb, uint8_t cycles) } +static void GB_rtc_run(GB_gameboy_t *gb, uint8_t cycles) +{ + if (gb->cartridge_type->mbc_type != GB_HUC3 && !gb->cartridge_type->has_rtc) return; + gb->rtc_cycles += cycles; + time_t current_time = 0; + + switch (gb->rtc_mode) { + case GB_RTC_MODE_SYNC_TO_HOST: + // Sync in a 1/32s resolution + if (gb->rtc_cycles < GB_get_unmultiplied_clock_rate(gb) / 16) return; + gb->rtc_cycles -= GB_get_unmultiplied_clock_rate(gb) / 16; + current_time = time(NULL); + break; + case GB_RTC_MODE_ACCURATE: + if (gb->rtc_cycles < GB_get_unmultiplied_clock_rate(gb) * 2) return; + gb->rtc_cycles -= GB_get_unmultiplied_clock_rate(gb) * 2; + current_time = gb->last_rtc_second + 1; + break; + } + + if (gb->cartridge_type->mbc_type == GB_HUC3) { + while (gb->last_rtc_second / 60 < current_time / 60) { + gb->last_rtc_second += 60; + gb->huc3_minutes++; + if (gb->huc3_minutes == 60 * 24) { + gb->huc3_days++; + gb->huc3_minutes = 0; + } + } + return; + } + + if ((gb->rtc_real.high & 0x40) == 0) { /* is timer running? */ + while (gb->last_rtc_second + 60 * 60 * 24 < current_time) { + gb->last_rtc_second += 60 * 60 * 24; + if (++gb->rtc_real.days == 0) { + if (gb->rtc_real.high & 1) { /* Bit 8 of days*/ + gb->rtc_real.high |= 0x80; /* Overflow bit */ + } + gb->rtc_real.high ^= 1; + } + } + + while (gb->last_rtc_second < current_time) { + gb->last_rtc_second++; + if (++gb->rtc_real.seconds != 60) continue; + gb->rtc_real.seconds = 0; + + if (++gb->rtc_real.minutes != 60) continue; + gb->rtc_real.minutes = 0; + + if (++gb->rtc_real.hours != 24) continue; + gb->rtc_real.hours = 0; + + if (++gb->rtc_real.days != 0) continue; + + if (gb->rtc_real.high & 1) { /* Bit 8 of days*/ + gb->rtc_real.high |= 0x80; /* Overflow bit */ + } + } + } +} + + void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles) { gb->apu.pcm_mask[0] = gb->apu.pcm_mask[1] = 0xFF; // Sort of hacky, but too many cross-component interactions to do it right @@ -280,6 +344,7 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles) GB_apu_run(gb); GB_display_run(gb, cycles); GB_ir_run(gb, cycles); + GB_rtc_run(gb, cycles); } /* @@ -303,52 +368,3 @@ void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac) } } } - -void GB_rtc_run(GB_gameboy_t *gb) -{ - if (gb->cartridge_type->mbc_type == GB_HUC3) { - time_t current_time = time(NULL); - while (gb->last_rtc_second / 60 < current_time / 60) { - gb->last_rtc_second += 60; - gb->huc3_minutes++; - if (gb->huc3_minutes == 60 * 24) { - gb->huc3_days++; - gb->huc3_minutes = 0; - } - } - return; - } - - if ((gb->rtc_real.high & 0x40) == 0) { /* is timer running? */ - time_t current_time = time(NULL); - - while (gb->last_rtc_second + 60 * 60 * 24 < current_time) { - gb->last_rtc_second += 60 * 60 * 24; - if (++gb->rtc_real.days == 0) { - if (gb->rtc_real.high & 1) { /* Bit 8 of days*/ - gb->rtc_real.high |= 0x80; /* Overflow bit */ - } - gb->rtc_real.high ^= 1; - } - } - - while (gb->last_rtc_second < current_time) { - gb->last_rtc_second++; - if (++gb->rtc_real.seconds == 60) { - gb->rtc_real.seconds = 0; - if (++gb->rtc_real.minutes == 60) { - gb->rtc_real.minutes = 0; - if (++gb->rtc_real.hours == 24) { - gb->rtc_real.hours = 0; - if (++gb->rtc_real.days == 0) { - if (gb->rtc_real.high & 1) { /* Bit 8 of days*/ - gb->rtc_real.high |= 0x80; /* Overflow bit */ - } - gb->rtc_real.high ^= 1; - } - } - } - } - } - } -} diff --git a/Core/timing.h b/Core/timing.h @@ -4,7 +4,6 @@ #ifdef GB_INTERNAL void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles); -void GB_rtc_run(GB_gameboy_t *gb); void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac); bool GB_timing_sync_turbo(GB_gameboy_t *gb); /* Returns true if should skip frame */ void GB_timing_sync(GB_gameboy_t *gb);
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.