mirror of
https://github.com/libretro/RetroArch
synced 2025-03-05 19:13:45 +00:00
Arghh... This is so goddamn annoying :(
This commit is contained in:
parent
42c68e21a2
commit
f135972a6b
50
movie.c
50
movie.c
@ -20,6 +20,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "general.h"
|
||||
#include "dynamic.h"
|
||||
#include <assert.h>
|
||||
|
||||
// CRC32 implementation taken from BSNES source :)
|
||||
|
||||
@ -88,7 +89,7 @@ struct bsv_movie
|
||||
FILE *file;
|
||||
uint8_t *state;
|
||||
|
||||
uint16_t *frame_state; // A ring buffer keeping track of many key presses were requested per frame.
|
||||
long *frame_pos; // A ring buffer keeping track of many key presses were requested per frame.
|
||||
size_t frame_mask;
|
||||
uint16_t current_frame_count;
|
||||
size_t frame_ptr;
|
||||
@ -221,25 +222,32 @@ void bsv_movie_free(bsv_movie_t *handle)
|
||||
if (handle->file)
|
||||
fclose(handle->file);
|
||||
free(handle->state);
|
||||
free(handle->frame_state);
|
||||
free(handle->frame_pos);
|
||||
free(handle);
|
||||
}
|
||||
}
|
||||
|
||||
bool bsv_movie_get_input(bsv_movie_t *handle, int16_t *input)
|
||||
{
|
||||
if (fread(input, sizeof(int16_t), 1, handle->file) != 1)
|
||||
return false;
|
||||
if (g_extern.frame_is_reverse)
|
||||
{
|
||||
*input = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fread(input, sizeof(int16_t), 1, handle->file) != 1)
|
||||
return false;
|
||||
|
||||
*input = swap_if_big16(*input);
|
||||
handle->current_frame_count++;
|
||||
return true;
|
||||
*input = swap_if_big16(*input);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void bsv_movie_set_input(bsv_movie_t *handle, int16_t input)
|
||||
{
|
||||
fwrite(&input, sizeof(int16_t), 1, handle->file);
|
||||
handle->current_frame_count++;
|
||||
if (!g_extern.frame_is_reverse)
|
||||
fwrite(&input, sizeof(int16_t), 1, handle->file);
|
||||
}
|
||||
|
||||
bsv_movie_t *bsv_movie_init(const char *path, enum ssnes_movie_type type)
|
||||
@ -256,7 +264,7 @@ bsv_movie_t *bsv_movie_init(const char *path, enum ssnes_movie_type type)
|
||||
else if (!init_record(handle, path))
|
||||
goto error;
|
||||
|
||||
if (!(handle->frame_state = malloc((1 << 20) * sizeof(uint16_t)))) // Just pick something really large :D
|
||||
if (!(handle->frame_pos = calloc((1 << 20), sizeof(long)))) // Just pick something really large :D
|
||||
goto error;
|
||||
handle->frame_mask = (1 << 20) - 1;
|
||||
|
||||
@ -267,14 +275,16 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bsv_movie_set_frame_start(bsv_movie_t *handle)
|
||||
{
|
||||
fprintf(stderr, "Starting frame: %u, Pos: %ld\n", (unsigned)handle->frame_ptr, ftell(handle->file));
|
||||
handle->frame_pos[handle->frame_ptr] = ftell(handle->file);
|
||||
}
|
||||
|
||||
void bsv_movie_set_frame_end(bsv_movie_t *handle)
|
||||
{
|
||||
fprintf(stderr, "Current frame count: %u\n", handle->current_frame_count);
|
||||
handle->frame_state[handle->frame_ptr] = handle->current_frame_count;
|
||||
handle->current_frame_count = 0;
|
||||
fprintf(stderr, "Frame++\n");
|
||||
handle->frame_ptr = (handle->frame_ptr + 1) & handle->frame_mask;
|
||||
|
||||
fprintf(stderr, "Frame end: Current pos: %ld\n", ftell(handle->file) - handle->min_file_pos);
|
||||
}
|
||||
|
||||
void bsv_movie_frame_rewind(bsv_movie_t *handle)
|
||||
@ -284,14 +294,16 @@ void bsv_movie_frame_rewind(bsv_movie_t *handle)
|
||||
if (!handle->playback)
|
||||
{
|
||||
fseek(handle->file, 4 * sizeof(uint32_t), SEEK_SET);
|
||||
psnes_serialize(handle->state, handle->min_file_pos - 4 * sizeof(uint32_t));
|
||||
fwrite(handle->state, 1, handle->min_file_pos - 4 * sizeof(uint32_t), handle->file);
|
||||
psnes_serialize(handle->state, psnes_serialize_size());
|
||||
fwrite(handle->state, 1, psnes_serialize_size(), handle->file);
|
||||
}
|
||||
else
|
||||
fseek(handle->file, handle->min_file_pos, SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Frame--\n");
|
||||
handle->frame_ptr = (handle->frame_ptr - 1) & handle->frame_mask;
|
||||
fseek(handle->file, -((long)handle->frame_state[handle->frame_ptr] * sizeof(int16_t)), SEEK_CUR);
|
||||
fseek(handle->file, handle->frame_pos[handle->frame_ptr], SEEK_SET);
|
||||
}
|
||||
fprintf(stderr, "Rewind: Current pos: %ld\n", ftell(handle->file) - handle->min_file_pos);
|
||||
}
|
||||
|
1
movie.h
1
movie.h
@ -38,6 +38,7 @@ bool bsv_movie_get_input(bsv_movie_t *handle, int16_t *input);
|
||||
void bsv_movie_set_input(bsv_movie_t *handle, int16_t input);
|
||||
|
||||
// Used for rewinding while playback/record.
|
||||
void bsv_movie_set_frame_start(bsv_movie_t *handle); // Debugging purposes.
|
||||
void bsv_movie_set_frame_end(bsv_movie_t *handle);
|
||||
void bsv_movie_frame_rewind(bsv_movie_t *handle);
|
||||
|
||||
|
9
rewind.c
9
rewind.c
@ -33,6 +33,7 @@ struct state_manager
|
||||
size_t top_ptr;
|
||||
size_t bottom_ptr;
|
||||
size_t state_size;
|
||||
bool first_pop;
|
||||
};
|
||||
|
||||
state_manager_t *state_manager_new(size_t state_size, size_t buffer_size, void *init_buffer)
|
||||
@ -77,6 +78,11 @@ void state_manager_free(state_manager_t *state)
|
||||
bool state_manager_pop(state_manager_t *state, void **data)
|
||||
{
|
||||
*data = state->tmp_state;
|
||||
if (state->first_pop)
|
||||
{
|
||||
state->first_pop = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (state->top_ptr == 0)
|
||||
state->top_ptr = state->buf_size - 1;
|
||||
@ -126,7 +132,7 @@ static void generate_delta(state_manager_t *state, const void *data)
|
||||
const uint32_t *new_state = data;
|
||||
|
||||
state->buffer[state->top_ptr++] = 0; // For each separate delta, we have a 0 value sentinel in between.
|
||||
if (state->top_ptr == state->bottom_ptr) // Check if top_ptr and bottom_ptr crossed eachother, which means we need to delete old cruft.
|
||||
if (state->top_ptr == state->bottom_ptr) // Check if top_ptr and bottom_ptr crossed each other, which means we need to delete old cruft.
|
||||
crossed = true;
|
||||
|
||||
for (uint64_t i = 0; i < state->state_size; i++)
|
||||
@ -156,6 +162,7 @@ bool state_manager_push(state_manager_t *state, const void *data)
|
||||
{
|
||||
generate_delta(state, data);
|
||||
memcpy(state->tmp_state, data, state->state_size * sizeof(uint32_t));
|
||||
state->first_pop = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
17
ssnes.c
17
ssnes.c
@ -241,7 +241,7 @@ static void input_poll(void)
|
||||
|
||||
static int16_t input_state(bool port, unsigned device, unsigned index, unsigned id)
|
||||
{
|
||||
if (g_extern.bsv_movie && g_extern.bsv_movie_playback && !g_extern.frame_is_reverse)
|
||||
if (g_extern.bsv_movie && g_extern.bsv_movie_playback)
|
||||
{
|
||||
int16_t ret;
|
||||
if (bsv_movie_get_input(g_extern.bsv_movie, &ret))
|
||||
@ -258,7 +258,7 @@ static int16_t input_state(bool port, unsigned device, unsigned index, unsigned
|
||||
binds[i] = g_settings.input.binds[i];
|
||||
|
||||
int16_t res = driver.input->input_state(driver.input_data, binds, port, device, index, id);
|
||||
if (g_extern.bsv_movie && !g_extern.bsv_movie_playback && !g_extern.frame_is_reverse)
|
||||
if (g_extern.bsv_movie && !g_extern.bsv_movie_playback)
|
||||
bsv_movie_set_input(g_extern.bsv_movie, res);
|
||||
|
||||
return res;
|
||||
@ -1037,19 +1037,26 @@ static void check_input_rate(void)
|
||||
static void check_rewind(void)
|
||||
{
|
||||
g_extern.frame_is_reverse = false;
|
||||
static bool first = true;
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_extern.state_manager)
|
||||
return;
|
||||
|
||||
if (driver.input->key_pressed(driver.input_data, SSNES_REWIND))
|
||||
{
|
||||
|
||||
msg_queue_clear(g_extern.msg_queue);
|
||||
void *buf;
|
||||
if (state_manager_pop(g_extern.state_manager, &buf))
|
||||
{
|
||||
g_extern.frame_is_reverse = true;
|
||||
msg_queue_push(g_extern.msg_queue, "Rewinding!", 0, 30);
|
||||
psnes_unserialize(buf, psnes_serialize_size());
|
||||
g_extern.frame_is_reverse = true;
|
||||
|
||||
if (g_extern.bsv_movie)
|
||||
{
|
||||
for (unsigned i = 0; i < (g_settings.rewind_granularity ? g_settings.rewind_granularity : 1); i++)
|
||||
@ -1254,6 +1261,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (g_extern.netplay)
|
||||
netplay_pre_frame(g_extern.netplay);
|
||||
if (g_extern.bsv_movie)
|
||||
bsv_movie_set_frame_start(g_extern.bsv_movie);
|
||||
|
||||
psnes_run();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user