From 807640fed351b24642c1a99ba8fc2ec40033fa87 Mon Sep 17 00:00:00 2001 From: Joe Osborn Date: Tue, 7 Mar 2023 15:10:59 -0800 Subject: [PATCH] Associate states with replays (#15070) * change bsv file suffix to replay, update strings * add trivial RPLY block to save states * WIP rerecording support, doesn't load states properly yet--issue with checking identifiers? * Fixed a type error to get time identifiers working right, ready for testing * handle case where state without replay data is loaded during replay * cleanups * whitespace cleanup * Cleanups, change replay file format magic, fix logic around future states * Remove failed future message * Add play-replay-from-slot command, fix load-state-from-slot to use given slot * build fixes * Fix race conditions in emscripten build and incorrect replay state incrementing * Style fix for single line if --------- Co-authored-by: Joseph C. Osborn --- Makefile.emscripten | 3 ++ command.c | 52 ++++++++++++------ command.h | 3 +- input/input_driver.c | 123 ++++++++++++++++++++++++++++++++++++++++++ input/input_driver.h | 4 ++ intl/msg_hash_ar.h | 4 +- intl/msg_hash_chs.h | 4 +- intl/msg_hash_cht.h | 4 +- intl/msg_hash_cs.h | 8 ++- intl/msg_hash_de.h | 4 +- intl/msg_hash_en.h | 4 +- intl/msg_hash_eo.h | 4 +- intl/msg_hash_es.h | 4 +- intl/msg_hash_fi.h | 4 +- intl/msg_hash_fr.h | 4 +- intl/msg_hash_hu.h | 4 +- intl/msg_hash_it.h | 4 +- intl/msg_hash_ja.h | 4 +- intl/msg_hash_ko.h | 4 +- intl/msg_hash_nl.h | 4 +- intl/msg_hash_pl.h | 4 +- intl/msg_hash_pt_br.h | 4 +- intl/msg_hash_pt_pt.h | 4 +- intl/msg_hash_ru.h | 4 +- intl/msg_hash_tr.h | 4 +- intl/msg_hash_us.h | 12 ++++- intl/msg_hash_vn.h | 4 +- msg_hash.h | 4 +- retroarch.c | 11 ++-- runloop.c | 12 +++++ tasks/task_movie.c | 60 +++++++++++++-------- tasks/task_save.c | 69 ++++++++++++++++++++++-- 32 files changed, 348 insertions(+), 93 deletions(-) diff --git a/Makefile.emscripten b/Makefile.emscripten index 36ea0d122b..e6c092fcc4 100644 --- a/Makefile.emscripten +++ b/Makefile.emscripten @@ -77,6 +77,9 @@ LDFLAGS := -L. --no-heap-copy -s $(LIBS) -s TOTAL_MEMORY=$(MEMORY) -s NO_EXIT_RU ifneq ($(PTHREAD), 0) LDFLAGS += -s WASM_MEM_MAX=1073741824 -pthread -s PTHREAD_POOL_SIZE=$(PTHREAD) CFLAGS += -pthread + HAVE_THREADS=1 +else + HAVE_THREADS=0 endif ifeq ($(ASYNC), 1) diff --git a/command.c b/command.c index d33b3d43bd..c3f9f30241 100644 --- a/command.c +++ b/command.c @@ -679,8 +679,7 @@ bool command_load_state_slot(command_t *cmd, const char *arg) state_path[0] = '\0'; if (savestates_enabled) { - runloop_get_current_savestate_path(state_path, - sizeof(state_path)); + runloop_get_savestate_path(state_path, sizeof(state_path), slot); core_serialize_size(&info); savestates_enabled = (info.size > 0); @@ -697,6 +696,40 @@ bool command_load_state_slot(command_t *cmd, const char *arg) return ret; } +bool command_play_replay_slot(command_t *cmd, const char *arg) +{ +#ifdef HAVE_BSV_MOVIE + char replay_path[16384]; + retro_ctx_size_info_t info; + char reply[128] = ""; + unsigned int slot = (unsigned int)strtoul(arg, NULL, 10); + char *reply_at = reply + snprintf(reply, sizeof(reply) - 1, "PLAY_REPLAY_SLOT %d", slot); + bool savestates_enabled = core_info_current_supports_savestate(); + bool ret = false; + replay_path[0] = '\0'; + if (savestates_enabled) + { + runloop_get_replay_path(replay_path, sizeof(replay_path), slot); + + core_serialize_size(&info); + savestates_enabled = (info.size > 0); + } + if (savestates_enabled) + { + ret = movie_start_playback(input_state_get_ptr(), replay_path); + if (ret) + command_post_state_loaded(); + } + else + ret = false; + + cmd->replier(cmd, reply, strlen(reply)); + return ret; +#else + return false; +#endif +} + #if defined(HAVE_CHEEVOS) bool command_read_ram(command_t *cmd, const char *arg) @@ -1302,7 +1335,7 @@ bool command_event_load_entry_state(settings_t *settings) ); if (ret) - configuration_set_int(settings, settings->ints.state_slot, runloop_st->entry_state_slot); + configuration_set_int(settings, settings->ints.state_slot, runloop_st->entry_state_slot); return ret; } @@ -1935,19 +1968,6 @@ bool command_event_main_state(unsigned cmd) case CMD_EVENT_LOAD_STATE_FROM_RAM: { bool res = false; -#ifdef HAVE_BSV_MOVIE - input_driver_state_t *input_st = input_state_get_ptr(); - if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING) - { - RARCH_ERR("[Load] [Movie] Can't load state during movie record\n"); - return false; - } - if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_PLAYBACK) - { - RARCH_LOG("[Load] [Movie] Loaded state during movie playback, halting playback\n"); - movie_stop(input_st); - } -#endif if (cmd == CMD_EVENT_LOAD_STATE) res = content_load_state(state_path, false, false); else diff --git a/command.h b/command.h index b38b439e41..ad3ac3e12e 100644 --- a/command.h +++ b/command.h @@ -409,6 +409,7 @@ bool command_get_status(command_t *cmd, const char* arg); bool command_get_config_param(command_t *cmd, const char* arg); bool command_show_osd_msg(command_t *cmd, const char* arg); bool command_load_state_slot(command_t *cmd, const char* arg); +bool command_play_replay_slot(command_t *cmd, const char* arg); #ifdef HAVE_CHEEVOS bool command_read_ram(command_t *cmd, const char *arg); bool command_write_ram(command_t *cmd, const char *arg); @@ -441,7 +442,7 @@ static const struct cmd_action_map action_map[] = { { "WRITE_CORE_MEMORY",command_write_memory, "
..." }, { "LOAD_STATE_SLOT",command_load_state_slot, ""}, - /*{ "PLAY_REPLAY_SLOT",command_play_replay_slot, ""},*/ + { "PLAY_REPLAY_SLOT",command_play_replay_slot, ""}, }; static const struct cmd_map map[] = { diff --git a/input/input_driver.c b/input/input_driver.c index 6facb1e255..31c9f3e27b 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -4827,6 +4827,129 @@ void bsv_movie_next_frame(input_driver_state_t *input_st) } } } +size_t replay_get_serialize_size(void) +{ + input_driver_state_t *input_st = input_state_get_ptr(); + if (input_st->bsv_movie_state.flags & (BSV_FLAG_MOVIE_RECORDING | BSV_FLAG_MOVIE_PLAYBACK)) + return sizeof(int32_t)+intfstream_tell(input_st->bsv_movie_state_handle->file); + else + return 0; +} + +bool replay_get_serialized_data(void* buffer) +{ + input_driver_state_t *input_st = input_state_get_ptr(); + bsv_movie_t *handle = input_st->bsv_movie_state_handle; + if (input_st->bsv_movie_state.flags & (BSV_FLAG_MOVIE_RECORDING | BSV_FLAG_MOVIE_PLAYBACK)) + { + long file_end = intfstream_tell(handle->file); + long read_amt = 0; + long file_end_lil = swap_if_big32(file_end); + uint8_t *file_end_bytes = (uint8_t *)(&file_end_lil); + uint8_t *buf = buffer; + buf[0] = file_end_bytes[0]; + buf[1] = file_end_bytes[1]; + buf[2] = file_end_bytes[2]; + buf[3] = file_end_bytes[3]; + buf += 4; + intfstream_rewind(handle->file); + read_amt = intfstream_read(handle->file, (void *)buf, file_end); + if (read_amt != file_end) + RARCH_ERR("[Replay] Failed to write correct number of replay bytes into state file: %d / %d\n", read_amt, file_end); + } + return true; +} +bool replay_set_serialized_data(void* buf) +{ + uint8_t *buffer = buf; + input_driver_state_t *input_st = input_state_get_ptr(); + bool playback = input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_PLAYBACK; + bool recording = input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING; + /* If there is no current replay, ignore this entirely. + TODO: Later, consider loading up the replay and allow the user to continue it? or would that be better done from the replay hotkeys? */ + if(!(playback || recording)) + return true; + if (buffer == NULL) + { + if (recording) + { + const char *load_fail_str = + msg_hash_to_str(MSG_REPLAY_LOAD_STATE_FAILED_INCOMPAT); + runloop_msg_queue_push(load_fail_str, + 1, 180, true, + NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR); + RARCH_ERR("[Replay] %s.\n", load_fail_str); + return false; + } + if (playback) + { + const char *load_warn_str = + msg_hash_to_str(MSG_REPLAY_LOAD_STATE_HALT_INCOMPAT); + runloop_msg_queue_push(load_warn_str, + 1, 180, true, + NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_WARNING); + RARCH_WARN("[Replay] %s.\n", load_warn_str); + movie_stop(input_st); + } + return true; + } + else + { + int32_t loaded_len = swap_if_big32(((int32_t *)buffer)[0]); + /* TODO: should factor the next few lines away, magic numbers ahoy */ + uint32_t *header = (uint32_t *)(buffer+sizeof(int32_t)); + int64_t *identifier_spot = (int64_t *)(header+4); + int64_t identifier = swap_if_big64(*identifier_spot); + int32_t handle_idx = intfstream_tell(input_st->bsv_movie_state_handle->file); + bool is_compatible = identifier == input_st->bsv_movie_state_handle->identifier; + if (is_compatible) + { + /* If the state is part of this replay, go back to that state + and rewind the replay; otherwise + halt playback and go to that state normally. */ + /* if the savestate movie is after the current replay + length we can replace the current replay data with it, + but if it's earlier we can rewind the replay to the + savestate movie time point. */ + /* This can truncate the current recording, so beware! */ + /* TODO: figure out what to do about rewinding across load */ + if (loaded_len > handle_idx) + { + /* TODO: Really, to be very careful, we should be + checking that the events in the loaded state are the + same up to handle_idx. Right? */ + intfstream_rewind(input_st->bsv_movie_state_handle->file); + intfstream_write(input_st->bsv_movie_state_handle->file, buffer+sizeof(int32_t), loaded_len); + } + else + intfstream_seek(input_st->bsv_movie_state_handle->file, loaded_len, SEEK_SET); + } + else + { + if (recording) + { + const char *load_fail_str = + msg_hash_to_str(MSG_REPLAY_LOAD_STATE_FAILED_INCOMPAT); + runloop_msg_queue_push(load_fail_str, + 1, 180, true, + NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR); + RARCH_ERR("[Replay] %s.\n", load_fail_str); + return false; + } + if (playback) + { + const char *load_warn_str = + msg_hash_to_str(MSG_REPLAY_LOAD_STATE_HALT_INCOMPAT); + runloop_msg_queue_push(load_warn_str, + 1, 180, true, + NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_WARNING); + RARCH_WARN("[Replay] %s.\n", load_warn_str); + movie_stop(input_st); + } + } + } + return true; +} #endif diff --git a/input/input_driver.h b/input/input_driver.h index a783070a13..b508bcfa65 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -150,6 +150,7 @@ struct bsv_movie size_t frame_ptr; size_t min_file_pos; size_t state_size; + int64_t identifier; /* Staging variables for keyboard events */ uint8_t key_event_count; @@ -1015,6 +1016,9 @@ bool movie_stop_playback(input_driver_state_t *input_st); bool movie_stop_record(input_driver_state_t *input_st); bool movie_stop(input_driver_state_t *input_st); +size_t replay_get_serialize_size(void); +bool replay_get_serialized_data(void* buffer); +bool replay_set_serialized_data(void* buffer); #endif /** diff --git a/intl/msg_hash_ar.h b/intl/msg_hash_ar.h index 608471b8dc..f63046abe3 100644 --- a/intl/msg_hash_ar.h +++ b/intl/msg_hash_ar.h @@ -8514,8 +8514,8 @@ MSG_HASH( "الذاكرة" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "ملف إعادة عرض فيلم الإدخال ليس ملف BSV1 صالح." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "ملف إعادة عرض فيلم الإدخال ليس ملف REPLAY صالح." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_chs.h b/intl/msg_hash_chs.h index adc6577bee..d5749b9198 100644 --- a/intl/msg_hash_chs.h +++ b/intl/msg_hash_chs.h @@ -11402,8 +11402,8 @@ MSG_HASH( "内存" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "视频不是有效的BSV1文件。" + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "视频不是有效的REPLAY文件。" ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_cht.h b/intl/msg_hash_cht.h index 29a0bad781..8ed914135a 100644 --- a/intl/msg_hash_cht.h +++ b/intl/msg_hash_cht.h @@ -13278,8 +13278,8 @@ MSG_HASH( "記憶體" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "操作重播不是有效的BSV1檔案。" + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "操作重播不是有效的REPLAY檔案。" ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_cs.h b/intl/msg_hash_cs.h index cdcb079a1b..6921eb4b38 100644 --- a/intl/msg_hash_cs.h +++ b/intl/msg_hash_cs.h @@ -7244,6 +7244,10 @@ MSG_HASH( MENU_ENUM_SUBLABEL_SAVEFILE_DIRECTORY, "Do tohoto adresáře uložte všechny uložené soubory. Pokud není nastaveno, pokusí se uložit do pracovního adresáře souboru s obsahem." ) +MSG_HASH( + MENU_ENUM_LABEL_HELP_SAVEFILE_DIRECTORY, + "Do tohoto adresáře uložte všechny ukládací soubory (*.srm). Patří sem i související soubory jako .rt, .psrm atd... Toto bude potlačeno explicitními volbami příkazového řádku." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SAVESTATE_DIRECTORY, "Uložené Pozice" @@ -12670,8 +12674,8 @@ MSG_HASH( "Paměť" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Vstupní soubor videa pro přehrávání videa není platným BSV1 souborem." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Vstupní soubor videa pro přehrávání videa není platným REPLAY souborem." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_de.h b/intl/msg_hash_de.h index 036132f24f..b0ce7aa62f 100644 --- a/intl/msg_hash_de.h +++ b/intl/msg_hash_de.h @@ -12646,8 +12646,8 @@ MSG_HASH( "Speicher" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Filmdatei ist keine gültige BSV1-Datei." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Filmdatei ist keine gültige REPLAY-Datei." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_en.h b/intl/msg_hash_en.h index a00bf7e780..6912a01f05 100644 --- a/intl/msg_hash_en.h +++ b/intl/msg_hash_en.h @@ -2006,8 +2006,8 @@ MSG_HASH( "Loading favourites file" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Input replay film file is not a valid BSV1 file." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Input replay film file is not a valid REPLAY file." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_eo.h b/intl/msg_hash_eo.h index 0152193b60..d5ddcbbc62 100644 --- a/intl/msg_hash_eo.h +++ b/intl/msg_hash_eo.h @@ -1002,8 +1002,8 @@ MSG_HASH( "CRC32 checksum mismatch between content file and saved content checksum in replay file header) replay highly likely to desync on playback." ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Movie file is not a valid BSV1 file." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Movie file is not a valid REPLAY file." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_es.h b/intl/msg_hash_es.h index 5f74fce1dc..8c048affa1 100644 --- a/intl/msg_hash_es.h +++ b/intl/msg_hash_es.h @@ -12966,8 +12966,8 @@ MSG_HASH( "Memoria" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "El archivo de la repetición de entrada no es un archivo BSV1 válido." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "El archivo de la repetición de entrada no es un archivo REPLAY válido." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_fi.h b/intl/msg_hash_fi.h index 1a91f2b658..fd1c950899 100644 --- a/intl/msg_hash_fi.h +++ b/intl/msg_hash_fi.h @@ -11982,8 +11982,8 @@ MSG_HASH( "Muisti" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Sisääntulon uudelleentoiston elokuvatiedosto ei ole kelvollinen BSV1-tiedosto." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Sisääntulon uudelleentoiston elokuvatiedosto ei ole kelvollinen REPLAY-tiedosto." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_fr.h b/intl/msg_hash_fr.h index b62f171a4f..472fdaec57 100644 --- a/intl/msg_hash_fr.h +++ b/intl/msg_hash_fr.h @@ -12922,8 +12922,8 @@ MSG_HASH( "Mémoire" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Le fichier vidéo de relecture n'est pas un fichier BSV1 valide." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Le fichier vidéo de relecture n'est pas un fichier REPLAY valide." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_hu.h b/intl/msg_hash_hu.h index 9f9bba2d24..d2e7219634 100644 --- a/intl/msg_hash_hu.h +++ b/intl/msg_hash_hu.h @@ -12734,8 +12734,8 @@ MSG_HASH( "Memória" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "A bemenet-újrajátszás fájl nem egy érvényes BSV1 fájl." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "A bemenet-újrajátszás fájl nem egy érvényes REPLAY fájl." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_it.h b/intl/msg_hash_it.h index ed6358e7c9..e993f7a3cb 100644 --- a/intl/msg_hash_it.h +++ b/intl/msg_hash_it.h @@ -12806,8 +12806,8 @@ MSG_HASH( "Memoria" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Il File del filmato non è un file valido di BSV1." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Il File del filmato non è un file valido di REPLAY." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index ff6e568027..77dd782d0c 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -10242,8 +10242,8 @@ MSG_HASH( "メモリ" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "入力リプレイムービーファイルは有効なBSV1ファイルではありません. " + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "入力リプレイムービーファイルは有効なREPLAYファイルではありません. " ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_ko.h b/intl/msg_hash_ko.h index f2dc8092e5..2167a8d138 100644 --- a/intl/msg_hash_ko.h +++ b/intl/msg_hash_ko.h @@ -13018,8 +13018,8 @@ MSG_HASH( "메모리" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "입력 리플레이 영상 파일이 올바른 BSV1 파일이 아닙니다." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "동영상 파일이 올바른 REPLAY 파일이 아닙니다." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_nl.h b/intl/msg_hash_nl.h index 5f5b0a2a8e..4ab8bd4186 100644 --- a/intl/msg_hash_nl.h +++ b/intl/msg_hash_nl.h @@ -5930,8 +5930,8 @@ MSG_HASH( "Geheugen" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Movie file is not a valid BSV1 file." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Movie file is not a valid REPLAY file." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_pl.h b/intl/msg_hash_pl.h index a02dd25e10..d0f03d2f15 100644 --- a/intl/msg_hash_pl.h +++ b/intl/msg_hash_pl.h @@ -11666,8 +11666,8 @@ MSG_HASH( "Pamięć" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Plik filmu nie jest prawidłowym plikiem BSV1." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Plik filmu nie jest prawidłowym plikiem REPLAY." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_pt_br.h b/intl/msg_hash_pt_br.h index ebe4a97cef..202facad3d 100644 --- a/intl/msg_hash_pt_br.h +++ b/intl/msg_hash_pt_br.h @@ -11770,8 +11770,8 @@ MSG_HASH( "Memória" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "O arquivo de filme não é um arquivo BSV1 válido." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "O arquivo de filme não é um arquivo REPLAY válido." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_pt_pt.h b/intl/msg_hash_pt_pt.h index 3176940014..d5530de8fd 100644 --- a/intl/msg_hash_pt_pt.h +++ b/intl/msg_hash_pt_pt.h @@ -4834,8 +4834,8 @@ MSG_HASH( "Memória" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "O ficheiro de vídeo não é um ficheiro BSV1 válido." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "O ficheiro de vídeo não é um ficheiro REPLAY válido." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_ru.h b/intl/msg_hash_ru.h index 017bc923ca..50bbfcd856 100644 --- a/intl/msg_hash_ru.h +++ b/intl/msg_hash_ru.h @@ -13034,8 +13034,8 @@ MSG_HASH( "Объём памяти" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Запись повтора не является правильным файлом BSV1." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Запись повтора не является правильным файлом REPLAY." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_tr.h b/intl/msg_hash_tr.h index 163d6c09c6..1acdf29172 100644 --- a/intl/msg_hash_tr.h +++ b/intl/msg_hash_tr.h @@ -12254,8 +12254,8 @@ MSG_HASH( "Bellek" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Giriş tekrar film dosyası geçerli bir BSV1 dosyası değil." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Giriş tekrar film dosyası geçerli bir REPLAY dosyası değil." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index dca3ae2f84..3893194931 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -13613,6 +13613,14 @@ MSG_HASH( MSG_FOUND_LAST_REPLAY_SLOT, "Found last replay slot" ) +MSG_HASH( + MSG_REPLAY_LOAD_STATE_FAILED_INCOMPAT, + "Not from current recording" + ) +MSG_HASH( + MSG_REPLAY_LOAD_STATE_HALT_INCOMPAT, + "Not compatible with replay" + ) MSG_HASH( MSG_FOUND_SHADER, "Found shader" @@ -13742,8 +13750,8 @@ MSG_HASH( "Memory" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Input replay movie file is not a valid BSV1 file." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Input replay movie file is not a valid REPLAY file." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/intl/msg_hash_vn.h b/intl/msg_hash_vn.h index 85710090f2..4e056e29a5 100644 --- a/intl/msg_hash_vn.h +++ b/intl/msg_hash_vn.h @@ -2518,8 +2518,8 @@ MSG_HASH( "Đang tải state" ) MSG_HASH( - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, - "Movie file is not a valid BSV1 file." + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, + "Movie file is not a valid REPLAY file." ) MSG_HASH( MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, diff --git a/msg_hash.h b/msg_hash.h index 0d1ef3935c..ac1385dde1 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -281,6 +281,8 @@ enum msg_hash_enums MSG_FAILED_TO_START_AUDIO_DRIVER, MSG_FOUND_LAST_STATE_SLOT, MSG_FOUND_LAST_REPLAY_SLOT, + MSG_REPLAY_LOAD_STATE_HALT_INCOMPAT, + MSG_REPLAY_LOAD_STATE_FAILED_INCOMPAT, MSG_RESTORED_OLD_SAVE_STATE, MSG_NO_STATE_HAS_BEEN_LOADED_YET, MSG_GOT_CONNECTION_FROM, @@ -337,7 +339,7 @@ enum msg_hash_enums MSG_LOADING_HISTORY_FILE, MSG_LOADING_FAVORITES_FILE, MSG_COULD_NOT_READ_STATE_FROM_MOVIE, - MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, + MSG_MOVIE_FILE_IS_NOT_A_VALID_REPLAY_FILE, MSG_OVERRIDES_NOT_SAVED, MSG_OVERRIDES_ACTIVE_NOT_SAVING, MSG_OVERRIDES_SAVED_SUCCESSFULLY, diff --git a/retroarch.c b/retroarch.c index 5bd56572e9..0b0e7f0366 100644 --- a/retroarch.c +++ b/retroarch.c @@ -2544,25 +2544,24 @@ bool command_event(enum event_command cmd, void *data) bool res = false; #ifdef HAVE_BSV_MOVIE input_driver_state_t *input_st = input_state_get_ptr(); + int replay_slot = settings->ints.replay_slot; char replay_path[PATH_MAX_LENGTH]; + if (settings->bools.replay_auto_index) + replay_slot += 1; res = true; /* TODO: Consider cloning and extending the current replay if we start recording during a recording */ if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING) res = false; else if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_PLAYBACK) res = movie_stop(input_st); - RARCH_ERR("[Movie] res after stop check: %d\n",res); - if (!runloop_get_current_replay_path(replay_path, sizeof(replay_path))) + if (!runloop_get_replay_path(replay_path, sizeof(replay_path), replay_slot)) res = false; - RARCH_ERR("[Movie] res after path get: %d\n",res); if(res) res = movie_start_record(input_st, replay_path); - RARCH_ERR("[Movie] res after start record: %d\n",res); if(res && settings->bools.replay_auto_index) { - int new_replay_slot = settings->ints.replay_slot + 1; - configuration_set_int(settings, settings->ints.replay_slot, new_replay_slot); + configuration_set_int(settings, settings->ints.replay_slot, replay_slot); } if(!res) { diff --git a/runloop.c b/runloop.c index 4768e10268..1567c22424 100644 --- a/runloop.c +++ b/runloop.c @@ -4114,6 +4114,18 @@ static bool event_init_content( if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_START_RECORDING) { configuration_set_uint(settings, settings->uints.rewind_granularity, 1); +#ifndef HAVE_THREADS + /* Hack: the regular scheduler doesn't do the right thing here at + least in emscripten builds. I would expect that the check in + task_movie.c:343 should defer recording until the movie task + is done, but maybe that task isn't enqueued again yet when the + movie-record task is checked? Or the finder call in + content_load_state_in_progress is not correct? Either way, + the load happens after the recording starts rather than the + right way around. + */ + task_queue_wait(NULL,NULL); +#endif movie_start_record(input_st, input_st->bsv_movie_state.movie_start_path); } else if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_START_PLAYBACK) diff --git a/tasks/task_movie.c b/tasks/task_movie.c index 3137bccbab..dd26b2f495 100644 --- a/tasks/task_movie.c +++ b/tasks/task_movie.c @@ -20,6 +20,7 @@ #include #include #include +#include