diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 2fd3d336..c00a6b8a 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -154,6 +154,9 @@ static Bitu Normal_Loop(void) { } } +//For trying other delays +#define wrap_delay(a) SDL_Delay(a) + void increaseticks() { //Make it return ticksRemain and set it in the function above to remove the global variable. if (GCC_UNLIKELY(ticksLocked)) { // For Fast Forward Mode ticksRemain=5; @@ -164,14 +167,36 @@ void increaseticks() { //Make it return ticksRemain and set it in the function a ticksScheduled = 0; return; } + + static Bit32s lastsleepDone = -1; + static Bitu sleep1count = 0; Bit32u ticksNew; ticksNew = GetTicks(); ticksScheduled += ticksAdded; if (ticksNew <= ticksLast) { //lower should not be possible, only equal. ticksAdded = 0; - SDL_Delay(1); - ticksDone -= GetTicks() - ticksNew; + + if (!CPU_CycleAutoAdjust || CPU_SkipCycleAutoAdjust || sleep1count < 3) { + wrap_delay(1); + } else { + /* Certain configurations always give an exact sleepingtime of 1, this causes problems due to the fact that + dosbox keeps track of full blocks. + This code introduces some randomness to the time slept, which improves stability on those configurations + */ + static const Bit32u sleeppattern[] = { 2, 2, 3, 2, 2, 4, 2}; + static Bit32u sleepindex = 0; + if (ticksDone != lastsleepDone) sleepindex = 0; + wrap_delay(sleeppattern[sleepindex++]); + sleepindex %= sizeof(sleeppattern) / sizeof(sleeppattern[0]); + } + Bit32s timeslept = GetTicks() - ticksNew; + // Count how many times in the current block (of 250 ms) the time slept was 1 ms + if (CPU_CycleAutoAdjust && !CPU_SkipCycleAutoAdjust && timeslept == 1) sleep1count++; + lastsleepDone = ticksDone; + + // Update ticksDone with the time spent sleeping + ticksDone -= timeslept; if (ticksDone < 0) ticksDone = 0; return; //0 @@ -249,9 +274,13 @@ void increaseticks() { //Make it return ticksRemain and set it in the function a } } } + + //Reset cycleguessing parameters. CPU_IODelayRemoved = 0; ticksDone = 0; ticksScheduled = 0; + lastsleepDone = -1; + sleep1count = 0; } else if (ticksAdded > 15) { /* ticksAdded > 15 but ticksScheduled < 5, lower the cycles but do not reset the scheduled/done ticks to take them into