/** ** Wait for interactive input event. ** ** Handles X11 events, keyboard, mouse. ** Video interrupt for sync. ** Network messages. ** Sound queue. ** ** We must handle atlast one X11 event ** ** FIXME: the initialition could be moved out of the loop */ global void WaitEventsAndKeepSync(void) { #if 0 int connection; int sound; fd_set readfd; fd_set writefd; int maxfd; sound=0; for( ;; ) { if( XPending(TheDisplay) ) { DoEvent(); } if( VideoInterrupts ) { return; } FD_ZERO(&readfd); maxfd=connection=ConnectionNumber(TheDisplay); FD_SET(connection,&readfd); FD_ZERO(&writefd); #ifndef USE_THREAD if( !SoundOff && (sound=SoundFildes)!=-1 ) { if( sound>maxfd ) { maxfd=sound; } FD_SET(sound,&writefd); } #else if( !SoundOff && !SoundThreadRunning && (sound=SoundFildes)!=-1 ) { if( sound>maxfd ) { maxfd=sound; } FD_SET(sound,&writefd); } #endif if( NetworkFildes!=-1 ) { if( NetworkFildes>maxfd ) { maxfd=NetworkFildes; } FD_SET(NetworkFildes,&readfd); } maxfd=select(maxfd+1,&readfd,&writefd,0,0); if( VideoInterrupts ) { return; } if( maxfd!=-1 ) { #ifndef USE_THREAD if( !SoundOff && sound!=-1 && FD_ISSET(sound,&writefd) ) { WriteSound(); continue; } #else if( !SoundOff && !SoundThreadRunning && sound!=-1 && FD_ISSET(sound,&writefd) ) { WriteSound(); continue; } #endif if( NetworkFildes!=-1 && FD_ISSET(NetworkFildes,&readfd) ) { NetworkEvent(); continue; } DoEvent(); } } #endif struct timeval tv; fd_set rfds; fd_set wfds; int maxfd; int* xfd; int n; int i; int morex; int connection; connection=ConnectionNumber(TheDisplay); for( ;; ) { // // Prepare select // tv.tv_sec=0; tv.tv_usec=0; FD_ZERO(&rfds); FD_ZERO(&wfds); maxfd=0; // // X11 how many events already in que // xfd=NULL; morex=XQLength(TheDisplay); if( !morex ) { // // X11 connections number // maxfd=connection; FD_SET(connection,&rfds); // // Get all X11 internal connections // if( !XInternalConnectionNumbers(TheDisplay,&xfd,&n) ) { DebugLevel0(__FUNCTION__": out of memory\n"); abort(); } for( i=n; i--; ) { FD_SET(xfd[i],&rfds); if( xfd[i]>maxfd ) { maxfd=xfd[i]; } } } // // Network // if( NetworkFildes!=-1 ) { if( NetworkFildes>maxfd ) { maxfd=NetworkFildes; } FD_SET(NetworkFildes,&rfds); } // // Sound // if( !SoundOff && !SoundThreadRunning ) { if( SoundFildes>maxfd ) { maxfd=SoundFildes; } FD_SET(SoundFildes,&wfds); } maxfd=select(maxfd+1,&rfds,&wfds,NULL,morex ? &tv : NULL); // // X11 // if( maxfd>0 ) { if( !morex ) { for( i=n; i--; ) { if( FD_ISSET(xfd[i],&rfds) ) { XProcessInternalConnection(TheDisplay,xfd[i]); } } XFree(xfd); if( FD_ISSET(connection,&rfds) ) { XEventsQueued(TheDisplay,QueuedAfterReading); } morex=XQLength(TheDisplay); } } if( morex ) { // handle new + *OLD* x11 events DoEvent(); } if( maxfd>0 ) { // // Network // if( NetworkFildes!=-1 && FD_ISSET(NetworkFildes,&rfds) ) { NetworkEvent(); } // // Network in sync and time for frame over: return // if( !morex && NetworkInSync && VideoInterrupts ) { return; } // // Sound // if( !SoundOff && !SoundThreadRunning && FD_ISSET(SoundFildes,&wfds) ) { WriteSound(); } } // // Network in sync and time for frame over: return // if( !morex && NetworkInSync && VideoInterrupts ) { return; } } }
/** ** Wait for interactive input event. ** ** Handles X11 events, keyboard, mouse. ** Video interrupt for sync. ** Network messages. ** Sound queue. ** ** We must handle atlast one X11 event ** ** FIXME: the initialition could be moved out of the loop */ global void WaitEventsAndKeepSync(void) { #ifndef USE_WIN32 struct timeval tv; fd_set rfds; fd_set wfds; int maxfd; #endif SDL_Event event[1]; for(;;) { // Not very nice, but this is the problem if you use other libraries // The event handling of SDL is very buggy and wrong designed. if( SDL_PollEvent(event) ) { // Handle SDL event DoEvent(event); } else { #ifndef USE_WIN32 // // Prepare select // tv.tv_sec=0; tv.tv_usec=0; FD_ZERO(&rfds); FD_ZERO(&wfds); maxfd=0; // // Network // if( NetworkFildes!=-1 ) { if( NetworkFildes>maxfd ) { maxfd=NetworkFildes; } FD_SET(NetworkFildes,&rfds); } // // Sound // if( !SoundOff && !SoundThreadRunning ) { if( SoundFildes>maxfd ) { maxfd=SoundFildes; } FD_SET(SoundFildes,&wfds); } maxfd=select(maxfd+1,&rfds,&wfds,NULL ,SDL_PollEvent(NULL) ? &tv : NULL); if( maxfd>0 ) { // // Network // if( NetworkFildes!=-1 && FD_ISSET(NetworkFildes,&rfds) ) { NetworkEvent(); } // // Network in sync and time for frame over: return // if( NetworkInSync && VideoInterrupts ) { return; } // // Sound // if( !SoundOff && !SoundThreadRunning && FD_ISSET(SoundFildes,&wfds) ) { WriteSound(); } } #endif } // // Network in sync and time for frame over: return // if(NetworkInSync && VideoInterrupts) { return; } } }
/** * Update the video, audio, and input subsystems with the provided * video (XBuf) and audio (Buffer) information. */ void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count) { extern int FCEUDnetplay; #ifdef CREATE_AVI if(LoggingEnabled == 2 || (eoptions&EO_NOTHROTTLE)) { if(LoggingEnabled == 2) { int16* MonoBuf = new int16[Count]; int n; for(n=0; n<Count; ++n) MonoBuf[n] = Buffer[n] & 0xFFFF; NESVideoLoggingAudio ( MonoBuf, FSettings.SndRate, 16, 1, Count ); delete [] MonoBuf; } Count /= 2; if(inited & 1) { if(Count > GetWriteSound()) Count = GetWriteSound(); if (!mutecapture) if(Count > 0 && Buffer) WriteSound(Buffer,Count); } if(inited & 2) FCEUD_UpdateInput(); if(XBuf && (inited & 4)) BlitScreen(XBuf); //SpeedThrottle(); return; } #endif int ocount = Count; // apply frame scaling to Count Count = (int)(Count / g_fpsScale); if(Count) { int32 can=GetWriteSound(); static int uflow=0; int32 tmpcan; // don't underflow when scaling fps if(can >= GetMaxSound() && g_fpsScale==1.0) uflow=1; /* Go into massive underflow mode. */ if(can > Count) can=Count; else uflow=0; #ifdef CREATE_AVI if (!mutecapture) #endif WriteSound(Buffer,can); //if(uflow) puts("Underflow"); tmpcan = GetWriteSound(); // don't underflow when scaling fps if(g_fpsScale>1.0 || ((tmpcan < Count*0.90) && !uflow)) { if(XBuf && (inited&4) && !(NoWaiting & 2)) BlitScreen(XBuf); Buffer+=can; Count-=can; if(Count) { if(NoWaiting) { can=GetWriteSound(); if(Count>can) Count=can; #ifdef CREATE_AVI if (!mutecapture) #endif WriteSound(Buffer,Count); } else { while(Count>0) { #ifdef CREATE_AVI if (!mutecapture) #endif WriteSound(Buffer,(Count<ocount) ? Count : ocount); Count -= ocount; } } } } //else puts("Skipped"); else if(!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 1.8))) { if(Count > tmpcan) Count=tmpcan; while(tmpcan > 0) { // printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan); #ifdef CREATE_AVI if (!mutecapture) #endif WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan); tmpcan -= Count; } } } else { if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused())) while (SpeedThrottle()) { FCEUD_UpdateInput(); } if(XBuf && (inited&4)) { BlitScreen(XBuf); } } FCEUD_UpdateInput(); //if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE)) // SpeedThrottle(); //if(XBuf && (inited&4)) //{ // BlitScreen(XBuf); //} //if(Count) // WriteSound(Buffer,Count,NoWaiting); //FCEUD_UpdateInput(); }