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