void LoadGame(){ char szChoice[MAX_PATH]={0}; OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = g_hWnd; ofn.lpstrFilter = "VB Files (*.vb, *.zip)\0*.vb;*.zip\0All files(*.*)\0*.*\0\0"; ofn.lpstrFile = (LPSTR)szChoice; ofn.lpstrTitle = "Select a file to open"; ofn.lpstrDefExt = "vb"; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; if(GetOpenFileName(&ofn)) { pcejin.romLoaded = true; pcejin.started = true; if(!MDFNI_LoadGame(NULL,szChoice)) { pcejin.started = false; pcejin.romLoaded = false; } if (AutoRWLoad) { //Open Ram Watch if its auto-load setting is checked OpenRWRecentFile(0); RamWatchHWnd = CreateDialog(winClass.hInstance, MAKEINTRESOURCE(IDD_RAMWATCH), g_hWnd, (DLGPROC) RamWatchProc); } FCEUI_StopMovie(); UpdateRecentRoms(szChoice); ResetFrameCount(); UpdateTitleWithFilename(szChoice); std::string romname = noExtension(RemovePath(szChoice)); std::string temp = pcejin.versionName; temp.append(" "); temp.append(romname); SetWindowText(g_hWnd, temp.c_str()); } }
void HK_StopMovie(int, bool justPressed) { FCEUI_StopMovie(); }
void ResetEmulation() { FCEUI_StopMovie(); FCEUI_ResetNES(); }
LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; switch(Message) { case WM_INITMENU: recentromsmenu = LoadMenu(g_hInstance, "RECENTROMS"); GetRecentRoms(); break; case WM_KEYDOWN: if(wParam != VK_PAUSE) break; // case WM_SYSKEYDOWN: case WM_CUSTKEYDOWN: { int modifiers = GetModifiers(wParam); if(!HandleKeyMessage(wParam,lParam, modifiers)) return 0; break; } case WM_KEYUP: if(wParam != VK_PAUSE) break; case WM_SYSKEYUP: case WM_CUSTKEYUP: { int modifiers = GetModifiers(wParam); HandleKeyUp(wParam, lParam, modifiers); } break; case WM_SIZE: switch(wParam) { case SIZE_MINIMIZED: break; case SIZE_MAXIMIZED: pcejin.maximized = true; break; case SIZE_RESTORED: pcejin.maximized = false; break; default: break; } return 0; case WM_MOVE: RECT rect; GetWindowRect(hWnd,&rect); WndX = rect.left; WndY = rect.top; return 0; case WM_DROPFILES: { char filename[MAX_PATH] = ""; DragQueryFile((HDROP)wParam,0,filename,MAX_PATH); DragFinish((HDROP)wParam); std::string fileDropped = filename; //------------------------------------------------------- //Check if Movie file //------------------------------------------------------- if (!(fileDropped.find(".mc2") == std::string::npos) && (fileDropped.find(".mc2") == fileDropped.length()-4)) { if (!pcejin.romLoaded) //If no ROM is loaded, prompt for one { soundDriver->pause(); LoadGame(); pcejin.tempUnPause(); } if (pcejin.romLoaded && !(fileDropped.find(".mc2") == std::string::npos)) FCEUI_LoadMovie(fileDropped.c_str(), 1, false, false); } //------------------------------------------------------- //Check if Savestate file //------------------------------------------------------- else if (!(fileDropped.find(".mc") == std::string::npos)) //Note: potential clash, mc2 will be loaded a movie file first { if (fileDropped.find(".mc") == fileDropped.length()-4) { if ((fileDropped[fileDropped.length()-1] >= '0' && fileDropped[fileDropped.length()-1] <= '9')) { extern int MDFNSS_Load(const char *fname, const char *suffix); MDFNSS_Load(filename, NULL); ClearDirectDrawOutput(); UpdateToolWindows(); } } } //------------------------------------------------------- //Check if Lua script file //------------------------------------------------------- else if (!(fileDropped.find(".lua") == std::string::npos) && (fileDropped.find(".lua") == fileDropped.length()-4)) //ROM is already loaded and .dsm in filename { if(LuaScriptHWnds.size() < 16) { char temp [1024]; strcpy(temp, fileDropped.c_str()); HWND IsScriptFileOpen(const char* Path); if(!IsScriptFileOpen(temp)) { HWND hDlg = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_LUA), hWnd, (DLGPROC) LuaScriptProc); SendDlgItemMessage(hDlg,IDC_EDIT_LUAPATH,WM_SETTEXT,0,(LPARAM)temp); } } } //------------------------------------------------------- //Check if watchlist file //------------------------------------------------------- else if (!(fileDropped.find(".wch") == std::string::npos) && (fileDropped.find(".wch") == fileDropped.length()-4)) //ROM is already loaded and .dsm in filename { if(!RamWatchHWnd) { RamWatchHWnd = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_RAMWATCH), hWnd, (DLGPROC) RamWatchProc); } else SetForegroundWindow(RamWatchHWnd); Load_Watches(true, fileDropped.c_str()); } //------------------------------------------------------- //Else load it as a ROM //------------------------------------------------------- else if(MDFNI_LoadGame(NULL,filename)) { pcejin.romLoaded = true; pcejin.started = true; //TODO: adelikat: This code is copied directly from the LoadGame() function, it should be come a separate function and called in both places //////////////////////////////// if (AutoRWLoad) { //Open Ram Watch if its auto-load setting is checked OpenRWRecentFile(0); RamWatchHWnd = CreateDialog(winClass.hInstance, MAKEINTRESOURCE(IDD_RAMWATCH), g_hWnd, (DLGPROC) RamWatchProc); } UpdateRecentRoms(filename); //////////////////////////////// } } return 0; case WM_ENTERMENULOOP: soundDriver->pause(); EnableMenuItem(GetMenu(hWnd), IDM_RECORD_MOVIE, MF_BYCOMMAND | (movieMode == MOVIEMODE_INACTIVE && pcejin.romLoaded) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), ID_RAM_WATCH, MF_BYCOMMAND | (movieMode == MOVIEMODE_INACTIVE && pcejin.romLoaded) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), ID_RAM_SEARCH, MF_BYCOMMAND | (movieMode == MOVIEMODE_INACTIVE && pcejin.romLoaded) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_MEMORY, MF_BYCOMMAND | (movieMode == MOVIEMODE_INACTIVE && pcejin.romLoaded) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_PLAY_MOVIE, MF_BYCOMMAND | (movieMode == MOVIEMODE_INACTIVE && pcejin.romLoaded) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_STOPMOVIE, MF_BYCOMMAND | (movieMode != MOVIEMODE_INACTIVE) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_FILE_STOPAVI, MF_BYCOMMAND | (DRV_AviIsRecording()) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_FILE_RECORDAVI, MF_BYCOMMAND | (!DRV_AviIsRecording()) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_FILE_STOPWAV, MF_BYCOMMAND | (DRV_WaveRecordActive()) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(GetMenu(hWnd), IDM_FILE_RECORDWAV, MF_BYCOMMAND | (!DRV_WaveRecordActive()) ? MF_ENABLED : MF_GRAYED); //Window Size checkMenu(IDC_WINDOW1X, ((pcejin.windowSize==1))); checkMenu(IDC_WINDOW15X, ((pcejin.windowSize==65535))); checkMenu(IDC_WINDOW2X, ((pcejin.windowSize==2))); checkMenu(IDC_WINDOW25X, ((pcejin.windowSize==65534))); checkMenu(IDC_WINDOW3X, ((pcejin.windowSize==3))); checkMenu(IDC_WINDOW4X, ((pcejin.windowSize==4))); checkMenu(IDC_ASPECT, ((pcejin.aspectRatio))); checkMenu(ID_VIEW_MIXLEFTRIGHT,MixVideoOutput); checkMenu(ID_COLOR_MODE_REDBLUE, ((MDFN_IEN_VB::GetColorMode()==0))); checkMenu(ID_COLOR_MODE_REDCYAN, ((MDFN_IEN_VB::GetColorMode()==1))); checkMenu(ID_COLOR_MODE_REDELECTRICCYAN, ((MDFN_IEN_VB::GetColorMode()==2))); checkMenu(ID_COLOR_MODE_REDGREEN, ((MDFN_IEN_VB::GetColorMode()==3))); checkMenu(ID_COLOR_MODE_GREENMAGENTA, ((MDFN_IEN_VB::GetColorMode()==4))); checkMenu(ID_COLOR_MODE_YELLOWBLUE, ((MDFN_IEN_VB::GetColorMode()==5))); checkMenu(ID_COLOR_MODE_GREYSCALE, ((MDFN_IEN_VB::GetColorMode()==6))); checkMenu(ID_SPLIT_MODE_ANAGLYPH, ((MDFN_IEN_VB::GetSplitMode()==MDFN_IEN_VB::VB3DMODE_ANAGLYPH))); checkMenu(ID_SPLIT_MODE_CSCOPE, ((MDFN_IEN_VB::GetSplitMode()==MDFN_IEN_VB::VB3DMODE_CSCOPE))); checkMenu(ID_SPLIT_MODE_SIDEBYSIDE, ((MDFN_IEN_VB::GetSplitMode()==MDFN_IEN_VB::VB3DMODE_SIDEBYSIDE))); checkMenu(ID_SPLIT_MODE_PBARRIER, ((MDFN_IEN_VB::GetSplitMode()==MDFN_IEN_VB::VB3DMODE_PBARRIER))); checkMenu(ID_VIEW_DISP_BOTH, ((DisplayLeftRightOutput==0))); checkMenu(ID_VIEW_DISP_LEFT, ((DisplayLeftRightOutput==1))); checkMenu(ID_VIEW_DISP_RIGHT, ((DisplayLeftRightOutput==2))); checkMenu(ID_VIEW_DISP_DISABLE, ((DisplayLeftRightOutput==3))); checkMenu(ID_VIEW_FRAMECOUNTER,Hud.FrameCounterDisplay); checkMenu(ID_VIEW_DISPLAYINPUT,Hud.ShowInputDisplay); checkMenu(ID_VIEW_OPENCONSOLE,OpenConsoleWindow); checkMenu(ID_VIEW_DISPLAYSTATESLOTS,Hud.DisplayStateSlots); checkMenu(ID_VIEW_DISPLAYLAG,Hud.ShowLagFrameCounter); checkMenu(IDM_MUTE,soundDriver->userMute); break; case WM_EXITMENULOOP: pcejin.tempUnPause(); break; case WM_CLOSE: { SaveIniSettings(); PostQuitMessage(0); } case WM_DESTROY: { PostQuitMessage(0); } // HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy); // HANDLE_MSG(hWnd, WM_PAINT, OnPaint); // HANDLE_MSG(hwnd, WM_COMMAND, OnCommand); case WM_COMMAND: if(wParam >= baseid && wParam <= baseid + MAX_RECENT_ROMS - 1) { int x = wParam - baseid; soundDriver->resume(); OpenRecentROM(x); } else if(wParam == clearid) { /* Clear all the recent ROMs */ if(IDOK == MessageBox(g_hWnd, "OK to clear recent ROMs list?","VBJin",MB_OKCANCEL)) ClearRecentRoms(); } wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDC_WINDOW1X: pcejin.windowSize=1; ScaleScreen((float)pcejin.windowSize); break; case IDC_WINDOW15X: pcejin.windowSize=65535; ScaleScreen((float)pcejin.windowSize); break; case IDC_WINDOW2X: pcejin.windowSize=2; ScaleScreen((float)pcejin.windowSize); break; case IDC_WINDOW25X: pcejin.windowSize=65534; ScaleScreen((float)pcejin.windowSize); break; case IDC_WINDOW3X: pcejin.windowSize=3; ScaleScreen((float)pcejin.windowSize); break; case IDC_WINDOW4X: pcejin.windowSize=4; ScaleScreen((float)pcejin.windowSize); break; case IDC_ASPECT: pcejin.aspectRatio ^= 1; ScaleScreen((float)pcejin.windowSize); break; case IDM_EXIT: SaveIniSettings(); PostQuitMessage(0); break; case IDM_RESET: //NEWTODO PCE_Power(); OpenRecentROM(0); break; case IDM_OPEN_ROM: soundDriver->pause(); LoadGame(); pcejin.tempUnPause(); break; case IDM_RECORD_MOVIE: soundDriver->pause(); MovieRecordTo(); pcejin.tempUnPause(); return 0; case IDM_PLAY_MOVIE: soundDriver->pause(); Replay_LoadMovie(); pcejin.tempUnPause(); return 0; case IDM_INPUT_CONFIG: soundDriver->pause(); DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_INPUTCONFIG), hWnd, DlgInputConfig); pcejin.tempUnPause(); // RunInputConfig(); break; case IDM_HOTKEY_CONFIG: { soundDriver->pause(); DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_KEYCUSTOM), hWnd, DlgHotkeyConfig); pcejin.tempUnPause(); } break; case ID_VIEW_MIXLEFTRIGHT: MixVideoOutput ^= true; MDFN_IEN_VB::SetMixVideoOutput(MixVideoOutput); WritePrivateProfileBool("Display", "MixLeftRight", MixVideoOutput, IniName); return 0; case ID_SPLIT_MODE_ANAGLYPH: MDFN_IEN_VB::SetSplitMode(MDFN_IEN_VB::VB3DMODE_ANAGLYPH); WritePrivateProfileInt("Display", "SplitMode", MDFN_IEN_VB::VB3DMODE_ANAGLYPH, IniName); break; case ID_SPLIT_MODE_CSCOPE: MDFN_IEN_VB::SetSplitMode(MDFN_IEN_VB::VB3DMODE_CSCOPE); WritePrivateProfileInt("Display", "SplitMode", MDFN_IEN_VB::VB3DMODE_CSCOPE, IniName); //Clear the DirectDraw buffers ClearDirectDrawOutput(); break; case ID_SPLIT_MODE_SIDEBYSIDE: MDFN_IEN_VB::SetSplitMode(MDFN_IEN_VB::VB3DMODE_SIDEBYSIDE); WritePrivateProfileInt("Display", "SplitMode", MDFN_IEN_VB::VB3DMODE_SIDEBYSIDE, IniName); //Clear the DirectDraw buffers ClearDirectDrawOutput(); break; case ID_SPLIT_MODE_PBARRIER: MDFN_IEN_VB::SetSplitMode(MDFN_IEN_VB::VB3DMODE_PBARRIER); WritePrivateProfileInt("Display", "SplitMode", MDFN_IEN_VB::VB3DMODE_PBARRIER, IniName); break; case ID_PIXEL_SEP_16: SideBySidePixels = 16; MDFN_IEN_VB::SetSideBySidePixels(SideBySidePixels); ClearDirectDrawOutput(); WritePrivateProfileInt("Display", "SideBySidePixels", SideBySidePixels, IniName); break; case ID_PIXEL_SEP_32: SideBySidePixels = 32; MDFN_IEN_VB::SetSideBySidePixels(SideBySidePixels); ClearDirectDrawOutput(); WritePrivateProfileInt("Display", "SideBySidePixels", SideBySidePixels, IniName); break; case ID_PIXEL_SEP_48: SideBySidePixels = 48; MDFN_IEN_VB::SetSideBySidePixels(SideBySidePixels); ClearDirectDrawOutput(); WritePrivateProfileInt("Display", "SideBySidePixels", SideBySidePixels, IniName); break; case ID_PIXEL_SEP_64: SideBySidePixels = 64; MDFN_IEN_VB::SetSideBySidePixels(SideBySidePixels); ClearDirectDrawOutput(); WritePrivateProfileInt("Display", "SideBySidePixels", SideBySidePixels, IniName); break; case ID_PIXEL_SEP_80: SideBySidePixels = 80; MDFN_IEN_VB::SetSideBySidePixels(SideBySidePixels); ClearDirectDrawOutput(); WritePrivateProfileInt("Display", "SideBySidePixels", SideBySidePixels, IniName); break; case ID_PIXEL_SEP_96: SideBySidePixels = 96; MDFN_IEN_VB::SetSideBySidePixels(SideBySidePixels); ClearDirectDrawOutput(); WritePrivateProfileInt("Display", "SideBySidePixels", SideBySidePixels, IniName); break; case ID_COLOR_MODE_REDBLUE: MDFN_IEN_VB::SetColorMode(0); WritePrivateProfileInt("Display", "ColorMode", 0, IniName); break; case ID_COLOR_MODE_REDCYAN: MDFN_IEN_VB::SetColorMode(1); WritePrivateProfileInt("Display", "ColorMode", 1, IniName); break; case ID_COLOR_MODE_REDELECTRICCYAN: MDFN_IEN_VB::SetColorMode(2); WritePrivateProfileInt("Display", "ColorMode", 2, IniName); break; case ID_COLOR_MODE_REDGREEN: MDFN_IEN_VB::SetColorMode(3); WritePrivateProfileInt("Display", "ColorMode", 3, IniName); break; case ID_COLOR_MODE_GREENMAGENTA: MDFN_IEN_VB::SetColorMode(4); WritePrivateProfileInt("Display", "ColorMode", 4, IniName); break; case ID_COLOR_MODE_YELLOWBLUE: MDFN_IEN_VB::SetColorMode(5); WritePrivateProfileInt("Display", "ColorMode", 5, IniName); break; case ID_COLOR_MODE_GREYSCALE: MDFN_IEN_VB::SetColorMode(6); WritePrivateProfileInt("Display", "ColorMode", 6, IniName); break; case ID_VIEW_DISP_BOTH: DisplayLeftRightOutput = 0; MDFN_IEN_VB::SetViewDisp(DisplayLeftRightOutput); WritePrivateProfileInt("Display", "ViewDisplay", DisplayLeftRightOutput, IniName); return 0; case ID_VIEW_DISP_LEFT: DisplayLeftRightOutput = 1; MDFN_IEN_VB::SetViewDisp(DisplayLeftRightOutput); WritePrivateProfileInt("Display", "ViewDisplay", DisplayLeftRightOutput, IniName); return 0; case ID_VIEW_DISP_RIGHT: DisplayLeftRightOutput = 2; MDFN_IEN_VB::SetViewDisp(DisplayLeftRightOutput); WritePrivateProfileInt("Display", "ViewDisplay", DisplayLeftRightOutput, IniName); return 0; case ID_VIEW_DISP_DISABLE: DisplayLeftRightOutput = 3; MDFN_IEN_VB::SetViewDisp(DisplayLeftRightOutput); // We're not saving this. Too many people would set it and forget it, then compain. // Someone can still set it manually in the ini file though. return 0; case ID_VIEW_FRAMECOUNTER: Hud.FrameCounterDisplay ^= true; WritePrivateProfileBool("Display", "FrameCounter", Hud.FrameCounterDisplay, IniName); return 0; case ID_VIEW_DISPLAYINPUT: Hud.ShowInputDisplay ^= true; WritePrivateProfileBool("Display", "Display Input", Hud.ShowInputDisplay, IniName); osd->clear(); return 0; case ID_VIEW_OPENCONSOLE: OpenConsoleWindow ^= true; WritePrivateProfileBool("Display", "OpenConsoleWindow", OpenConsoleWindow, IniName); return 0; case ID_VIEW_DISPLAYSTATESLOTS: Hud.DisplayStateSlots ^= true; WritePrivateProfileBool("Display", "Display State Slots", Hud.DisplayStateSlots, IniName); osd->clear(); return 0; case ID_VIEW_DISPLAYLAG: Hud.ShowLagFrameCounter ^= true; WritePrivateProfileBool("Display", "Display Lag Counter", Hud.ShowLagFrameCounter, IniName); osd->clear(); return 0; case IDC_NEW_LUA_SCRIPT: if(LuaScriptHWnds.size() < 16) { CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_LUA), g_hWnd, (DLGPROC) LuaScriptProc); } break; break; case IDM_MUTE: soundDriver->doUserMute(); break; case IDM_STOPMOVIE: FCEUI_StopMovie(); return 0; break; case ID_RAM_SEARCH: if(!RamSearchHWnd) { if (pcejin.romLoaded) { InitRamSearch(false); RamSearchHWnd = CreateDialog(winClass.hInstance, MAKEINTRESOURCE(IDD_RAMSEARCH), hWnd, (DLGPROC) RamSearchProc); } } else SetForegroundWindow(RamSearchHWnd); break; case ID_RAM_WATCH: if(!RamWatchHWnd) { if(pcejin.romLoaded) RamWatchHWnd = CreateDialog(winClass.hInstance, MAKEINTRESOURCE(IDD_RAMWATCH), hWnd, (DLGPROC) RamWatchProc); } else SetForegroundWindow(RamWatchHWnd); return 0; case IDM_MEMORY: if (!RegWndClass("MemView_ViewBox", MemView_ViewBoxProc, 0, sizeof(CMemView*))) return 0; OpenToolWindow(new CMemView()); return 0; case IDM_ABOUT: soundDriver->pause(); DialogBox(winClass.hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); pcejin.tempUnPause(); break; case IDM_FILE_RECORDAVI: soundDriver->pause(); RecordAvi(); pcejin.tempUnPause(); break; case IDM_FILE_STOPAVI: StopAvi(); break; case IDM_FILE_RECORDWAV: soundDriver->pause(); CreateSoundSave(); pcejin.tempUnPause(); break; case IDM_FILE_STOPWAV: DRV_EndWaveRecord(); break; } break; } return DefWindowProc(hWnd, Message, wParam, lParam); }
void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata) { FILE *fp; char *fn; int poweron=0; uint8 padding[4] = {0,0,0,0}; int n_padding; FCEUI_StopMovie(); char origname[512]; if(fname) { fp = FCEUD_UTF8fopen(fname, "wb"); strcpy(origname,fname); } else { fp=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0),"wb"); strcpy(origname,fn); free(fn); } if(!fp) return; // don't need the movieSyncHackOn sync hack for newly recorded movies flags |= MOVIE_FLAG_NOSYNCHACK; resetDMCacc=movieSyncHackOn=0; // add PAL flag if(FCEUI_GetCurrentVidSystem(0,0)) flags |= MOVIE_FLAG_PAL; if(flags & MOVIE_FLAG_FROM_POWERON) { poweron=1; flags &= ~MOVIE_FLAG_FROM_POWERON; flags |= MOVIE_FLAG_FROM_RESET; } // write header write32le(MOVIE_MAGIC, fp); write32le(MOVIE_VERSION, fp); fputc(flags, fp); fputc(0, fp); // reserved fputc(0, fp); // reserved fputc(0, fp); // reserved write32le(0, fp); // leave room for length frames write32le(0, fp); // leave room for rerecord count write32le(0, fp); // leave room for movie data size write32le(0, fp); // leave room for savestate_offset write32le(0, fp); // leave room for offset_to_controller_data fwrite(FCEUGameInfo->MD5, 1, 16, fp); // write ROM checksum write32le(FCEU_VERSION_NUMERIC, fp); // write emu version used fputs(FileBase, fp); // write ROM name used fputc(0, fp); if(metadata) { if(strlen(metadata) < MOVIE_MAX_METADATA) fputs(metadata, fp); else fwrite(metadata, 1, MOVIE_MAX_METADATA-1, fp); } fputc(0, fp); // add padding n_padding = (4 - (ftell(fp) & 0x3)) & 0x3; fwrite(padding, 1, n_padding, fp); if(flags & MOVIE_FLAG_FROM_RESET) { if(poweron) { // make a for-movie-recording power-on clear the game's save data, too // (note: FCEU makes a save state immediately after this and that loads that on movie playback) extern char lastLoadedGameName [2048]; extern int disableBatteryLoading, suppressAddPowerCommand; suppressAddPowerCommand=1; disableBatteryLoading=1; suppressMovieStop=1; { // NOTE: this will NOT write an FCEUNPCMD_POWER into the movie file FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName); if(!gi) PowerNES(); // and neither will this, if it can even happen } suppressMovieStop=0; disableBatteryLoading=0; suppressAddPowerCommand=0; } } savestate_offset = ftell(fp); FCEUSS_SaveFP(fp); fseek(fp, 0, SEEK_END); ResetInputTypes(); // add padding n_padding = (4 - (ftell(fp) & 0x3)) & 0x3; fwrite(padding, 1, n_padding, fp); firstframeoffset = ftell(fp); // finish header fseek(fp, 24, SEEK_SET); // offset_to_savestate offset write32le(savestate_offset, fp); write32le(firstframeoffset, fp); fseek(fp, firstframeoffset, SEEK_SET); // set recording flag current=CurrentMovie; movie_readonly = 0; frameptr = 0; framecount = 0; rerecord_count = 0; slots[current] = fp; memset(joop,0,sizeof(joop)); current++; framets=0; nextd = -1; // trigger a reset if(flags & MOVIE_FLAG_FROM_RESET) { if(poweron) { PowerNES(); // NOTE: this will write an FCEUNPCMD_POWER into the movie file } else ResetNES(); // NOTE: this will write an FCEUNPCMD_RESET into the movie file } if(!fname) FCEUI_SelectMovie(CurrentMovie,1); /* Quick hack to display status. */ else FCEU_DispMessage("Movie recording started."); strcpy(curMovieFilename, origname); }
// PlayMovie / MoviePlay function void FCEUI_LoadMovie(char *fname, int _read_only) { char buffer [512]; fname = (char*)convertToFCM(fname,buffer); FILE *fp; char *fn = NULL; FCEUI_StopMovie(); #if 0 if(!fname) fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0); #endif #if 0 char origname[512]; strcpy(origname,fname); #endif // check movie_readonly movie_readonly = _read_only; if(access(fname, W_OK)) movie_readonly = 2; fp = fopen(fname, (movie_readonly>=2) ? "rb" : "r+b"); if(fn) { free(fn); fname = NULL; } if(!fp) return; // read header { uint32 magic; uint32 version; uint8 flags[4]; read32le(&magic, fp); if(magic != MOVIE_MAGIC) { fclose(fp); return; } //DEBUG_COMPARE_RAM(__LINE__); read32le(&version, fp); if(version == 1) { // attempt to load previous version's format fclose(fp); printf("movie: trying movie v1\n"); FCEUI_LoadMovie_v1(fname, _read_only); return; } else if(version == MOVIE_VERSION) {} else { // unsupported version printf("movie: unsupported version\n"); fclose(fp); return; } fread(flags, 1, 4, fp); read32le(&framecount, fp); read32le(&rerecord_count, fp); read32le(&moviedatasize, fp); read32le(&savestate_offset, fp); read32le(&firstframeoffset, fp); if(fseek(fp, savestate_offset, SEEK_SET)) { fclose(fp); return; } // FCEU_PrintError("flags[0] & MOVIE_FLAG_NOSYNCHACK=%d",flags[0] & MOVIE_FLAG_NOSYNCHACK); if(flags[0] & MOVIE_FLAG_NOSYNCHACK) movieSyncHackOn=0; else movieSyncHackOn=1; } // fully reload the game to reinitialize everything before playing any movie // to try fixing nondeterministic playback of some games #if 0 // do we need this? { extern char lastLoadedGameName [2048]; #if 0 // TODO? extern int disableBatteryLoading, suppressAddPowerCommand; suppressAddPowerCommand=1; suppressMovieStop=1; #endif { FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName); if(!gi) PowerNES(); } #if 0 // TODO? suppressMovieStop=0; suppressAddPowerCommand=0; #endif } #endif // Loading new savestates doesn't work and even breaks FDS //if(!FCEUSS_LoadFP(fp,1)) return; ResetInputTypes(); fseek(fp, firstframeoffset, SEEK_SET); moviedata = (uint8*)realloc(moviedata, moviedatasize); fread(moviedata, 1, moviedatasize, fp); framecount = 0; // movies start at frame 0! frameptr = 0; current = CurrentMovie; slots[current] = fp; memset(joop,0,sizeof(joop)); current = -1 - current; framets=0; nextts=0; nextd = -1; MovieStatus[CurrentMovie] = 1; #if 0 if(!fname) FCEUI_SelectMovie(CurrentMovie,1); /* Quick hack to display status. */ else #endif FCEU_DispMessage("Movie playback started."); #if 0 strcpy(curMovieFilename, origname); #else strcpy(curMovieFilename, fname); #endif }