mirror of
https://github.com/libretro/RetroArch.git
synced 2024-12-03 13:51:02 +00:00
Basic rewind works!
This commit is contained in:
parent
c5f825eaa5
commit
351e098da1
@ -1,6 +1,6 @@
|
||||
TARGET = ssnes.exe
|
||||
JTARGET = ssnes-joyconfig.exe
|
||||
OBJ = ssnes.o file.o driver.o conf/config_file.o settings.o dynamic.o message.o
|
||||
OBJ = ssnes.o file.o driver.o conf/config_file.o settings.o dynamic.o message.o rewind.o
|
||||
JOBJ = conf/config_file.o tools/main-stub.o tools/ssnes-joyconfig.o
|
||||
|
||||
CC = gcc
|
||||
|
@ -184,6 +184,7 @@ static const struct snes_keybind snes_keybinds_1[] = {
|
||||
{ SSNES_STATE_SLOT_PLUS, SDLK_F7, NO_BTN, AXIS_NONE },
|
||||
{ SSNES_AUDIO_INPUT_RATE_PLUS, SDLK_KP_PLUS, NO_BTN, AXIS_NONE },
|
||||
{ SSNES_AUDIO_INPUT_RATE_MINUS, SDLK_KP_MINUS, NO_BTN, AXIS_NONE },
|
||||
{ SSNES_REWIND, SDLK_r, NO_BTN, AXIS_NONE },
|
||||
{ -1 }
|
||||
};
|
||||
|
||||
|
1
driver.h
1
driver.h
@ -36,6 +36,7 @@ enum
|
||||
SSNES_STATE_SLOT_MINUS,
|
||||
SSNES_AUDIO_INPUT_RATE_PLUS,
|
||||
SSNES_AUDIO_INPUT_RATE_MINUS,
|
||||
SSNES_REWIND,
|
||||
};
|
||||
|
||||
struct snes_keybind
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <stdio.h>
|
||||
#include "record/ffemu.h"
|
||||
#include "message.h"
|
||||
#include "rewind.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
@ -35,7 +36,7 @@
|
||||
|
||||
|
||||
#define MAX_PLAYERS 5
|
||||
#define MAX_BINDS 22 // Needs to be increased every time there are new binds added.
|
||||
#define MAX_BINDS 23 // Needs to be increased every time there are new binds added.
|
||||
#define SSNES_NO_JOYPAD 0xFFFF
|
||||
struct settings
|
||||
{
|
||||
@ -145,6 +146,10 @@ struct global
|
||||
|
||||
msg_queue_t *msg_queue;
|
||||
|
||||
state_manager_t *state_manager;
|
||||
void *state_buf;
|
||||
bool rewind_enable;
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
ffemu_t *rec;
|
||||
char record_path[256];
|
||||
|
6
rewind.c
6
rewind.c
@ -21,6 +21,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
//#include <stdio.h>
|
||||
|
||||
struct state_manager
|
||||
{
|
||||
uint64_t *buffer;
|
||||
@ -120,6 +122,7 @@ static void reassign_bottom(state_manager_t *state)
|
||||
|
||||
static void generate_delta(state_manager_t *state, const void *data, bool aligned)
|
||||
{
|
||||
unsigned patch_size = 0;
|
||||
bool crossed = false;
|
||||
const uint32_t *old_state = state->tmp_state;
|
||||
uint32_t *new_state = aligned ? (uint32_t*)data : state->scratch_buf;
|
||||
@ -138,6 +141,7 @@ static void generate_delta(state_manager_t *state, const void *data, bool aligne
|
||||
// This, if states don't really differ much, we'll save lots of space :) Hopefully this will work really well with save states.
|
||||
if (xor)
|
||||
{
|
||||
patch_size++;
|
||||
state->buffer[state->top_ptr] = (i << 32) | xor;
|
||||
state->top_ptr = (state->top_ptr + 1) % state->buf_size;
|
||||
|
||||
@ -148,6 +152,8 @@ static void generate_delta(state_manager_t *state, const void *data, bool aligne
|
||||
|
||||
if (crossed)
|
||||
reassign_bottom(state);
|
||||
|
||||
//fprintf(stderr, "DELTA SIZE: %u, ORIG SIZE: %u\n", (unsigned)patch_size << 3, (unsigned)state->state_size << 2);
|
||||
}
|
||||
|
||||
bool state_manager_push(state_manager_t *state, const void *data, bool aligned)
|
||||
|
38
ssnes.c
38
ssnes.c
@ -28,6 +28,7 @@
|
||||
#include "general.h"
|
||||
#include "dynamic.h"
|
||||
#include "record/ffemu.h"
|
||||
#include "rewind.h"
|
||||
#include <assert.h>
|
||||
#ifdef HAVE_SRC
|
||||
#include <samplerate.h>
|
||||
@ -636,6 +637,22 @@ static void deinit_msg_queue(void)
|
||||
msg_queue_free(g_extern.msg_queue);
|
||||
}
|
||||
|
||||
static void init_rewind(void)
|
||||
{
|
||||
size_t serial_size = snes_serialize_size();
|
||||
g_extern.state_buf = malloc(serial_size);
|
||||
snes_serialize(g_extern.state_buf, serial_size);
|
||||
g_extern.state_manager = state_manager_new(serial_size, 10 << 20, g_extern.state_buf);
|
||||
}
|
||||
|
||||
static void deinit_rewind(void)
|
||||
{
|
||||
if (g_extern.state_manager)
|
||||
state_manager_free(g_extern.state_manager);
|
||||
if (g_extern.state_buf)
|
||||
free(g_extern.state_buf);
|
||||
}
|
||||
|
||||
static void fill_pathnames(void)
|
||||
{
|
||||
switch (g_extern.game_type)
|
||||
@ -773,6 +790,24 @@ static void check_input_rate(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void check_rewind(void)
|
||||
{
|
||||
if (!g_extern.state_manager)
|
||||
return;
|
||||
|
||||
if (driver.input->key_pressed(driver.input_data, SSNES_REWIND))
|
||||
{
|
||||
void *buf;
|
||||
if (state_manager_pop(g_extern.state_manager, &buf))
|
||||
snes_unserialize(buf, snes_serialize_size());
|
||||
}
|
||||
else
|
||||
{
|
||||
snes_serialize(g_extern.state_buf, snes_serialize_size());
|
||||
state_manager_push(g_extern.state_manager, g_extern.state_buf, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_state_checks(void)
|
||||
{
|
||||
set_fast_forward_button(driver.input->key_pressed(driver.input_data, SSNES_FAST_FORWARD_KEY));
|
||||
@ -781,6 +816,7 @@ static void do_state_checks(void)
|
||||
check_savestates();
|
||||
check_fullscreen();
|
||||
check_input_rate();
|
||||
check_rewind();
|
||||
}
|
||||
|
||||
|
||||
@ -817,6 +853,7 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
init_msg_queue();
|
||||
init_rewind();
|
||||
|
||||
// Main loop
|
||||
for(;;)
|
||||
@ -833,6 +870,7 @@ int main(int argc, char *argv[])
|
||||
psnes_run();
|
||||
}
|
||||
|
||||
deinit_rewind();
|
||||
deinit_msg_queue();
|
||||
#ifdef HAVE_FFMPEG
|
||||
deinit_recording();
|
||||
|
Loading…
Reference in New Issue
Block a user