From d2fee771fd3a141c8ff273af76b8b6f6d3f97973 Mon Sep 17 00:00:00 2001 From: laqieer Date: Sun, 7 Aug 2022 18:54:49 +0000 Subject: [PATCH] Add VBA Movie Version 2 Add new format for recording VBA Movies that records inputs since the time of the last input instead of the beginning of the movie. Keep the extension `.vmv` the same, the format is determined from the header of the file. Make this the new default format for recording VBA Movies. Signed-off-by: Rafael Kitover --- po/wxvbam/wxvbam.pot | 138 ++++++++++++++++++++--------------------- src/common/ffmpeg.cpp | 20 +++--- src/wx/cmdevents.cpp | 100 ++++++++++++++++++++++++++++-- src/wx/sys.cpp | 139 +++++++++++++++++++++++++++++++++++++----- src/wx/wxvbam.h | 20 +++++- 5 files changed, 311 insertions(+), 106 deletions(-) diff --git a/po/wxvbam/wxvbam.pot b/po/wxvbam/wxvbam.pot index d9851be2..152dfe11 100644 --- a/po/wxvbam/wxvbam.pot +++ b/po/wxvbam/wxvbam.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-23 17:25-0700\n" +"POT-Creation-Date: 2022-08-06 20:51+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -358,7 +358,7 @@ msgid "Text files (*.txt;*.log)|*.txt;*.log|" msgstr "" #: viewers.cpp:562 viewers.cpp:772 gfxviewers.cpp:1600 gfxviewers.cpp:1742 -#: cmdevents.cpp:1157 cmdevents.cpp:1235 cmdevents.cpp:1305 cmdevents.cpp:1332 +#: cmdevents.cpp:1157 cmdevents.cpp:1235 cmdevents.cpp:1305 cmdevents.cpp:1374 #: viewsupt.cpp:1180 msgid "Select output file" msgstr "" @@ -729,105 +729,101 @@ msgstr "" msgid "Error saving snapshot file %s" msgstr "" -#: cmdevents.cpp:1182 sys.cpp:450 +#: cmdevents.cpp:1182 sys.cpp:524 #, c-format msgid "Wrote snapshot %s" msgstr "" -#: cmdevents.cpp:1203 cmdevents.cpp:1273 +#: cmdevents.cpp:1203 cmdevents.cpp:1273 cmdevents.cpp:1344 cmdevents.cpp:1408 msgid " files (" msgstr "" -#: cmdevents.cpp:1333 cmdevents.cpp:1354 -msgid "VBA Movie files|*.vmv" -msgstr "" - -#: cmdevents.cpp:1353 +#: cmdevents.cpp:1439 msgid "Select file" msgstr "" -#: cmdevents.cpp:1668 cmdevents.cpp:1761 +#: cmdevents.cpp:1756 cmdevents.cpp:1849 msgid "Select state file" msgstr "" -#: cmdevents.cpp:1669 cmdevents.cpp:1762 +#: cmdevents.cpp:1757 cmdevents.cpp:1850 msgid "VisualBoyAdvance saved game files|*.sgm" msgstr "" -#: cmdevents.cpp:1792 cmdevents.cpp:1802 cmdevents.cpp:1813 +#: cmdevents.cpp:1880 cmdevents.cpp:1890 cmdevents.cpp:1901 #, c-format msgid "Current state slot #%d" msgstr "" -#: cmdevents.cpp:1883 +#: cmdevents.cpp:1971 msgid "Cannot use Colorizer Hack when GB BIOS File is enabled." msgstr "" -#: cmdevents.cpp:2098 +#: cmdevents.cpp:2186 msgid "Sound enabled" msgstr "" -#: cmdevents.cpp:2098 +#: cmdevents.cpp:2186 msgid "Sound disabled" msgstr "" -#: cmdevents.cpp:2111 cmdevents.cpp:2125 +#: cmdevents.cpp:2199 cmdevents.cpp:2213 #, c-format msgid "Volume: %d%%" msgstr "" -#: cmdevents.cpp:2200 +#: cmdevents.cpp:2288 msgid "Set to 0 for pseudo tty" msgstr "" -#: cmdevents.cpp:2202 +#: cmdevents.cpp:2290 msgid "Port to wait for connection:" msgstr "" -#: cmdevents.cpp:2203 +#: cmdevents.cpp:2291 msgid "GDB Connection" msgstr "" -#: cmdevents.cpp:2256 +#: cmdevents.cpp:2344 #, c-format msgid "Waiting for connection at %s" msgstr "" -#: cmdevents.cpp:2263 +#: cmdevents.cpp:2351 #, c-format msgid "Waiting for connection on port %d" msgstr "" -#: cmdevents.cpp:2266 +#: cmdevents.cpp:2354 msgid "Waiting for GDB..." msgstr "" -#: cmdevents.cpp:2681 +#: cmdevents.cpp:2769 #, c-format msgid "Using pixel filter #%d" msgstr "" -#: cmdevents.cpp:2696 +#: cmdevents.cpp:2784 #, c-format msgid "Using interframe blending #%d" msgstr "" -#: cmdevents.cpp:2735 panel.cpp:192 panel.cpp:306 +#: cmdevents.cpp:2823 panel.cpp:192 panel.cpp:306 msgid "Could not initialize the sound driver!" msgstr "" -#: cmdevents.cpp:2839 +#: cmdevents.cpp:2927 msgid "Nintendo GameBoy (+Color+Advance) emulator." msgstr "" -#: cmdevents.cpp:2840 +#: cmdevents.cpp:2928 msgid "" "Copyright (C) 1999-2003 Forgotten\n" "Copyright (C) 2004-2006 VBA development team\n" "Copyright (C) 2007-2020 VBA-M development team" msgstr "" -#: cmdevents.cpp:2841 +#: cmdevents.cpp:2929 msgid "" "This program is free software: you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" @@ -843,114 +839,114 @@ msgid "" "along with this program. If not, see http://www.gnu.org/licenses ." msgstr "" -#: cmdevents.cpp:3101 +#: cmdevents.cpp:3189 msgid "Cannot use GB BIOS when Colorizer Hack is enabled." msgstr "" -#: cmdevents.cpp:3161 +#: cmdevents.cpp:3249 msgid "LAN link is already active. Disable link mode to disconnect." msgstr "" -#: cmdevents.cpp:3167 +#: cmdevents.cpp:3255 msgid "Network is not supported in local mode." msgstr "" -#: opts.cpp:648 opts.cpp:950 +#: opts.cpp:649 opts.cpp:951 #, c-format msgid "Invalid value %s for option %s; valid values are %s%s%s" msgstr "" -#: opts.cpp:665 opts.cpp:962 +#: opts.cpp:666 opts.cpp:963 #, c-format msgid "Invalid value %d for option %s; valid values are %d - %d" msgstr "" -#: opts.cpp:672 opts.cpp:681 opts.cpp:970 opts.cpp:978 +#: opts.cpp:673 opts.cpp:682 opts.cpp:971 opts.cpp:979 #, c-format msgid "Invalid value %f for option %s; valid values are %f - %f" msgstr "" -#: opts.cpp:738 opts.cpp:759 opts.cpp:1046 +#: opts.cpp:739 opts.cpp:760 opts.cpp:1047 #, c-format msgid "Invalid key binding %s for %s" msgstr "" -#: opts.cpp:933 +#: opts.cpp:934 #, c-format msgid "Invalid flag option %s - %s ignored" msgstr "" -#: sys.cpp:125 sys.cpp:181 +#: sys.cpp:161 sys.cpp:221 msgid "No game in progress to record" msgstr "" -#: sys.cpp:138 +#: sys.cpp:178 #, c-format msgid "Cannot open output file %s" msgstr "" -#: sys.cpp:145 sys.cpp:165 sys.cpp:311 +#: sys.cpp:185 sys.cpp:205 sys.cpp:355 msgid "Error writing game recording" msgstr "" -#: sys.cpp:186 +#: sys.cpp:226 msgid "Cannot play game recording while recording" msgstr "" -#: sys.cpp:199 +#: sys.cpp:243 #, c-format msgid "Cannot open recording file %s" msgstr "" -#: sys.cpp:206 sys.cpp:216 +#: sys.cpp:250 sys.cpp:260 msgid "Error reading game recording" msgstr "" -#: sys.cpp:322 +#: sys.cpp:371 sys.cpp:391 msgid "Playback ended" msgstr "" -#: sys.cpp:341 +#: sys.cpp:415 #, c-format msgid "%d%%(%d, %d fps)" msgstr "" -#: sys.cpp:349 +#: sys.cpp:423 #, c-format msgid "%d%%" msgstr "" -#: sys.cpp:769 xrc/GBPrinter.xrc:65 +#: sys.cpp:843 xrc/GBPrinter.xrc:65 msgid "&Discard" msgstr "" -#: sys.cpp:803 +#: sys.cpp:877 msgid "Image files (*.bmp;*.jpg;*.png)|*.bmp;*.jpg;*.png|" msgstr "" -#: sys.cpp:812 +#: sys.cpp:886 msgid "Save printer image to" msgstr "" -#: sys.cpp:826 sys.cpp:1009 +#: sys.cpp:900 sys.cpp:1083 #, c-format msgid "Wrote printer output to %s" msgstr "" -#: sys.cpp:831 sys.cpp:902 +#: sys.cpp:905 sys.cpp:976 msgid "&Close" msgstr "" -#: sys.cpp:897 +#: sys.cpp:971 msgid "Printed" msgstr "" -#: sys.cpp:1199 +#: sys.cpp:1273 #, c-format msgid "Error opening pseudo tty: %s" msgstr "" -#: sys.cpp:1298 +#: sys.cpp:1372 #, c-format msgid "Error setting up server socket (%d)" msgstr "" @@ -1046,70 +1042,70 @@ msgstr "" msgid "Error writing rewind state" msgstr "" -#: panel.cpp:2198 +#: panel.cpp:2201 msgid "Failed to set glXSwapIntervalEXT" msgstr "" -#: panel.cpp:2207 +#: panel.cpp:2210 msgid "Failed to set glXSwapIntervalSGI" msgstr "" -#: panel.cpp:2216 +#: panel.cpp:2219 msgid "Failed to set glXSwapIntervalMESA" msgstr "" -#: panel.cpp:2222 +#: panel.cpp:2225 msgid "No support for wglGetExtensionsStringEXT" msgstr "" -#: panel.cpp:2225 +#: panel.cpp:2228 msgid "No support for WGL_EXT_swap_control" msgstr "" -#: panel.cpp:2234 +#: panel.cpp:2237 msgid "Failed to set wglSwapIntervalEXT" msgstr "" -#: panel.cpp:2240 +#: panel.cpp:2243 msgid "No VSYNC available on this platform" msgstr "" -#: panel.cpp:2336 +#: panel.cpp:2339 msgid "memory allocation error" msgstr "" -#: panel.cpp:2339 +#: panel.cpp:2342 msgid "error initializing codec" msgstr "" -#: panel.cpp:2342 +#: panel.cpp:2345 msgid "error writing to output file" msgstr "" -#: panel.cpp:2345 +#: panel.cpp:2348 msgid "can't guess output format from file name" msgstr "" -#: panel.cpp:2350 +#: panel.cpp:2353 msgid "programming error; aborting!" msgstr "" -#: panel.cpp:2362 panel.cpp:2391 +#: panel.cpp:2365 panel.cpp:2394 #, c-format msgid "Unable to begin recording to %s (%s)" msgstr "" -#: panel.cpp:2419 +#: panel.cpp:2422 #, c-format msgid "Error in audio/video recording (%s); aborting" msgstr "" -#: panel.cpp:2425 +#: panel.cpp:2428 #, c-format msgid "Error in audio recording (%s); aborting" msgstr "" -#: panel.cpp:2435 +#: panel.cpp:2438 #, c-format msgid "Error in video recording (%s); aborting" msgstr "" @@ -1170,12 +1166,12 @@ msgstr "" msgid "CONTROL" msgstr "" -#: widgets/sdljoy.cpp:177 +#: widgets/sdljoy.cpp:170 #, c-format msgid "Connected %s: %s" msgstr "" -#: widgets/sdljoy.cpp:192 +#: widgets/sdljoy.cpp:185 #, c-format msgid "Disconnected %s" msgstr "" diff --git a/src/common/ffmpeg.cpp b/src/common/ffmpeg.cpp index 0c2161ad..e85c88d7 100644 --- a/src/common/ffmpeg.cpp +++ b/src/common/ffmpeg.cpp @@ -25,36 +25,32 @@ const supportedCodecs videoSupported[] = { std::vector recording::getSupVidNames() { std::vector result; - size_t size = sizeof(videoSupported) / sizeof(videoSupported[0]); - for (size_t i = 0; i < size; ++i) - result.push_back((char *)videoSupported[i].longName); + for (auto&& codec : videoSupported) + result.push_back((char *)codec.longName); return result; } std::vector recording::getSupVidExts() { std::vector result; - size_t size = sizeof(videoSupported) / sizeof(videoSupported[0]); - for (size_t i = 0; i < size; ++i) - result.push_back((char *)videoSupported[i].exts); + for (auto&& codec : videoSupported) + result.push_back((char *)codec.exts); return result; } std::vector recording::getSupAudNames() { std::vector result; - size_t size = sizeof(audioSupported) / sizeof(audioSupported[0]); - for (size_t i = 0; i < size; ++i) - result.push_back((char *)audioSupported[i].longName); + for (auto&& codec : audioSupported) + result.push_back((char *)codec.longName); return result; } std::vector recording::getSupAudExts() { std::vector result; - size_t size = sizeof(audioSupported) / sizeof(audioSupported[0]); - for (size_t i = 0; i < size; ++i) - result.push_back((char *)audioSupported[i].exts); + for (auto&& codec : audioSupported) + result.push_back((char *)codec.exts); return result; } diff --git a/src/wx/cmdevents.cpp b/src/wx/cmdevents.cpp index 05369351..e5942767 100644 --- a/src/wx/cmdevents.cpp +++ b/src/wx/cmdevents.cpp @@ -1327,17 +1327,61 @@ static wxString mov_path; EVT_HANDLER_MASK(RecordMovieStartRecording, "Start game recording...", CMDEN_NGREC) { + static wxString mov_exts; + static int mov_extno; + static wxString mov_path; + + if (!mov_exts.size()) { + mov_extno = -1; + int extno = 0; + + std::vector fmts = getSupMovNamesToRecord(); + std::vector exts = getSupMovExtsToRecord(); + + for (auto&& fmt : fmts) + { + mov_exts.append(wxString(fmt, wxConvLibc)); + mov_exts.append(_(" files (")); + wxString ext(exts[extno], wxConvLibc); + ext.Replace(wxT(","), wxT(";*.")); + ext.insert(0, wxT("*.")); + + if (mov_extno < 0 && ext.find(wxT("*.vmv")) != wxString::npos) + mov_extno = extno; + + mov_exts.append(ext); + mov_exts.append(wxT(")|")); + mov_exts.append(ext); + mov_exts.append(wxT('|')); + extno++; + } + + if (mov_extno < 0) + mov_extno = extno; + } + mov_path = GetGamePath(gopts.recording_dir); - wxString def_name = panel->game_name() + wxT(".vmv"); + wxString def_name = panel->game_name(); + wxString extoff = mov_exts; + + for (int i = 0; i < mov_extno; i++) { + extoff = extoff.Mid(extoff.Find(wxT('|')) + 1); + extoff = extoff.Mid(extoff.Find(wxT('|')) + 1); + } + + extoff = extoff.Mid(extoff.Find(wxT('|')) + 2); // skip * + def_name += extoff.Left(wxStrcspn(extoff, wxT(";|"))); wxFileDialog dlg(this, _("Select output file"), mov_path, def_name, - _("VBA Movie files|*.vmv"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + mov_exts, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + dlg.SetFilterIndex(mov_extno); int ret = ShowModal(&dlg); + mov_extno = dlg.GetFilterIndex(); mov_path = dlg.GetDirectory(); if (ret != wxID_OK) return; - systemStartGameRecording(dlg.GetPath()); + systemStartGameRecording(dlg.GetPath(), getSupMovFormatsToRecord()[mov_extno]); } EVT_HANDLER_MASK(RecordMovieStopRecording, "Stop game recording", CMDEN_GREC) @@ -1347,18 +1391,62 @@ EVT_HANDLER_MASK(RecordMovieStopRecording, "Stop game recording", CMDEN_GREC) EVT_HANDLER_MASK(PlayMovieStartPlaying, "Start playing movie...", CMDEN_NGREC | CMDEN_NGPLAY) { + static wxString mov_exts; + static int mov_extno; + static wxString mov_path; + + if (!mov_exts.size()) { + mov_extno = -1; + int extno = 0; + + std::vector fmts = getSupMovNamesToPlayback(); + std::vector exts = getSupMovExtsToPlayback(); + + for (size_t i = 0; i < fmts.size(); ++i) + { + mov_exts.append(wxString(fmts[i], wxConvLibc)); + mov_exts.append(_(" files (")); + wxString ext(exts[i], wxConvLibc); + ext.Replace(wxT(","), wxT(";*.")); + ext.insert(0, wxT("*.")); + + if (mov_extno < 0 && ext.find(wxT("*.vmv")) != wxString::npos) + mov_extno = extno; + + mov_exts.append(ext); + mov_exts.append(wxT(")|")); + mov_exts.append(ext); + mov_exts.append(wxT('|')); + extno++; + } + + if (mov_extno < 0) + mov_extno = extno; + } + mov_path = GetGamePath(gopts.recording_dir); systemStopGamePlayback(); - wxString def_name = panel->game_name() + wxT(".vmv"); + wxString def_name = panel->game_name(); + wxString extoff = mov_exts; + + for (int i = 0; i < mov_extno; i++) { + extoff = extoff.Mid(extoff.Find(wxT('|')) + 1); + extoff = extoff.Mid(extoff.Find(wxT('|')) + 1); + } + + extoff = extoff.Mid(extoff.Find(wxT('|')) + 2); // skip * + def_name += extoff.Left(wxStrcspn(extoff, wxT(";|"))); wxFileDialog dlg(this, _("Select file"), mov_path, def_name, - _("VBA Movie files|*.vmv"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); + mov_exts, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + dlg.SetFilterIndex(mov_extno); int ret = ShowModal(&dlg); + mov_extno = dlg.GetFilterIndex(); mov_path = dlg.GetDirectory(); if (ret != wxID_OK) return; - systemStartGamePlayback(dlg.GetPath()); + systemStartGamePlayback(dlg.GetPath(), getSupMovFormatsToPlayback()[mov_extno]); } EVT_HANDLER_MASK(PlayMovieStopPlaying, "Stop playing movie", CMDEN_GPLAY) diff --git a/src/wx/sys.cpp b/src/wx/sys.cpp index 2f330284..238819d9 100644 --- a/src/wx/sys.cpp +++ b/src/wx/sys.cpp @@ -107,17 +107,87 @@ void systemDrawScreen() // .vmv = keystroke log; all values little-endian ints: // .32 = 1 // for every joypad change (init to 0) and once at end of movie { -// .32 = frames since start of movie +// .32 = frames since start of movie in version 1 and frames since the previous change in version 2 // .32 = default joypad reading at that time // } // .vm0 = saved state +struct supportedMovie { + MVFormatID formatId; + char const* longName; + char const* exts; +}; + +const supportedMovie movieSupportedToRecord[] = { + { MV_FORMAT_ID_VMV2, "VBA Movie v2, Time Diff Format", "vmv" }, + { MV_FORMAT_ID_VMV1, "VBA Movie v1, Old Version for Compatibility", "vmv" }, +}; + +std::vector getSupMovFormatsToRecord() +{ + std::vector result; + for (auto&& fmt: movieSupportedToRecord) + result.push_back(fmt.formatId); + return result; +} + +std::vector getSupMovNamesToRecord() +{ + std::vector result; + for (auto&& fmt: movieSupportedToRecord) + result.push_back((char*)fmt.longName); + return result; +} + +std::vector getSupMovExtsToRecord() +{ + std::vector result; + for (auto&& fmt: movieSupportedToRecord) + result.push_back((char*)fmt.exts); + return result; +} + +const supportedMovie movieSupportedToPlayback[] = { + { MV_FORMAT_ID_VMV, "VBA Movie", "vmv" }, +}; + +std::vector getSupMovFormatsToPlayback() +{ + std::vector result; + for (auto&& fmt: movieSupportedToPlayback) + result.push_back(fmt.formatId); + return result; +} + +std::vector getSupMovNamesToPlayback() +{ + std::vector result; + for (auto&& fmt: movieSupportedToPlayback) + result.push_back((char*)fmt.longName); + return result; +} + +std::vector getSupMovExtsToPlayback() +{ + std::vector result; + for (auto&& fmt: movieSupportedToPlayback) + result.push_back((char*)fmt.exts); + return result; +} + +const MVFormatID VMVFormatVersions[] = { + MV_FORMAT_ID_VMV, + MV_FORMAT_ID_VMV1, + MV_FORMAT_ID_VMV2, +}; + +enum MVFormatID recording_format; wxFFile game_file; bool game_recording, game_playback; uint32_t game_frame; uint32_t game_joypad; -void systemStartGameRecording(const wxString& fname) +void systemStartGameRecording(const wxString& fname, MVFormatID format) { GameArea* panel = wxGetApp().frame->GetPanel(); @@ -129,11 +199,16 @@ void systemStartGameRecording(const wxString& fname) systemStopGamePlayback(); wxString fn = fname; + recording_format = format; + if (fn.size() < 4 || !wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".vmv"), false)) fn.append(wxT(".vmv")); uint32_t version = 1; + if (recording_format == MV_FORMAT_ID_VMV2) + version = 2; + if (!game_file.Open(fn, wxT("wb")) || game_file.Write(&version, sizeof(version)) != sizeof(version)) { wxLogError(_("Cannot open output file %s"), fname.c_str()); return; @@ -173,7 +248,7 @@ void systemStopGameRecording() uint32_t game_next_frame, game_next_joypad; -void systemStartGamePlayback(const wxString& fname) +void systemStartGamePlayback(const wxString& fname, MVFormatID format) { GameArea* panel = wxGetApp().frame->GetPanel(); @@ -190,16 +265,20 @@ void systemStartGamePlayback(const wxString& fname) systemStopGamePlayback(); wxString fn = fname; + recording_format = format; + if (fn.size() < 4 || !wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".vmv"), false)) fn.append(wxT(".vmv")); uint32_t version; - if (!game_file.Open(fn, wxT("rb")) || game_file.Read(&version, sizeof(version)) != sizeof(version) || wxUINT32_SWAP_ON_BE(version) != 1) { + if (!game_file.Open(fn, wxT("rb")) || game_file.Read(&version, sizeof(version)) != sizeof(version) || wxUINT32_SWAP_ON_BE(version) < 1 || wxUINT32_SWAP_ON_BE(version) > 2) { wxLogError(_("Cannot open recording file %s"), fname.c_str()); return; } + recording_format = VMVFormatVersions[version]; + uint32_t gf, jp; if (game_file.Read(&gf, sizeof(gf)) != sizeof(gf) || game_file.Read(&jp, sizeof(jp)) != sizeof(jp)) { @@ -310,22 +389,52 @@ uint32_t systemReadJoypad(int joy) game_recording = false; wxLogError(_("Error writing game recording")); } + + if (recording_format == MV_FORMAT_ID_VMV2) + game_frame = 0; } } else if (game_playback) { - while (game_frame >= game_next_frame) { - game_joypad = game_next_joypad; - uint32_t gf, jp; + switch (recording_format) { + case MV_FORMAT_ID_VMV2: + if (game_frame >= game_next_frame) { + game_joypad = game_next_joypad; + uint32_t gf, jp; - if (game_file.Read(&gf, sizeof(gf)) != sizeof(gf) || game_file.Read(&jp, sizeof(jp)) != sizeof(jp)) { - game_file.Close(); - game_playback = false; - wxString msg(_("Playback ended")); - systemScreenMessage(msg); - break; + if (game_file.Read(&gf, sizeof(gf)) != sizeof(gf) || game_file.Read(&jp, sizeof(jp)) != sizeof(jp)) { + game_file.Close(); + game_playback = false; + wxString msg(_("Playback ended")); + systemScreenMessage(msg); + break; + } + + game_next_frame = wxUINT32_SWAP_ON_BE(gf); + game_next_joypad = wxUINT32_SWAP_ON_BE(jp); + + game_frame = 0; } + break; - game_next_frame = wxUINT32_SWAP_ON_BE(gf); - game_next_joypad = wxUINT32_SWAP_ON_BE(jp); + case MV_FORMAT_ID_VMV1: + while (game_frame >= game_next_frame) { + game_joypad = game_next_joypad; + uint32_t gf, jp; + + if (game_file.Read(&gf, sizeof(gf)) != sizeof(gf) || game_file.Read(&jp, sizeof(jp)) != sizeof(jp)) { + game_file.Close(); + game_playback = false; + wxString msg(_("Playback ended")); + systemScreenMessage(msg); + break; + } + + game_next_frame = wxUINT32_SWAP_ON_BE(gf); + game_next_joypad = wxUINT32_SWAP_ON_BE(jp); + } + break; + + default: + break; } ret = game_joypad; diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index fcc6752c..f81588ca 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -794,12 +794,28 @@ extern bool debugStartListen(int port); extern bool debugWaitSocket(); #endif +// supported movie format for game recording +enum MVFormatID { + MV_FORMAT_ID_NONE, + + /* movie formats */ + MV_FORMAT_ID_VMV, + MV_FORMAT_ID_VMV1, + MV_FORMAT_ID_VMV2, +}; +std::vector getSupMovFormatsToRecord(); +std::vector getSupMovNamesToRecord(); +std::vector getSupMovExtsToRecord(); +std::vector getSupMovFormatsToPlayback(); +std::vector getSupMovNamesToPlayback(); +std::vector getSupMovExtsToPlayback(); + // perhaps these functions should not be called systemXXX // perhaps they should move to panel.cpp/GameArea // but they must integrate with systemReadJoypad -void systemStartGameRecording(const wxString& fname); +void systemStartGameRecording(const wxString& fname, MVFormatID format); void systemStopGameRecording(); -void systemStartGamePlayback(const wxString& fname); +void systemStartGamePlayback(const wxString& fname, MVFormatID format); void systemStopGamePlayback(); // true if turbo mode (like pressing turbo button constantly)