-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optionally add underclocking of TIMER and potentially overall. #495
Comments
An exact CPU cycle match is not a goal of this project, it really isn't possible due to the way QB64 works. As such a setting to emulate a specific MHz CPU speed just isn't going to be implemented (mostly because it's not really possible to do in an effective way). That said, the other things are a bit different:
I would say overall though that delays like looping on |
Thanks for providing the alternatives and input on other issues. I suppose (with the suggested optional mode) accessing TIMER could actually sleep CPU when the TIMER global is accessed (let CPU rest 1ms maybe? The math would have to be worked out, but that may be fine enough since even locking to 60fps is 16.6... [repeating 6] ms so it is probably fine-grained enough) so then you'd know where the delay should go (:edit: except for games that just assume a clock speed and don't even do frame locking. That's why I mentioned FLOPS...it would be possible to count the number of FLOPS and limit the FLOPS that way, placing the delay wherever math is done too many times per second, though maybe that is ugly). My goal is to get old programs to work. Certain games have awkward custom licenses not allowing redistribution, but I understand you don't want to encourage bad patterns. I'll try to find a timer example used in this way (which would max CPU if code is used literally) but so far I only found: Just demos, so it is hard to tell if speed is as expected: |
@Poikilos thanks so much for sharing this repo: https://github.com/robhagemans/hoard-of-gwbasic/tree/master ! |
@grymmjack You're welcome. I found it almost by chance! GitHub (using Linguist) often doesn't label repos as BASIC correctly, but:
|
@Poikilos Oh that is a great trick! I will add my own language detection fixes to my repos. Smart thinking on how to search too! You might find some more by using |
Is your feature request related to a problem? Please describe.
Back when QBasic was popular for making indie games, a "tick" wasn't a fixed millisecond or microsecond. It could be a CPU cycle, and entirely dependent on the clock speed of the CPU. Certain old QBasic games, like certain other DOS games, depend on the speed of the CPU in order to run properly. For example, if a game programmed for a 66 MHz processor were played on a 133Mhz processor, the game would be approximately double the speed and be unplayable. Specifically, TIMER seems to be the CPU cycle divided by 18.2 (according to https://www.tek-tips.com/faqs.cfm?fid=917), which seems like entirely different behavior than described at https://qb64phoenix.com/qb64wiki/index.php/TIMER. There were some games that tried to count the number of TIMER ticks in one second, which I tried to do, but once the clock speed got above a certain point, that wouldn't work anymore and would just max out the CPU then cause an integer overflow...unless my math didn't account for it flipping around to 0 more quickly than expected. Even if it did, my code isn't the only code out there. Games that expected TIMER not to flip to 0 (or not to flip to 0 more than once) over the course of 1 frame still wouldn't work. In the worse case, some games don't even attempt to use frame locking--they just assume the computer's speed, and only work correctly on old computers (games of this era typically only run at the correct speed on a 33MHz or 66MHz processor).
Describe the solution you'd like
A "virtual MHz" compile option to affect either or both (maybe allow enabling each separately):
Describe alternatives you've considered
DOSBox or changing the code: but neither is ideal since compatibility with old code is a goal of this project.
Additional context
List of framerate locking methods of old QBasic games (may require being split into different issues):
WAIT &H3DA, 8
: waits for next screen refresh--This is probably the most reliable method, though is technically affected by hardware (such as 120 Hz displays or CRTs with odd refresh rates) and therefore would also need underclocking to produce expected behavior. Examples:WAIT &H3DA, 8, 8
on next line, not sure why)WAIT &H3DA, 8
: https://github.com/goalieca/ancient-code1/blob/master/breakout-qbasic/BREAKOUT.BASWAIT 938, 8
I'm not sure why this is used instead ofWAIT &H3DA, 8
(3DA is 986 in decimal; 938 would be 3AA), but it runs a little fast on my 60Hz display on Fedora 38 and the reason is not clear. Example: Spinball at https://www.qbasic.net/en/qbasic-downloads/games/action-3.htmThe text was updated successfully, but these errors were encountered: