⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emuthread.cpp

📁 著名的任天堂FC游戏机模拟器VirtuaNes 085版的源码!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
					::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 + -