diff --git a/src/driver.h b/src/driver.h index 84fed9f9..a1670194 100644 --- a/src/driver.h +++ b/src/driver.h @@ -206,6 +206,7 @@ void FCEUI_MovieToggleReadOnly(void); void FCEUI_MovieToggleFrameDisplay(void); void FCEUI_ToggleInputDisplay(void); + void FCEUD_MovieRecordTo(void); void FCEUD_MovieReplayFrom(void); @@ -287,7 +288,11 @@ void FCEUI_SetEmulationPaused(int val); ///toggles the paused bit (bit0) for EmulationPaused. caused FCEUD_DebugUpdate() to fire if the emulation pauses void FCEUI_ToggleEmulationPause(void); +///called when the emulator closes a game +void FCEUD_OnCloseGame(void); + void FCEUI_FrameAdvance(void); +void FCEUI_FrameAdvanceEnd(void); /* AVI Output */ int FCEUI_AviBegin(const char* fname); diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index 29b7516e..27a9a0d6 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -31,6 +31,7 @@ #include "main.h" #include "window.h" #include "video.h" +#include "memwatch.h" extern CFGSTRUCT NetplayConfig[]; extern CFGSTRUCT InputConfig[]; @@ -137,7 +138,7 @@ static CFGSTRUCT fceuconfig[] = { AC(autoHoldClearKey), AC(frame_display), AC(input_display), - //ACS(MemWatchDir), //mbg merge 7/18/06 removed + ACS(MemWatchDir), //mbg merge 7/18/06 removed ACS(BasicBotDir), AC(EnableBackgroundInput), ENDCFGSTRUCT diff --git a/src/drivers/win/debugger.cpp b/src/drivers/win/debugger.cpp index aa304611..68e6a16c 100644 --- a/src/drivers/win/debugger.cpp +++ b/src/drivers/win/debugger.cpp @@ -824,6 +824,14 @@ BOOL CALLBACK PatcherCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam extern char *iNesShortFName(); +void DebuggerExit() +{ + FCEUI_Debugger().badopbreak = 0; + debugger_open = 0; + DeleteObject(hNewFont); + DestroyWindow(hDebug); +} + BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { LOGFONT lf; RECT wrect; @@ -919,10 +927,7 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara case WM_CLOSE: case WM_QUIT: exitdebug: - FCEUI_Debugger().badopbreak = 0; - debugger_open = 0; - DeleteObject(hNewFont); - DestroyWindow(hwndDlg); + DebuggerExit(); break; case WM_MOVING: break; diff --git a/src/drivers/win/input.cpp b/src/drivers/win/input.cpp index 3edc5f8f..ed7cbe4b 100644 --- a/src/drivers/win/input.cpp +++ b/src/drivers/win/input.cpp @@ -1392,7 +1392,7 @@ int FCEUD_TestCommandState(int c) || c == EMUCMD_SPEED_SLOWER || c == EMUCMD_SPEED_FASTER*/) { - keys=GetKeyboard(); + keys=GetKeyboard_nr(); /* if((cmdmask & CMD_KEY_LALT) == CMD_KEY_LALT || (cmdmask & CMD_KEY_RALT) == CMD_KEY_RALT || (cmdmask & CMD_KEY_LALT) == CMD_KEY_LALT @@ -1400,12 +1400,11 @@ int FCEUD_TestCommandState(int c) || (cmdmask & CMD_KEY_RCTRL) == CMD_KEY_RCTRL || (cmdmask & CMD_KEY_LSHIFT) == CMD_KEY_LSHIFT || (cmdmask & CMD_KEY_RSHIFT) == CMD_KEY_RSHIFT)*/ - keys_nr=GetKeyboard(); + keys_nr=GetKeyboard_nr(); // else // keys_nr=GetKeyboard_nr(); } - else - if(c != EMUCMD_SPEED_TURBO) // TODO: this should be made more general by detecting if the command has an "off" function, but right now Turbo is the only command that has it + else if(c != EMUCMD_SPEED_TURBO) // TODO: this should be made more general by detecting if the command has an "off" function, but right now Turbo is the only command that has it { keys=GetKeyboard_jd(); keys_nr=GetKeyboard_nr(); diff --git a/src/drivers/win/keyboard.cpp b/src/drivers/win/keyboard.cpp index 3110a486..2f6441e6 100644 --- a/src/drivers/win/keyboard.cpp +++ b/src/drivers/win/keyboard.cpp @@ -50,8 +50,6 @@ void KeyboardUpdateState(void) if(GetAsyncKeyState(VK_PAUSE)) // normally this should have & 0x8000, but apparently this key is too special for that to work tk[0xC5] = 0x80; - DWORD time = timeGetTime(); - switch(ddrval) { case DI_OK: //memcpy(keys,tk,256);break; @@ -67,16 +65,16 @@ void KeyboardUpdateState(void) #define KEY_JUST_DOWN_DURATION (4) // must be >= 1 and <= 255 int i; - for(i = 0 ; i < 256 ; i++) - if(tk[i]) { - if(keys_nr[i] == 0) - keys_nr[i] = time; - } + if(tk[i]) + if(keys_nr[i] < 255) + keys_nr[i]++; // activate key, and count up for repeat + else + keys_nr[i] = 255 - KEY_REPEAT_REPEATING_DELAY; // oscillate for repeat else - keys_nr[i] = 0; + keys_nr[i] = 0; // deactivate key - memcpy(keys,keys_nr,256*4); + memcpy(keys,keys_nr,256); // key-down detection for(i = 0 ; i < 256 ; i++) @@ -90,18 +88,18 @@ void KeyboardUpdateState(void) else if(keys_jd[i] /*&& (i != 0x2A && i != 0x36 && i != 0x1D && i != 0x38)*/) { - if(time - keys_jd[i] > KEY_JUST_DOWN_DURATION) + if(++keys_jd[i] > KEY_JUST_DOWN_DURATION) { keys_jd[i] = 0; keys_jd_lock[i] = 1; } } else - keys_jd[i] = time; + keys_jd[i] = 1; // key repeat for(i = 0 ; i < 256 ; i++) - if(time - keys[i] >= KEY_REPEAT_INITIAL_DELAY && !((time-keys[i])%KEY_REPEAT_REPEATING_DELAY)) + if(keys[i] >= KEY_REPEAT_INITIAL_DELAY && !(keys[i]%KEY_REPEAT_REPEATING_DELAY)) keys[i] = 0; } break; @@ -109,7 +107,7 @@ void KeyboardUpdateState(void) case DIERR_INPUTLOST: case DIERR_NOTACQUIRED: - memset(keys,0,256*4); + memset(keys,0,256); IDirectInputDevice7_Acquire(lpdid); break; } @@ -160,6 +158,17 @@ int KeyboardInitialize(void) return 0; } + ////--set to buffered mode + //DIPROPDWORD dipdw; + //dipdw.diph.dwSize = sizeof(DIPROPDWORD); + //dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + //dipdw.diph.dwObj = 0; + //dipdw.diph.dwHow = DIPH_DEVICE; + //dipdw.dwData = 64; + + //ddrval = IDirectInputDevice7_SetProperty(lpdid,DIPROP_BUFFERSIZE, &dipdw.diph); + ////-------- + ddrval=IDirectInputDevice7_Acquire(lpdid); /* Not really a fatal error. */ //if(ddrval != DI_OK) diff --git a/src/drivers/win/main.cpp b/src/drivers/win/main.cpp index 5d76af3f..7a12ce66 100644 --- a/src/drivers/win/main.cpp +++ b/src/drivers/win/main.cpp @@ -49,6 +49,7 @@ #include "memview.h" #include "tracer.h" #include "cdlogger.h" +#include "throttle.h" #include "main.h" #include "basicbot.h" @@ -366,9 +367,11 @@ void DoFCEUExit() closeGame = 1;//mbg 6/30/06 - for housekeeping purposes we need to exit after the emulation cycle finishes } -/** -* Changes the thread priority of the main thread. -**/ +void FCEUD_OnCloseGame() +{ +} + +//Changes the thread priority of the main thread. void DoPriority() { if(eoptions & EO_HIGHPRIO) @@ -616,6 +619,8 @@ int main(int argc,char *argv[]) return 1; } + InitSpeedThrottle(); + UpdateCheckedMenuItems(); if(t) @@ -970,17 +975,25 @@ void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count) //update debugging displays _updateWindow(); + extern bool JustFrameAdvanced; + //MBG TODO - think about this logic //throttle extern bool turbo; //needs to be declared better if(!(eoptions&EO_NOTHROTTLE)) //if throttling is enabled.. if(!turbo) //and turbo is disabled.. - if(!FCEUI_EmulationPaused()) + if(!FCEUI_EmulationPaused() + ||JustFrameAdvanced + ) //then throttle - win_Throttle(); + while(SpeedThrottle()) { + FCEUD_UpdateInput(); + _updateWindow(); + } + //sleep just to be polite - if(FCEUI_EmulationPaused()) { + if(!JustFrameAdvanced && FCEUI_EmulationPaused()) { Sleep(50); } diff --git a/src/drivers/win/sound.cpp b/src/drivers/win/sound.cpp index 59cc45ee..b71a0dcf 100644 --- a/src/drivers/win/sound.cpp +++ b/src/drivers/win/sound.cpp @@ -270,6 +270,14 @@ void DoTrashSound() { trashPending = false; } + +void TrashSoundNow() { + DoTrashSound(); + //is this safe? +} + + + bool CheckTrashSound() { if(trashPending) { @@ -287,7 +295,10 @@ void win_Throttle() { void win_SoundInit(int bits) { dsout = new OAKRA_Module_OutputDS(); - dsout->start(hAppWnd); + if(soundoptions&SO_GFOCUS) + dsout->start(0); + else + dsout->start(hAppWnd); dsout->beginThread(); OAKRA_Format fmt; fmt.format = bits==8?OAKRA_U8:OAKRA_S16; @@ -447,7 +458,7 @@ BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara } if(soundo) { - TrashSound(); + TrashSoundNow(); soundo=InitSound(); UpdateSD(hwndDlg); } @@ -470,7 +481,7 @@ BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara case 122:soundoptions^=SO_FORCE8BIT; if(soundo) { - TrashSound(); + TrashSoundNow(); soundo=InitSound(); UpdateSD(hwndDlg); } @@ -478,7 +489,7 @@ BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara case 123:soundoptions^=SO_SECONDARY; if(soundo) { - TrashSound(); + TrashSoundNow(); soundo=InitSound(); UpdateSD(hwndDlg); } @@ -486,7 +497,7 @@ BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara case 124:soundoptions^=SO_GFOCUS; if(soundo) { - TrashSound(); + TrashSoundNow(); soundo=InitSound(); UpdateSD(hwndDlg); } @@ -496,7 +507,7 @@ BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara case 131:soundoptions^=SO_OLDUP; if(soundo) { - TrashSound(); + TrashSoundNow(); soundo=InitSound(); UpdateSD(hwndDlg); } @@ -564,58 +575,4 @@ void FCEUD_SoundVolumeAdjust(int n) FCEU_DispMessage("Sound volume %d.", soundvolume); } -//----------- -//throttle stuff -//----------- - -static uint64 desiredfps; - -static int32 fps_scale_table[]= -{ 3, 3, 4, 8, 16, 32, 64, 128, 192, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 16384}; -int32 fps_scale = 256; - -void RefreshThrottleFPS() -{ - fflush(stdout); - desiredfps=FCEUI_GetDesiredFPS()>>8; - desiredfps=(desiredfps*fps_scale)>>8; -} - -static void IncreaseEmulationSpeed(void) -{ - int i; - for(i=1; fps_scale_table[i]>8); -} - - //#include "wave.cpp" diff --git a/src/drivers/win/sound.h b/src/drivers/win/sound.h index a8264008..46b40383 100644 --- a/src/drivers/win/sound.h +++ b/src/drivers/win/sound.h @@ -1,6 +1,5 @@ extern int32 fps_scale; -void RefreshThrottleFPS(); void ConfigSound(); int InitSound(); void TrashSound(); diff --git a/src/drivers/win/throttle.cpp b/src/drivers/win/throttle.cpp new file mode 100644 index 00000000..803c910d --- /dev/null +++ b/src/drivers/win/throttle.cpp @@ -0,0 +1,151 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../../types.h" +#include "../../fceu.h" +#include "windows.h" + +static uint64 tmethod,tfreq; +static uint64 desiredfps; + +static int32 fps_scale_table[]= +{ 3, 3, 4, 8, 16, 32, 64, 128, 192, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 16384}; +int32 fps_scale = 256; + +void RefreshThrottleFPS(void) +{ + desiredfps=FCEUI_GetDesiredFPS()>>8; + desiredfps=(desiredfps*fps_scale)>>8; +} + +static uint64 GetCurTime(void) +{ + if(tmethod) + { + uint64 tmp; + + /* Practically, LARGE_INTEGER and uint64 differ only by signness and name. */ + QueryPerformanceCounter((LARGE_INTEGER*)&tmp); + + return(tmp); + } + else + return((uint64)GetTickCount()); + +} + +void InitSpeedThrottle(void) +{ + tmethod=0; + if(QueryPerformanceFrequency((LARGE_INTEGER*)&tfreq)) + { + tmethod=1; + } + else + tfreq=1000; + tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */ +} + + +int SpeedThrottle(void) +{ + static uint64 ttime,ltime; + + waiter: + + ttime=GetCurTime(); + + + if( (ttime-ltime) < (tfreq/desiredfps) ) + { + uint64 sleepy; + sleepy=(tfreq/desiredfps)-(ttime-ltime); + sleepy*=1000; + if(tfreq>=65536) + sleepy/=tfreq>>16; + else + sleepy=0; + if(sleepy>100) + { + // block for a max of 100ms to + // keep the gui responsive + Sleep(100); + return 1; + } + Sleep(sleepy); + goto waiter; + } + if( (ttime-ltime) >= (tfreq*4/desiredfps)) + ltime=ttime; + else + { + ltime+=tfreq/desiredfps; + + if( (ttime-ltime) >= (tfreq/desiredfps) ) // Oops, we're behind! + return(1); + } + return(0); +} + +// Quick code for internal FPS display. +uint64 FCEUD_GetTime(void) +{ + return(GetCurTime()); +} +uint64 FCEUD_GetTimeFreq(void) +{ + return(tfreq>>16); +} + +static void IncreaseEmulationSpeed(void) +{ + int i; + for(i=1; fps_scale_table[i]>8); +} diff --git a/src/drivers/win/throttle.h b/src/drivers/win/throttle.h new file mode 100644 index 00000000..61601d83 --- /dev/null +++ b/src/drivers/win/throttle.h @@ -0,0 +1,3 @@ +void InitSpeedThrottle(void); +int SpeedThrottle(void); +void RefreshThrottleFPS(); \ No newline at end of file diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index fda4a607..57d7c76d 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -43,6 +43,7 @@ #include "tracer.h" #include "cdlogger.h" #include "basicbot.h" +#include "throttle.h" #include "guiconfig.h" #include "timing.h" diff --git a/src/fceu.cpp b/src/fceu.cpp index e6e0da70..b1e08ee6 100644 --- a/src/fceu.cpp +++ b/src/fceu.cpp @@ -66,6 +66,11 @@ static int RWWrap=0; //bit0 indicates whether emulation is paused //bit1 indicates whether emulation is in frame step mode static int EmulationPaused=0; +bool frameAdvanceRequested=false; +int frameAdvanceDelay; + +//indicates that the emulation core just frame advanced (consumed the frame advance state and paused) +bool JustFrameAdvanced=false; static int RewindStatus[4] = {0, 0, 0, 0}; //is it safe to load rewind state static int RewindIndex = 0; //which rewind state we're on @@ -253,6 +258,12 @@ static void CloseGame(void) ResetExState(0,0); + //mbg 5/9/08 - clear screen when game is closed + //http://sourceforge.net/tracker/index.php?func=detail&aid=1787298&group_id=13536&atid=113536 + extern uint8 *XBuf; + if(XBuf) + memset(XBuf,0,256*256); + CloseGenie(); delete GameInfo; @@ -473,6 +484,20 @@ void UpdateRewind(void); void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) { int r,ssize; + + JustFrameAdvanced = false; + + if(frameAdvanceRequested) { + if(frameAdvanceDelay==0) { + EmulationPaused = 3; + frameAdvanceDelay++; + } else { + if(frameAdvanceDelay>=10) { + EmulationPaused = 3; + } else frameAdvanceDelay++; + } + } + if(EmulationPaused&2) EmulationPaused &= ~1; // clear paused flag temporarily (frame advance) @@ -523,6 +548,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski // if(soundoptions&SO_MUTEFA) //#endif *SoundBufSize=0; // keep sound muted + JustFrameAdvanced = true; } } @@ -762,9 +788,15 @@ void FCEUI_ToggleEmulationPause(void) EmulationPaused = (EmulationPaused&1)^1; } +void FCEUI_FrameAdvanceEnd(void) +{ + frameAdvanceRequested = false; +} + void FCEUI_FrameAdvance(void) { - EmulationPaused |= 1|2; + frameAdvanceRequested = true; + frameAdvanceDelay = 0; } static int RewindCounter = 0; diff --git a/src/input.cpp b/src/input.cpp index f72f2159..4605b897 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -552,7 +552,7 @@ struct EMUCMDTABLE FCEUI_CommandTable[]= { EMUCMD_POWER, EMUCMDTYPE_MISC, FCEUI_PowerNES, 0, 0, "Power", }, { EMUCMD_RESET, EMUCMDTYPE_MISC, FCEUI_ResetNES, 0, 0, "Reset", }, { EMUCMD_PAUSE, EMUCMDTYPE_MISC, FCEUI_ToggleEmulationPause, 0, 0, "Pause", }, - { EMUCMD_FRAME_ADVANCE, EMUCMDTYPE_MISC, FCEUI_FrameAdvance, 0, 0, "Frame Advance", }, + { EMUCMD_FRAME_ADVANCE, EMUCMDTYPE_MISC, FCEUI_FrameAdvance, FCEUI_FrameAdvanceEnd, 0, "Frame Advance", }, { EMUCMD_SCREENSHOT, EMUCMDTYPE_MISC, FCEUI_SaveSnapshot, 0, 0, "Screenshot", }, { EMUCMD_HIDE_MENU_TOGGLE, EMUCMDTYPE_MISC, FCEUD_HideMenuToggle, 0, 0, "Hide Menu Toggle", }, diff --git a/vc8/fceux.vcproj b/vc8/fceux.vcproj index cb47bec9..1c195ace 100644 --- a/vc8/fceux.vcproj +++ b/vc8/fceux.vcproj @@ -1140,6 +1140,14 @@ RelativePath="..\src\drivers\win\state.h" > + + + +