Back movie data off movie file structure
This commit is contained in:
parent
d9b70e893d
commit
ceb35eb72c
14 changed files with 462 additions and 142 deletions
|
@ -223,6 +223,6 @@ private:
|
|||
void save(zip::writer& w) throw(std::bad_alloc, std::runtime_error);
|
||||
};
|
||||
|
||||
void emerg_save_movie(const moviefile& mv, const controller_frame_vector& v);
|
||||
void emerg_save_movie(const moviefile& mv);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <set>
|
||||
#include "json.hpp"
|
||||
#include "binarystream.hpp"
|
||||
#include "integer-pool.hpp"
|
||||
|
||||
/**
|
||||
* Memory to allocate for controller frame.
|
||||
|
@ -1212,15 +1213,45 @@ public:
|
|||
void notify_sync_change(short polarity) {
|
||||
uint64_t old_frame_count = real_frame_count;
|
||||
real_frame_count = real_frame_count + polarity;
|
||||
if(on_framecount_change && !freeze_count) on_framecount_change(*this, old_frame_count);
|
||||
if(!freeze_count) call_framecount_notification(old_frame_count);
|
||||
}
|
||||
/**
|
||||
* Set where to deliver frame count change notifications to.
|
||||
*
|
||||
* Parameter cb: Callback to register.
|
||||
* Returns: Handle for callback.
|
||||
*/
|
||||
void set_framecount_notification(std::function<void(controller_frame_vector& src, uint64_t old)> cb)
|
||||
uint64_t set_framecount_notification(std::function<void(controller_frame_vector& src, uint64_t old)> cb)
|
||||
{
|
||||
on_framecount_change = cb;
|
||||
integer_pool::holder h(cb_handles);
|
||||
on_framecount_change[h()] = cb;
|
||||
return h.commit();
|
||||
}
|
||||
/**
|
||||
* Clear framecount change notification.
|
||||
*
|
||||
* Parameter handle: Handle to clear.
|
||||
*/
|
||||
void clear_framecount_notification(uint64_t handle)
|
||||
{
|
||||
on_framecount_change.erase(handle);
|
||||
cb_handles(handle);
|
||||
}
|
||||
/**
|
||||
* Call framecount change notification.
|
||||
*/
|
||||
void call_framecount_notification(uint64_t oldcount)
|
||||
{
|
||||
for(auto& i : on_framecount_change)
|
||||
try { i.second(*this, oldcount); } catch(...) {}
|
||||
}
|
||||
/**
|
||||
* Swap frame data.
|
||||
*
|
||||
* Only the frame data is swapped, not the notifications.
|
||||
*/
|
||||
void swap_data(controller_frame_vector& v) throw();
|
||||
|
||||
/**
|
||||
* Freeze framecount notifications.
|
||||
*/
|
||||
|
@ -1237,8 +1268,7 @@ public:
|
|||
{
|
||||
frozen.freeze_count--;
|
||||
if(frozen.freeze_count == 0)
|
||||
if(frozen.on_framecount_change)
|
||||
frozen.on_framecount_change(frozen, frozen.frame_count_at_freeze);
|
||||
frozen.call_framecount_notification(frozen.frame_count_at_freeze);
|
||||
}
|
||||
private:
|
||||
notify_freeze(const notify_freeze&);
|
||||
|
@ -1263,7 +1293,8 @@ private:
|
|||
uint64_t real_frame_count;
|
||||
uint64_t frame_count_at_freeze;
|
||||
size_t freeze_count;
|
||||
std::function<void(controller_frame_vector& src, uint64_t old)> on_framecount_change;
|
||||
std::map<uint64_t, std::function<void(controller_frame_vector& src, uint64_t old)>> on_framecount_change;
|
||||
integer_pool cb_handles;
|
||||
size_t walk_helper(size_t frame, bool sflag) throw();
|
||||
void clear_cache()
|
||||
{
|
||||
|
|
81
include/library/integer-pool.hpp
Normal file
81
include/library/integer-pool.hpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#ifndef _library__integer_pool__hpp__included__
|
||||
#define _library__integer_pool__hpp__included__
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
class integer_pool
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a new pool
|
||||
*/
|
||||
integer_pool() throw();
|
||||
/**
|
||||
* Draw a number from the pool.
|
||||
*
|
||||
* Returns: The number drawn.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
uint64_t operator()() throw(std::bad_alloc);
|
||||
/**
|
||||
* Return a number into the pool.
|
||||
*
|
||||
* Parameter num: The number to return.
|
||||
*/
|
||||
void operator()(uint64_t num) throw();
|
||||
/**
|
||||
* Temporarily hold an integer.
|
||||
*/
|
||||
class holder
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Allocate an integer.
|
||||
*/
|
||||
holder(integer_pool& _pool)
|
||||
: pool(_pool)
|
||||
{
|
||||
i = pool();
|
||||
own = true;
|
||||
}
|
||||
/**
|
||||
* Release an integer.
|
||||
*/
|
||||
~holder()
|
||||
{
|
||||
if(own) pool(i);
|
||||
}
|
||||
/**
|
||||
* Grab the integer without transferring ownership.
|
||||
*
|
||||
* Returns: The integer.
|
||||
*/
|
||||
uint64_t operator()()
|
||||
{
|
||||
return i;
|
||||
}
|
||||
/**
|
||||
* Transfer the ownership.
|
||||
*
|
||||
* Returns: The integer.
|
||||
*/
|
||||
uint64_t commit()
|
||||
{
|
||||
own = false;
|
||||
return i;
|
||||
}
|
||||
private:
|
||||
holder(const holder&);
|
||||
holder& operator=(const holder&);
|
||||
integer_pool& pool;
|
||||
bool own;
|
||||
uint64_t i;
|
||||
};
|
||||
private:
|
||||
std::vector<uint8_t> _bits;
|
||||
uint8_t _bits2;
|
||||
uint8_t* bits;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -19,6 +19,11 @@ public:
|
|||
*/
|
||||
movie() throw(std::bad_alloc);
|
||||
|
||||
/**
|
||||
* Dtor.
|
||||
*/
|
||||
~movie();
|
||||
|
||||
/**
|
||||
* Is the movie in readonly mode?
|
||||
*
|
||||
|
@ -71,7 +76,7 @@ public:
|
|||
*
|
||||
* returns: The number of frames.
|
||||
*/
|
||||
uint64_t get_frame_count() throw() { movie_data.count_frames(); }
|
||||
uint64_t get_frame_count() throw() { movie_data->count_frames(); }
|
||||
|
||||
/**
|
||||
* Get number of current frame in movie
|
||||
|
@ -151,14 +156,6 @@ public:
|
|||
void load(const std::string& rerecs, const std::string& project_id, controller_frame_vector& input)
|
||||
throw(std::bad_alloc, std::runtime_error);
|
||||
|
||||
/**
|
||||
* Saves the movie data.
|
||||
*
|
||||
* returns: The movie data.
|
||||
* throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
controller_frame_vector save() throw(std::bad_alloc);
|
||||
|
||||
/**
|
||||
* This method serializes the state of movie code.
|
||||
*
|
||||
|
@ -241,10 +238,6 @@ public:
|
|||
* Set the poll flag handler.
|
||||
*/
|
||||
void set_pflag_handler(poll_flag* handler);
|
||||
/**
|
||||
* Get the internal controller frame vector.
|
||||
*/
|
||||
controller_frame_vector& get_frame_vector() throw() { return movie_data; }
|
||||
/**
|
||||
* Flush caches.
|
||||
*/
|
||||
|
@ -282,8 +275,18 @@ public:
|
|||
*/
|
||||
bool compatible(controller_frame_vector& with)
|
||||
{
|
||||
return movie_data.compatible(with, current_frame, pollcounters.rawdata());
|
||||
return movie_data->compatible(with, current_frame, pollcounters.rawdata());
|
||||
}
|
||||
/**
|
||||
* Set external movie data.
|
||||
*
|
||||
* Parameter data: New movie data.
|
||||
*/
|
||||
void set_movie_data(controller_frame_vector* data);
|
||||
/**
|
||||
* Copy ctor.
|
||||
*/
|
||||
movie(const movie& mov);
|
||||
private:
|
||||
//Sequence number.
|
||||
uint64_t seqno;
|
||||
|
@ -298,7 +301,7 @@ private:
|
|||
//Project ID.
|
||||
std::string _project_id;
|
||||
//The actual controller data.
|
||||
controller_frame_vector movie_data;
|
||||
controller_frame_vector* movie_data;
|
||||
//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).
|
||||
|
@ -312,6 +315,8 @@ private:
|
|||
//Cached subframes.
|
||||
uint64_t cached_frame;
|
||||
uint64_t cached_subframe;
|
||||
//Handle for notifications.
|
||||
uint64_t movie_data_nh;
|
||||
//Count present subframes in frame starting from first_subframe (returns 0 if out of movie).
|
||||
uint32_t count_changes(uint64_t first_subframe) throw();
|
||||
};
|
||||
|
|
|
@ -151,7 +151,7 @@ namespace
|
|||
void fatal_signal_handler(int sig)
|
||||
{
|
||||
write(2, "Caught fatal signal!\n", 21);
|
||||
emerg_save_movie(our_movie, movb.get_movie().get_frame_vector());
|
||||
emerg_save_movie(our_movie);
|
||||
signal(sig, SIG_DFL);
|
||||
raise(sig);
|
||||
}
|
||||
|
@ -159,14 +159,14 @@ namespace
|
|||
void terminate_handler()
|
||||
{
|
||||
write(2, "Terminating abnormally!\n", 24);
|
||||
emerg_save_movie(our_movie, movb.get_movie().get_frame_vector());
|
||||
emerg_save_movie(our_movie);
|
||||
std::cerr << "Exiting on fatal error" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
command::fnptr<const std::string&> test4(lsnes_cmd, "panicsave-movie", "", "",
|
||||
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
|
||||
emerg_save_movie(our_movie, movb.get_movie().get_frame_vector());
|
||||
emerg_save_movie(our_movie);
|
||||
});
|
||||
|
||||
//% is intentionally missing.
|
||||
|
@ -326,7 +326,7 @@ std::string get_config_path() throw(std::bad_alloc)
|
|||
|
||||
void OOM_panic()
|
||||
{
|
||||
emerg_save_movie(our_movie, movb.get_movie().get_frame_vector());
|
||||
emerg_save_movie(our_movie);
|
||||
messages << "FATAL: Out of memory!" << std::endl;
|
||||
fatal_error();
|
||||
}
|
||||
|
|
|
@ -222,7 +222,6 @@ void do_save_state(const std::string& filename, int binary) throw(std::bad_alloc
|
|||
get_framebuffer().save(our_movie.screenshot);
|
||||
movb.get_movie().save_state(our_movie.projectid, our_movie.save_frame, our_movie.lagged_frames,
|
||||
our_movie.pollcounters);
|
||||
our_movie.input = movb.get_movie().save();
|
||||
our_movie.poll_flag = our_rom.rtype->get_pflag();
|
||||
auto prj = project_get();
|
||||
if(prj) {
|
||||
|
@ -264,7 +263,6 @@ void do_save_movie(const std::string& filename, int binary) throw(std::bad_alloc
|
|||
try {
|
||||
uint64_t origtime = get_utime();
|
||||
our_movie.is_savestate = false;
|
||||
our_movie.input = movb.get_movie().save();
|
||||
auto prj = project_get();
|
||||
if(prj) {
|
||||
our_movie.gamename = prj->gamename;
|
||||
|
@ -312,9 +310,11 @@ void reinitialize_movie(core_sysregion* sysreg)
|
|||
mov.lazy_project_create = true;
|
||||
our_movie = mov;
|
||||
movie newmovie;
|
||||
newmovie.set_movie_data(&mov.input);
|
||||
newmovie.load("0", mov.projectid, mov.input);
|
||||
newmovie.readonly_mode(false);
|
||||
movb.get_movie() = newmovie;
|
||||
movb.get_movie().set_movie_data(&our_movie.input);
|
||||
}
|
||||
|
||||
void do_load_beginning(bool reload) throw(std::bad_alloc, std::runtime_error)
|
||||
|
@ -459,10 +459,13 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
|||
lmode = LOAD_STATE_PRESERVE;
|
||||
|
||||
movie newmovie;
|
||||
if(lmode == LOAD_STATE_PRESERVE)
|
||||
if(lmode == LOAD_STATE_PRESERVE) {
|
||||
newmovie = movb.get_movie();
|
||||
else
|
||||
newmovie.set_movie_data(&our_movie.input);
|
||||
} else {
|
||||
newmovie.set_movie_data(&_movie.input);
|
||||
newmovie.load(_movie.rerecords, _movie.projectid, _movie.input);
|
||||
}
|
||||
|
||||
if(will_load_state)
|
||||
newmovie.restore_state(_movie.save_frame, _movie.lagged_frames, _movie.pollcounters, true,
|
||||
|
@ -512,9 +515,10 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
|||
}
|
||||
|
||||
//Okay, copy the movie data.
|
||||
if(lmode != LOAD_STATE_PRESERVE)
|
||||
if(lmode != LOAD_STATE_PRESERVE) {
|
||||
our_movie = _movie;
|
||||
else {
|
||||
movb.get_movie().set_movie_data(&our_movie.input);
|
||||
} else {
|
||||
//Some fields MUST be taken from movie or one gets desyncs.
|
||||
our_movie.is_savestate = _movie.is_savestate;
|
||||
our_movie.rtc_second = _movie.rtc_second;
|
||||
|
@ -533,6 +537,7 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
|||
if(lmode != LOAD_STATE_PRESERVE)
|
||||
lua_callback_movie_lost("load");
|
||||
movb.get_movie() = newmovie;
|
||||
movb.get_movie().set_movie_data(&our_movie.input);
|
||||
//Activate RW mode if needed.
|
||||
if(lmode == LOAD_STATE_RW)
|
||||
movb.get_movie().readonly_mode(false);
|
||||
|
|
|
@ -993,9 +993,10 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void emerg_save_movie(const moviefile& mv, const controller_frame_vector& v)
|
||||
void emerg_save_movie(const moviefile& mv)
|
||||
{
|
||||
//Whee, assume state of the emulator is totally busted.
|
||||
const controller_frame_vector& v = mv.input;
|
||||
if(!mv.gametype)
|
||||
return; //No valid movie. Trying to save would segfault.
|
||||
char header[] = {'l', 's', 'm', 'v', '\x1a'};
|
||||
|
|
|
@ -8,7 +8,7 @@ __all__.files: $(CORES_FILES)
|
|||
lua ../genfilelist.lua $^ >$@
|
||||
cat $(CORES_FLAGS) >$(ALLFLAGS)
|
||||
|
||||
make-ports.exe: make-ports.cpp ../library/json.cpp ../library/utf8.cpp ../library/string.cpp ../library/controller-parse.cpp ../library/controller-data.cpp ../library/sha256.cpp ../library/assembler.cpp ../library/hex.cpp ../library/eatarg.cpp ../library/int24.cpp ../library/binarystream.cpp
|
||||
make-ports.exe: make-ports.cpp ../library/json.cpp ../library/utf8.cpp ../library/string.cpp ../library/controller-parse.cpp ../library/controller-data.cpp ../library/sha256.cpp ../library/assembler.cpp ../library/hex.cpp ../library/eatarg.cpp ../library/int24.cpp ../library/binarystream.cpp ../library/integer-pool.cpp
|
||||
$(HOSTCC) -g -std=gnu++0x -I../../include/library -o $@ $^ -lboost_regex$(HOST_BOOST_POSTFIX) -lboost_system$(HOST_BOOST_POSTFIX)
|
||||
|
||||
bsnes-legacy/$(ALLFILES): forcelook make-ports.exe
|
||||
|
|
|
@ -514,7 +514,7 @@ size_t controller_frame_vector::recount_frames() throw()
|
|||
|
||||
}
|
||||
real_frame_count = ret;
|
||||
if(on_framecount_change) on_framecount_change(*this, old_frame_count);
|
||||
call_framecount_notification(old_frame_count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -528,7 +528,7 @@ void controller_frame_vector::clear(const port_type_set& p) throw(std::runtime_e
|
|||
clear_cache();
|
||||
pages.clear();
|
||||
real_frame_count = 0;
|
||||
if(on_framecount_change) on_framecount_change(*this, old_frame_count);
|
||||
call_framecount_notification(old_frame_count);
|
||||
}
|
||||
|
||||
controller_frame_vector::~controller_frame_vector() throw()
|
||||
|
@ -601,7 +601,7 @@ controller_frame_vector& controller_frame_vector::operator=(const controller_fra
|
|||
const page& pg2 = v.pages.find(i)->second;
|
||||
pg = pg2;
|
||||
}
|
||||
if(on_framecount_change) on_framecount_change(*this, old_frame_count);
|
||||
call_framecount_notification(old_frame_count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -625,7 +625,7 @@ void controller_frame_vector::resize(size_t newsize) throw(std::bad_alloc)
|
|||
memset(pages[pages_needed - 1].content + offset, 0, CONTROLLER_PAGE_SIZE - offset);
|
||||
}
|
||||
frames = newsize;
|
||||
if(on_framecount_change) on_framecount_change(*this, old_frame_count);
|
||||
call_framecount_notification(old_frame_count);
|
||||
} else if(newsize > frames) {
|
||||
//Enlarge movie.
|
||||
size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
|
||||
|
@ -643,7 +643,7 @@ void controller_frame_vector::resize(size_t newsize) throw(std::bad_alloc)
|
|||
}
|
||||
frames = newsize;
|
||||
//This can use real_frame_count, because the real frame count won't change.
|
||||
if(on_framecount_change) on_framecount_change(*this, real_frame_count);
|
||||
call_framecount_notification(real_frame_count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -755,6 +755,24 @@ void controller_frame_vector::load_binary(binarystream::input& stream) throw(std
|
|||
recount_frames();
|
||||
}
|
||||
|
||||
void controller_frame_vector::swap_data(controller_frame_vector& v) throw()
|
||||
{
|
||||
uint64_t toldsize = real_frame_count;
|
||||
uint64_t voldsize = v.real_frame_count;
|
||||
std::swap(pages, v.pages);
|
||||
std::swap(frames_per_page, v.frames_per_page);
|
||||
std::swap(frame_size, v.frame_size);
|
||||
std::swap(frames, v.frames);
|
||||
std::swap(types, v.types);
|
||||
std::swap(cache_page_num, v.cache_page_num);
|
||||
std::swap(cache_page, v.cache_page);
|
||||
std::swap(real_frame_count, v.real_frame_count);
|
||||
if(!freeze_count)
|
||||
call_framecount_notification(toldsize);
|
||||
if(!v.freeze_count)
|
||||
v.call_framecount_notification(voldsize);
|
||||
}
|
||||
|
||||
controller_frame::controller_frame() throw()
|
||||
{
|
||||
memset(memory, 0, sizeof(memory));
|
||||
|
|
151
src/library/integer-pool.cpp
Normal file
151
src/library/integer-pool.cpp
Normal file
|
@ -0,0 +1,151 @@
|
|||
#include "integer-pool.hpp"
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned special_level = 21;
|
||||
uint64_t level_base[] = {
|
||||
0ULL,
|
||||
1ULL,
|
||||
9ULL,
|
||||
73ULL,
|
||||
585ULL,
|
||||
4681ULL,
|
||||
37449ULL,
|
||||
299593ULL,
|
||||
2396745ULL,
|
||||
19173961ULL,
|
||||
153391689ULL,
|
||||
1227133513ULL,
|
||||
9817068105ULL,
|
||||
78536544841ULL,
|
||||
628292358729ULL,
|
||||
5026338869833ULL,
|
||||
40210710958665ULL,
|
||||
321685687669321ULL,
|
||||
2573485501354569ULL,
|
||||
20587884010836553ULL,
|
||||
164703072086692425ULL,
|
||||
1317624576693539401ULL,
|
||||
3623467585907233353ULL, //Special: Fits 2^64 bits.
|
||||
};
|
||||
uint64_t level_size[] = {
|
||||
1ULL,
|
||||
8ULL,
|
||||
64ULL,
|
||||
512ULL,
|
||||
4096ULL,
|
||||
32768ULL,
|
||||
262144ULL,
|
||||
2097152ULL,
|
||||
16777216ULL,
|
||||
134217728ULL,
|
||||
1073741824ULL,
|
||||
8589934592ULL,
|
||||
68719476736ULL,
|
||||
549755813888ULL,
|
||||
4398046511104ULL,
|
||||
35184372088832ULL,
|
||||
281474976710656ULL,
|
||||
2251799813685248ULL,
|
||||
18014398509481984ULL,
|
||||
144115188075855872ULL,
|
||||
1152921504606846976ULL,
|
||||
2305843009213693952ULL, //Special: 2^64 bits.
|
||||
};
|
||||
|
||||
const unsigned levels = 22;
|
||||
unsigned level_from_size(uint64_t size)
|
||||
{
|
||||
for(unsigned i = 0; i < levels; i++) {
|
||||
if(size <= level_base[i + 1]) return i;
|
||||
}
|
||||
return levels;
|
||||
}
|
||||
|
||||
uint64_t get_levelsize(unsigned n)
|
||||
{
|
||||
static uint64_t table[levels];
|
||||
static bool init = false;
|
||||
if(!init) {
|
||||
uint64_t r = 1;
|
||||
for(unsigned i = 0; i < levels; i++) {
|
||||
table[i] = r;
|
||||
r = 8 * r + 1;
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
return table[n];
|
||||
}
|
||||
|
||||
unsigned lsbz(uint8_t b)
|
||||
{
|
||||
return ((b & 1) ? ((b & 2) ? ((b & 4) ? ((b & 8) ? ((b & 16) ? ((b & 32) ? ((b & 64) ?
|
||||
((b & 128) ? 8 : 7) : 6) : 5) : 4) : 3) : 2) : 1) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
integer_pool::integer_pool() throw()
|
||||
{
|
||||
_bits2 = 0;
|
||||
bits = &_bits2;
|
||||
}
|
||||
|
||||
uint64_t integer_pool::operator()() throw(std::bad_alloc)
|
||||
{
|
||||
//If the first byte is 0xFF, we got to expand the array.
|
||||
if(bits[0] == 0xFF) {
|
||||
unsigned level = level_from_size(_bits.size()); //If bits.size() == 0, this correctly returns 0.
|
||||
assert(level < special_level);
|
||||
std::vector<uint8_t> newbits;
|
||||
newbits.resize(level_base[level + 2]);
|
||||
memset(&newbits[0], 0, level_base[level + 2]);
|
||||
for(unsigned i = 0; i <= level; i++)
|
||||
memcpy(&newbits[level_base[i + 1]], &bits[level_base[i]], level_size[i]);
|
||||
newbits[0] = 1;
|
||||
std::swap(_bits, newbits);
|
||||
bits = &_bits[0];
|
||||
}
|
||||
//Find a free byte.
|
||||
unsigned level = level_from_size(_bits.size()); //If bits.size() == 0, this correctly returns 0.
|
||||
uint64_t pathbits = 0;
|
||||
for(unsigned i = 0; i < level; i++) {
|
||||
uint64_t byte = level_base[i] + pathbits;
|
||||
assert(bits[byte] < 255);
|
||||
unsigned lsb = lsbz(bits[byte]);
|
||||
pathbits = 8 * pathbits + lsb;
|
||||
}
|
||||
|
||||
//Check if there are free integers in pool.
|
||||
if(pathbits > 0x1FFFFFFFFFFFFFFFULL) throw std::bad_alloc();
|
||||
|
||||
//Reserve it, and propagate fullness downward if needed.
|
||||
uint64_t byte = level_base[level] + pathbits;
|
||||
assert(bits[byte] < 255);
|
||||
unsigned lsb = lsbz(bits[byte]);
|
||||
pathbits = 8 * pathbits + lsb;
|
||||
uint64_t bit = pathbits;
|
||||
bool carry = true;
|
||||
for(unsigned i = level; i <= level; i--) {
|
||||
if(carry) {
|
||||
byte = level_base[i] + (pathbits >> 3);
|
||||
bits[byte] |= (1 << (pathbits & 7));
|
||||
carry = (bits[byte] == 255);
|
||||
pathbits >>= 3;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
return bit;
|
||||
}
|
||||
|
||||
void integer_pool::operator()(uint64_t num) throw()
|
||||
{
|
||||
unsigned level = level_from_size(_bits.size()); //If bits.size() == 0, this correctly returns 0.
|
||||
for(unsigned i = level; i <= level; i--) {
|
||||
uint64_t byte = level_base[i] + (num >> 3);
|
||||
bits[byte] &= ~(1 << (num & 7));
|
||||
num >>= 3;
|
||||
}
|
||||
}
|
|
@ -22,6 +22,12 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
movie::~movie()
|
||||
{
|
||||
if(movie_data)
|
||||
movie_data->clear_framecount_notification(movie_data_nh);
|
||||
}
|
||||
|
||||
void movie::set_all_DRDY() throw()
|
||||
{
|
||||
pollcounters.set_all_DRDY();
|
||||
|
@ -59,14 +65,14 @@ void movie::set_controls(controller_frame controls) throw()
|
|||
|
||||
uint32_t movie::count_changes(uint64_t first_subframe) throw()
|
||||
{
|
||||
return movie_data.subframe_count(first_subframe);
|
||||
return movie_data->subframe_count(first_subframe);
|
||||
}
|
||||
|
||||
controller_frame movie::get_controls() throw()
|
||||
{
|
||||
if(!readonly)
|
||||
return current_controls;
|
||||
controller_frame c = movie_data.blank_frame(false);
|
||||
controller_frame c = movie_data->blank_frame(false);
|
||||
//Before the beginning? Somebody screwed up (but return released / neutral anyway)...
|
||||
if(current_frame == 0)
|
||||
return c;
|
||||
|
@ -74,10 +80,10 @@ controller_frame movie::get_controls() throw()
|
|||
uint32_t changes = count_changes(current_frame_first_subframe);
|
||||
if(!changes)
|
||||
return c; //End of movie.
|
||||
for(size_t i = 0; i < movie_data.get_types().indices(); i++) {
|
||||
for(size_t i = 0; i < movie_data->get_types().indices(); i++) {
|
||||
uint32_t polls = pollcounters.get_polls(i);
|
||||
uint32_t index = (changes > polls) ? polls : changes - 1;
|
||||
c.axis2(i, movie_data[current_frame_first_subframe + index].axis2(i));
|
||||
c.axis2(i, (*movie_data)[current_frame_first_subframe + index].axis2(i));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
@ -108,8 +114,8 @@ void movie::next_frame() throw(std::bad_alloc)
|
|||
//debuglog << "Frame " << current_frame << " is lag" << std::endl << std::flush;
|
||||
if(!readonly) {
|
||||
//If in read-write mode, write a dummy record for the frame. Force sync flag.
|
||||
//As index should be movie_data.size(), it is correct afterwards.
|
||||
movie_data.append(current_controls.copy(true));
|
||||
//As index should be movie_data->size(), it is correct afterwards.
|
||||
movie_data->append(current_controls.copy(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +144,7 @@ short movie::next_input(unsigned port, unsigned controller, unsigned ctrl) throw
|
|||
if(readonly) {
|
||||
//In readonly mode...
|
||||
//If at the end of the movie, return released / neutral (but also record the poll)...
|
||||
if(current_frame_first_subframe >= movie_data.size()) {
|
||||
if(current_frame_first_subframe >= movie_data->size()) {
|
||||
pollcounters.increment_polls(port, controller, ctrl);
|
||||
return 0;
|
||||
}
|
||||
|
@ -149,7 +155,7 @@ short movie::next_input(unsigned port, unsigned controller, unsigned ctrl) throw
|
|||
uint32_t changes = count_changes(current_frame_first_subframe);
|
||||
uint32_t polls = pollcounters.get_polls(port, controller, ctrl);
|
||||
uint32_t index = (changes > polls) ? polls : changes - 1;
|
||||
int16_t data = movie_data[current_frame_first_subframe + index].axis3(port, controller, ctrl);
|
||||
int16_t data = (*movie_data)[current_frame_first_subframe + index].axis3(port, controller, ctrl);
|
||||
pollcounters.increment_polls(port, controller, ctrl);
|
||||
return data;
|
||||
} else {
|
||||
|
@ -159,26 +165,26 @@ short movie::next_input(unsigned port, unsigned controller, unsigned ctrl) throw
|
|||
if(current_frame == 0)
|
||||
return 0;
|
||||
//If at movie end, insert complete input with frame sync set (this is the first subframe).
|
||||
if(current_frame_first_subframe >= movie_data.size()) {
|
||||
movie_data.append(current_controls.copy(true));
|
||||
//current_frame_first_subframe should be movie_data.size(), so it is right.
|
||||
if(current_frame_first_subframe >= movie_data->size()) {
|
||||
movie_data->append(current_controls.copy(true));
|
||||
//current_frame_first_subframe should be movie_data->size(), so it is right.
|
||||
pollcounters.increment_polls(port, controller, ctrl);
|
||||
return movie_data[current_frame_first_subframe].axis3(port, controller, ctrl);
|
||||
return (*movie_data)[current_frame_first_subframe].axis3(port, controller, ctrl);
|
||||
}
|
||||
short new_value = current_controls.axis3(port, controller, ctrl);
|
||||
//Fortunately, we know this frame is the last one in movie_data.
|
||||
uint32_t pollcounter = pollcounters.get_polls(port, controller, ctrl);
|
||||
if(current_frame_first_subframe + pollcounter < movie_data.size()) {
|
||||
if(current_frame_first_subframe + pollcounter < movie_data->size()) {
|
||||
//The index is within existing size. Change the value and propagate to all subsequent
|
||||
//subframes.
|
||||
for(uint64_t i = current_frame_first_subframe + pollcounter; i < movie_data.size(); i++)
|
||||
movie_data[i].axis3(port, controller, ctrl, new_value);
|
||||
} else if(new_value != movie_data[movie_data.size() - 1].axis3(port, controller, ctrl)) {
|
||||
for(uint64_t i = current_frame_first_subframe + pollcounter; i < movie_data->size(); i++)
|
||||
(*movie_data)[i].axis3(port, controller, ctrl, new_value);
|
||||
} else if(new_value != (*movie_data)[movie_data->size() - 1].axis3(port, controller, ctrl)) {
|
||||
//The index is not within existing size and value does not match. We need to create a new
|
||||
//subframes(s), copying the last subframe.
|
||||
while(current_frame_first_subframe + pollcounter >= movie_data.size())
|
||||
movie_data.append(movie_data[movie_data.size() - 1].copy(false));
|
||||
movie_data[current_frame_first_subframe + pollcounter].axis3(port, controller, ctrl,
|
||||
while(current_frame_first_subframe + pollcounter >= movie_data->size())
|
||||
movie_data->append((*movie_data)[movie_data->size() - 1].copy(false));
|
||||
(*movie_data)[current_frame_first_subframe + pollcounter].axis3(port, controller, ctrl,
|
||||
new_value);
|
||||
}
|
||||
pollcounters.increment_polls(port, controller, ctrl);
|
||||
|
@ -188,6 +194,7 @@ short movie::next_input(unsigned port, unsigned controller, unsigned ctrl) throw
|
|||
|
||||
movie::movie() throw(std::bad_alloc)
|
||||
{
|
||||
movie_data = NULL;
|
||||
seqno = 0;
|
||||
readonly = false;
|
||||
rerecords = "0";
|
||||
|
@ -197,17 +204,6 @@ movie::movie() throw(std::bad_alloc)
|
|||
lag_frames = 0;
|
||||
pflag_handler = NULL;
|
||||
clear_caches();
|
||||
movie_data.set_framecount_notification([this](controller_frame_vector& src, uint64_t old_frames) -> void {
|
||||
//Recompute frame_first_subframe.
|
||||
while(current_frame_first_subframe < movie_data.size() && current_frame > old_frames + 1) {
|
||||
//OK, movie has been extended.
|
||||
current_frame_first_subframe += count_changes(current_frame_first_subframe);
|
||||
old_frames++;
|
||||
}
|
||||
//Nobody is this stupid, right?
|
||||
current_frame_first_subframe = min(current_frame_first_subframe,
|
||||
static_cast<uint64_t>(movie_data.size()));
|
||||
});
|
||||
}
|
||||
|
||||
void movie::load(const std::string& rerecs, const std::string& project_id, controller_frame_vector& input)
|
||||
|
@ -224,16 +220,10 @@ void movie::load(const std::string& rerecs, const std::string& project_id, contr
|
|||
current_frame_first_subframe = 0;
|
||||
pollcounters = pollcounter_vector(input.get_types());
|
||||
lag_frames = 0;
|
||||
movie_data = input;
|
||||
//This is to force internal type of current_controls to become correct.
|
||||
current_controls = input.blank_frame(false);
|
||||
}
|
||||
|
||||
controller_frame_vector movie::save() throw(std::bad_alloc)
|
||||
{
|
||||
return movie_data;
|
||||
}
|
||||
|
||||
unsigned movie::next_poll_number()
|
||||
{
|
||||
return pollcounters.max_polls() + 1;
|
||||
|
@ -248,16 +238,16 @@ void movie::readonly_mode(bool enable) throw(std::bad_alloc)
|
|||
//Transitioning to readwrite mode, we have to adjust the length of the movie data.
|
||||
if(current_frame == 0) {
|
||||
//WTF... At before first frame. Blank the entiere movie.
|
||||
movie_data.clear();
|
||||
movie_data->clear();
|
||||
return;
|
||||
}
|
||||
//Fun special case: Current frame is not in movie (current_frame_first_subframe >= movie_data.size()).
|
||||
//In this case, we have to extend the movie data.
|
||||
if(current_frame_first_subframe >= movie_data.size()) {
|
||||
//Fun special case: Current frame is not in movie (current_frame_first_subframe >=
|
||||
//movie_data->size()). In this case, we have to extend the movie data.
|
||||
if(current_frame_first_subframe >= movie_data->size()) {
|
||||
//Yes, this will insert one extra frame... But we will lose it later if it is not needed.
|
||||
while(movie_data.count_frames() < current_frame)
|
||||
movie_data.append(movie_data.blank_frame(true));
|
||||
current_frame_first_subframe = movie_data.size() - 1;
|
||||
while(movie_data->count_frames() < current_frame)
|
||||
movie_data->append(movie_data->blank_frame(true));
|
||||
current_frame_first_subframe = movie_data->size() - 1;
|
||||
}
|
||||
|
||||
//We have to take the part up to furthest currently readable subframe. Also, we need to propagate
|
||||
|
@ -268,14 +258,15 @@ void movie::readonly_mode(bool enable) throw(std::bad_alloc)
|
|||
if(max_readable_subframes > next_frame_first_subframe)
|
||||
max_readable_subframes = next_frame_first_subframe;
|
||||
|
||||
movie_data.resize(max_readable_subframes);
|
||||
movie_data->resize(max_readable_subframes);
|
||||
next_frame_first_subframe = max_readable_subframes;
|
||||
//Propagate buttons. The only one that needs special handling is sync flag (index 0, tuple 0,0,0).
|
||||
for(size_t i = 1; i < movie_data.get_types().indices(); i++) {
|
||||
for(size_t i = 1; i < movie_data->get_types().indices(); i++) {
|
||||
uint32_t polls = pollcounters.get_polls(i);
|
||||
polls = polls ? polls : 1;
|
||||
for(uint64_t j = current_frame_first_subframe + polls; j < next_frame_first_subframe; j++)
|
||||
movie_data[j].axis2(i, movie_data[current_frame_first_subframe + polls - 1].axis2(i));
|
||||
(*movie_data)[j].axis2(i, (*movie_data)[current_frame_first_subframe + polls - 1].
|
||||
axis2(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,7 +288,7 @@ size_t movie::restore_state(uint64_t curframe, uint64_t lagframe, const std::vec
|
|||
{
|
||||
if(!pollcounters.check(pcounters))
|
||||
throw std::runtime_error("Wrong number of poll counters");
|
||||
if(old_movie && !movies_compatible(*old_movie, movie_data, curframe, &pcounters[0], old_projectid,
|
||||
if(old_movie && !movies_compatible(*old_movie, *movie_data, curframe, &pcounters[0], old_projectid,
|
||||
_project_id))
|
||||
throw std::runtime_error("Save is not from this movie");
|
||||
uint64_t tmp_firstsubframe = 0;
|
||||
|
@ -342,11 +333,11 @@ controller_frame movie::read_subframe(uint64_t frame, uint64_t subframe) throw()
|
|||
cached_subframe = p;
|
||||
uint64_t max = count_changes(p);
|
||||
if(!max) {
|
||||
return movie_data.blank_frame(true);
|
||||
return movie_data->blank_frame(true);
|
||||
}
|
||||
if(max <= subframe)
|
||||
subframe = max - 1;
|
||||
return movie_data[p + subframe];
|
||||
return (*movie_data)[p + subframe];
|
||||
}
|
||||
|
||||
void movie::reset_state() throw()
|
||||
|
@ -371,7 +362,7 @@ void movie::fast_load(uint64_t& _frame, uint64_t& _ptr, uint64_t& _lagc, std::ve
|
|||
{
|
||||
readonly = true;
|
||||
current_frame = _frame;
|
||||
current_frame_first_subframe = (_ptr <= movie_data.size()) ? _ptr : movie_data.size();
|
||||
current_frame_first_subframe = (_ptr <= movie_data->size()) ? _ptr : movie_data->size();
|
||||
lag_frames = _lagc;
|
||||
pollcounters.load_state(_counters);
|
||||
readonly_mode(false);
|
||||
|
@ -383,7 +374,6 @@ movie& movie::operator=(const movie& m)
|
|||
readonly = m.readonly;
|
||||
rerecords = m.rerecords;
|
||||
_project_id = m._project_id;
|
||||
movie_data = m.movie_data;
|
||||
current_frame = m.current_frame;
|
||||
current_frame_first_subframe = m.current_frame_first_subframe;
|
||||
pollcounters = m.pollcounters;
|
||||
|
@ -402,11 +392,11 @@ void movie::set_pflag_handler(poll_flag* handler)
|
|||
int16_t movie::read_subframe_at_index(uint32_t subframe, unsigned port, unsigned controller, unsigned ctrl)
|
||||
{
|
||||
//Readwrite, Past the end of movie or before the beginning?
|
||||
if(!readonly || current_frame_first_subframe >= movie_data.size() || current_frame == 0)
|
||||
if(!readonly || current_frame_first_subframe >= movie_data->size() || current_frame == 0)
|
||||
return 0;
|
||||
uint32_t changes = count_changes(current_frame_first_subframe);
|
||||
uint32_t index = (changes > subframe) ? subframe : changes - 1;
|
||||
return movie_data[current_frame_first_subframe + index].axis3(port, controller, ctrl);
|
||||
return (*movie_data)[current_frame_first_subframe + index].axis3(port, controller, ctrl);
|
||||
}
|
||||
|
||||
void movie::write_subframe_at_index(uint32_t subframe, unsigned port, unsigned controller, unsigned ctrl,
|
||||
|
@ -415,42 +405,81 @@ void movie::write_subframe_at_index(uint32_t subframe, unsigned port, unsigned c
|
|||
if(!readonly || current_frame == 0)
|
||||
return;
|
||||
bool extended = false;
|
||||
while(current_frame > movie_data.count_frames()) {
|
||||
while(current_frame > movie_data->count_frames()) {
|
||||
//Extend the movie by a blank frame.
|
||||
extended = true;
|
||||
movie_data.append(movie_data.blank_frame(true));
|
||||
movie_data->append(movie_data->blank_frame(true));
|
||||
}
|
||||
if(extended) {
|
||||
clear_caches();
|
||||
current_frame_first_subframe = movie_data.size() - 1;
|
||||
current_frame_first_subframe = movie_data->size() - 1;
|
||||
}
|
||||
if(current_frame < movie_data.count_frames()) {
|
||||
if(current_frame < movie_data->count_frames()) {
|
||||
//If we are not on the last frame, write is possible if it is not on extension.
|
||||
uint32_t changes = count_changes(current_frame_first_subframe);
|
||||
if(subframe < changes)
|
||||
movie_data[current_frame_first_subframe + subframe].axis3(port, controller, ctrl, x);
|
||||
(*movie_data)[current_frame_first_subframe + subframe].axis3(port, controller, ctrl, x);
|
||||
} else {
|
||||
//Writing to the last frame. If not on extension, handle like non-last frame.
|
||||
//Note that if movie had to be extended, it was done before, resulting movie like in state with
|
||||
//0 stored subframes.
|
||||
uint32_t changes = count_changes(current_frame_first_subframe);
|
||||
if(subframe < changes)
|
||||
movie_data[current_frame_first_subframe + subframe].axis3(port, controller, ctrl, x);
|
||||
(*movie_data)[current_frame_first_subframe + subframe].axis3(port, controller, ctrl, x);
|
||||
else {
|
||||
//If there is no frame at all, create one.
|
||||
if(current_frame_first_subframe >= movie_data.size()) {
|
||||
movie_data.append(movie_data.blank_frame(true));
|
||||
if(current_frame_first_subframe >= movie_data->size()) {
|
||||
movie_data->append(movie_data->blank_frame(true));
|
||||
}
|
||||
//Create needed subframes.
|
||||
while(count_changes(current_frame_first_subframe) <= subframe)
|
||||
movie_data.append(movie_data.blank_frame(false));
|
||||
movie_data->append(movie_data->blank_frame(false));
|
||||
//Write it.
|
||||
movie_data[current_frame_first_subframe + subframe].axis3(port, controller, ctrl, x);
|
||||
(*movie_data)[current_frame_first_subframe + subframe].axis3(port, controller, ctrl, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
movie::poll_flag::~poll_flag()
|
||||
{
|
||||
}
|
||||
|
||||
movie::movie(const movie& mov)
|
||||
{
|
||||
seqno++;
|
||||
readonly = mov.readonly;
|
||||
latch_end = mov.latch_end;
|
||||
rerecords = mov.rerecords;
|
||||
_project_id = mov._project_id;
|
||||
movie_data = NULL;
|
||||
current_frame = mov.current_frame;
|
||||
current_frame_first_subframe = mov.current_frame_first_subframe;
|
||||
pollcounters = mov.pollcounters;
|
||||
current_controls = mov.current_controls;
|
||||
lag_frames = mov.lag_frames;
|
||||
cached_frame = mov.cached_frame;
|
||||
cached_subframe = mov.cached_subframe;
|
||||
}
|
||||
|
||||
void movie::set_movie_data(controller_frame_vector* data)
|
||||
{
|
||||
uint64_t old_nh = movie_data_nh;
|
||||
controller_frame_vector* old = movie_data;
|
||||
if(data)
|
||||
movie_data_nh = data->set_framecount_notification([this](controller_frame_vector& src,
|
||||
uint64_t old_frames) {
|
||||
//Recompute frame_first_subframe.
|
||||
while(current_frame_first_subframe < movie_data->size() && current_frame > old_frames + 1) {
|
||||
//OK, movie has been extended.
|
||||
current_frame_first_subframe += count_changes(current_frame_first_subframe);
|
||||
old_frames++;
|
||||
}
|
||||
//Nobody is this stupid, right?
|
||||
current_frame_first_subframe = min(current_frame_first_subframe,
|
||||
static_cast<uint64_t>(movie_data->size()));
|
||||
});
|
||||
movie_data = data;
|
||||
clear_caches();
|
||||
if(old)
|
||||
old->clear_framecount_notification(old_nh);
|
||||
}
|
||||
|
|
|
@ -114,14 +114,14 @@ namespace
|
|||
movie& m = movb.get_movie();
|
||||
if(!m.readonly_mode())
|
||||
throw std::runtime_error("Not in read-only mode");
|
||||
if(!allow_past_end && frame >= movb.get_movie().get_frame_vector().size())
|
||||
if(!allow_past_end && frame >= our_movie.input.size())
|
||||
throw std::runtime_error("Index out of movie");
|
||||
int32_t pc = get_pc_for(port, controller, button, true);
|
||||
if(pc < 0)
|
||||
throw std::runtime_error("Invalid control to edit");
|
||||
uint64_t firstframe = m.get_current_frame_first_subframe();
|
||||
uint64_t minframe = firstframe + pc;
|
||||
uint64_t msize = movb.get_movie().get_frame_vector().size();
|
||||
uint64_t msize = our_movie.input.size();
|
||||
if(minframe > msize || firstframe >= msize)
|
||||
throw std::runtime_error("Can not edit finished movie");
|
||||
if(frame < minframe)
|
||||
|
@ -181,12 +181,12 @@ namespace
|
|||
if(n >= v.size())
|
||||
throw std::runtime_error("Requested frame outside movie");
|
||||
//Checks if requested frame is from movie.
|
||||
if(&v == &movb.get_movie().get_frame_vector())
|
||||
if(&v == &our_movie.input)
|
||||
check_can_edit(0, 0, 0, n);
|
||||
|
||||
v[n] = f->get_frame();
|
||||
|
||||
if(&v == &movb.get_movie().get_frame_vector()) {
|
||||
if(&v == &our_movie.input) {
|
||||
//This can't add frames, so no need to adjust the movie.
|
||||
update_movie_state();
|
||||
platform::notify_status();
|
||||
|
@ -256,7 +256,7 @@ namespace
|
|||
for(uint64_t i = 0; i < count; i++)
|
||||
v.append(v.blank_frame(true));
|
||||
}
|
||||
if(&v == &movb.get_movie().get_frame_vector()) {
|
||||
if(&v == &our_movie.input) {
|
||||
update_movie_state();
|
||||
platform::notify_status();
|
||||
}
|
||||
|
@ -271,13 +271,13 @@ namespace
|
|||
P(f);
|
||||
|
||||
v.append(v.blank_frame(true));
|
||||
if(&v == &movb.get_movie().get_frame_vector()) {
|
||||
if(&v == &our_movie.input) {
|
||||
update_movie_state();
|
||||
platform::notify_status();
|
||||
check_can_edit(0, 0, 0, v.size() - 1);
|
||||
}
|
||||
v[v.size() - 1] = f->get_frame();
|
||||
if(&v == &movb.get_movie().get_frame_vector()) {
|
||||
if(&v == &our_movie.input) {
|
||||
if(!v[v.size() - 1].sync()) {
|
||||
update_movie_state();
|
||||
}
|
||||
|
@ -295,10 +295,10 @@ namespace
|
|||
|
||||
if(n > v.size())
|
||||
throw std::runtime_error("Requested truncate length longer than existing");
|
||||
if(&v == &movb.get_movie().get_frame_vector())
|
||||
if(&v == &our_movie.input)
|
||||
check_can_edit(0, 0, 0, n);
|
||||
v.resize(n);
|
||||
if(&v == &movb.get_movie().get_frame_vector()) {
|
||||
if(&v == &our_movie.input) {
|
||||
update_movie_state();
|
||||
platform::notify_status();
|
||||
}
|
||||
|
@ -319,11 +319,11 @@ namespace
|
|||
P.expected("number or boolean");
|
||||
|
||||
movie& m = movb.get_movie();
|
||||
if(&v == &movb.get_movie().get_frame_vector())
|
||||
if(&v == &our_movie.input)
|
||||
check_can_edit(port, controller, button, frame);
|
||||
v[frame].axis3(port, controller, button, value);
|
||||
|
||||
if(&v == &movb.get_movie().get_frame_vector()) {
|
||||
if(&v == &our_movie.input) {
|
||||
update_movie_state();
|
||||
platform::notify_status();
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ namespace
|
|||
throw std::runtime_error("Destination index out of movie");
|
||||
|
||||
movie& m = movb.get_movie();
|
||||
if(&dstv == &movb.get_movie().get_frame_vector())
|
||||
if(&dstv == &our_movie.input)
|
||||
check_can_edit(0, 0, 0, dst, true);
|
||||
|
||||
{
|
||||
|
@ -360,7 +360,7 @@ namespace
|
|||
for(uint64_t i = backwards ? (count - 1) : 0; i < count; i = backwards ? (i - 1) : (i + 1))
|
||||
dstv[dst + i] = srcv[src + i];
|
||||
}
|
||||
if(&dstv == &movb.get_movie().get_frame_vector()) {
|
||||
if(&dstv == &our_movie.input) {
|
||||
update_movie_state();
|
||||
platform::notify_status();
|
||||
}
|
||||
|
@ -590,11 +590,11 @@ namespace
|
|||
{
|
||||
if(P.is_nil()) {
|
||||
P.skip();
|
||||
return movb.get_movie().get_frame_vector();
|
||||
return our_movie.input;
|
||||
} else if(P.is<lua_inputmovie>())
|
||||
return *(P.arg<lua_inputmovie*>()->get_frame_vector());
|
||||
else
|
||||
return movb.get_movie().get_frame_vector();
|
||||
return our_movie.input;
|
||||
}
|
||||
|
||||
lua::_class<lua_inputmovie> class_inputmovie(lua_class_movie, "INPUTMOVIE", {}, {
|
||||
|
|
|
@ -794,7 +794,7 @@ namespace
|
|||
uint64_t real_first_editable(frame_controls& fc, unsigned idx)
|
||||
{
|
||||
uint64_t cffs = movb.get_movie().get_current_frame_first_subframe();
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
pollcounter_vector& pv = movb.get_movie().get_pollcounters();
|
||||
uint64_t vsize = fv.size();
|
||||
uint32_t pc = fc.read_pollcount(pv, idx);
|
||||
|
@ -817,7 +817,7 @@ namespace
|
|||
uint64_t real_first_nextframe(frame_controls& fc)
|
||||
{
|
||||
uint64_t base = real_first_editable(fc, 0);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
for(uint32_t i = 0;; i++)
|
||||
if(base + i >= vsize || fv[base + i].sync())
|
||||
|
@ -860,7 +860,7 @@ wxeditor_movie::_moviepanel::_moviepanel(wxeditor_movie* v)
|
|||
void wxeditor_movie::_moviepanel::update_cache()
|
||||
{
|
||||
movie& m = movb.get_movie();
|
||||
controller_frame_vector& fv = m.get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
if(&m == prev_obj && prev_seqno == m.get_seqno()) {
|
||||
//Just process new subframes if any.
|
||||
for(uint64_t i = max_subframe; i < fv.size(); i++) {
|
||||
|
@ -979,7 +979,7 @@ void wxeditor_movie::_moviepanel::render_linen(text_framebuffer& fb, controller_
|
|||
void wxeditor_movie::_moviepanel::render(text_framebuffer& fb, unsigned long long pos)
|
||||
{
|
||||
spos = pos;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
controller_frame cf = fv.blank_frame(false);
|
||||
int _width = width(cf);
|
||||
fb.set_size(_width, lines_to_display + 3);
|
||||
|
@ -1023,7 +1023,7 @@ void wxeditor_movie::_moviepanel::do_toggle_buttons(unsigned idx, uint64_t row1,
|
|||
if(!movb.get_movie().readonly_mode())
|
||||
return;
|
||||
uint64_t fedit = real_first_editable(*_fcontrols, idx);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
controller_frame_vector::notify_freeze freeze(fv);
|
||||
for(uint64_t i = _press_line; i <= line; i++) {
|
||||
if(i < fedit || i >= fv.size())
|
||||
|
@ -1053,7 +1053,7 @@ void wxeditor_movie::_moviepanel::do_alter_axis(unsigned idx, uint64_t row1, uin
|
|||
return;
|
||||
}
|
||||
uint64_t fedit = real_first_editable(*_fcontrols, idx);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
if(line < fedit || line >= fv.size()) {
|
||||
valid = false;
|
||||
return;
|
||||
|
@ -1077,7 +1077,7 @@ void wxeditor_movie::_moviepanel::do_alter_axis(unsigned idx, uint64_t row1, uin
|
|||
std::swap(line, line2);
|
||||
runemufn([idx, line, line2, value, _fcontrols]() {
|
||||
uint64_t fedit = real_first_editable(*_fcontrols, idx);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
controller_frame_vector::notify_freeze freeze(fv);
|
||||
for(uint64_t i = line; i <= line2; i++) {
|
||||
if(i < fedit || i >= fv.size())
|
||||
|
@ -1105,7 +1105,7 @@ void wxeditor_movie::_moviepanel::do_sweep_axis(unsigned idx, uint64_t row1, uin
|
|||
return;
|
||||
}
|
||||
uint64_t fedit = real_first_editable(*_fcontrols, idx);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
if(line2 < fedit || line2 >= fv.size()) {
|
||||
valid = false;
|
||||
return;
|
||||
|
@ -1119,7 +1119,7 @@ void wxeditor_movie::_moviepanel::do_sweep_axis(unsigned idx, uint64_t row1, uin
|
|||
return;
|
||||
runemufn([idx, line, line2, value, value2, _fcontrols]() {
|
||||
uint64_t fedit = real_first_editable(*_fcontrols, idx);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
controller_frame_vector::notify_freeze freeze(fv);
|
||||
for(uint64_t i = line + 1; i <= line2 - 1; i++) {
|
||||
if(i < fedit || i >= fv.size())
|
||||
|
@ -1141,7 +1141,7 @@ void wxeditor_movie::_moviepanel::do_append_frames(uint64_t count)
|
|||
runemufn([_count]() {
|
||||
if(!movb.get_movie().readonly_mode())
|
||||
return;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
controller_frame_vector::notify_freeze freeze(fv);
|
||||
for(uint64_t i = 0; i < _count; i++)
|
||||
fv.append(fv.blank_frame(true));
|
||||
|
@ -1174,7 +1174,7 @@ void wxeditor_movie::_moviepanel::do_insert_frame_after(uint64_t row)
|
|||
runemufn([_row, _fcontrols]() {
|
||||
if(!movb.get_movie().readonly_mode())
|
||||
return;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t fedit = real_first_editable(*_fcontrols, 0);
|
||||
//Find the start of the next frame.
|
||||
uint64_t nframe = _row + 1;
|
||||
|
@ -1206,7 +1206,7 @@ void wxeditor_movie::_moviepanel::do_delete_frame(uint64_t row1, uint64_t row2,
|
|||
frame_controls* _fcontrols = &fcontrols;
|
||||
if(_row1 > _row2) std::swap(_row1, _row2);
|
||||
runemufn([_row1, _row2, _wholeframe, _fcontrols]() {
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
if(_row1 >= vsize)
|
||||
return; //Nothing to do.
|
||||
|
@ -1275,7 +1275,7 @@ void wxeditor_movie::_moviepanel::do_truncate(uint64_t row)
|
|||
uint64_t _row = row;
|
||||
frame_controls* _fcontrols = &fcontrols;
|
||||
runemufn([_row, _fcontrols]() {
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
if(_row >= vsize)
|
||||
return;
|
||||
|
@ -1380,7 +1380,7 @@ void wxeditor_movie::_moviepanel::popup_axis_panel(uint64_t row, control_info ci
|
|||
runemufn([ciX, row, c, _fcontrols]() {
|
||||
uint64_t fedit = real_first_editable(*_fcontrols, ciX.index);
|
||||
if(row < fedit) return;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
controller_frame cf = fv[row];
|
||||
_fcontrols->write_index(cf, ciX.index, c.first);
|
||||
});
|
||||
|
@ -1416,7 +1416,7 @@ void wxeditor_movie::_moviepanel::popup_axis_panel(uint64_t row, control_info ci
|
|||
uint64_t fedit = real_first_editable(*_fcontrols, ciX.index);
|
||||
fedit = max(fedit, real_first_editable(*_fcontrols, ciY.index));
|
||||
if(row < fedit) return;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
controller_frame cf = fv[row];
|
||||
_fcontrols->write_index(cf, ciX.index, c.first);
|
||||
_fcontrols->write_index(cf, ciY.index, c.second);
|
||||
|
@ -1428,7 +1428,7 @@ void wxeditor_movie::_moviepanel::popup_axis_panel(uint64_t row, control_info ci
|
|||
uint64_t fedit = real_first_editable(*_fcontrols, ciX.index);
|
||||
fedit = max(fedit, real_first_editable(*_fcontrols, ciY.index));
|
||||
if(row < fedit) return;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
controller_frame cf = fv[row];
|
||||
_fcontrols->write_index(cf, ciX.index, c.first);
|
||||
_fcontrols->write_index(cf, ciY.index, c.second);
|
||||
|
@ -1765,7 +1765,7 @@ void wxeditor_movie::_moviepanel::on_mouse2(unsigned x, unsigned y, bool polarit
|
|||
|
||||
int wxeditor_movie::_moviepanel::get_lines()
|
||||
{
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
return fv.size();
|
||||
}
|
||||
|
||||
|
@ -1873,7 +1873,7 @@ void wxeditor_movie::_moviepanel::do_copy(uint64_t row1, uint64_t row2, unsigned
|
|||
std::swap(line, line2);
|
||||
std::string copied;
|
||||
runemufn([port, controller, line, line2, _fcontrols, &copied]() {
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
if(!vsize)
|
||||
return;
|
||||
|
@ -1892,7 +1892,7 @@ void wxeditor_movie::_moviepanel::do_copy(uint64_t row1, uint64_t row2)
|
|||
std::swap(line, line2);
|
||||
std::string copied;
|
||||
runemufn([line, line2, &copied]() {
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
if(!vsize)
|
||||
return;
|
||||
|
@ -1939,7 +1939,7 @@ void wxeditor_movie::_moviepanel::do_paste(uint64_t row, bool append)
|
|||
while(std::getline(y, z))
|
||||
gaplen++;
|
||||
}
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
if(gapstart < real_first_editable(*_fcontrols, 0))
|
||||
return;
|
||||
|
@ -1997,7 +1997,7 @@ void wxeditor_movie::_moviepanel::do_paste(uint64_t row, unsigned port, unsigned
|
|||
newframes++;
|
||||
}
|
||||
}
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
if(gapstart < real_first_editable(*_fcontrols, iset))
|
||||
return;
|
||||
|
@ -2036,7 +2036,7 @@ void wxeditor_movie::_moviepanel::do_insert_controller(uint64_t row, unsigned po
|
|||
//Insert enough lines for the pasted content.
|
||||
if(!movb.get_movie().readonly_mode())
|
||||
return;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
if(gapstart < real_first_editable(*_fcontrols, iset))
|
||||
return;
|
||||
|
@ -2065,7 +2065,7 @@ void wxeditor_movie::_moviepanel::do_delete_controller(uint64_t row1, uint64_t r
|
|||
//Insert enough lines for the pasted content.
|
||||
if(!movb.get_movie().readonly_mode())
|
||||
return;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame_vector& fv = our_movie.input;
|
||||
uint64_t vsize = fv.size();
|
||||
if(gapstart < real_first_editable(*_fcontrols, iset))
|
||||
return;
|
||||
|
|
|
@ -581,7 +581,6 @@ void wxeditor_uploaddialog::on_ok(wxCommandEvent& e)
|
|||
if(fn.length() < 6 || fn.substr(fn.length() - 5) != ".lsmv")
|
||||
filename->SetValue(towxstring(fn + ".lsmv"));
|
||||
our_movie.is_savestate = false;
|
||||
our_movie.input = movb.get_movie().save();
|
||||
auto prj = project_get();
|
||||
if(prj) {
|
||||
our_movie.gamename = prj->gamename;
|
||||
|
|
Loading…
Add table
Reference in a new issue