Setting sets

This commit is contained in:
Ilari Liusvaara 2014-05-13 09:06:14 +03:00
parent 66839ba82f
commit 6f35061747
21 changed files with 544 additions and 155 deletions

View file

@ -21,6 +21,7 @@ struct emulator_instance
memory_space memory;
lua::state lua;
lsnes_memorywatch_set mwatch;
settingvar::group settings;
settingvar::cache setcache;
voice_commentary commentary;
subtitle_commentary subtitles;

View file

@ -34,8 +34,8 @@ void reload_current_rom();
void do_break_pause();
void convert_break_to_pause();
extern settingvar::variable<settingvar::model_bool<settingvar::yes_no>> jukebox_dflt_binary;
extern settingvar::variable<settingvar::model_bool<settingvar::yes_no>> movie_dflt_binary;
extern settingvar::variable<settingvar::model_bool<settingvar::yes_no>> save_dflt_binary;
extern settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> jukebox_dflt_binary;
extern settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> movie_dflt_binary;
extern settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> save_dflt_binary;
#endif

View file

@ -3,6 +3,6 @@
#include "library/settingvar.hpp"
extern settingvar::group lsnes_vset;
extern settingvar::set lsnes_setgrp;
#endif

View file

@ -13,6 +13,10 @@ namespace settingvar
class base;
class group;
class description;
class set;
class superbase;
threads::rlock& get_setting_lock();
/**
* A settings listener.
@ -29,6 +33,64 @@ struct listener
virtual void on_setting_change(group& _group, const base& val) = 0;
};
/**
* Set add/drop listener.
*/
class set_listener
{
public:
/**
* Dtor.
*/
virtual ~set_listener();
/**
* New item in set.
*/
virtual void create(set& s, const std::string& name, superbase& svar) = 0;
/**
* Deleted item from set.
*/
virtual void destroy(set& s, const std::string& name) = 0;
/**
* Destroyed the entiere set.
*/
virtual void kill(set& s) = 0;
};
/**
* A set of setting variables.
*/
class set
{
public:
/**
* Create a set.
*/
set();
/**
* Destructor.
*/
~set();
/**
* Register a supervariable.
*/
void do_register(const std::string& name, superbase& info);
/**
* Unregister a supervariable.
*/
void do_unregister(const std::string& name, superbase& info);
/**
* Add a callback on new supervariable.
*/
void add_callback(set_listener& listener) throw(std::bad_alloc);
/**
* Drop a callback on new supervariable.
*/
void drop_callback(set_listener& listener);
private:
char dummy;
};
/**
* Group of setting variables.
*/
@ -71,10 +133,30 @@ public:
* Fire listener.
*/
void fire_listener(base& var) throw();
/**
* Add a set of settings.
*/
void add_set(set& s) throw(std::bad_alloc);
/**
* Remove a set of settings.
*/
void drop_set(set& s);
private:
class xlistener : public set_listener
{
public:
xlistener(group& _grp);
~xlistener();
void create(set& s, const std::string& name, superbase& sb);
void destroy(set& s, const std::string& name);
void kill(set& s);
private:
group& grp;
} _listener;
std::map<std::string, class base*> settings;
std::set<struct listener*> listeners;
threads::lock lock;
std::set<struct set*> sets_listened;
bool dtor_running;
};
/**
@ -134,7 +216,6 @@ public:
std::string get_hname(const std::string& name) throw(std::bad_alloc, std::runtime_error);
private:
group& grp;
threads::lock lock;
std::map<std::string, std::string> badcache;
};
@ -181,6 +262,33 @@ struct description
*/
template<class T> static class description& description_get(T dummy);
/**
* Supervariable.
*/
class superbase
{
public:
/**
* Constructor.
*/
void _superbase(set& _s, const std::string& iname) throw(std::bad_alloc);
/**
* Destructor.
*/
virtual ~superbase() throw();
/**
* Make a variable.
*/
virtual base* make(group& grp) = 0;
/**
* Notify set death.
*/
void set_died();
private:
set* s;
std::string iname;
};
/**
* Setting variable.
*/
@ -190,8 +298,7 @@ public:
/**
* Constructor.
*/
base(group& _group, const std::string& iname, const std::string& hname)
throw(std::bad_alloc);
base(group& _group, const std::string& iname, const std::string& hname, bool dynamic) throw(std::bad_alloc);
/**
* Destructor.
*/
@ -213,13 +320,17 @@ public:
* Get setting description.
*/
virtual const description& get_description() const throw() = 0;
/**
* Notify group death.
*/
void group_died();
protected:
base(const base&);
base& operator=(const base&);
group& sgroup;
group* sgroup;
std::string iname;
std::string hname;
mutable threads::lock lock;
bool is_dynamic;
};
/**
@ -235,8 +346,8 @@ public:
* Constructor.
*/
variable(group& sgroup, const std::string& iname, const std::string& hname,
valtype_t defaultvalue)
: base(sgroup, iname, hname)
valtype_t defaultvalue, bool dynamic = false)
: base(sgroup, iname, hname, dynamic)
{
value = defaultvalue;
}
@ -252,17 +363,17 @@ public:
void str(const std::string& val) throw(std::runtime_error, std::bad_alloc)
{
{
threads::alock h(lock);
threads::arlock h(get_setting_lock());
value = model::read(val);
}
sgroup.fire_listener(*this);
sgroup->fire_listener(*this);
}
/**
* Get setting.
*/
std::string str() const throw(std::runtime_error, std::bad_alloc)
{
threads::alock h(lock);
threads::arlock h(get_setting_lock());
return model::write(value);
}
/**
@ -271,19 +382,19 @@ public:
void set(valtype_t _value) throw(std::runtime_error, std::bad_alloc)
{
{
threads::alock h(lock);
threads::arlock h(get_setting_lock());
if(!model::valid(value))
throw std::runtime_error("Invalid value");
value = _value;
}
sgroup.fire_listener(*this);
sgroup->fire_listener(*this);
}
/**
* Get setting.
*/
valtype_t get() throw(std::bad_alloc)
{
threads::alock h(lock);
threads::arlock h(get_setting_lock());
return model::transform(value);
}
/**
@ -305,6 +416,69 @@ private:
model dummy;
};
/**
* Supervariable with model.
*/
template<class model> class supervariable : public superbase
{
typedef typename model::valtype_t valtype_t;
supervariable(const supervariable<model>&);
supervariable<model>& operator=(const supervariable<model>&);
public:
/**
* Constructor.
*/
supervariable(set& _s, const std::string& _iname, const std::string& _hname, valtype_t _defaultvalue)
throw(std::bad_alloc)
: s(_s)
{
iname = _iname;
hname = _hname;
defaultvalue = _defaultvalue;
_superbase(_s, iname);
}
/**
* Destructor.
*/
~supervariable() throw()
{
}
/**
* Make a variable.
*/
base* make(group& grp)
{
return new variable<model>(grp, iname, hname, defaultvalue, true);
}
/**
* Read value in instance.
*/
valtype_t operator()(group& grp)
{
base* b = &grp[iname];
variable<model>* m = dynamic_cast<variable<model>*>(b);
if(!m)
throw std::runtime_error("No such setting in target group");
return m->get();
}
/**
* Write value in instance.
*/
void operator()(group& grp, valtype_t val)
{
base* b = &grp[iname];
variable<model>* m = dynamic_cast<variable<model>*>(b);
if(!m)
throw std::runtime_error("No such setting in target group");
m->set(val);
}
private:
set& s;
std::string iname;
std::string hname;
valtype_t defaultvalue;
};
/**
* Yes-no.
*/

