mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
The drivers stage marks the rewind buffer pending instead of setting it up, and runloop_check_state sets it up on the next frame, before the core runs, so the full serialize it takes is no longer part of the load. Rewind init and deinit clear the pending mark. The content_load harness checks no frame of a load sets up the buffer and the first frame after does.
113 lines
3.4 KiB
C
113 lines
3.4 KiB
C
/* RetroArch - A frontend for libretro.
|
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
|
* Copyright (C) 2014-2017 - Alfred Agrell
|
|
*
|
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
|
* 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.
|
|
*
|
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __STATE_MANAGER_H
|
|
#define __STATE_MANAGER_H
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
#include <boolean.h>
|
|
#include <retro_common_api.h>
|
|
#include <retro_atomic.h>
|
|
|
|
#include "dynamic.h"
|
|
|
|
RETRO_BEGIN_DECLS
|
|
|
|
enum state_manager_rewind_st_flags
|
|
{
|
|
STATE_MGR_REWIND_ST_FLAG_FRAME_IS_REVERSED = (1 << 0),
|
|
STATE_MGR_REWIND_ST_FLAG_INIT_ATTEMPTED = (1 << 1),
|
|
STATE_MGR_REWIND_ST_FLAG_HOTKEY_WAS_CHECKED = (1 << 2),
|
|
STATE_MGR_REWIND_ST_FLAG_HOTKEY_WAS_PRESSED = (1 << 3),
|
|
/* A load wants the buffer: it is set up on the frame after,
|
|
* before the core runs, rather than inside the load */
|
|
STATE_MGR_REWIND_ST_FLAG_INIT_PENDING = (1 << 4)
|
|
};
|
|
|
|
struct state_manager
|
|
{
|
|
uint8_t *data;
|
|
/* Reading and writing is done here here. */
|
|
uint8_t *head;
|
|
/* If head comes close to this, discard a frame. */
|
|
uint8_t *tail;
|
|
|
|
uint8_t *thisblock;
|
|
uint8_t *nextblock;
|
|
#if STRICT_BUF_SIZE
|
|
uint8_t *debugblock;
|
|
size_t debugsize;
|
|
#endif
|
|
|
|
size_t capacity;
|
|
/* This one is rounded up from reset::blocksize. */
|
|
size_t blocksize;
|
|
/* size_t + (blocksize + 131071) / 131072 *
|
|
* (blocksize + u16 + u16) + u16 + u32 + size_t
|
|
* (yes, the math is a bit ugly). */
|
|
size_t maxcompsize;
|
|
|
|
unsigned entries;
|
|
bool thisblock_valid;
|
|
};
|
|
|
|
typedef struct state_manager state_manager_t;
|
|
|
|
struct state_manager_rewind_state
|
|
{
|
|
/* Rewind support. */
|
|
state_manager_t *state;
|
|
size_t size;
|
|
uint8_t flags;
|
|
/* Cross-thread mirror of FRAME_IS_REVERSED. The flags word is
|
|
* main-thread-only rewind logic; this atomic is what
|
|
* state_manager_frame_is_reversed() reads, because its callers
|
|
* include the video thread (every FrameDirection uniform, per
|
|
* frame) and the task worker (task_save), while the writer is
|
|
* check_rewind on main, per frame. Release-stored wherever the
|
|
* flag bit changes, acquire-loaded by the reader. */
|
|
retro_atomic_int_t frame_reversed_atomic;
|
|
};
|
|
|
|
bool state_manager_frame_is_reversed(void);
|
|
|
|
void state_manager_event_deinit(
|
|
struct state_manager_rewind_state *rewind_st,
|
|
struct retro_core_t *current_core);
|
|
|
|
void state_manager_event_init(struct state_manager_rewind_state *rewind_st,
|
|
unsigned rewind_buffer_size);
|
|
|
|
/**
|
|
* check_rewind:
|
|
* @pressed : was rewind key pressed or held?
|
|
*
|
|
* Checks if rewind toggle/hold was being pressed and/or held.
|
|
**/
|
|
bool state_manager_check_rewind(
|
|
struct state_manager_rewind_state *rewind_st,
|
|
struct retro_core_t *current_core,
|
|
bool pressed,
|
|
unsigned rewind_granularity, bool is_paused,
|
|
char *s, size_t len, unsigned *time);
|
|
|
|
RETRO_END_DECLS
|
|
|
|
#endif
|