2011-09-13 17:50:18 +03:00
|
|
|
#ifndef _movie__hpp__included__
|
|
|
|
#define _movie__hpp__included__
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <stdexcept>
|
2012-01-09 21:55:55 +02:00
|
|
|
#include "controllerframe.hpp"
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Movie being played back or recorded
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
class movie
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Construct new empty movie.
|
|
|
|
*
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
movie() throw(std::bad_alloc);
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Is the movie in readonly mode?
|
2011-09-13 17:50:18 +03:00
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: True if in read-only mode, false if in read-write mode.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
bool readonly_mode() throw();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Switches movie to read-only or read-write mode. If switching to read-write mode, the movie is truncated.
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* parameter enable: If true, switch to read-only mode, else to read-write mode.
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void readonly_mode(bool enable) throw(std::bad_alloc);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the movie rerecord count (this is not the same thing as global rerecord count).
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: The movie rerecord count
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
std::string rerecord_count() throw(std::bad_alloc);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the movie rerecord count (this is not the same thing as global rerecord count).
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* parameter count: The new rerecord count
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void rerecord_count(const std::string& count) throw(std::bad_alloc);
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Read project ID
|
|
|
|
*
|
|
|
|
* returns: The project ID
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
std::string project_id() throw(std::bad_alloc);
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* brief Set project ID
|
|
|
|
*
|
|
|
|
* parameter id: New project ID.
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void project_id(const std::string& id) throw(std::bad_alloc);
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Get number of frames in movie
|
|
|
|
*
|
|
|
|
* returns: The number of frames.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint64_t get_frame_count() throw();
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Get number of current frame in movie
|
2011-09-13 17:50:18 +03:00
|
|
|
*
|
|
|
|
* The first frame in movie is 1. 0 is "before first frame" value.
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: The number of frame
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint64_t get_current_frame() throw();
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Get number of lag frames so far
|
|
|
|
*
|
|
|
|
* returns: The number of lag frames.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
uint64_t get_lag_frames() throw();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function advances to next frame in movie, discarding subframes not used. If the frame is lag frame, it is
|
|
|
|
* counted as lag frame and subframe entry for it is made (if in readwrite mode).
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void next_frame() throw(std::bad_alloc);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the data ready flag. On new frame, all data ready flags are unset. On reading control, its data ready
|
|
|
|
* flag is unset.
|
|
|
|
*
|
2012-01-09 21:55:55 +02:00
|
|
|
* parameter pid: Physical controller id.
|
|
|
|
* parameter index: Control ID.
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: The read value.
|
|
|
|
* throws std::logic_error: Invalid control index.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2012-01-09 21:55:55 +02:00
|
|
|
bool get_DRDY(unsigned pid, unsigned index) throw(std::logic_error);
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Set all data ready flags
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void set_all_DRDY() throw();
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Poll a control by (port, controller, index) tuple.
|
2011-09-13 17:50:18 +03:00
|
|
|
*
|
2012-01-09 21:55:55 +02:00
|
|
|
* parameter pid: Physical controller ID.
|
2011-09-16 21:09:22 +03:00
|
|
|
* parameter index: The index of control in controller (0 to 11)
|
|
|
|
* returns: The read value
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
|
|
|
* throws std::logic_error: Invalid port, controller or index or before movie start.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2012-01-09 21:55:55 +02:00
|
|
|
short next_input(unsigned pid, unsigned index) throw(std::bad_alloc, std::logic_error);
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set current control values. These are read in readwrite mode.
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* parameter controls: The new controls.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2012-01-09 21:55:55 +02:00
|
|
|
void set_controls(controller_frame controls) throw();
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get current control values in effect.
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: Controls
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2012-01-09 21:55:55 +02:00
|
|
|
controller_frame get_controls() throw();
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads a movie plus some other parameters. The playback pointer is positioned to start of movie and readonly
|
|
|
|
* mode is enabled.
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* parameter rerecs: Movie rerecord count.
|
|
|
|
* parameter project_id: Project ID of movie.
|
|
|
|
* parameter input: The input track.
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
|
|
|
* throws std::runtime_error: Bad movie data.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2012-01-09 21:55:55 +02:00
|
|
|
void load(const std::string& rerecs, const std::string& project_id, controller_frame_vector& input)
|
2011-09-13 17:50:18 +03:00
|
|
|
throw(std::bad_alloc, std::runtime_error);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Saves the movie data.
|
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: The movie data.
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2012-01-09 21:55:55 +02:00
|
|
|
controller_frame_vector save() throw(std::bad_alloc);
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This method serializes the state of movie code.
|
|
|
|
*
|
2011-11-24 08:51:25 +02:00
|
|
|
* Parameter proj_id: The project ID is written here.
|
|
|
|
* Parameter curframe: Current frame is written here.
|
|
|
|
* Parameter lagframes: Lag counter is written here.
|
|
|
|
* Parameter pcounters: Poll counters are written here.
|
2011-09-16 21:09:22 +03:00
|
|
|
* throws std::bad_alloc: Not enough memory.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2011-11-24 08:51:25 +02:00
|
|
|
void save_state(std::string& proj_id, uint64_t& curframe, uint64_t& lagframes,
|
|
|
|
std::vector<uint32_t>& pcounters) throw(std::bad_alloc);
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Given previous serialized state from this movie, restore the state.
|
|
|
|
*
|
2011-11-24 08:51:25 +02:00
|
|
|
* Parameter curframe: Current frame.
|
|
|
|
* Parameter lagframe: Lag counter.
|
|
|
|
* Parameter pcounters: Poll counters.
|
|
|
|
* Parameter ro: If true, restore in readonly mode.
|
|
|
|
* Parameter old_movie: Old movie to check for compatiblity against.
|
|
|
|
* Parameter old_projectid: Old project ID to check against.
|
|
|
|
* Returns: ???
|
|
|
|
* Throws std::bad_alloc: Not enough memory.
|
|
|
|
* Throws std::runtime_error: Movie check failure.
|
|
|
|
*/
|
|
|
|
size_t restore_state(uint64_t curframe, uint64_t lagframe, const std::vector<uint32_t>& pcounters, bool ro,
|
2012-01-09 21:55:55 +02:00
|
|
|
controller_frame_vector* old_movie, const std::string& old_projectid) throw(std::bad_alloc,
|
2011-11-24 08:51:25 +02:00
|
|
|
std::runtime_error);
|
2012-01-13 07:25:02 +02:00
|
|
|
/**
|
|
|
|
* Reset the state of movie to initial state.
|
|
|
|
*/
|
|
|
|
void reset_state() throw();
|
2011-09-13 17:50:18 +03:00
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Get reset status for current frame.
|
2011-09-15 22:56:33 +03:00
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: -1 if current frame doesn't have a reset. Otherwise number of cycles to wait for delayed reset (0 is
|
2011-09-13 17:50:18 +03:00
|
|
|
* immediate reset).
|
|
|
|
*/
|
|
|
|
long get_reset_status() throw();
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Commit a reset (writes a reset into current frame in readwrite mode).
|
|
|
|
*
|
|
|
|
* parameter delay: The number of cycles to delay the reset.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
void commit_reset(long delay) throw(std::bad_alloc);
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Get how manyth poll in the frame next poll would be?
|
2011-09-15 22:56:33 +03:00
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: Poll number.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
unsigned next_poll_number();
|
2011-09-16 21:09:22 +03:00
|
|
|
/**
|
|
|
|
* Get how many subframes there are in specified frame.
|
|
|
|
*
|
|
|
|
* parameter frame: The frame number.
|
|
|
|
* returns: Number of subframes (0 if outside movie).
|
|
|
|
*/
|
|
|
|
uint64_t frame_subframes(uint64_t frame) throw();
|
|
|
|
/**
|
|
|
|
* Read controls from specified subframe of specified frame.
|
|
|
|
*
|
|
|
|
* parameter frame: The frame number.
|
|
|
|
* parameter subframe: Subframe within frame (first is 0).
|
|
|
|
* returns: The controls for subframe. If subframe is too great, reads last present subframe. If frame is outside
|
|
|
|
* movie, reads all released.
|
|
|
|
*/
|
2012-01-09 21:55:55 +02:00
|
|
|
controller_frame read_subframe(uint64_t frame, uint64_t subframe) throw();
|
2012-05-19 14:37:49 +03:00
|
|
|
/**
|
|
|
|
* Fast save.
|
|
|
|
*/
|
|
|
|
void fast_save(uint64_t& _frame, uint64_t& _ptr, uint64_t& _lagc, std::vector<uint32_t>& counters);
|
|
|
|
/**
|
|
|
|
* Fast load.
|
|
|
|
*/
|
|
|
|
void fast_load(uint64_t& _frame, uint64_t& _ptr, uint64_t& _lagc, std::vector<uint32_t>& counters);
|
|
|
|
|
2011-09-13 17:50:18 +03:00
|
|
|
private:
|
|
|
|
//TRUE if readonly mode is active.
|
|
|
|
bool readonly;
|
|
|
|
//Movie (not global!) rerecord count.
|
|
|
|
std::string rerecords;
|
|
|
|
//Project ID.
|
|
|
|
std::string _project_id;
|
|
|
|
//The actual controller data.
|
2012-01-09 21:55:55 +02:00
|
|
|
controller_frame_vector movie_data;
|
2011-09-13 17:50:18 +03:00
|
|
|
//Current frame + 1 (0 before next_frame() has been called.
|
|
|
|
uint64_t current_frame;
|
|
|
|
//First subframe in current frame (movie_data.size() if no subframes have been stored).
|
|
|
|
uint64_t current_frame_first_subframe;
|
|
|
|
//How many times has each control been polled (bit 31 is data ready bit)?
|
2012-01-09 21:55:55 +02:00
|
|
|
pollcounter_vector pollcounters;
|
2011-09-13 17:50:18 +03:00
|
|
|
//Current state of buttons.
|
2012-01-09 21:55:55 +02:00
|
|
|
controller_frame current_controls;
|
2011-09-13 17:50:18 +03:00
|
|
|
//Number of known lag frames.
|
|
|
|
uint64_t lag_frames;
|
|
|
|
//Number of frames in movie.
|
|
|
|
uint64_t frames_in_movie;
|
|
|
|
//Cached subframes.
|
2011-09-16 21:09:22 +03:00
|
|
|
void clear_caches() throw();
|
2011-09-13 17:50:18 +03:00
|
|
|
uint64_t cached_frame;
|
|
|
|
uint64_t cached_subframe;
|
|
|
|
//Count present subframes in frame starting from first_subframe (returns 0 if out of movie).
|
2011-09-16 21:09:22 +03:00
|
|
|
uint32_t count_changes(uint64_t first_subframe) throw();
|
2011-09-13 17:50:18 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Class encapsulating bridge logic between bsnes interface and movie code.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
class movie_logic
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Create new bridge.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2011-09-16 06:13:33 +03:00
|
|
|
movie_logic() throw();
|
2011-09-13 17:50:18 +03:00
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Get the movie instance associated.
|
|
|
|
*
|
|
|
|
* returns: The movie instance.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
movie& get_movie() throw();
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Notify about new frame starting.
|
2011-09-15 22:56:33 +03:00
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* returns: Reset status for the new frame.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
long new_frame_starting(bool dont_poll) throw(std::bad_alloc, std::runtime_error);
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Poll for input.
|
2011-09-15 22:56:33 +03:00
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* parameter port: The port number.
|
|
|
|
* parameter dev: The controller index.
|
|
|
|
* parameter id: Control id.
|
|
|
|
* returns: Value for polled input.
|
|
|
|
* throws std::bad_alloc: Not enough memory.
|
|
|
|
* throws std::runtime_error: Error polling for input.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
|
|
|
short input_poll(bool port, unsigned dev, unsigned id) throw(std::bad_alloc, std::runtime_error);
|
|
|
|
|
|
|
|
/**
|
2011-09-16 21:09:22 +03:00
|
|
|
* Called when movie code needs new controls snapshot.
|
2011-09-15 22:56:33 +03:00
|
|
|
*
|
2011-09-16 21:09:22 +03:00
|
|
|
* parameter subframe: True if this is for subframe update, false if for frame update.
|
2011-09-13 17:50:18 +03:00
|
|
|
*/
|
2012-01-09 21:55:55 +02:00
|
|
|
controller_frame update_controls(bool subframe) throw(std::bad_alloc, std::runtime_error);
|
2011-09-13 17:50:18 +03:00
|
|
|
private:
|
2011-09-16 06:13:33 +03:00
|
|
|
movie mov;
|
2011-09-13 17:50:18 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|