View file

@ -105,13 +105,14 @@ namespace
messages << "Saved PNG screenshot" << std::endl;
});
settingvar::variable<settingvar::model_int<0, 8191>> dtb(lsnes_vset, "top-border", "UI‣Top padding", 0);
settingvar::variable<settingvar::model_int<0, 8191>> dbb(lsnes_vset, "bottom-border",
settingvar::supervariable<settingvar::model_int<0, 8191>> dtb(lsnes_setgrp, "top-border",
"UI‣Top padding", 0);
settingvar::supervariable<settingvar::model_int<0, 8191>> dbb(lsnes_setgrp, "bottom-border",
"UI‣Bottom padding", 0);
settingvar::variable<settingvar::model_int<0, 8191>> dlb(lsnes_vset, "left-border",
settingvar::supervariable<settingvar::model_int<0, 8191>> dlb(lsnes_setgrp, "left-border",
"UI‣Left padding", 0);
settingvar::variable<settingvar::model_int<0, 8191>> drb(lsnes_vset, "right-border", "UI‣Right padding",
0);
settingvar::supervariable<settingvar::model_int<0, 8191>> drb(lsnes_setgrp, "right-border",
"UI‣Right padding", 0);
bool last_redraw_no_lua = false;
}
@ -170,10 +171,10 @@ void redraw_framebuffer(framebuffer::raw& todraw, bool no_lua, bool spontaneous)
ri.fbuf = todraw;
ri.hscl = hscl;
ri.vscl = vscl;
ri.lgap = max(lrc.left_gap, (unsigned)dlb);
ri.rgap = max(lrc.right_gap, (unsigned)drb);
ri.tgap = max(lrc.top_gap, (unsigned)dtb);
ri.bgap = max(lrc.bottom_gap, (unsigned)dbb);
ri.lgap = max(lrc.left_gap, (unsigned)dlb(CORE().settings));
ri.rgap = max(lrc.right_gap, (unsigned)drb(CORE().settings));
ri.tgap = max(lrc.top_gap, (unsigned)dtb(CORE().settings));
ri.bgap = max(lrc.bottom_gap, (unsigned)dbb(CORE().settings));
CORE().mwatch.watch(ri.rq);
buffering.put_write();
notify_screen_update();

View file

@ -4,7 +4,7 @@
#include "core/keymapper.hpp"
emulator_instance::emulator_instance()
: setcache(lsnes_vset), subtitles(&mlogic), mbranch(&mlogic), mteditor(&mlogic),
: setcache(settings), subtitles(&mlogic), mbranch(&mlogic), mteditor(&mlogic),
status(status_A, status_B, status_C), mapper(keyboard, command)
{
status_A.valid = false;
@ -12,6 +12,7 @@ emulator_instance::emulator_instance()
status_C.valid = false;
command.add_set(lsnes_cmds);
mapper.add_invbind_set(lsnes_invbinds);
settings.add_set(lsnes_setgrp);
}
emulator_instance lsnes_instance;
@ -19,4 +20,4 @@ emulator_instance lsnes_instance;
emulator_instance& CORE()
{
return lsnes_instance;
}
}

View file

