📄 emuthread.cpp
字号:
::SetEvent( g_hEventAccept );
break;
case EV_FRAMESKIP_AUTO:
if( !NetPlay.IsConnect() ) {
DirectDraw.SetMessageString( "FrameSkip Auto." );
nFrameSkip = 0;
}
::SetEvent( g_hEventAccept );
break;
case EV_FRAMESKIP_UP:
if( !NetPlay.IsConnect() ) {
if( nFrameSkip < 20 )
nFrameSkip++;
::wsprintf( szStr, "FrameSkip %d", nFrameSkip );
DirectDraw.SetMessageString( szStr );
}
::SetEvent( g_hEventAccept );
break;
case EV_FRAMESKIP_DOWN:
if( !NetPlay.IsConnect() ) {
if( nFrameSkip )
nFrameSkip--;
if( nFrameSkip ) {
::wsprintf( szStr, "FrameSkip %d", nFrameSkip );
DirectDraw.SetMessageString( szStr );
} else {
DirectDraw.SetMessageString( "FrameSkip Auto." );
}
}
::SetEvent( g_hEventAccept );
break;
case EV_STATE_LOAD:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
if( g_nes->LoadState( (const char*)Param ) ) {
if( Param2 < 0 )
::wsprintf( szStr, "State Load." );
else
::wsprintf( szStr, "State Load #%d", Param2 );
DirectDraw.SetMessageString( szStr );
}
} else {
netev.Event = EV_STATE_LOAD;
netev.Param = 0;
NetEventQueue.push_back( netev );
}
}
::SetEvent( g_hEventAccept );
break;
case EV_STATE_SAVE:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
if( g_nes->SaveState( (const char*)Param ) ) {
if( Param2 < 0 )
::wsprintf( szStr, "State Save." );
else
::wsprintf( szStr, "State Save #%d", Param2 );
DirectDraw.SetMessageString( szStr );
}
} else {
netev.Event = EV_STATE_SAVE;
netev.Param = 0;
NetEventQueue.push_back( netev );
}
}
::SetEvent( g_hEventAccept );
break;
case EV_DISK_COMMAND:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
DiskCommand( Param );
} else {
netev.Event = EV_DISK_COMMAND;
netev.Param = Param;
NetEventQueue.push_back( netev );
}
}
::SetEvent( g_hEventAccept );
break;
case EV_EXCONTROLLER:
if( g_nes )
g_nes->CommandParam( NES::NESCMD_EXCONTROLLER, Param );
::SetEvent( g_hEventAccept );
break;
case EV_SOUND_MUTE:
{
if( g_nes )
if( g_nes->CommandParam( NES::NESCMD_SOUND_MUTE, Param ) ) {
::wsprintf( szStr, "%s Enable.", g_lpSoundMuteStringTable[Param] );
} else {
::wsprintf( szStr, "%s Mute.", g_lpSoundMuteStringTable[Param] );
}
DirectDraw.SetMessageString( szStr );
}
::SetEvent( g_hEventAccept );
break;
case EV_MOVIE_PLAY:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
if( g_nes->MoviePlay( (const char*)Param ) ) {
DirectDraw.SetMessageString( "Movie replay." );
}
}
}
::SetEvent( g_hEventAccept );
break;
case EV_MOVIE_REC:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
if( g_nes->MovieRec( (const char*)Param ) ) {
DirectDraw.SetMessageString( "Movie record." );
}
}
}
::SetEvent( g_hEventAccept );
break;
case EV_MOVIE_RECAPPEND:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
if( g_nes->MovieRecAppend( (const char*)Param ) ) {
DirectDraw.SetMessageString( "Movie append record." );
}
}
}
::SetEvent( g_hEventAccept );
break;
case EV_MOVIE_STOP:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
g_nes->MovieStop();
}
}
::SetEvent( g_hEventAccept );
break;
case EV_SNAPSHOT:
if( g_nes ) {
if( g_nes->Snapshot() ) {
DirectDraw.SetMessageString( "Snap shot." );
}
}
::SetEvent( g_hEventAccept );
break;
case EV_WAVEREC_START:
if( g_nes ) {
DWORD nRate, nBits;
DirectSound.GetSamplingRate( nRate, nBits );
g_WaveRec.Start( (LPSTR)Param, nRate, nBits, FALSE );
}
DirectDraw.SetMessageString( "Wave recording start." );
::SetEvent( g_hEventAccept );
break;
case EV_WAVEREC_STOP:
if( g_nes ) {
g_WaveRec.Stop();
DirectDraw.SetMessageString( "Wave recording stop." );
}
::SetEvent( g_hEventAccept );
break;
case EV_TAPE_PLAY:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
if( g_nes->TapePlay( (const char*)Param ) ) {
DirectDraw.SetMessageString( "Tape play." );
}
}
}
::SetEvent( g_hEventAccept );
break;
case EV_TAPE_REC:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
if( g_nes->TapeRec( (const char*)Param ) ) {
DirectDraw.SetMessageString( "Tape record." );
}
}
}
::SetEvent( g_hEventAccept );
break;
case EV_TAPE_STOP:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
g_nes->TapeStop();
}
}
::SetEvent( g_hEventAccept );
break;
case EV_BARCODE:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
g_nes->SetBarcodeData( (LPBYTE)Param, (INT)Param2 );
}
}
::SetEvent( g_hEventAccept );
break;
case EV_TURBOFILE:
if( g_nes ) {
if( !NetPlay.IsConnect() ) {
g_nes->SetTurboFileBank( (INT)Param );
}
}
::SetEvent( g_hEventAccept );
break;
case EV_MESSAGE_OUT:
DirectDraw.SetMessageString( (LPSTR)Param );
::SetEvent( g_hEventAccept );
break;
default:
DEBUGOUT( "ThreadProc:Unknown event.\n" );
::SetEvent( g_hEventAccept );
break;
}
} catch( CHAR* str ) {
bPause = TRUE;
::strcpy( g_szErrorMessage, str );
::PostMessage( g_hWnd, WM_VNS_ERRORMSG, 0, (LPARAM)g_szErrorMessage );
::SetEvent( g_hEventAccept );
#ifndef _DEBUG
} catch(...) {
bPause = TRUE;
::PostMessage( g_hWnd, WM_VNS_ERRORMSG, 0, (LPARAM)CApp::GetErrorString( IDS_ERROR_UNKNOWN ) );
::SetEvent( g_hEventAccept );
#endif
}
if( bPause ) {
// 僀儀儞僩敪惗偺堊
DirectInput.Poll();
// 偐偭偙埆偄乧
CMainFrame::OnKeyControl();
// 屇偽側偄偲Windows偑廳偔側傞偺偱(NT宯埲奜偼摿偵)
::Sleep( 20 );
} else {
try {
INT nNetBuffer = 0;
BOOL bNoFrame = FALSE;
BOOL bAddFrame = FALSE;
bSleep = TRUE;
if( !NetPlay.IsConnect() ) {
// 捠忢
BOOL bKeyThrottle = FALSE;
// 僉乕僠僃僢僋
{
BYTE* pKey = (BYTE*)DirectInput.m_Sw;
WORD* pShortCutKey = Config.shortcut.nShortCut;
INT* pShortCutKeyID = Config.ShortcutKeyID;
for( INT i = 0; pShortCutKeyID[i*3+0]; i++ ) {
if( pShortCutKeyID[i*3+0] == ID_KEYTHROTTLE ) {
if( (pKey[pShortCutKey[pShortCutKeyID[i*3+2] ]] & 0x80) && pShortCutKey[pShortCutKeyID[i*3+2] ]
|| (pKey[pShortCutKey[pShortCutKeyID[i*3+2]+128]] & 0x80) && pShortCutKey[pShortCutKeyID[i*3+2]+128] ) {
bKeyThrottle = TRUE;
}
break;
}
}
}
if( Config.general.bScreenMode ) {
// FullScreen
// if( Config.graphics.bSyncDraw ) {
if( Config.graphics.bSyncDraw && Config.graphics.bSyncNoSleep ) {
bSleep = FALSE;
} else if( Config.emulator.bAutoFrameSkip ) {
bSleep = TRUE;
} else {
bSleep = FALSE;
}
} else {
// Window
// if( Config.graphics.bWindowVSync ) {
if( Config.graphics.bWindowVSync && Config.graphics.bSyncNoSleep ) {
bSleep = FALSE;
} else if( Config.emulator.bAutoFrameSkip ) {
bSleep = TRUE;
} else {
bSleep = FALSE;
}
}
frame_period = 1000.0/g_nes->nescfg->FrameRate;
// 僼儗乕儉僗僉僢僾悢偺寁嶼
current_time = ::timeGetTime();
now_time = current_time - start_time;
if( Config.emulator.bAutoFrameSkip && bSleep ) {
if( g_nes->IsDiskThrottle() ) {
frame_period = g_nes->nescfg->FramePeriod/10.0f;
} else if( !nFrameSkip ) {
// Auto
double fps = 0.0;
if( (bThrottle||bKeyThrottle) ) {
fps = (double)Config.emulator.nThrottleFPS;
} else {
fps = g_nes->nescfg->FrameRate;
}
if( fps < 0.0 ) fps = 60.0;
if( fps > 600.0 ) fps = 600.0;
frame_period = 1000.0/fps;
} else {
frame_period = (1000.0/g_nes->nescfg->FrameRate)/(nFrameSkip+1);
}
if( !nFrameSkip && !g_nes->IsDiskThrottle() ) {
frameskipno = (INT)(((double)now_time-frame_time) / frame_period);
if( frameskipno < 0 || frameskipno > 20 ) {
frameskipno = 1;
frame_time = 0.0;
start_time = ::timeGetTime();
}
} else if( g_nes->IsDiskThrottle() ) {
frameskipno = 10;
frame_time = 0.0;
start_time = ::timeGetTime();
} else {
if( nFrameSkip < 0 )
frameskipno = 1;
else
frameskipno = nFrameSkip+1;
}
} else {
if( g_nes->IsDiskThrottle() ) {
frameskipno = 10;
}
if( bThrottle||bKeyThrottle ) {
frameskipno = (INT)(((double)Config.emulator.nThrottleFPS+30)/60.0);
} else {
// 僆乕僩傪奜偟偰VSYNC摨婜偺帪偵傕僼儗乕儉僗僉僢僾傪偡傞堊偺慬抲
if( nFrameSkip < 0 ) {
frameskipno = 1;
} else {
frameskipno = nFrameSkip+1;
}
}
}
} else {
bSleep = TRUE;
// 僱僢僩僾儗僀拞偼僼儗乕儉僗僉僢僾晄壜
frame_period = 1000.0/g_nes->nescfg->FrameRate;
// 僼儗乕儉僗僉僢僾悢偺寁嶼
current_time = ::timeGetTime();
now_time = current_time - start_time;
frameskipno = (INT)(((double)now_time-frame_time) / frame_period);
if( frameskipno > 20-1 ) {
frameskipno = 20;
frame_time = 0.0f;
start_time = ::timeGetTime();
}
if( !NetPlay.RecvBuffer() ) {
bPause = TRUE;
goto _emulate_error;
}
// 僶僢僼傽晄懌偱彮偟抶傜偣傞傋偒偐偳偆偐偺僠僃僢僋
INT ret = NetPlay.BufferCheck();
if( ret > 0 ) {
bAddFrame = TRUE;
if( frameskipno > 1 ) {
frameskipno++;
} else {
frameskipno = 2;
}
}
if( ret < 0 ) {
bNoFrame = TRUE;
}
// Timeout check
if( bNoFrame ) {
nNetTimeoutCount++;
if( nNetTimeoutCount > 10*60 ) {
NetPlay.Disconnect();
bPause = TRUE;
goto _emulate_error;
}
} else {
nNetTimeoutCount = 0;
}
nNetBuffer = NetPlay.GetRecvBufferSize();
}
// Emulation
if( (!bEmuPause || bOneStep) && g_nes ) {
g_nes->ppu->SetScreenPtr( DirectDraw.GetRenderScreen(), DirectDraw.GetLineColormode() );
if( !bOneStep ) {
for( i = 0; i < frameskipno-1; i++ ) {
if( !bNoFrame ) {
// Skip frames
if( !FrameInput() ) {
bPause = TRUE;
goto _emulate_error;
}
g_nes->EmulateFrame( FALSE );
}
if( !bAddFrame ) {
frame_time += frame_period;
}
bAddFrame = FALSE;
// Sound streaming
StreamProcess( bEmuPause );
}
}
if( !bNoFrame ) {
if( !FrameInput() ) {
bPause = TRUE;
goto _emulate_error;
}
g_nes->EmulateFrame( TRUE );
}
frame_time += frame_period;
} else {
// 僀儀儞僩敪惗偺堊
DirectInput.Poll();
for( i = 0; i < frameskipno-1; i++ ) {
frame_time += frame_period;
}
frame_time += frame_period;
}
// 偐偭偙埆偄乧
CMainFrame::OnKeyControl();
// // 昤夋
// if( g_nes->ppu->GetExtMonoMode() ) {
// DirectDraw.SetPaletteMode( (PPUREG[1]&PPU_BGCOLOR_BIT)>>5, 0 );
// } else {
// DirectDraw.SetPaletteMode( (PPUREG[1]&PPU_BGCOLOR_BIT)>>5, PPUREG[1]&PPU_COLORMODE_BIT );
// }
// 僨傿僗僋傾僋僙僗儔儞僾
DirectDraw.SetDiskAccessLamp( (Config.graphics.bDiskAccessLamp && g_nes->mapper->ExCmdRead( Mapper::EXCMDRD_DISKACCESS ))?TRUE:FALSE );
// blit
DirectDraw.Blt();
// Sound streaming
StreamProcess( bEmuPause );
// 壣側帪娫懸偪
sleep_time = (frame_time+frame_period) - (LONG)(::timeGetTime() - start_time);
if( bSleep && (sleep_time > 0) ) {
::Sleep( sleep_time-1 );
} else {
::Sleep( 0 );
}
DirectDraw.Flip();
#if _DEBUGOUT
{
static BOOL bPalettePut = FALSE;
if( ::GetAsyncKeyState( VK_ESCAPE ) & 0x8000 ) {
if( !bPalettePut ) {
int i;
DEBUGOUT( "BG\t" );
for( i = 0; i < 16; i++ ) {
DEBUGOUT( "%02X ", BGPAL[i] );
}
DEBUGOUT( "\n" );
DEBUGOUT( "SP\t" );
for( i = 0; i < 16; i++ ) {
DEBUGOUT( "%02X ", SPPAL[i] );
}
DEBUGOUT( "\n" );
}
bPalettePut = TRUE;
} else {
bPalettePut = FALSE;
}
}
#endif
// FPS昞帵
dwFrameTime[nFrameCount] = ::timeGetTime();
if( ++nFrameCount > 32-1 ) {
nFrameCount = 0;
if( Config.graphics.bFPSDisp ) {
if( dwFrameTime[32-1]-dwFrameTime[0] > 0 ) {
FPS = 1000*10*(32-1)/(dwFrameTime[32-1]-dwFrameTime[0]);
} else {
FPS = 0;
}
} else {
FPS = 0;
}
}
if( Config.graphics.bFPSDisp ) {
#if !(defined(_DEBUG)||defined(_DEBUGOUT))
sprintf( szStr, "FPS:%d.%01d", FPS/10, FPS%10 );
#else
if( !NetPlay.IsConnect() ) {
sprintf( szStr, "FPS:%d.%01d", FPS/10, FPS%10 );
} else {
sprintf( szStr, "FPS:%d.%01d NET:%3d NOFRM:%d TOUT:%3d", FPS/10, FPS%10, nNetBuffer, bNoFrame, nNetTimeoutCount );
}
#endif
DirectDraw.SetInfoString( szStr );
} else {
DirectDraw.SetInfoString( NULL );
}
_emulate_error:;
} catch( CHAR* str ) {
bPause = TRUE;
::strcpy( g_szErrorMessage, str );
::PostMessage( g_hWnd, WM_VNS_ERRORMSG, 0, (LPARAM)g_szErrorMessage );
#ifndef _DEBUG
} catch(...) {
bPause = TRUE;
::PostMessage( g_hWnd, WM_VNS_ERRORMSG, 0, (LPARAM)CApp::GetErrorString( IDS_ERROR_UNKNOWN ) );
#endif
}
}
}
g_WaveRec.Stop();
return 0;
}
void CEmuThread::StreamProcess( BOOL bPause )
{
if( g_pThis && g_nes && !bPause && !DirectSound.IsStreamPause() ) {
DWORD dwWrite, dwSize;
LPVOID lpLockPtr;
DWORD dwLockSize;
if( DirectSound.GetStreamLockPosition( &dwWrite, &dwSize ) ) {
if( DirectSound.StreamLock( dwWrite, dwSize, &lpLockPtr, &dwLockSize, NULL, NULL, 0 ) ) {
g_nes->apu->Process( (LPBYTE)lpLockPtr, dwLockSize );
g_WaveRec.Out( lpLockPtr, dwLockSize );
DirectSound.StreamUnlock( lpLockPtr, dwLockSize, NULL, NULL );
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -