Move BSV runloop code over to runloop.c
This commit is contained in:
parent
364d518726
commit
b48ab663b0
328
retroarch.c
328
retroarch.c
|
@ -20071,193 +20071,6 @@ void recording_driver_update_streaming_url(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_BSV_MOVIE
|
#ifdef HAVE_BSV_MOVIE
|
||||||
/* BSV MOVIE */
|
|
||||||
static bool bsv_movie_init_playback(
|
|
||||||
bsv_movie_t *handle, const char *path)
|
|
||||||
{
|
|
||||||
uint32_t state_size = 0;
|
|
||||||
uint32_t content_crc = 0;
|
|
||||||
uint32_t header[4] = {0};
|
|
||||||
intfstream_t *file = intfstream_open_file(path,
|
|
||||||
RETRO_VFS_FILE_ACCESS_READ,
|
|
||||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
|
||||||
|
|
||||||
if (!file)
|
|
||||||
{
|
|
||||||
RARCH_ERR("Could not open BSV file for playback, path : \"%s\".\n", path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle->file = file;
|
|
||||||
handle->playback = true;
|
|
||||||
|
|
||||||
intfstream_read(handle->file, header, sizeof(uint32_t) * 4);
|
|
||||||
/* Compatibility with old implementation that
|
|
||||||
* used incorrect documentation. */
|
|
||||||
if (swap_if_little32(header[MAGIC_INDEX]) != BSV_MAGIC
|
|
||||||
&& swap_if_big32(header[MAGIC_INDEX]) != BSV_MAGIC)
|
|
||||||
{
|
|
||||||
RARCH_ERR("%s\n", msg_hash_to_str(MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
content_crc = content_get_crc();
|
|
||||||
|
|
||||||
if (content_crc != 0)
|
|
||||||
if (swap_if_big32(header[CRC_INDEX]) != content_crc)
|
|
||||||
RARCH_WARN("%s.\n", msg_hash_to_str(MSG_CRC32_CHECKSUM_MISMATCH));
|
|
||||||
|
|
||||||
state_size = swap_if_big32(header[STATE_SIZE_INDEX]);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
RARCH_ERR("----- debug %u -----\n", header[0]);
|
|
||||||
RARCH_ERR("----- debug %u -----\n", header[1]);
|
|
||||||
RARCH_ERR("----- debug %u -----\n", header[2]);
|
|
||||||
RARCH_ERR("----- debug %u -----\n", header[3]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (state_size)
|
|
||||||
{
|
|
||||||
retro_ctx_size_info_t info;
|
|
||||||
retro_ctx_serialize_info_t serial_info;
|
|
||||||
uint8_t *buf = (uint8_t*)malloc(state_size);
|
|
||||||
|
|
||||||
if (!buf)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
handle->state = buf;
|
|
||||||
handle->state_size = state_size;
|
|
||||||
if (intfstream_read(handle->file,
|
|
||||||
handle->state, state_size) != state_size)
|
|
||||||
{
|
|
||||||
RARCH_ERR("%s\n", msg_hash_to_str(MSG_COULD_NOT_READ_STATE_FROM_MOVIE));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
core_serialize_size( &info);
|
|
||||||
|
|
||||||
if (info.size == state_size)
|
|
||||||
{
|
|
||||||
serial_info.data_const = handle->state;
|
|
||||||
serial_info.size = state_size;
|
|
||||||
core_unserialize(&serial_info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
RARCH_WARN("%s\n",
|
|
||||||
msg_hash_to_str(MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
handle->min_file_pos = sizeof(header) + state_size;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool bsv_movie_init_record(
|
|
||||||
bsv_movie_t *handle, const char *path)
|
|
||||||
{
|
|
||||||
retro_ctx_size_info_t info;
|
|
||||||
uint32_t state_size = 0;
|
|
||||||
uint32_t content_crc = 0;
|
|
||||||
uint32_t header[4] = {0};
|
|
||||||
intfstream_t *file = intfstream_open_file(path,
|
|
||||||
RETRO_VFS_FILE_ACCESS_WRITE,
|
|
||||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
|
||||||
|
|
||||||
if (!file)
|
|
||||||
{
|
|
||||||
RARCH_ERR("Could not open BSV file for recording, path : \"%s\".\n", path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle->file = file;
|
|
||||||
|
|
||||||
content_crc = content_get_crc();
|
|
||||||
|
|
||||||
/* This value is supposed to show up as
|
|
||||||
* BSV1 in a HEX editor, big-endian. */
|
|
||||||
header[MAGIC_INDEX] = swap_if_little32(BSV_MAGIC);
|
|
||||||
header[CRC_INDEX] = swap_if_big32(content_crc);
|
|
||||||
|
|
||||||
core_serialize_size(&info);
|
|
||||||
|
|
||||||
state_size = (unsigned)info.size;
|
|
||||||
|
|
||||||
header[STATE_SIZE_INDEX] = swap_if_big32(state_size);
|
|
||||||
|
|
||||||
intfstream_write(handle->file, header, 4 * sizeof(uint32_t));
|
|
||||||
|
|
||||||
handle->min_file_pos = sizeof(header) + state_size;
|
|
||||||
handle->state_size = state_size;
|
|
||||||
|
|
||||||
if (state_size)
|
|
||||||
{
|
|
||||||
retro_ctx_serialize_info_t serial_info;
|
|
||||||
uint8_t *st = (uint8_t*)malloc(state_size);
|
|
||||||
|
|
||||||
if (!st)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
handle->state = st;
|
|
||||||
|
|
||||||
serial_info.data = handle->state;
|
|
||||||
serial_info.size = state_size;
|
|
||||||
|
|
||||||
core_serialize(&serial_info);
|
|
||||||
|
|
||||||
intfstream_write(handle->file,
|
|
||||||
handle->state, state_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bsv_movie_free(bsv_movie_t *handle)
|
|
||||||
{
|
|
||||||
if (!handle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
intfstream_close(handle->file);
|
|
||||||
free(handle->file);
|
|
||||||
|
|
||||||
free(handle->state);
|
|
||||||
free(handle->frame_pos);
|
|
||||||
free(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bsv_movie_t *bsv_movie_init_internal(const char *path,
|
|
||||||
enum rarch_movie_type type)
|
|
||||||
{
|
|
||||||
size_t *frame_pos = NULL;
|
|
||||||
bsv_movie_t *handle = (bsv_movie_t*)calloc(1, sizeof(*handle));
|
|
||||||
|
|
||||||
if (!handle)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (type == RARCH_MOVIE_PLAYBACK)
|
|
||||||
{
|
|
||||||
if (!bsv_movie_init_playback(handle, path))
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
else if (!bsv_movie_init_record(handle, path))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Just pick something really large
|
|
||||||
* ~1 million frames rewind should do the trick. */
|
|
||||||
if (!(frame_pos = (size_t*)calloc((1 << 20), sizeof(size_t))))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
handle->frame_pos = frame_pos;
|
|
||||||
|
|
||||||
handle->frame_pos[0] = handle->min_file_pos;
|
|
||||||
handle->frame_mask = (1 << 20) - 1;
|
|
||||||
|
|
||||||
return handle;
|
|
||||||
|
|
||||||
error:
|
|
||||||
bsv_movie_free(handle);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bsv_movie_frame_rewind(void)
|
void bsv_movie_frame_rewind(void)
|
||||||
{
|
{
|
||||||
bsv_movie_t *handle = runloop_state.bsv_movie_state_handle;
|
bsv_movie_t *handle = runloop_state.bsv_movie_state_handle;
|
||||||
|
@ -20312,147 +20125,6 @@ void bsv_movie_frame_rewind(void)
|
||||||
intfstream_seek(handle->file, (int)handle->min_file_pos, SEEK_SET);
|
intfstream_seek(handle->file, (int)handle->min_file_pos, SEEK_SET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bsv_movie_init(runloop_state_t *p_runloop)
|
|
||||||
{
|
|
||||||
if (p_runloop->bsv_movie_state.movie_start_playback)
|
|
||||||
{
|
|
||||||
if (!(p_runloop->bsv_movie_state_handle = bsv_movie_init_internal(
|
|
||||||
p_runloop->bsv_movie_state.movie_start_path,
|
|
||||||
RARCH_MOVIE_PLAYBACK)))
|
|
||||||
{
|
|
||||||
RARCH_ERR("%s: \"%s\".\n",
|
|
||||||
msg_hash_to_str(MSG_FAILED_TO_LOAD_MOVIE_FILE),
|
|
||||||
p_runloop->bsv_movie_state.movie_start_path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
p_runloop->bsv_movie_state.movie_playback = true;
|
|
||||||
runloop_msg_queue_push(msg_hash_to_str(MSG_STARTING_MOVIE_PLAYBACK),
|
|
||||||
2, 180, false,
|
|
||||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
|
||||||
RARCH_LOG("%s.\n", msg_hash_to_str(MSG_STARTING_MOVIE_PLAYBACK));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (p_runloop->bsv_movie_state.movie_start_recording)
|
|
||||||
{
|
|
||||||
char msg[8192];
|
|
||||||
|
|
||||||
if (!(p_runloop->bsv_movie_state_handle = bsv_movie_init_internal(
|
|
||||||
p_runloop->bsv_movie_state.movie_start_path,
|
|
||||||
RARCH_MOVIE_RECORD)))
|
|
||||||
{
|
|
||||||
runloop_msg_queue_push(
|
|
||||||
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD),
|
|
||||||
1, 180, true,
|
|
||||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
|
||||||
RARCH_ERR("%s.\n",
|
|
||||||
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(msg, sizeof(msg),
|
|
||||||
"%s \"%s\".",
|
|
||||||
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
|
||||||
p_runloop->bsv_movie_state.movie_start_path);
|
|
||||||
|
|
||||||
runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
|
||||||
RARCH_LOG("%s \"%s\".\n",
|
|
||||||
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
|
||||||
p_runloop->bsv_movie_state.movie_start_path);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bsv_movie_deinit(runloop_state_t *p_runloop)
|
|
||||||
{
|
|
||||||
if (p_runloop->bsv_movie_state_handle)
|
|
||||||
bsv_movie_free(p_runloop->bsv_movie_state_handle);
|
|
||||||
p_runloop->bsv_movie_state_handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool runloop_check_movie_init(runloop_state_t *p_runloop,
|
|
||||||
settings_t *settings)
|
|
||||||
{
|
|
||||||
char msg[16384], path[8192];
|
|
||||||
int state_slot = settings->ints.state_slot;
|
|
||||||
|
|
||||||
msg[0] = path[0] = '\0';
|
|
||||||
|
|
||||||
configuration_set_uint(settings, settings->uints.rewind_granularity, 1);
|
|
||||||
|
|
||||||
if (state_slot > 0)
|
|
||||||
snprintf(path, sizeof(path), "%s%d.bsv",
|
|
||||||
p_runloop->bsv_movie_state.movie_path,
|
|
||||||
state_slot);
|
|
||||||
else
|
|
||||||
snprintf(path, sizeof(path), "%s.bsv",
|
|
||||||
p_runloop->bsv_movie_state.movie_path);
|
|
||||||
|
|
||||||
snprintf(msg, sizeof(msg), "%s \"%s\".",
|
|
||||||
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
|
||||||
path);
|
|
||||||
|
|
||||||
if (!(p_runloop->bsv_movie_state_handle = bsv_movie_init_internal(
|
|
||||||
path, RARCH_MOVIE_RECORD)))
|
|
||||||
{
|
|
||||||
runloop_msg_queue_push(
|
|
||||||
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD),
|
|
||||||
2, 180, true,
|
|
||||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
|
||||||
RARCH_ERR("%s\n",
|
|
||||||
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
runloop_msg_queue_push(msg, 2, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
|
||||||
RARCH_LOG("%s \"%s\".\n",
|
|
||||||
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
|
||||||
path);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool bsv_movie_check(
|
|
||||||
runloop_state_t *p_runloop,
|
|
||||||
settings_t *settings)
|
|
||||||
{
|
|
||||||
if (!p_runloop->bsv_movie_state_handle)
|
|
||||||
return runloop_check_movie_init(p_runloop, settings);
|
|
||||||
|
|
||||||
if (p_runloop->bsv_movie_state.movie_playback)
|
|
||||||
{
|
|
||||||
/* Checks if movie is being played back. */
|
|
||||||
if (!p_runloop->bsv_movie_state.movie_end)
|
|
||||||
return false;
|
|
||||||
runloop_msg_queue_push(
|
|
||||||
msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED), 2, 180, false,
|
|
||||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
|
||||||
RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED));
|
|
||||||
|
|
||||||
p_runloop->bsv_movie_state.movie_end = false;
|
|
||||||
p_runloop->bsv_movie_state.movie_playback = false;
|
|
||||||
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checks if movie is being recorded. */
|
|
||||||
if (!p_runloop->bsv_movie_state_handle)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
runloop_msg_queue_push(
|
|
||||||
msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED), 2, 180, true,
|
|
||||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
|
||||||
RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED));
|
|
||||||
|
|
||||||
end:
|
|
||||||
bsv_movie_deinit(p_runloop);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* INPUT OVERLAY */
|
/* INPUT OVERLAY */
|
||||||
|
|
20
retroarch.h
20
retroarch.h
|
@ -47,6 +47,7 @@
|
||||||
#include "audio/audio_defines.h"
|
#include "audio/audio_defines.h"
|
||||||
#include "gfx/video_shader_parse.h"
|
#include "gfx/video_shader_parse.h"
|
||||||
|
|
||||||
|
#include "configuration.h"
|
||||||
#include "core_type.h"
|
#include "core_type.h"
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "core_option_manager.h"
|
#include "core_option_manager.h"
|
||||||
|
@ -89,6 +90,11 @@ RETRO_BEGIN_DECLS
|
||||||
#define MEASURE_FRAME_TIME_SAMPLES_COUNT (2 * 1024)
|
#define MEASURE_FRAME_TIME_SAMPLES_COUNT (2 * 1024)
|
||||||
#define AUDIO_BUFFER_FREE_SAMPLES_COUNT (8 * 1024)
|
#define AUDIO_BUFFER_FREE_SAMPLES_COUNT (8 * 1024)
|
||||||
|
|
||||||
|
#define MAGIC_INDEX 0
|
||||||
|
#define SERIALIZER_INDEX 1
|
||||||
|
#define CRC_INDEX 2
|
||||||
|
#define STATE_SIZE_INDEX 3
|
||||||
|
|
||||||
#ifdef HAVE_BSV_MOVIE
|
#ifdef HAVE_BSV_MOVIE
|
||||||
#define BSV_MAGIC 0x42535631
|
#define BSV_MAGIC 0x42535631
|
||||||
|
|
||||||
|
@ -221,6 +227,12 @@ enum runloop_action
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_BSV_MOVIE
|
#ifdef HAVE_BSV_MOVIE
|
||||||
|
enum rarch_movie_type
|
||||||
|
{
|
||||||
|
RARCH_MOVIE_PLAYBACK = 0,
|
||||||
|
RARCH_MOVIE_RECORD
|
||||||
|
};
|
||||||
|
|
||||||
struct bsv_state
|
struct bsv_state
|
||||||
{
|
{
|
||||||
/* Movie playback/recording support. */
|
/* Movie playback/recording support. */
|
||||||
|
@ -2372,6 +2384,14 @@ void core_option_manager_flush(
|
||||||
config_file_t *conf,
|
config_file_t *conf,
|
||||||
core_option_manager_t *opt);
|
core_option_manager_t *opt);
|
||||||
|
|
||||||
|
#ifdef HAVE_BSV_MOVIE
|
||||||
|
bool bsv_movie_check(
|
||||||
|
runloop_state_t *p_runloop,
|
||||||
|
settings_t *settings);
|
||||||
|
void bsv_movie_deinit(runloop_state_t *p_runloop);
|
||||||
|
bool bsv_movie_init(runloop_state_t *p_runloop);
|
||||||
|
#endif
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -62,12 +62,6 @@
|
||||||
|
|
||||||
#define DEBUG_INFO_FILENAME "debug_info.txt"
|
#define DEBUG_INFO_FILENAME "debug_info.txt"
|
||||||
|
|
||||||
#define MAGIC_INDEX 0
|
|
||||||
#define SERIALIZER_INDEX 1
|
|
||||||
#define CRC_INDEX 2
|
|
||||||
#define STATE_SIZE_INDEX 3
|
|
||||||
|
|
||||||
|
|
||||||
#define TIME_TO_FPS(last_time, new_time, frames) ((1000000.0f * (frames)) / ((new_time) - (last_time)))
|
#define TIME_TO_FPS(last_time, new_time, frames) ((1000000.0f * (frames)) / ((new_time) - (last_time)))
|
||||||
|
|
||||||
#define MENU_SOUND_FORMATS "ogg|mod|xm|s3m|mp3|flac|wav"
|
#define MENU_SOUND_FORMATS "ogg|mod|xm|s3m|mp3|flac|wav"
|
||||||
|
@ -1249,12 +1243,6 @@ enum runloop_state
|
||||||
RUNLOOP_STATE_QUIT
|
RUNLOOP_STATE_QUIT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum rarch_movie_type
|
|
||||||
{
|
|
||||||
RARCH_MOVIE_PLAYBACK = 0,
|
|
||||||
RARCH_MOVIE_RECORD
|
|
||||||
};
|
|
||||||
|
|
||||||
enum poll_type_override_t
|
enum poll_type_override_t
|
||||||
{
|
{
|
||||||
POLL_TYPE_OVERRIDE_DONTCARE = 0,
|
POLL_TYPE_OVERRIDE_DONTCARE = 0,
|
||||||
|
|
|
@ -130,13 +130,6 @@ static bool video_driver_find_driver(
|
||||||
settings_t *settings,
|
settings_t *settings,
|
||||||
const char *prefix, bool verbosity_enabled);
|
const char *prefix, bool verbosity_enabled);
|
||||||
|
|
||||||
#ifdef HAVE_BSV_MOVIE
|
|
||||||
static void bsv_movie_deinit(runloop_state_t *p_runloop);
|
|
||||||
static bool bsv_movie_init(runloop_state_t *p_runloop);
|
|
||||||
static bool bsv_movie_check(runloop_state_t *p_runloop,
|
|
||||||
settings_t *settings);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void driver_uninit(struct rarch_state *p_rarch, int flags);
|
static void driver_uninit(struct rarch_state *p_rarch, int flags);
|
||||||
static void drivers_init(struct rarch_state *p_rarch,
|
static void drivers_init(struct rarch_state *p_rarch,
|
||||||
settings_t *settings,
|
settings_t *settings,
|
||||||
|
|
332
runloop.c
332
runloop.c
|
@ -22,6 +22,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
#include "content.h"
|
||||||
#include "file_path_special.h"
|
#include "file_path_special.h"
|
||||||
#include "paths.h"
|
#include "paths.h"
|
||||||
#include "retroarch.h"
|
#include "retroarch.h"
|
||||||
|
@ -516,6 +517,337 @@ error:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_BSV_MOVIE
|
||||||
|
/* BSV MOVIE */
|
||||||
|
static bool bsv_movie_init_playback(
|
||||||
|
bsv_movie_t *handle, const char *path)
|
||||||
|
{
|
||||||
|
uint32_t state_size = 0;
|
||||||
|
uint32_t content_crc = 0;
|
||||||
|
uint32_t header[4] = {0};
|
||||||
|
intfstream_t *file = intfstream_open_file(path,
|
||||||
|
RETRO_VFS_FILE_ACCESS_READ,
|
||||||
|
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Could not open BSV file for playback, path : \"%s\".\n", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->file = file;
|
||||||
|
handle->playback = true;
|
||||||
|
|
||||||
|
intfstream_read(handle->file, header, sizeof(uint32_t) * 4);
|
||||||
|
/* Compatibility with old implementation that
|
||||||
|
* used incorrect documentation. */
|
||||||
|
if (swap_if_little32(header[MAGIC_INDEX]) != BSV_MAGIC
|
||||||
|
&& swap_if_big32(header[MAGIC_INDEX]) != BSV_MAGIC)
|
||||||
|
{
|
||||||
|
RARCH_ERR("%s\n", msg_hash_to_str(MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
content_crc = content_get_crc();
|
||||||
|
|
||||||
|
if (content_crc != 0)
|
||||||
|
if (swap_if_big32(header[CRC_INDEX]) != content_crc)
|
||||||
|
RARCH_WARN("%s.\n", msg_hash_to_str(MSG_CRC32_CHECKSUM_MISMATCH));
|
||||||
|
|
||||||
|
state_size = swap_if_big32(header[STATE_SIZE_INDEX]);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
RARCH_ERR("----- debug %u -----\n", header[0]);
|
||||||
|
RARCH_ERR("----- debug %u -----\n", header[1]);
|
||||||
|
RARCH_ERR("----- debug %u -----\n", header[2]);
|
||||||
|
RARCH_ERR("----- debug %u -----\n", header[3]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (state_size)
|
||||||
|
{
|
||||||
|
retro_ctx_size_info_t info;
|
||||||
|
retro_ctx_serialize_info_t serial_info;
|
||||||
|
uint8_t *buf = (uint8_t*)malloc(state_size);
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
handle->state = buf;
|
||||||
|
handle->state_size = state_size;
|
||||||
|
if (intfstream_read(handle->file,
|
||||||
|
handle->state, state_size) != state_size)
|
||||||
|
{
|
||||||
|
RARCH_ERR("%s\n", msg_hash_to_str(MSG_COULD_NOT_READ_STATE_FROM_MOVIE));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
core_serialize_size( &info);
|
||||||
|
|
||||||
|
if (info.size == state_size)
|
||||||
|
{
|
||||||
|
serial_info.data_const = handle->state;
|
||||||
|
serial_info.size = state_size;
|
||||||
|
core_unserialize(&serial_info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
RARCH_WARN("%s\n",
|
||||||
|
msg_hash_to_str(MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->min_file_pos = sizeof(header) + state_size;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool bsv_movie_init_record(
|
||||||
|
bsv_movie_t *handle, const char *path)
|
||||||
|
{
|
||||||
|
retro_ctx_size_info_t info;
|
||||||
|
uint32_t state_size = 0;
|
||||||
|
uint32_t content_crc = 0;
|
||||||
|
uint32_t header[4] = {0};
|
||||||
|
intfstream_t *file = intfstream_open_file(path,
|
||||||
|
RETRO_VFS_FILE_ACCESS_WRITE,
|
||||||
|
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Could not open BSV file for recording, path : \"%s\".\n", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->file = file;
|
||||||
|
|
||||||
|
content_crc = content_get_crc();
|
||||||
|
|
||||||
|
/* This value is supposed to show up as
|
||||||
|
* BSV1 in a HEX editor, big-endian. */
|
||||||
|
header[MAGIC_INDEX] = swap_if_little32(BSV_MAGIC);
|
||||||
|
header[CRC_INDEX] = swap_if_big32(content_crc);
|
||||||
|
|
||||||
|
core_serialize_size(&info);
|
||||||
|
|
||||||
|
state_size = (unsigned)info.size;
|
||||||
|
|
||||||
|
header[STATE_SIZE_INDEX] = swap_if_big32(state_size);
|
||||||
|
|
||||||
|
intfstream_write(handle->file, header, 4 * sizeof(uint32_t));
|
||||||
|
|
||||||
|
handle->min_file_pos = sizeof(header) + state_size;
|
||||||
|
handle->state_size = state_size;
|
||||||
|
|
||||||
|
if (state_size)
|
||||||
|
{
|
||||||
|
retro_ctx_serialize_info_t serial_info;
|
||||||
|
uint8_t *st = (uint8_t*)malloc(state_size);
|
||||||
|
|
||||||
|
if (!st)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
handle->state = st;
|
||||||
|
|
||||||
|
serial_info.data = handle->state;
|
||||||
|
serial_info.size = state_size;
|
||||||
|
|
||||||
|
core_serialize(&serial_info);
|
||||||
|
|
||||||
|
intfstream_write(handle->file,
|
||||||
|
handle->state, state_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bsv_movie_free(bsv_movie_t *handle)
|
||||||
|
{
|
||||||
|
if (!handle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
intfstream_close(handle->file);
|
||||||
|
free(handle->file);
|
||||||
|
|
||||||
|
free(handle->state);
|
||||||
|
free(handle->frame_pos);
|
||||||
|
free(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bsv_movie_t *bsv_movie_init_internal(const char *path,
|
||||||
|
enum rarch_movie_type type)
|
||||||
|
{
|
||||||
|
size_t *frame_pos = NULL;
|
||||||
|
bsv_movie_t *handle = (bsv_movie_t*)calloc(1, sizeof(*handle));
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (type == RARCH_MOVIE_PLAYBACK)
|
||||||
|
{
|
||||||
|
if (!bsv_movie_init_playback(handle, path))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else if (!bsv_movie_init_record(handle, path))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* Just pick something really large
|
||||||
|
* ~1 million frames rewind should do the trick. */
|
||||||
|
if (!(frame_pos = (size_t*)calloc((1 << 20), sizeof(size_t))))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
handle->frame_pos = frame_pos;
|
||||||
|
|
||||||
|
handle->frame_pos[0] = handle->min_file_pos;
|
||||||
|
handle->frame_mask = (1 << 20) - 1;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
|
||||||
|
error:
|
||||||
|
bsv_movie_free(handle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bsv_movie_init(runloop_state_t *p_runloop)
|
||||||
|
{
|
||||||
|
if (p_runloop->bsv_movie_state.movie_start_playback)
|
||||||
|
{
|
||||||
|
if (!(p_runloop->bsv_movie_state_handle = bsv_movie_init_internal(
|
||||||
|
p_runloop->bsv_movie_state.movie_start_path,
|
||||||
|
RARCH_MOVIE_PLAYBACK)))
|
||||||
|
{
|
||||||
|
RARCH_ERR("%s: \"%s\".\n",
|
||||||
|
msg_hash_to_str(MSG_FAILED_TO_LOAD_MOVIE_FILE),
|
||||||
|
p_runloop->bsv_movie_state.movie_start_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_runloop->bsv_movie_state.movie_playback = true;
|
||||||
|
runloop_msg_queue_push(msg_hash_to_str(MSG_STARTING_MOVIE_PLAYBACK),
|
||||||
|
2, 180, false,
|
||||||
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
RARCH_LOG("%s.\n", msg_hash_to_str(MSG_STARTING_MOVIE_PLAYBACK));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (p_runloop->bsv_movie_state.movie_start_recording)
|
||||||
|
{
|
||||||
|
char msg[8192];
|
||||||
|
|
||||||
|
if (!(p_runloop->bsv_movie_state_handle = bsv_movie_init_internal(
|
||||||
|
p_runloop->bsv_movie_state.movie_start_path,
|
||||||
|
RARCH_MOVIE_RECORD)))
|
||||||
|
{
|
||||||
|
runloop_msg_queue_push(
|
||||||
|
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD),
|
||||||
|
1, 180, true,
|
||||||
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
RARCH_ERR("%s.\n",
|
||||||
|
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(msg, sizeof(msg),
|
||||||
|
"%s \"%s\".",
|
||||||
|
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
||||||
|
p_runloop->bsv_movie_state.movie_start_path);
|
||||||
|
|
||||||
|
runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
RARCH_LOG("%s \"%s\".\n",
|
||||||
|
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
||||||
|
p_runloop->bsv_movie_state.movie_start_path);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsv_movie_deinit(runloop_state_t *p_runloop)
|
||||||
|
{
|
||||||
|
if (p_runloop->bsv_movie_state_handle)
|
||||||
|
bsv_movie_free(p_runloop->bsv_movie_state_handle);
|
||||||
|
p_runloop->bsv_movie_state_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool runloop_check_movie_init(runloop_state_t *p_runloop,
|
||||||
|
settings_t *settings)
|
||||||
|
{
|
||||||
|
char msg[16384], path[8192];
|
||||||
|
int state_slot = settings->ints.state_slot;
|
||||||
|
|
||||||
|
msg[0] = path[0] = '\0';
|
||||||
|
|
||||||
|
configuration_set_uint(settings, settings->uints.rewind_granularity, 1);
|
||||||
|
|
||||||
|
if (state_slot > 0)
|
||||||
|
snprintf(path, sizeof(path), "%s%d.bsv",
|
||||||
|
p_runloop->bsv_movie_state.movie_path,
|
||||||
|
state_slot);
|
||||||
|
else
|
||||||
|
snprintf(path, sizeof(path), "%s.bsv",
|
||||||
|
p_runloop->bsv_movie_state.movie_path);
|
||||||
|
|
||||||
|
snprintf(msg, sizeof(msg), "%s \"%s\".",
|
||||||
|
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
||||||
|
path);
|
||||||
|
|
||||||
|
if (!(p_runloop->bsv_movie_state_handle = bsv_movie_init_internal(
|
||||||
|
path, RARCH_MOVIE_RECORD)))
|
||||||
|
{
|
||||||
|
runloop_msg_queue_push(
|
||||||
|
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD),
|
||||||
|
2, 180, true,
|
||||||
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
RARCH_ERR("%s\n",
|
||||||
|
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
runloop_msg_queue_push(msg, 2, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
RARCH_LOG("%s \"%s\".\n",
|
||||||
|
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
||||||
|
path);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bsv_movie_check(
|
||||||
|
runloop_state_t *p_runloop,
|
||||||
|
settings_t *settings)
|
||||||
|
{
|
||||||
|
if (!p_runloop->bsv_movie_state_handle)
|
||||||
|
return runloop_check_movie_init(p_runloop, settings);
|
||||||
|
|
||||||
|
if (p_runloop->bsv_movie_state.movie_playback)
|
||||||
|
{
|
||||||
|
/* Checks if movie is being played back. */
|
||||||
|
if (!p_runloop->bsv_movie_state.movie_end)
|
||||||
|
return false;
|
||||||
|
runloop_msg_queue_push(
|
||||||
|
msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED), 2, 180, false,
|
||||||
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED));
|
||||||
|
|
||||||
|
p_runloop->bsv_movie_state.movie_end = false;
|
||||||
|
p_runloop->bsv_movie_state.movie_playback = false;
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checks if movie is being recorded. */
|
||||||
|
if (!p_runloop->bsv_movie_state_handle)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
runloop_msg_queue_push(
|
||||||
|
msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED), 2, 180, true,
|
||||||
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED));
|
||||||
|
|
||||||
|
end:
|
||||||
|
bsv_movie_deinit(p_runloop);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Fetches core options path for current core/content
|
/* Fetches core options path for current core/content
|
||||||
* - path: path from which options should be read
|
* - path: path from which options should be read
|
||||||
* from/saved to
|
* from/saved to
|
||||||
|
|
Loading…
Reference in New Issue