Fixed problem with frames running ahead of the sound thread.

This involved fixing V65C02 (by subtracting out cycle overruns) and fixing
the main thread callback wait loop. As someone once said, "Threading is
hard." :-P
This commit is contained in:
Shamus Hammons 2013-09-11 17:33:54 -05:00
parent a2e007c1e0
commit cf5ff906a6
3 changed files with 32 additions and 4 deletions

View File

@ -188,6 +188,7 @@ WriteLog("CPU: Execute65C02(&mainCPU, cycles);\n");
}
#endif
WriteLog("CPUThread: Supposedly end of frame...\n");
#ifdef THREAD_DEBUGGING
WriteLog("CPU: SDL_mutexP(cpuMutex);\n");
@ -1155,6 +1156,8 @@ Z $DA $9A $DA $9A
ESC $9B $9B $9B $9B No xlation
*/
static uint64_t lastCPUCycles = 0;
static uint32_t frameCount = 0;
static void FrameCallback(void)
{
SDL_Event event;
@ -1297,7 +1300,7 @@ else if (event.key.keysym.sym == SDLK_F10)
}
}
#warning "!!! Taking MAJOR time hit with the video frame rendering !!!"
//#warning "!!! Taking MAJOR time hit with the video frame rendering !!!"
RenderVideoFrame();
SetCallbackTime(FrameCallback, 16666.66666667);
@ -1321,10 +1324,26 @@ if (counter == 60)
//Actually, slows things down too much...
//SDL_Delay(10);
// while (SDL_GetTicks() - startTicks < 16); // Wait for next frame...
while (SDL_GetTicks() - startTicks < 16)
// This is the problem: If you set the interval to 16, it runs faster than
// 1/60s per frame. If you set it to 17, it runs slower. What we need is to
// have it do 16 for one frame, then 17 for two others. Then it should average
// out to 1/60s per frame every 3 frames.
frameCount = (frameCount + 1) % 3;
uint32_t waitFrameTime = 17 - (frameCount == 0 ? 1 : 0);
while (SDL_GetTicks() - startTicks < waitFrameTime)
SDL_Delay(1); // Wait for next frame...
startTicks = SDL_GetTicks();
#if 1
uint64_t cpuCycles = GetCurrentV65C02Clock();
uint32_t cyclesBurned = (uint32_t)(cpuCycles - lastCPUCycles);
WriteLog("FrameCallback: used %i cycles\n", cyclesBurned);
lastCPUCycles = cpuCycles;
#endif
//let's wait, then signal...
//works longer, but then still falls behind...
#ifdef THREADED_65C02

View File

@ -162,7 +162,7 @@ static void SDLSoundCallback(void * /*userdata*/, Uint8 * buffer8, int length8)
// Let's try using a mutex for shared resource consumption...
//Actually, I think Lock/UnlockAudio() does this already...
//WriteLog("SDLSoundCallback(): SDL_mutexP(mutex2)\n");
WriteLog("SDLSoundCallback: soundBufferPos = %i\n", soundBufferPos);
SDL_mutexP(mutex2);
// Recast this as a 16-bit type...

View File

@ -2850,6 +2850,9 @@ bool dumpDis = false;
//bleh.
//static uint32_t limit = 0;
// This should be in the regs struct, in case we have multiple CPUs...
#warning "!!! Move overflow into regs struct !!!"
static uint64_t overflow = 0;
//
// Function to execute 65C02 for "cycles" cycles
//
@ -2875,7 +2878,7 @@ Let's see...
if (regs.clock + cycles > 0xFFFFFFFF)
wraparound = true;
*/
uint64_t endCycles = regs.clock + (uint64_t)cycles;
uint64_t endCycles = regs.clock + (uint64_t)cycles - overflow;
while (regs.clock < endCycles)
{
@ -3020,6 +3023,12 @@ WriteLog("\n*** IRQ ***\n\n");
}
}
// If we went longer than the passed in cycles, make a note of it so we can
// subtract it out from a subsequent run. It's guaranteed to be positive,
// because the condition that exits the main loop above is written such
// that regs.clock has to be larger than endCycles to exit from it.
overflow = regs.clock - endCycles;
myMemcpy(context, &regs, sizeof(V65C02REGS));
}