2012-04-21 21:13:50 +00:00
|
|
|
/* RetroArch - A frontend for libretro.
|
2014-01-01 00:50:59 +00:00
|
|
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
2017-03-22 02:09:18 +00:00
|
|
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
2017-12-12 07:55:31 +00:00
|
|
|
*
|
2012-04-21 21:13:50 +00:00
|
|
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
2011-02-02 10:47:05 +00:00
|
|
|
* of the GNU General Public License as published by the Free Software Found-
|
|
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
*
|
2012-04-21 21:13:50 +00:00
|
|
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
2011-02-02 10:47:05 +00:00
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
|
|
*
|
2012-04-21 21:31:57 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
2011-02-02 10:47:05 +00:00
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2012-01-11 18:22:18 +00:00
|
|
|
#include <string.h>
|
2015-09-05 17:51:55 +00:00
|
|
|
|
2017-12-14 23:31:37 +00:00
|
|
|
#include <libretro.h>
|
2015-09-05 17:51:55 +00:00
|
|
|
#include <rhash.h>
|
2016-09-05 22:56:00 +00:00
|
|
|
#include <compat/strl.h>
|
2015-09-14 01:33:50 +00:00
|
|
|
#include <retro_endianness.h>
|
2015-09-05 17:51:55 +00:00
|
|
|
|
2016-03-22 01:45:25 +00:00
|
|
|
#include "configuration.h"
|
2015-11-30 23:04:04 +00:00
|
|
|
#include "movie.h"
|
2016-05-08 03:29:10 +00:00
|
|
|
#include "core.h"
|
2016-01-22 15:09:48 +00:00
|
|
|
#include "content.h"
|
2016-03-22 01:45:25 +00:00
|
|
|
#include "retroarch.h"
|
2015-11-30 23:04:04 +00:00
|
|
|
#include "msg_hash.h"
|
2015-11-23 11:03:38 +00:00
|
|
|
#include "verbosity.h"
|
2011-02-02 10:47:05 +00:00
|
|
|
|
2016-09-16 23:54:33 +00:00
|
|
|
#include "command.h"
|
|
|
|
#include "file_path_special.h"
|
|
|
|
|
2019-01-13 06:46:35 +00:00
|
|
|
bsv_movie_t *bsv_movie_state_handle = NULL;
|
2019-01-14 03:39:58 +00:00
|
|
|
struct bsv_state bsv_movie_state;
|
2015-12-01 00:47:26 +00:00
|
|
|
|
2017-02-17 01:53:40 +00:00
|
|
|
static bool bsv_movie_init_playback(bsv_movie_t *handle, const char *path)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2017-05-07 20:47:00 +00:00
|
|
|
uint32_t state_size = 0;
|
2017-05-06 14:41:22 +00:00
|
|
|
uint32_t content_crc = 0;
|
2016-01-22 15:09:48 +00:00
|
|
|
uint32_t header[4] = {0};
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_t *file = intfstream_open_file(path,
|
|
|
|
RETRO_VFS_FILE_ACCESS_READ,
|
|
|
|
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
2015-04-01 16:32:40 +00:00
|
|
|
|
2017-02-17 01:53:40 +00:00
|
|
|
if (!file)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2016-07-01 08:01:58 +00:00
|
|
|
RARCH_ERR("Could not open BSV file for playback, path : \"%s\".\n", path);
|
2011-02-02 10:47:05 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-02-17 01:53:40 +00:00
|
|
|
handle->file = file;
|
|
|
|
handle->playback = true;
|
|
|
|
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_read(handle->file, header, sizeof(uint32_t) * 4);
|
2014-09-02 14:13:42 +00:00
|
|
|
/* 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)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2016-06-28 10:08:30 +00:00
|
|
|
RARCH_ERR("%s\n", msg_hash_to_str(MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE));
|
2011-02-02 10:47:05 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-05-06 14:41:22 +00:00
|
|
|
content_crc = content_get_crc();
|
2016-01-22 15:09:48 +00:00
|
|
|
|
2017-05-06 14:41:22 +00:00
|
|
|
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));
|
2011-02-02 10:47:05 +00:00
|
|
|
|
2015-01-10 05:43:56 +00:00
|
|
|
state_size = swap_if_big32(header[STATE_SIZE_INDEX]);
|
2011-02-02 10:47:05 +00:00
|
|
|
|
2017-09-27 22:55:47 +00:00
|
|
|
#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
|
2017-05-30 03:49:12 +00:00
|
|
|
|
2011-11-10 23:55:35 +00:00
|
|
|
if (state_size)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2016-01-27 06:09:30 +00:00
|
|
|
retro_ctx_size_info_t info;
|
2017-01-22 17:22:45 +00:00
|
|
|
retro_ctx_serialize_info_t serial_info;
|
|
|
|
uint8_t *buf = (uint8_t*)malloc(state_size);
|
2016-01-27 06:09:30 +00:00
|
|
|
|
2017-01-22 17:22:45 +00:00
|
|
|
if (!buf)
|
2011-11-10 23:55:35 +00:00
|
|
|
return false;
|
2011-02-02 10:47:05 +00:00
|
|
|
|
2017-01-22 17:22:45 +00:00
|
|
|
handle->state = buf;
|
|
|
|
handle->state_size = state_size;
|
2017-12-11 11:53:47 +00:00
|
|
|
if (intfstream_read(handle->file,
|
|
|
|
handle->state, state_size) != state_size)
|
2011-11-10 23:55:35 +00:00
|
|
|
{
|
2016-06-28 10:08:30 +00:00
|
|
|
RARCH_ERR("%s\n", msg_hash_to_str(MSG_COULD_NOT_READ_STATE_FROM_MOVIE));
|
2011-11-10 23:55:35 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-07 23:33:57 +00:00
|
|
|
core_serialize_size( &info);
|
2016-01-27 06:09:30 +00:00
|
|
|
|
|
|
|
if (info.size == state_size)
|
2016-01-27 06:21:12 +00:00
|
|
|
{
|
|
|
|
serial_info.data_const = handle->state;
|
|
|
|
serial_info.size = state_size;
|
2016-05-07 23:33:57 +00:00
|
|
|
core_unserialize(&serial_info);
|
2016-01-27 06:21:12 +00:00
|
|
|
}
|
2012-03-10 17:10:54 +00:00
|
|
|
else
|
2016-06-20 02:01:58 +00:00
|
|
|
RARCH_WARN("%s\n",
|
|
|
|
msg_hash_to_str(MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION));
|
2011-02-02 19:15:00 +00:00
|
|
|
}
|
2011-11-10 23:55:35 +00:00
|
|
|
|
|
|
|
handle->min_file_pos = sizeof(header) + state_size;
|
|
|
|
|
2011-02-02 10:47:05 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-02-17 01:53:40 +00:00
|
|
|
static bool bsv_movie_init_record(bsv_movie_t *handle, const char *path)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2016-01-27 06:09:30 +00:00
|
|
|
retro_ctx_size_info_t info;
|
2017-05-07 20:47:00 +00:00
|
|
|
uint32_t state_size = 0;
|
2017-05-06 14:41:22 +00:00
|
|
|
uint32_t content_crc = 0;
|
2016-01-22 15:09:48 +00:00
|
|
|
uint32_t header[4] = {0};
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_t *file = intfstream_open_file(path,
|
|
|
|
RETRO_VFS_FILE_ACCESS_WRITE,
|
|
|
|
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
2015-01-10 05:43:56 +00:00
|
|
|
|
2017-02-17 01:53:40 +00:00
|
|
|
if (!file)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2016-07-01 08:01:58 +00:00
|
|
|
RARCH_ERR("Could not open BSV file for recording, path : \"%s\".\n", path);
|
2011-02-02 10:47:05 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-05-06 14:41:22 +00:00
|
|
|
handle->file = file;
|
2017-02-17 01:53:40 +00:00
|
|
|
|
2017-05-06 14:41:22 +00:00
|
|
|
content_crc = content_get_crc();
|
2016-01-22 15:09:48 +00:00
|
|
|
|
2014-09-03 04:14:13 +00:00
|
|
|
/* This value is supposed to show up as
|
|
|
|
* BSV1 in a HEX editor, big-endian. */
|
2015-04-01 16:32:40 +00:00
|
|
|
header[MAGIC_INDEX] = swap_if_little32(BSV_MAGIC);
|
2017-05-06 14:41:22 +00:00
|
|
|
header[CRC_INDEX] = swap_if_big32(content_crc);
|
2016-01-27 06:09:30 +00:00
|
|
|
|
2016-05-07 23:33:57 +00:00
|
|
|
core_serialize_size(&info);
|
2016-01-27 06:09:30 +00:00
|
|
|
|
2017-02-26 09:33:03 +00:00
|
|
|
state_size = (unsigned)info.size;
|
2016-01-27 06:09:30 +00:00
|
|
|
|
2011-02-02 10:47:05 +00:00
|
|
|
header[STATE_SIZE_INDEX] = swap_if_big32(state_size);
|
2017-05-30 03:49:12 +00:00
|
|
|
#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
|
|
|
|
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_write(handle->file, header, 4 * sizeof(uint32_t));
|
2011-02-02 10:47:05 +00:00
|
|
|
|
2015-04-01 16:32:40 +00:00
|
|
|
handle->min_file_pos = sizeof(header) + state_size;
|
|
|
|
handle->state_size = state_size;
|
2011-02-25 10:47:27 +00:00
|
|
|
|
2012-03-10 17:10:54 +00:00
|
|
|
if (state_size)
|
2011-11-18 17:03:24 +00:00
|
|
|
{
|
2016-01-27 06:21:12 +00:00
|
|
|
retro_ctx_serialize_info_t serial_info;
|
|
|
|
|
2012-03-10 17:10:54 +00:00
|
|
|
handle->state = (uint8_t*)malloc(state_size);
|
|
|
|
if (!handle->state)
|
|
|
|
return false;
|
|
|
|
|
2016-01-27 06:21:12 +00:00
|
|
|
serial_info.data = handle->state;
|
|
|
|
serial_info.size = state_size;
|
|
|
|
|
2016-05-07 23:33:57 +00:00
|
|
|
core_serialize(&serial_info);
|
2016-01-27 06:21:12 +00:00
|
|
|
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_write(handle->file,
|
|
|
|
handle->state, state_size);
|
2011-11-18 17:03:24 +00:00
|
|
|
}
|
|
|
|
|
2011-02-02 10:47:05 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-02-07 00:56:03 +00:00
|
|
|
static void bsv_movie_free(bsv_movie_t *handle)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2015-01-10 05:43:56 +00:00
|
|
|
if (!handle)
|
|
|
|
return;
|
|
|
|
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_close(handle->file);
|
2017-12-11 19:24:00 +00:00
|
|
|
free(handle->file);
|
2017-02-17 01:53:40 +00:00
|
|
|
|
2015-01-10 05:43:56 +00:00
|
|
|
free(handle->state);
|
|
|
|
free(handle->frame_pos);
|
|
|
|
free(handle);
|
2011-02-02 10:47:05 +00:00
|
|
|
}
|
|
|
|
|
2017-05-07 16:15:30 +00:00
|
|
|
static bsv_movie_t *bsv_movie_init_internal(const char *path,
|
2016-02-07 00:56:03 +00:00
|
|
|
enum rarch_movie_type type)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2016-12-25 00:57:15 +00:00
|
|
|
size_t *frame_pos = NULL;
|
2011-12-24 12:46:12 +00:00
|
|
|
bsv_movie_t *handle = (bsv_movie_t*)calloc(1, sizeof(*handle));
|
2017-02-17 01:53:40 +00:00
|
|
|
|
2011-02-02 10:47:05 +00:00
|
|
|
if (!handle)
|
|
|
|
return NULL;
|
|
|
|
|
2012-04-21 21:25:32 +00:00
|
|
|
if (type == RARCH_MOVIE_PLAYBACK)
|
2011-02-02 10:47:05 +00:00
|
|
|
{
|
2017-02-17 01:53:40 +00:00
|
|
|
if (!bsv_movie_init_playback(handle, path))
|
2011-02-02 10:47:05 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2017-02-17 01:53:40 +00:00
|
|
|
else if (!bsv_movie_init_record(handle, path))
|
2011-02-02 10:47:05 +00:00
|
|
|
goto error;
|
|
|
|
|
2017-12-12 07:55:31 +00:00
|
|
|
/* Just pick something really large
|
2014-09-02 14:13:42 +00:00
|
|
|
* ~1 million frames rewind should do the trick. */
|
2016-12-25 00:57:15 +00:00
|
|
|
if (!(frame_pos = (size_t*)calloc((1 << 20), sizeof(size_t))))
|
2017-12-12 07:55:31 +00:00
|
|
|
goto error;
|
2011-11-10 23:55:35 +00:00
|
|
|
|
2016-12-25 00:57:15 +00:00
|
|
|
handle->frame_pos = frame_pos;
|
|
|
|
|
2015-04-01 16:32:40 +00:00
|
|
|
handle->frame_pos[0] = handle->min_file_pos;
|
|
|
|
handle->frame_mask = (1 << 20) - 1;
|
2011-02-25 10:47:27 +00:00
|
|
|
|
2011-02-02 10:47:05 +00:00
|
|
|
return handle;
|
|
|
|
|
|
|
|
error:
|
|
|
|
bsv_movie_free(handle);
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-02-25 10:47:27 +00:00
|
|
|
|
2016-01-30 02:29:12 +00:00
|
|
|
static void bsv_movie_frame_rewind(bsv_movie_t *handle)
|
2011-02-25 10:47:27 +00:00
|
|
|
{
|
2011-02-26 00:13:52 +00:00
|
|
|
handle->did_rewind = true;
|
2011-11-10 23:55:35 +00:00
|
|
|
|
2017-12-12 07:55:31 +00:00
|
|
|
if ( (handle->frame_ptr <= 1)
|
2016-02-07 00:56:03 +00:00
|
|
|
&& (handle->frame_pos[0] == handle->min_file_pos))
|
2011-02-26 00:13:52 +00:00
|
|
|
{
|
2014-09-02 14:13:42 +00:00
|
|
|
/* If we're at the beginning... */
|
2011-02-25 23:59:17 +00:00
|
|
|
handle->frame_ptr = 0;
|
2018-04-09 13:56:45 +00:00
|
|
|
intfstream_seek(handle->file, (int)handle->min_file_pos, SEEK_SET);
|
2011-02-26 00:13:52 +00:00
|
|
|
}
|
2011-02-25 23:59:17 +00:00
|
|
|
else
|
|
|
|
{
|
2014-09-02 14:13:42 +00:00
|
|
|
/* First time rewind is performed, the old frame is simply replayed.
|
|
|
|
* However, playing back that frame caused us to read data, and push
|
|
|
|
* data to the ring buffer.
|
|
|
|
*
|
|
|
|
* Sucessively rewinding frames, we need to rewind past the read data,
|
|
|
|
* plus another. */
|
|
|
|
handle->frame_ptr = (handle->frame_ptr -
|
|
|
|
(handle->first_rewind ? 1 : 2)) & handle->frame_mask;
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_seek(handle->file,
|
2018-04-09 13:56:45 +00:00
|
|
|
(int)handle->frame_pos[handle->frame_ptr], SEEK_SET);
|
2011-02-25 23:59:17 +00:00
|
|
|
}
|
|
|
|
|
2017-12-11 11:53:47 +00:00
|
|
|
if (intfstream_tell(handle->file) <= (long)handle->min_file_pos)
|
2011-02-25 10:47:27 +00:00
|
|
|
{
|
2014-09-02 14:13:42 +00:00
|
|
|
/* We rewound past the beginning. */
|
|
|
|
|
2011-02-25 10:47:27 +00:00
|
|
|
if (!handle->playback)
|
|
|
|
{
|
2016-01-27 06:21:12 +00:00
|
|
|
retro_ctx_serialize_info_t serial_info;
|
|
|
|
|
2014-09-02 14:13:42 +00:00
|
|
|
/* If recording, we simply reset
|
|
|
|
* the starting point. Nice and easy. */
|
2016-01-27 06:21:12 +00:00
|
|
|
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_seek(handle->file, 4 * sizeof(uint32_t), SEEK_SET);
|
2016-01-27 06:21:12 +00:00
|
|
|
|
|
|
|
serial_info.data = handle->state;
|
|
|
|
serial_info.size = handle->state_size;
|
|
|
|
|
2016-05-07 23:33:57 +00:00
|
|
|
core_serialize(&serial_info);
|
2016-01-27 06:21:12 +00:00
|
|
|
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_write(handle->file, handle->state, handle->state_size);
|
2011-02-25 10:47:27 +00:00
|
|
|
}
|
2011-02-25 23:31:13 +00:00
|
|
|
else
|
2018-04-09 13:56:45 +00:00
|
|
|
intfstream_seek(handle->file, (int)handle->min_file_pos, SEEK_SET);
|
2011-02-25 10:47:27 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-11 18:22:18 +00:00
|
|
|
|
2017-05-07 16:15:30 +00:00
|
|
|
bool bsv_movie_init(void)
|
2015-11-30 23:04:04 +00:00
|
|
|
{
|
2017-04-29 12:10:00 +00:00
|
|
|
bool set_granularity = false;
|
2017-05-07 16:15:30 +00:00
|
|
|
bool ret = true;
|
2015-11-30 23:04:04 +00:00
|
|
|
|
2017-05-06 16:14:16 +00:00
|
|
|
if (bsv_movie_state.movie_start_playback)
|
2015-11-30 23:04:04 +00:00
|
|
|
{
|
2017-05-07 16:15:30 +00:00
|
|
|
ret = bsv_movie_init_handle(bsv_movie_state.movie_start_path,
|
|
|
|
RARCH_MOVIE_PLAYBACK);
|
|
|
|
if (!ret)
|
2015-11-30 23:04:04 +00:00
|
|
|
{
|
|
|
|
RARCH_ERR("%s: \"%s\".\n",
|
|
|
|
msg_hash_to_str(MSG_FAILED_TO_LOAD_MOVIE_FILE),
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_start_path);
|
2016-05-09 05:09:26 +00:00
|
|
|
retroarch_fail(1, "event_init_movie()");
|
2015-11-30 23:04:04 +00:00
|
|
|
}
|
|
|
|
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_playback = true;
|
2016-12-22 22:36:11 +00:00
|
|
|
runloop_msg_queue_push(msg_hash_to_str(MSG_STARTING_MOVIE_PLAYBACK),
|
2018-11-22 14:45:52 +00:00
|
|
|
2, 180, false,
|
|
|
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
2015-11-30 23:04:04 +00:00
|
|
|
RARCH_LOG("%s.\n", msg_hash_to_str(MSG_STARTING_MOVIE_PLAYBACK));
|
2017-04-27 21:34:47 +00:00
|
|
|
|
2017-04-29 12:10:00 +00:00
|
|
|
set_granularity = true;
|
2015-11-30 23:04:04 +00:00
|
|
|
}
|
2017-02-17 01:53:40 +00:00
|
|
|
else if (bsv_movie_state.movie_start_recording)
|
2015-11-30 23:04:04 +00:00
|
|
|
{
|
2018-09-28 19:49:06 +00:00
|
|
|
char msg[8192];
|
2015-11-30 23:04:04 +00:00
|
|
|
snprintf(msg, sizeof(msg),
|
|
|
|
"%s \"%s\".",
|
|
|
|
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_start_path);
|
2015-11-30 23:04:04 +00:00
|
|
|
|
2017-05-07 16:15:30 +00:00
|
|
|
ret = bsv_movie_init_handle(bsv_movie_state.movie_start_path,
|
|
|
|
RARCH_MOVIE_RECORD);
|
|
|
|
if (!ret)
|
2015-11-30 23:04:04 +00:00
|
|
|
{
|
2016-12-22 22:36:11 +00:00
|
|
|
runloop_msg_queue_push(
|
2016-02-07 00:56:03 +00:00
|
|
|
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD),
|
2018-11-22 14:45:52 +00:00
|
|
|
1, 180, true,
|
|
|
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
2017-09-27 22:55:47 +00:00
|
|
|
RARCH_ERR("%s.\n",
|
|
|
|
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD));
|
2017-05-07 16:15:30 +00:00
|
|
|
return ret;
|
2015-11-30 23:04:04 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 14:45:52 +00:00
|
|
|
runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
2015-11-30 23:04:04 +00:00
|
|
|
RARCH_LOG("%s \"%s\".\n",
|
|
|
|
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_start_path);
|
2017-04-27 21:34:47 +00:00
|
|
|
|
2017-04-29 12:10:00 +00:00
|
|
|
set_granularity = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (set_granularity)
|
|
|
|
{
|
|
|
|
settings_t *settings = config_get_ptr();
|
2017-09-27 22:55:47 +00:00
|
|
|
configuration_set_uint(settings,
|
|
|
|
settings->uints.rewind_granularity, 1);
|
2015-11-30 23:04:04 +00:00
|
|
|
}
|
2017-05-07 16:15:30 +00:00
|
|
|
|
|
|
|
return ret;
|
2015-11-30 23:04:04 +00:00
|
|
|
}
|
|
|
|
|
2017-01-22 16:03:42 +00:00
|
|
|
bool bsv_movie_get_input(int16_t *bsv_data)
|
|
|
|
{
|
2017-12-11 11:53:47 +00:00
|
|
|
if (intfstream_read(bsv_movie_state_handle->file, bsv_data, 1) != 1)
|
2017-01-22 16:03:42 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
*bsv_data = swap_if_big16(*bsv_data);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-20 08:40:11 +00:00
|
|
|
bool bsv_movie_is_playback_on(void)
|
|
|
|
{
|
|
|
|
return bsv_movie_state_handle && bsv_movie_state.movie_playback;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool bsv_movie_is_playback_off(void)
|
|
|
|
{
|
|
|
|
return bsv_movie_state_handle && !bsv_movie_state.movie_playback;
|
|
|
|
}
|
|
|
|
|
2015-11-30 23:04:04 +00:00
|
|
|
bool bsv_movie_ctl(enum bsv_ctl_state state, void *data)
|
|
|
|
{
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case BSV_MOVIE_CTL_IS_INITED:
|
2017-10-02 22:53:09 +00:00
|
|
|
return (bsv_movie_state_handle != NULL);
|
2015-12-01 00:25:36 +00:00
|
|
|
case BSV_MOVIE_CTL_SET_START_RECORDING:
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_start_recording = true;
|
2015-12-01 00:25:36 +00:00
|
|
|
break;
|
|
|
|
case BSV_MOVIE_CTL_UNSET_START_RECORDING:
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_start_recording = false;
|
2015-12-01 00:25:36 +00:00
|
|
|
break;
|
|
|
|
case BSV_MOVIE_CTL_SET_START_PLAYBACK:
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_start_playback = true;
|
2015-12-01 00:25:36 +00:00
|
|
|
break;
|
|
|
|
case BSV_MOVIE_CTL_UNSET_START_PLAYBACK:
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_start_playback = false;
|
2015-12-01 00:25:36 +00:00
|
|
|
break;
|
2015-12-01 00:29:16 +00:00
|
|
|
case BSV_MOVIE_CTL_SET_END_EOF:
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.eof_exit = true;
|
2015-12-01 00:29:16 +00:00
|
|
|
break;
|
2015-11-30 23:16:48 +00:00
|
|
|
case BSV_MOVIE_CTL_SET_END:
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_end = true;
|
2015-11-30 23:16:48 +00:00
|
|
|
break;
|
|
|
|
case BSV_MOVIE_CTL_UNSET_END:
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_end = false;
|
2015-11-30 23:16:48 +00:00
|
|
|
break;
|
|
|
|
case BSV_MOVIE_CTL_UNSET_PLAYBACK:
|
2015-12-01 00:47:26 +00:00
|
|
|
bsv_movie_state.movie_playback = false;
|
2015-11-30 23:16:48 +00:00
|
|
|
break;
|
2015-11-30 23:19:15 +00:00
|
|
|
case BSV_MOVIE_CTL_FRAME_REWIND:
|
2017-02-17 01:37:12 +00:00
|
|
|
bsv_movie_frame_rewind(bsv_movie_state_handle);
|
2015-11-30 23:19:15 +00:00
|
|
|
break;
|
2016-01-30 02:25:47 +00:00
|
|
|
case BSV_MOVIE_CTL_SET_INPUT:
|
|
|
|
{
|
|
|
|
int16_t *bsv_data = (int16_t*)data;
|
|
|
|
|
|
|
|
*bsv_data = swap_if_big16(*bsv_data);
|
2017-12-11 11:53:47 +00:00
|
|
|
intfstream_write(bsv_movie_state_handle->file, bsv_data, 1);
|
2016-01-30 02:25:47 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BSV_MOVIE_CTL_NONE:
|
2015-11-30 23:04:04 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2015-12-01 00:38:45 +00:00
|
|
|
|
|
|
|
void bsv_movie_set_path(const char *path)
|
|
|
|
{
|
2016-02-07 00:56:03 +00:00
|
|
|
strlcpy(bsv_movie_state.movie_path,
|
|
|
|
path, sizeof(bsv_movie_state.movie_path));
|
2015-12-01 00:38:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void bsv_movie_set_start_path(const char *path)
|
|
|
|
{
|
2015-12-01 00:47:26 +00:00
|
|
|
strlcpy(bsv_movie_state.movie_start_path, path,
|
|
|
|
sizeof(bsv_movie_state.movie_start_path));
|
2015-12-01 00:38:45 +00:00
|
|
|
}
|
|
|
|
|
2017-05-07 16:28:07 +00:00
|
|
|
bool bsv_movie_init_handle(const char *path,
|
|
|
|
enum rarch_movie_type type)
|
|
|
|
{
|
2017-05-08 00:39:43 +00:00
|
|
|
bsv_movie_t *state = bsv_movie_init_internal(path, type);
|
|
|
|
if (!state)
|
2017-05-07 16:28:07 +00:00
|
|
|
return false;
|
2017-05-08 00:39:43 +00:00
|
|
|
|
|
|
|
bsv_movie_state_handle = state;
|
2017-05-07 16:28:07 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-05-07 16:15:30 +00:00
|
|
|
void bsv_movie_deinit(void)
|
|
|
|
{
|
|
|
|
if (!bsv_movie_state_handle)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bsv_movie_free(bsv_movie_state_handle);
|
|
|
|
bsv_movie_state_handle = NULL;
|
|
|
|
}
|
|
|
|
|
2016-09-16 23:54:33 +00:00
|
|
|
/* Checks if movie is being played back. */
|
2017-02-17 01:53:40 +00:00
|
|
|
static bool bsv_movie_check_movie_playback(void)
|
2016-09-16 23:54:33 +00:00
|
|
|
{
|
2016-12-22 22:36:11 +00:00
|
|
|
runloop_msg_queue_push(
|
2018-11-22 14:45:52 +00:00
|
|
|
msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED), 2, 180, false,
|
|
|
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
2016-09-16 23:54:33 +00:00
|
|
|
RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED));
|
|
|
|
|
|
|
|
command_event(CMD_EVENT_BSV_MOVIE_DEINIT, NULL);
|
|
|
|
|
2017-02-17 01:53:40 +00:00
|
|
|
bsv_movie_state.movie_end = false;
|
|
|
|
bsv_movie_state.movie_playback = false;
|
2016-09-16 23:54:33 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Checks if movie is being recorded. */
|
|
|
|
static bool runloop_check_movie_record(void)
|
|
|
|
{
|
2017-02-17 01:37:12 +00:00
|
|
|
if (!bsv_movie_state_handle)
|
2016-09-16 23:54:33 +00:00
|
|
|
return false;
|
|
|
|
|
2016-12-22 22:36:11 +00:00
|
|
|
runloop_msg_queue_push(
|
2018-11-22 14:45:52 +00:00
|
|
|
msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED), 2, 180, true,
|
|
|
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
2016-09-16 23:54:33 +00:00
|
|
|
RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED));
|
|
|
|
|
|
|
|
command_event(CMD_EVENT_BSV_MOVIE_DEINIT, NULL);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool runloop_check_movie_init(void)
|
|
|
|
{
|
2018-10-04 14:32:40 +00:00
|
|
|
char msg[16384], path[8192];
|
2016-09-16 23:54:33 +00:00
|
|
|
settings_t *settings = config_get_ptr();
|
|
|
|
|
2017-04-27 21:34:47 +00:00
|
|
|
msg[0] = path[0] = '\0';
|
|
|
|
|
2017-04-28 19:03:04 +00:00
|
|
|
configuration_set_uint(settings, settings->uints.rewind_granularity, 1);
|
2016-09-16 23:54:33 +00:00
|
|
|
|
2017-04-28 17:12:48 +00:00
|
|
|
if (settings->ints.state_slot > 0)
|
2016-09-16 23:54:33 +00:00
|
|
|
snprintf(path, sizeof(path), "%s%d",
|
2017-04-29 12:10:00 +00:00
|
|
|
bsv_movie_state.movie_path,
|
|
|
|
settings->ints.state_slot);
|
2016-09-16 23:54:33 +00:00
|
|
|
else
|
2017-02-17 01:53:40 +00:00
|
|
|
strlcpy(path, bsv_movie_state.movie_path, sizeof(path));
|
2016-09-16 23:54:33 +00:00
|
|
|
|
|
|
|
strlcat(path,
|
|
|
|
file_path_str(FILE_PATH_BSV_EXTENSION),
|
|
|
|
sizeof(path));
|
|
|
|
|
|
|
|
snprintf(msg, sizeof(msg), "%s \"%s\".",
|
|
|
|
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
|
|
|
path);
|
|
|
|
|
|
|
|
bsv_movie_init_handle(path, RARCH_MOVIE_RECORD);
|
|
|
|
|
2017-02-17 01:37:12 +00:00
|
|
|
if (!bsv_movie_state_handle)
|
2016-09-16 23:54:33 +00:00
|
|
|
{
|
2016-12-22 22:36:11 +00:00
|
|
|
runloop_msg_queue_push(
|
2016-09-16 23:54:33 +00:00
|
|
|
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD),
|
2018-11-22 14:45:52 +00:00
|
|
|
2, 180, true,
|
|
|
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
2016-09-16 23:54:33 +00:00
|
|
|
RARCH_ERR("%s\n",
|
|
|
|
msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD));
|
2017-05-08 00:39:43 +00:00
|
|
|
return false;
|
2016-09-16 23:54:33 +00:00
|
|
|
}
|
|
|
|
|
2018-11-22 14:45:52 +00:00
|
|
|
runloop_msg_queue_push(msg, 2, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
2017-05-08 00:39:43 +00:00
|
|
|
RARCH_LOG("%s \"%s\".\n",
|
|
|
|
msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
|
|
|
|
path);
|
|
|
|
|
2016-09-16 23:54:33 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool bsv_movie_check(void)
|
|
|
|
{
|
2017-05-08 22:40:13 +00:00
|
|
|
if (!bsv_movie_state_handle)
|
|
|
|
return runloop_check_movie_init();
|
|
|
|
|
|
|
|
if (bsv_movie_state.movie_playback)
|
2017-02-17 01:53:40 +00:00
|
|
|
{
|
|
|
|
if (!bsv_movie_state.movie_end)
|
|
|
|
return false;
|
|
|
|
return bsv_movie_check_movie_playback();
|
|
|
|
}
|
|
|
|
|
2016-09-16 23:54:33 +00:00
|
|
|
return runloop_check_movie_record();
|
|
|
|
}
|