@ -65,10 +65,10 @@ namespace
class bitrate_tracker;
class inthread_th;
settingvar::variable<settingvar::model_int<OPUS_MIN_BITRATE,OPUS_MAX_BITRATE>> opus_bitrate(lsnes_vset,
settingvar::supervariable<settingvar::model_int<OPUS_MIN_BITRATE,OPUS_MAX_BITRATE>> opus_bitrate(lsnes_setgrp,
"opus-bitrate", "commentary‣Bitrate", OPUS_BITRATE);
settingvar::variable<settingvar::model_int<OPUS_MIN_BITRATE,OPUS_MAX_BITRATE>> opus_max_bitrate(lsnes_vset,
"opus-max-bitrate", "commentary‣Max bitrate", OPUS_MAX_BITRATE);
settingvar::supervariable<settingvar::model_int<OPUS_MIN_BITRATE,OPUS_MAX_BITRATE>> opus_max_bitrate(
lsnes_setgrp, "opus-max-bitrate", "commentary‣Max bitrate", OPUS_MAX_BITRATE);
struct voicesub_state
{
@ -588,7 +588,7 @@ out:
throw std::runtime_error("Only mono streams are supported");
uint64_t samples = serialization::u64l(header + 8);
opus::encoder enc(opus::samplerate::r48k, false, opus::application::voice);
enc.ctl(opus::bitrate(opus_bitrate.get()));
enc.ctl(opus::bitrate(opus_bitrate(lsnes_instance.settings)));
int32_t pregap = enc.ctl(opus::lookahead);
pregap_length = pregap;
for(uint64_t i = 0; i < samples + pregap; i += OPUS_BLOCK_SIZE) {
@ -615,7 +615,8 @@ out:
for(size_t j = bs; j < OPUS_BLOCK_SIZE; j++)
tmp[j] = 0;
try {
const size_t opus_out_max2 = opus_max_bitrate.get() * OPUS_BLOCK_SIZE / 384000;
const size_t opus_out_max2 = opus_max_bitrate(lsnes_instance.settings) *
OPUS_BLOCK_SIZE / 384000;
size_t r = enc.encode(tmp, OPUS_BLOCK_SIZE, tmpi, opus_out_max2);
write(OPUS_BLOCK_SIZE / 120, tmpi, r);
brtrack.submit(r, bs);
@ -1446,7 +1447,7 @@ out:
cblock = 120;
else
return; //No valid data to compress.
const size_t opus_out_max2 = opus_max_bitrate.get() * cblock / 384000;
const size_t opus_out_max2 = opus_max_bitrate(lsnes_instance.settings) * cblock / 384000;
try {
size_t c = e.encode(buf, cblock, opus_output, opus_out_max2);
//Successfully compressed a block.
@ -1529,7 +1530,7 @@ out:
return;
try {
e.ctl(opus::reset);
e.ctl(opus::bitrate(opus_bitrate.get()));
e.ctl(opus::bitrate(opus_bitrate(lsnes_instance.settings)));
brtrack.reset();
uint64_t ctime;
{
@ -1621,7 +1622,7 @@ out:
return;
opus::encoder oenc(opus::samplerate::r48k, false, opus::application::voice);
oenc.ctl(opus::bitrate(opus_bitrate.get()));
oenc.ctl(opus::bitrate(opus_bitrate(lsnes_instance.settings)));
audioapi_resampler rin;
audioapi_resampler rout;
const unsigned buf_max = 6144; //These buffers better be large.

View file

@ -47,22 +47,22 @@
void update_movie_state();
time_t random_seed_value = 0;
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> jukebox_dflt_binary(lsnes_vset,
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> jukebox_dflt_binary(lsnes_setgrp,
"jukebox-default-binary", "Movie‣Saving‣Saveslots binary", true);
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> movie_dflt_binary(lsnes_vset, "movie-default-binary",
"Movie‣Saving‣Movies binary", false);
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> save_dflt_binary(lsnes_vset,
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> movie_dflt_binary(lsnes_setgrp,
"movie-default-binary", "Movie‣Saving‣Movies binary", false);
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> save_dflt_binary(lsnes_setgrp,
"savestate-default-binary", "Movie‣Saving‣Savestates binary", false);
namespace
{
settingvar::variable<settingvar::model_int<0,999999>> advance_timeout_first(lsnes_vset, "advance-timeout",
"Delays‣First frame advance", 500);
settingvar::variable<settingvar::model_int<0,999999>> advance_timeout_subframe(lsnes_vset,
settingvar::supervariable<settingvar::model_int<0,999999>> advance_timeout_first(lsnes_setgrp,
"advance-timeout", "Delays‣First frame advance", 500);
settingvar::supervariable<settingvar::model_int<0,999999>> advance_timeout_subframe(lsnes_setgrp,
"advance-subframe-timeout", "Delays‣Subframe advance", 100);
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> pause_on_end(lsnes_vset, "pause-on-end",
"Movie‣Pause on end", false);
settingvar::variable<settingvar::model_int<0,999999999>> jukebox_size(lsnes_vset, "jukebox-size",
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> pause_on_end(lsnes_setgrp,
"pause-on-end", "Movie‣Pause on end", false);
settingvar::supervariable<settingvar::model_int<0,999999999>> jukebox_size(lsnes_setgrp, "jukebox-size",
"Movie‣Number of save slots", 12);
enum advance_mode
@ -175,9 +175,9 @@ controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_allo
if(amode == ADVANCE_SUBFRAME) {
if(!cancel_advance) {
if(!advanced_once)
platform::wait(advance_timeout_first * 1000);
platform::wait(advance_timeout_first(CORE().settings) * 1000);
else
platform::wait(advance_timeout_subframe * 1000);
platform::wait(advance_timeout_subframe(CORE().settings) * 1000);
advanced_once = true;
}
if(cancel_advance) {
@ -205,9 +205,9 @@ controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_allo
if(!cancel_advance) {
uint64_t wait = 0;
if(!advanced_once)
wait = advance_timeout_first * 1000;
wait = advance_timeout_first(CORE().settings) * 1000;
else if(amode == ADVANCE_SUBFRAME)
wait = advance_timeout_subframe * 1000;
wait = advance_timeout_subframe(CORE().settings) * 1000;
else
wait = to_wait_frame(get_utime());
platform::wait(wait);
@ -220,7 +220,7 @@ controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_allo
}
platform::set_paused(amode == ADVANCE_PAUSE);
} else if(amode == ADVANCE_AUTO && CORE().mlogic.get_movie().readonly_mode() &&
pause_on_end && !stop_at_frame_active) {
pause_on_end(CORE().settings) && !stop_at_frame_active) {
if(CORE().mlogic.get_movie().get_current_frame() ==
CORE().mlogic.get_movie().get_frame_count()) {
stop_at_frame_active = false;
@ -286,16 +286,18 @@ namespace
struct jukebox_size_listener : public settingvar::listener
{
jukebox_size_listener() { lsnes_vset.add_listener(*this); }
~jukebox_size_listener() throw() {lsnes_vset.remove_listener(*this); };
void on_setting_change(settingvar::group& grp, const settingvar::base& val)
jukebox_size_listener(settingvar::group& _grp) : grp(_grp) { grp.add_listener(*this); }
~jukebox_size_listener() throw() { grp.remove_listener(*this); };
void on_setting_change(settingvar::group& _grp, const settingvar::base& val)
{
if(val.get_iname() == "jukebox-size") {
if(save_jukebox_pointer >= (size_t)jukebox_size)
if(save_jukebox_pointer >= (size_t)jukebox_size(_grp))
save_jukebox_pointer = 0;
}
update_movie_state();
}
private:
settingvar::group& grp;
};
}
@ -353,7 +355,7 @@ void update_movie_state()
else
_status.mode = 'F';
}
if(jukebox_size > 0) {
if(jukebox_size(CORE().settings) > 0) {
_status.saveslot_valid = true;
int tmp = -1;
std::string sfilen = translate_name_mprefix(save_jukebox_name(save_jukebox_pointer), tmp, -1);
@ -593,13 +595,14 @@ namespace
command::fnptr<> save_jukebox_prev(lsnes_cmds, "cycle-jukebox-backward", "Cycle save jukebox backwards",
"Syntax: cycle-jukebox-backward\nCycle save jukebox backwards\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(jukebox_size == 0)
size_t jbsize = jukebox_size(CORE().settings);
if(jbsize == 0)
return;
if(save_jukebox_pointer == 0)
save_jukebox_pointer = jukebox_size - 1;
save_jukebox_pointer = jbsize - 1;
else
save_jukebox_pointer--;
if(save_jukebox_pointer >= (size_t)jukebox_size)
if(save_jukebox_pointer >= (size_t)jbsize)
save_jukebox_pointer = 0;
update_movie_state();
});
@ -607,13 +610,14 @@ namespace
command::fnptr<> save_jukebox_next(lsnes_cmds, "cycle-jukebox-forward", "Cycle save jukebox forwards",
"Syntax: cycle-jukebox-forward\nCycle save jukebox forwards\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(jukebox_size == 0)
size_t jbsize = jukebox_size(CORE().settings);
if(jbsize == 0)
return;
if(save_jukebox_pointer + 1 >= (size_t)jukebox_size)
if(save_jukebox_pointer + 1 >= (size_t)jbsize)
save_jukebox_pointer = 0;
else
save_jukebox_pointer++;
if(save_jukebox_pointer >= (size_t)jukebox_size)
if(save_jukebox_pointer >= (size_t)jbsize)
save_jukebox_pointer = 0;
update_movie_state();
});
@ -624,7 +628,7 @@ namespace
if(!regex_match("[1-9][0-9]{0,8}", args))
throw std::runtime_error("Bad slot number");
uint32_t slot = parse_value<uint32_t>(args);
if(slot >= (size_t)jukebox_size)
if(slot >= (size_t)jukebox_size(CORE().settings))
throw std::runtime_error("Bad slot number");
save_jukebox_pointer = slot - 1;
update_movie_state();
@ -633,7 +637,7 @@ namespace
command::fnptr<> load_jukebox(lsnes_cmds, "load-jukebox", "Load save from jukebox",
"Syntax: load-jukebox\nLoad save from jukebox\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(jukebox_size == 0)
if(jukebox_size(CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_CURRENT);
});
@ -641,7 +645,7 @@ namespace
command::fnptr<> load_jukebox_readwrite(lsnes_cmds, "load-jukebox-readwrite", "Load save from jukebox in"
" read-write mode", "Syntax: load-jukebox-readwrite\nLoad save from jukebox in read-write mode\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(jukebox_size == 0)
if(jukebox_size(CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_RW);
});
@ -649,7 +653,7 @@ namespace
command::fnptr<> load_jukebox_readonly(lsnes_cmds, "load-jukebox-readonly", "Load save from jukebox in "
"read-only mode", "Syntax: load-jukebox-readonly\nLoad save from jukebox in read-only mode\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(jukebox_size == 0)
if(jukebox_size(CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_RO);
});
@ -657,7 +661,7 @@ namespace
command::fnptr<> load_jukebox_preserve(lsnes_cmds, "load-jukebox-preserve", "Load save from jukebox, "
"preserving input", "Syntax: load-jukebox-preserve\nLoad save from jukebox, preserving input\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(jukebox_size == 0)
if(jukebox_size(CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_PRESERVE);
});
@ -665,7 +669,7 @@ namespace
command::fnptr<> load_jukebox_movie(lsnes_cmds, "load-jukebox-movie", "Load save from jukebox as movie",
"Syntax: load-jukebox-movie\nLoad save from jukebox as movie\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(jukebox_size == 0)
if(jukebox_size(CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_MOVIE);
});
@ -673,7 +677,7 @@ namespace
command::fnptr<> save_jukebox_c(lsnes_cmds, "save-jukebox", "Save save to jukebox",
"Syntax: save-jukebox\nSave save to jukebox\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(jukebox_size == 0)
if(jukebox_size(CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_save(save_jukebox_name(save_jukebox_pointer), SAVE_STATE, -1);
});
@ -873,20 +877,20 @@ namespace
command::fnptr<> tpon(lsnes_cmds, "toggle-pause-on-end", "Toggle pause on end", "Toggle pause on end\n",
[]() throw(std::bad_alloc, std::runtime_error) {
bool tmp = pause_on_end;
pause_on_end.set(!tmp);
bool tmp = pause_on_end(CORE().settings);
pause_on_end(CORE().settings, !tmp);
messages << "Pause-on-end is now " << (tmp ? "OFF" : "ON") << std::endl;
});
command::fnptr<> spon(lsnes_cmds, "set-pause-on-end", "Set pause on end", "Set pause on end\n",
[]() throw(std::bad_alloc, std::runtime_error) {
pause_on_end.set(true);
pause_on_end(CORE().settings, true);
messages << "Pause-on-end is now ON" << std::endl;
});
command::fnptr<> cpon(lsnes_cmds, "clear-pause-on-end", "Clear pause on end", "Clear pause on end\n",
[]() throw(std::bad_alloc, std::runtime_error) {
pause_on_end.set(false);
pause_on_end(CORE().settings, false);
messages << "Pause-on-end is now OFF" << std::endl;
});
@ -1226,7 +1230,7 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_
//Basic initialization.
dispatch_set_error_streams(&messages.getstream());
emulation_thread = threads::this_id();
jukebox_size_listener jlistener;
jukebox_size_listener jlistener(CORE().settings);
CORE().commentary.init();
init_special_screens();
our_rom = rom;

View file

@ -31,9 +31,9 @@ void update_movie_state();
namespace
{
settingvar::variable<settingvar::model_int<0, 9>> savecompression(lsnes_vset, "savecompression",
settingvar::supervariable<settingvar::model_int<0, 9>> savecompression(lsnes_setgrp, "savecompression",
"Movie‣Saving‣Compression", 7);
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> readonly_load_preserves(lsnes_vset,
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> readonly_load_preserves(lsnes_setgrp,
"preserve_on_readonly_load", "Movie‣Loading‣Preserve on readonly load", true);
threads::lock mprefix_lock;
std::string mprefix;
@ -140,7 +140,7 @@ std::string translate_name_mprefix(std::string original, int& binary, int save)
regex_results r = regex("\\$SLOT:(.*)", original);
if(r) {
if(binary < 0)
binary = jukebox_dflt_binary ? 1 : 0;
binary = jukebox_dflt_binary(lsnes_instance.settings) ? 1 : 0;
if(p) {
uint64_t branch = p->get_current_branch();
std::string branch_str;
@ -161,7 +161,8 @@ std::string translate_name_mprefix(std::string original, int& binary, int save)
}
} else {
if(binary < 0)
binary = (save ? save_dflt_binary : movie_dflt_binary) ? 1 : 0;
binary = (save ? save_dflt_binary(lsnes_instance.settings) :
movie_dflt_binary(lsnes_instance.settings)) ? 1 : 0;
return original;
}
}
@ -226,7 +227,8 @@ void do_save_state(const std::string& filename, int binary) throw(std::bad_alloc
target.authors = prj->authors;
}
target.active_macros = controls.get_macro_frames();
target.save(filename2, savecompression, binary > 0, lsnes_instance.mlogic.get_rrdata());
target.save(filename2, savecompression(CORE().settings), binary > 0,
lsnes_instance.mlogic.get_rrdata());
uint64_t took = get_utime() - origtime;
std::string kind = (binary > 0) ? "(binary format)" : "(zip format)";
messages << "Saved state " << kind << " '" << filename2 << "' in " << took << " microseconds."
@ -267,7 +269,8 @@ void do_save_movie(const std::string& filename, int binary) throw(std::bad_alloc
target.authors = prj->authors;
}
target.active_macros.clear();
target.save(filename2, savecompression, binary > 0, lsnes_instance.mlogic.get_rrdata());
target.save(filename2, savecompression(lsnes_instance.settings), binary > 0,
lsnes_instance.mlogic.get_rrdata());
uint64_t took = get_utime() - origtime;
std::string kind = (binary > 0) ? "(binary format)" : "(zip format)";
messages << "Saved movie " << kind << " '" << filename2 << "' in " << took << " microseconds."
@ -644,7 +647,7 @@ void do_load_state(struct moviefile& _movie, int lmode, bool& used)
warn_roms(_movie, our_rom, will_load_state);
//In certain conditions, trun LOAD_STATE_CURRENT into LOAD_STATE_PRESERVE.
if(lmode == LOAD_STATE_CURRENT && current_mode && readonly_load_preserves)
if(lmode == LOAD_STATE_CURRENT && current_mode && readonly_load_preserves(CORE().settings))
lmode = LOAD_STATE_PRESERVE;
//If movie file changes, turn LOAD_STATE_CURRENT into LOAD_STATE_RO
if(lmode == LOAD_STATE_CURRENT && lsnes_instance.mlogic.get_mfile().projectid != _movie.projectid)

View file

@ -44,7 +44,7 @@ namespace
{
uint16_t null_cover_fbmem[512 * 448];
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> savestate_no_check(lsnes_vset,
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> savestate_no_check(lsnes_setgrp,
"dont-check-savestate", "Movie‣Loading‣Don't check savestates", false);
//Framebuffer.
@ -675,7 +675,7 @@ void loaded_rom::load_core_state(const std::vector<char>& buf, bool nochecksum)
if(buf.size() < 32)
throw std::runtime_error("Savestate corrupt");
if(!savestate_no_check) {
if(!savestate_no_check(CORE().settings)) {
unsigned char tmp[32];
#ifdef USE_LIBGCRYPT_SHA256
gcry_md_hash_buffer(GCRY_MD_SHA256, tmp, &buf[0], buf.size() - 32);

View file

@ -1,12 +1,13 @@
#include "core/command.hpp"
#include "core/settings.hpp"
settingvar::group lsnes_vset;
settingvar::set lsnes_setgrp;
namespace
{
settingvar::variable<settingvar::model_path> rompath(lsnes_vset, "rompath", "Paths‣ROMs", "");
settingvar::variable<settingvar::model_path> moviepath(lsnes_vset, "moviepath", "Paths‣Movies", "");
settingvar::variable<settingvar::model_path> firmwarepath(lsnes_vset, "firmwarepath", "Paths‣Firmware", "");
settingvar::variable<settingvar::model_path> slotpath(lsnes_vset, "slotpath", "Paths‣Save slots", "");
settingvar::supervariable<settingvar::model_path> rompath(lsnes_setgrp, "rompath", "Paths‣ROMs", "");
settingvar::supervariable<settingvar::model_path> moviepath(lsnes_setgrp, "moviepath", "Paths‣Movies", "");
settingvar::supervariable<settingvar::model_path> firmwarepath(lsnes_setgrp, "firmwarepath",
"Paths‣Firmware", "");
settingvar::supervariable<settingvar::model_path> slotpath(lsnes_setgrp, "slotpath", "Paths‣Save slots", "");
}

View file

@ -29,6 +29,7 @@
#include "core/dispatch.hpp"
#include "core/settings.hpp"
#include "core/framebuffer.hpp"
#include "core/instance.hpp"
#include "core/window.hpp"
#include "interface/callbacks.hpp"
#include "interface/cover.hpp"
@ -51,9 +52,9 @@
namespace
{
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> output_native(lsnes_vset,
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> output_native(lsnes_setgrp,
"gambatte-native-sound", "Gambatte‣Sound Output at native rate", false);
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> gbchawk_timings(lsnes_vset,
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> gbchawk_timings(lsnes_setgrp,
"gambatte-gbchawk-fuckup", "Gambatte‣Use Fucked up GBCHawk timings", false);
bool do_reset_flag = false;
@ -560,7 +561,7 @@ namespace
std::pair<uint32_t, uint32_t> c_video_rate() { return std::make_pair(262144, 4389); }
double c_get_PAR() { return 1.0; }
std::pair<uint32_t, uint32_t> c_audio_rate() {
if(output_native)
if(output_native(CORE().settings))
return std::make_pair(2097152, 1);
else
return std::make_pair(32768, 1);
@ -636,8 +637,8 @@ namespace
void c_emulate() {
if(!internal_rom)
return;
bool timings_fucked_up = gbchawk_timings;
bool native_rate = output_native;
bool timings_fucked_up = gbchawk_timings(CORE().settings);
bool native_rate = output_native(CORE().settings);
int16_t reset = ecore_callbacks->get_input(0, 0, 1);
if(reset) {
instance->reset();

View file

@ -165,6 +165,7 @@ keyboard& mapper::get_keyboard() throw()
mapper::mapper(keyboard& _kbd, command::group& _domain) throw(std::bad_alloc)
: _listener(*this), kbd(_kbd), domain(_domain)
{
dtor_running = false;
register_queue<mapper, invbind>::do_ready(*this, true);
register_queue<mapper, ctrlrkey>::do_ready(*this, true);
}

View file

@ -1,30 +1,58 @@
#include "settingvar.hpp"
#include "register-queue.hpp"
#include "stateobject.hpp"
namespace settingvar
{
namespace
{
threads::rlock* global_lock;
typedef register_queue<group, base> regqueue_t;
struct set_internal
{
std::map<std::string, superbase*> supervars;
std::set<set_listener*> callbacks;
};
typedef stateobject::type<set, set_internal> set_internal_t;
}
threads::rlock& get_setting_lock()
{
if(!global_lock) global_lock = new threads::rlock;
return *global_lock;
}
listener::~listener() throw()
{
}
group::group() throw(std::bad_alloc)
set_listener::~set_listener() throw()
{
}
group::group() throw(std::bad_alloc)
: _listener(*this)
{
dtor_running = false;
regqueue_t::do_ready(*this, true);
}
group::~group() throw()
{
dtor_running = true;
threads::arlock h(get_setting_lock());
regqueue_t::do_ready(*this, false);
for(auto i : settings)
i.second->group_died();
for(auto i : sets_listened)
i->drop_callback(_listener);
}
std::set<std::string> group::get_settings_set() throw(std::bad_alloc)
{
threads::alock(lock);
threads::arlock h(get_setting_lock());
std::set<std::string> x;
for(auto i : settings)
x.insert(i.first);
@ -33,7 +61,7 @@ std::set<std::string> group::get_settings_set() throw(std::bad_alloc)
base& group::operator[](const std::string& name)
{
threads::alock(lock);
threads::arlock h(get_setting_lock());
if(!settings.count(name))
throw std::runtime_error("No such setting");
return *settings[name];
@ -43,7 +71,7 @@ void group::fire_listener(base& var) throw()
{
std::set<listener*> l;
{
threads::alock h(lock);
threads::arlock h(get_setting_lock());
for(auto i : listeners)
l.insert(i);
}
@ -56,38 +84,187 @@ void group::fire_listener(base& var) throw()
void group::add_listener(struct listener& listener) throw(std::bad_alloc)
{
threads::alock(lock);
threads::arlock h(get_setting_lock());
listeners.insert(&listener);
}
void group::remove_listener(struct listener& listener) throw(std::bad_alloc)
{
threads::alock(lock);
threads::arlock h(get_setting_lock());
listeners.erase(&listener);
}
void group::do_register(const std::string& name, base& _setting) throw(std::bad_alloc)
{
threads::alock h(lock);
threads::arlock h(get_setting_lock());
settings[name] = &_setting;
}
void group::do_unregister(const std::string& name, base* dummy) throw(std::bad_alloc)
{
threads::alock h(lock);
threads::arlock h(get_setting_lock());
settings.erase(name);
}
base::base(group& _group, const std::string& _iname, const std::string& _hname)
throw(std::bad_alloc)
: sgroup(_group), iname(_iname), hname(_hname)
void group::add_set(set& s) throw(std::bad_alloc)
{
regqueue_t::do_register(sgroup, iname, *this);
threads::arlock u(get_setting_lock());
if(sets_listened.count(&s)) return;
try {
sets_listened.insert(&s);
s.add_callback(_listener);
} catch(...) {
sets_listened.erase(&s);
}
}
void group::drop_set(set& s)
{
threads::arlock h(get_setting_lock());
//Drop the callback. This unregisters all.
s.drop_callback(_listener);
sets_listened.erase(&s);
}
group::xlistener::xlistener(group& _grp)
: grp(_grp)
{
}
group::xlistener::~xlistener()
{
}
void group::xlistener::create(set& s, const std::string& name, superbase& sb)
{
threads::arlock h(get_setting_lock());
sb.make(grp);
}
void group::xlistener::destroy(set& s, const std::string& name)
{
threads::arlock h(get_setting_lock());
if(grp.dtor_running) return;
grp.settings.erase(name);
}
void group::xlistener::kill(set& s)
{
threads::arlock h(get_setting_lock());
if(grp.dtor_running) return;
grp.sets_listened.erase(&s);
}
set::set()
{
}
set::~set()
{
auto state = set_internal_t::get_soft(this);
if(!state) return;
threads::arlock u(get_setting_lock());
//Call all DCBs on all factories.
for(auto i : state->supervars)
for(auto j : state->callbacks)
j->destroy(*this, i.first);
//Call all TCBs.
for(auto j : state->callbacks)
j->kill(*this);
//Notify all factories that base set died.
for(auto i : state->supervars)
i.second->set_died();
//We assume factories look after themselves, so we don't destroy those.
set_internal_t::clear(this);
}
void set::do_register(const std::string& name, superbase& info)
{
threads::arlock u(get_setting_lock());
auto& state = set_internal_t::get(this);
if(state.supervars.count(name)) {
std::cerr << "WARNING: Command collision for " << name << "!" << std::endl;
return;
}
state.supervars[name] = &info;
//Call all CCBs on this.
for(auto i : state.callbacks)
i->create(*this, name, info);
}
void set::do_unregister(const std::string& name, superbase& info)
{
threads::arlock u(get_setting_lock());
auto state = set_internal_t::get_soft(this);
if(!state) return;
if(!state->supervars.count(name) || state->supervars[name] != &info) return; //Not this.
state->supervars.erase(name);
//Call all DCBs on this.
for(auto i : state->callbacks)
i->destroy(*this, name);
}
void set::add_callback(set_listener& listener) throw(std::bad_alloc)
{
threads::arlock u(get_setting_lock());
auto& state = set_internal_t::get(this);
state.callbacks.insert(&listener);
//To avoid races, call CCBs on all factories for this.
for(auto j : state.supervars)
listener.create(*this, j.first, *j.second);
}
void set::drop_callback(set_listener& listener)
{
threads::arlock u(get_setting_lock());
auto state = set_internal_t::get_soft(this);
if(!state) return;
if(state->callbacks.count(&listener)) {
//To avoid races, call DCBs on all factories for this.
for(auto j : state->supervars)
listener.destroy(*this, j.first);
state->callbacks.erase(&listener);
}
}
base::base(group& _group, const std::string& _iname, const std::string& _hname, bool dynamic)
throw(std::bad_alloc)
: sgroup(&_group), iname(_iname), hname(_hname), is_dynamic(dynamic)
{
regqueue_t::do_register(*sgroup, iname, *this);
}
base::~base() throw()
{
regqueue_t::do_unregister(sgroup, iname);
threads::arlock u(get_setting_lock());
if(sgroup)
regqueue_t::do_unregister(*sgroup, iname);
}
void base::group_died()
{
threads::arlock u(get_setting_lock());
sgroup = NULL;
if(is_dynamic) delete this;
}
void superbase::_superbase(set& _s, const std::string& _iname) throw(std::bad_alloc)
{
s = &_s;
iname = _iname;
s->do_register(iname, *this);
}
superbase::~superbase() throw()
{
threads::arlock u(get_setting_lock());
if(s)
s->do_unregister(iname, *this);
}
void superbase::set_died()
{
s = NULL;
}
cache::cache(group& _grp)
@ -116,13 +293,13 @@ void cache::set(const std::string& name, const std::string& value, bool allow_in
{
try {
grp[name].str(value);
threads::alock h(lock);
threads::arlock u(get_setting_lock());
badcache.erase(name);
} catch(std::bad_alloc& e) {
throw;
} catch(std::exception& e) {
if(allow_invalid) {
threads::alock h(lock);
threads::arlock u(get_setting_lock());
badcache[name] = value;
} else
throw;

View file

@ -175,7 +175,7 @@ namespace
threads::thread* emulation_thread;
bool status_updated = false;
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> background_audio(lsnes_vset,
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> background_audio(lsnes_instance.settings,
"background-audio", "GUI‣Enable background audio", true);
class _status_timer : public wxTimer
@ -1412,7 +1412,8 @@ namespace
p.types.push_back(filedialog_type_entry("Savestates [all branches]", "*." + ext +
";*." + ext + ".backup", ext));
}
p.default_type = save ? (state ? save_dflt_binary : movie_dflt_binary) : 0;
p.default_type = save ? (state ? save_dflt_binary(lsnes_instance.settings) :
movie_dflt_binary(lsnes_instance.settings)) : 0;
return p;
}
std::pair<std::string, std::string> output(const filedialog_output_params& p, bool save) const

View file

@ -52,7 +52,7 @@ namespace
};
wxeditor_esettings_advanced::wxeditor_esettings_advanced(wxWindow* parent)
: settings_tab(parent), _listener(lsnes_vset, *this)
: settings_tab(parent), _listener(lsnes_instance.settings, *this)
{
wxSizer* top_s = new wxBoxSizer(wxVERTICAL);
SetSizer(top_s);

View file

@ -9,6 +9,7 @@
#include "library/minmax.hpp"
#include "library/workthread.hpp"
#include "core/misc.hpp"
#include "core/instance.hpp"
#include "core/settings.hpp"
#include "core/moviedata.hpp"
#include "core/moviefile.hpp"
@ -82,30 +83,31 @@ namespace
return 48000;
}
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> dump_large(lsnes_vset, "avi-large",
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> dump_large(lsnes_setgrp, "avi-large",
"AVI‣Large dump", false);
settingvar::variable<settingvar::model_int<0, 32>> fixed_xfact(lsnes_vset, "avi-xfactor",
settingvar::supervariable<settingvar::model_int<0, 32>> fixed_xfact(lsnes_setgrp, "avi-xfactor",
"AVI‣Fixed X factor", 0);
settingvar::variable<settingvar::model_int<0, 32>> fixed_yfact(lsnes_vset, "avi-yfactor",
settingvar::supervariable<settingvar::model_int<0, 32>> fixed_yfact(lsnes_setgrp, "avi-yfactor",
"AVI‣Fixed Y factor", 0);
settingvar::variable<settingvar::model_int<0, 8191>> dtb(lsnes_vset, "avi-top-border", "AVI‣Top padding", 0);
settingvar::variable<settingvar::model_int<0, 8191>> dbb(lsnes_vset, "avi-bottom-border",
settingvar::supervariable<settingvar::model_int<0, 8191>> dtb(lsnes_setgrp, "avi-top-border",
"AVI‣Top padding", 0);
settingvar::supervariable<settingvar::model_int<0, 8191>> dbb(lsnes_setgrp, "avi-bottom-border",
"AVI‣Bottom padding", 0);
settingvar::variable<settingvar::model_int<0, 8191>> dlb(lsnes_vset, "avi-left-border",
settingvar::supervariable<settingvar::model_int<0, 8191>> dlb(lsnes_setgrp, "avi-left-border",
"AVI‣Left padding", 0);
settingvar::variable<settingvar::model_int<0, 8191>> drb(lsnes_vset, "avi-right-border", "AVI‣Right padding",
0);
settingvar::variable<settingvar::model_int<0, 999999999>> max_frames_per_segment(lsnes_vset, "avi-maxframes",
"AVI‣Max frames per segment", 0);
settingvar::supervariable<settingvar::model_int<0, 8191>> drb(lsnes_setgrp, "avi-right-border",
"AVI‣Right padding", 0);
settingvar::supervariable<settingvar::model_int<0, 999999999>> max_frames_per_segment(lsnes_setgrp,
"avi-maxframes", "AVI‣Max frames per segment", 0);
#ifdef WITH_SECRET_RABBIT_CODE
settingvar::enumeration soundrates {"nearest-common", "round-down", "round-up", "multiply",
"High quality 44.1kHz", "High quality 48kHz"};
settingvar::variable<settingvar::model_enumerated<&soundrates>> soundrate_setting(lsnes_vset, "avi-soundrate",
"AVI‣Sound mode", 5);
settingvar::supervariable<settingvar::model_enumerated<&soundrates>> soundrate_setting(lsnes_setgrp,
"avi-soundrate", "AVI‣Sound mode", 5);
#else
settingvar::enumeration soundrates {"nearest-common", "round-down", "round-up", "multiply"};
settingvar::variable<settingvar::model_enumerated<&soundrates>> soundrate_setting(lsnes_vset, "avi-soundrate",
"AVI‣Sound mode", 2);
settingvar::supervariable<settingvar::model_enumerated<&soundrates>> soundrate_setting(lsnes_setgrp,
"avi-soundrate", "AVI‣Sound mode", 2);
#endif
std::pair<avi_video_codec_type*, avi_audio_codec_type*> find_codecs(const std::string& mode)
@ -332,17 +334,18 @@ again:
: information_dispatch("dump-avi-int")
{
enable_send_sound();
unsigned srate_setting = soundrate_setting(CORE().settings);
chans = info.audio_chans = 2;
soundrate = get_sound_rate();
audio_record_rate = info.sample_rate = get_rate(soundrate.first, soundrate.second,
soundrate_setting);
srate_setting);
worker = new avi_worker(info);
soxdumper = new sox_dumper(info.prefix + ".sox", static_cast<double>(soundrate.first) /
soundrate.second, 2);
dcounter = 0;
have_dumped_frame = false;
resampler_w = NULL;
if(soundrate_setting == 4 || soundrate_setting == 5) {
if(srate_setting == 4 || srate_setting == 5) {
double ratio = 1.0 * audio_record_rate * soundrate.second / soundrate.first;
sbuffer_fill = 0;
sbuffer.resize(RESAMPLE_BUFFER * chans);
@ -361,14 +364,17 @@ again:
void on_frame(struct framebuffer::raw& _frame, uint32_t fps_n, uint32_t fps_d)
{
uint32_t hscl = 1, vscl = 1;
if(fixed_xfact != 0 && fixed_yfact != 0) {
hscl = fixed_xfact;
vscl = fixed_yfact;
} else if(dump_large) {
unsigned fxfact = fixed_xfact(CORE().settings);
unsigned fyfact = fixed_yfact(CORE().settings);
if(fxfact != 0 && fyfact != 0) {
hscl = fxfact;
vscl = fyfact;
} else if(dump_large(CORE().settings)) {
rpair(hscl, vscl) = our_rom.rtype->get_scale_factors(_frame.get_width(),
_frame.get_height());
}
if(!render_video_hud(dscr, _frame, hscl, vscl, dlb, dtb, drb, dbb, waitfn)) {
if(!render_video_hud(dscr, _frame, hscl, vscl, dlb(CORE().settings), dtb(CORE().settings),
drb(CORE().settings), dbb(CORE().settings), waitfn)) {
akill += killed_audio_length(fps_n, fps_d, akillfrac);
return;
}
@ -504,7 +510,7 @@ again:
struct avi_info info;
info.audio_chans = 2;
info.sample_rate = 32000;
info.max_frames = max_frames_per_segment;
info.max_frames = max_frames_per_segment(CORE().settings);
info.prefix = prefix;
rpair(vcodec, acodec) = find_codecs(mode);
info.vcodec = vcodec->get_instance();

View file

@ -1,4 +1,5 @@
#include "video/avi/codec.hpp"
#include "core/instance.hpp"
#include "core/settings.hpp"
#include "library/zlibstream.hpp"
#include <limits>
@ -10,9 +11,9 @@
namespace
{
settingvar::variable<settingvar::model_int<0,9>> clvl(lsnes_vset, "avi-cscd-compression",
settingvar::supervariable<settingvar::model_int<0,9>> clvl(lsnes_setgrp, "avi-cscd-compression",
"AVI‣CSCD‣Compression", 7);
settingvar::variable<settingvar::model_int<0,999999999>> kint(lsnes_vset, "avi-cscd-keyint",
settingvar::supervariable<settingvar::model_int<0,999999999>> kint(lsnes_setgrp, "avi-cscd-keyint",
"AVI‣CSCD‣Keyframe interval", 0);
struct avi_codec_cscd : public avi_video_codec
@ -135,5 +136,7 @@ namespace
}
avi_video_codec_type rgb("cscd", "Camstudio video codec",
[]() -> avi_video_codec* { return new avi_codec_cscd(clvl, kint);});
[]() -> avi_video_codec* {
return new avi_codec_cscd(clvl(CORE().settings), kint(CORE().settings));
});
}

View file

@ -1,6 +1,7 @@
#include "video/avi/codec.hpp"
#include "library/minmax.hpp"
#include "library/zlibstream.hpp"
#include "core/instance.hpp"
#include "core/settings.hpp"
#include <limits>
#include <cassert>
@ -14,9 +15,9 @@ const void* check;
namespace
{
settingvar::variable<settingvar::model_int<0,9>> clvl(lsnes_vset, "avi-tscc-compression",
settingvar::supervariable<settingvar::model_int<0,9>> clvl(lsnes_setgrp, "avi-tscc-compression",
"AVI‣TSCC‣Compression", 7);
settingvar::variable<settingvar::model_int<0,999999999>> kint(lsnes_vset, "avi-tscc-keyint",
settingvar::supervariable<settingvar::model_int<0,999999999>> kint(lsnes_setgrp, "avi-tscc-keyint",
"AVI‣TSCC‣Keyframe interval", 299);
struct msrle_compressor
@ -176,7 +177,7 @@ namespace
struct avi_codec_tscc : public avi_video_codec
{
avi_codec_tscc(unsigned level);
avi_codec_tscc(unsigned level, unsigned _keyint);
~avi_codec_tscc();
avi_video_codec::format reset(uint32_t width, uint32_t height, uint32_t fps_n, uint32_t fps_d);
void frame(uint32_t* data, uint32_t stride);
@ -206,9 +207,10 @@ namespace
return _level;
}
avi_codec_tscc::avi_codec_tscc(unsigned compression)
avi_codec_tscc::avi_codec_tscc(unsigned compression, unsigned _keyint)
: z(getzlevel(compression))
{
max_pframes = _keyint;
frameno = 0;
}
@ -307,5 +309,7 @@ namespace
}
avi_video_codec_type rgb("tscc", "TSCC video codec",
[]() -> avi_video_codec* { return new avi_codec_tscc(clvl);});
[]() -> avi_video_codec* {
return new avi_codec_tscc(clvl(CORE().settings), kint(CORE().settings));
});
}

View file

@ -1,4 +1,5 @@
#include "video/avi/codec.hpp"
#include "core/instance.hpp"
#include "core/settings.hpp"
#include "library/zlibstream.hpp"
#include <zlib.h>
@ -12,15 +13,15 @@
namespace
{
settingvar::variable<settingvar::model_int<0,9>> clvl(lsnes_vset, "avi-zmbv-compression",
settingvar::supervariable<settingvar::model_int<0,9>> clvl(lsnes_setgrp, "avi-zmbv-compression",
"AVI‣ZMBV‣Compression", 7);
settingvar::variable<settingvar::model_int<0,999999999>> kint(lsnes_vset, "avi-zmbv-keyint",
settingvar::supervariable<settingvar::model_int<0,999999999>> kint(lsnes_setgrp, "avi-zmbv-keyint",
"AVI‣ZMBV‣Keyframe interval", 299);
settingvar::variable<settingvar::model_int<8,64>> bwv(lsnes_vset, "avi-zmbv-blockw", "AVI‣ZMBV‣Block width",
16);
settingvar::variable<settingvar::model_int<8,64>> bhv(lsnes_vset, "avi-zmbv-blockh", "AVI‣ZMBV‣Block height",
16);
settingvar::variable<settingvar::model_bool<settingvar::yes_no>> fullsearch(lsnes_vset,
settingvar::supervariable<settingvar::model_int<8,64>> bwv(lsnes_setgrp, "avi-zmbv-blockw",
"AVI‣ZMBV‣Block width", 16);
settingvar::supervariable<settingvar::model_int<8,64>> bhv(lsnes_setgrp, "avi-zmbv-blockh",
"AVI‣ZMBV‣Block height", 16);
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> fsrch(lsnes_setgrp,
"avi-zmbv-fullsearch", "AVI‣ZMBV‣Full search (slow)", false);
//Motion vector.
@ -37,7 +38,7 @@ namespace
//The main ZMBV decoder state.
struct avi_codec_zmbv : public avi_video_codec
{
avi_codec_zmbv(uint32_t _level, uint32_t maxpframes, uint32_t _bw, uint32_t _bh);
avi_codec_zmbv(uint32_t _level, uint32_t maxpframes, uint32_t _bw, uint32_t _bh, bool _fullsearch);
~avi_codec_zmbv();
avi_video_codec::format reset(uint32_t width, uint32_t height, uint32_t fps_n, uint32_t fps_d);
void frame(uint32_t* data, uint32_t stride);
@ -61,6 +62,8 @@ namespace
//Size of one block.
uint32_t bw;
uint32_t bh;
//Full search flag.
bool fullsearch;
//Motion vector buffer, one motion vector for each block, in left-to-right, top-to-bottom order.
std::vector<motion> mv;
//Pixel buffer (2 full frames and one block).
@ -241,12 +244,14 @@ compress:
return _level;
}
avi_codec_zmbv::avi_codec_zmbv(uint32_t _level, uint32_t maxpframes, uint32_t _bw, uint32_t _bh)
avi_codec_zmbv::avi_codec_zmbv(uint32_t _level, uint32_t maxpframes, uint32_t _bw, uint32_t _bh,
bool _fullsearch)
: z(getzlevel(_level))
{
bh = _bh;
bw = _bw;
max_pframes = maxpframes;
fullsearch = _fullsearch;
}
avi_video_codec::format avi_codec_zmbv::reset(uint32_t width, uint32_t height, uint32_t fps_n, uint32_t fps_d)
@ -345,5 +350,8 @@ compress:
//ZMBV encoder factory object.
avi_video_codec_type rgb("zmbv", "Zip Motion Blocks Video codec",
[]() -> avi_video_codec* { return new avi_codec_zmbv(clvl, kint, bwv, bhv);});
[]() -> avi_video_codec* {
return new avi_codec_zmbv(clvl(CORE().settings), kint(CORE().settings), bwv(CORE().settings),
bhv(CORE().settings), fsrch(CORE().settings));
});
}

View file

@ -1,5 +1,6 @@
#include "core/advdumper.hpp"
#include "core/dispatch.hpp"
#include "core/instance.hpp"
#include "core/settings.hpp"
#include "core/window.hpp"
#include "library/serialization.hpp"
@ -19,7 +20,8 @@
namespace
{
settingvar::variable<settingvar::model_int<0,9>> clevel(lsnes_vset, "jmd-compression", "JMD‣Compression", 7);
settingvar::supervariable<settingvar::model_int<0,9>> clevel(lsnes_setgrp, "jmd-compression",
"JMD‣Compression", 7);
uint64_t akill = 0;
double akillfrac = 0;
@ -35,7 +37,7 @@ namespace
: information_dispatch("dump-jmd")
{
enable_send_sound();
complevel = clevel;
complevel = clevel(CORE().settings);
if(tcp_flag) {
jmd = &(socket_address(filename).connect());
deleter = socket_address::deleter();
@ -424,7 +426,7 @@ namespace
x << "Error starting JMD dump: " << e.what();
throw std::runtime_error(x.str());
}
messages << "Dumping to " << prefix << " at level " << clevel << std::endl;
messages << "Dumping to " << prefix << " at level " << clevel(CORE().settings) << std::endl;
information_dispatch::do_dumper_update();
akill = 0;
akillfrac = 0;