AlexOberhofer/SDL2-GNUBoy

sys_sleep doesnt guard against negative delays

Ryzee119 opened this issue · 3 comments

If the frame time is longer than framelen, the delay will be negative. See

delay = framelen - sys_elapsed(timer);

sys_sleep in nix and windows dont check this and will hang. I encountered this went disabling sound.

Upsteam does this:
https://github.com/rofl0r/gnuboy/blob/1655356c6430c7c68c3c6071e1a44e3bea5066e9/sys/nix/nix.c#L63

Secondly,

pcm_submit always returns 1. This should return 0 if not using sound to fall back to the manual delay

int pcm_submit()
{
#ifdef SOUND
if (!pcm.buf)
return 0;
if (pcm.pos < pcm.len)
return 1;
while (!audio_done)
SDL_Delay(4);
audio_done = 0;
pcm.pos = 0;
#endif
return 1;
}

Both these fixes need to be implemented to allow disabling sound while maintaining accurate timing

Do you have recreation steps in how you were getting the application to hang up? It still seems to freeze up when resizing/moving the window when the binary was compiled with the SILENT flag

Adding an extra check to the system sleep similar to how it was done in upstream allows me to move/resize without hanging the emulation thread... Are there any other use cases I should try before I merge in that fix? See PR #9

Normally this wouldnt actually happen as the code always did this manual delay and never returned 0 so the alternate delay loop never was called. If you did disable sound the game just ran really fast.

SDL_Delay(4);

It occurred if you disabled sound and made that function return 0 like its meant to, which made it fallback to the alternative delay:

SDL2-GNUBoy/src/emu.c

Lines 86 to 91 in f4427f2

if (!pcm_submit())
{
delay = framelen - sys_elapsed(timer);
sys_sleep(delay);
sys_elapsed(timer);
}