lsnes rr0-β20
This commit is contained in:
parent
44d8822af2
commit
ff4d045882
5 changed files with 941 additions and 2 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,4 +5,4 @@
|
|||
*.exe
|
||||
docs
|
||||
rom
|
||||
core
|
||||
/core
|
||||
|
|
409
include/core/dispatch.hpp
Normal file
409
include/core/dispatch.hpp
Normal file
|
@ -0,0 +1,409 @@
|
|||
#ifndef _dispatch__hpp__included__
|
||||
#define _dispatch__hpp__included__
|
||||
|
||||
#include "render.hpp"
|
||||
#include "keymapper.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* Video data region is NTSC.
|
||||
*/
|
||||
#define VIDEO_REGION_NTSC 0
|
||||
/**
|
||||
* Video data region is PAL.
|
||||
*/
|
||||
#define VIDEO_REGION_PAL 1
|
||||
|
||||
/**
|
||||
* Information about run.
|
||||
*/
|
||||
struct gameinfo_struct
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct game info.
|
||||
*/
|
||||
gameinfo_struct() throw(std::bad_alloc);
|
||||
/**
|
||||
* Game name.
|
||||
*/
|
||||
std::string gamename;
|
||||
/**
|
||||
* Run length in seconds.
|
||||
*/
|
||||
double length;
|
||||
/**
|
||||
* Rerecord count (base 10 ASCII)
|
||||
*/
|
||||
std::string rerecords;
|
||||
/**
|
||||
* Authors. The first components are real names, the second components are nicknames. Either (but not both) may be
|
||||
* blank.
|
||||
*/
|
||||
std::vector<std::pair<std::string, std::string>> authors;
|
||||
/**
|
||||
* Format human-redable representation of the length.
|
||||
*
|
||||
* Parameter digits: Number of sub-second digits to use.
|
||||
* Returns: The time formated.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
std::string get_readable_time(unsigned digits) const throw(std::bad_alloc);
|
||||
/**
|
||||
* Get number of authors.
|
||||
*
|
||||
* Returns: Number of authors.
|
||||
*/
|
||||
size_t get_author_count() const throw();
|
||||
/**
|
||||
* Get short name of author (nickname if present, otherwise full name).
|
||||
*
|
||||
* Parameter idx: Index of author (0-based).
|
||||
* Returns: The short name.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
std::string get_author_short(size_t idx) const throw(std::bad_alloc);
|
||||
/**
|
||||
* Get rerecord count as a number. If rerecord count is too high, returns the maximum representatible count.
|
||||
*
|
||||
* Returns: The rerecord count.
|
||||
*/
|
||||
uint64_t get_rerecords() const throw();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Information dispatch.
|
||||
*
|
||||
* This class handles dispatching information between the components of the emulator.
|
||||
*
|
||||
* Each kind of information has virtual method on_foo() which can be overridden to handle events of that type, and
|
||||
* static method do_foo(), which calls on_foo on all known objects.
|
||||
*
|
||||
* The information is delivered to each instance of this class.
|
||||
*/
|
||||
class information_dispatch
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create new object to receive information dispatch events.
|
||||
*
|
||||
* Parameter name: The name for the object.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
information_dispatch(const std::string& name) throw(std::bad_alloc);
|
||||
/**
|
||||
* Destroy object.
|
||||
*/
|
||||
~information_dispatch() throw();
|
||||
/**
|
||||
* Window close event received (this is not emulator close!)
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*/
|
||||
virtual void on_close();
|
||||
/**
|
||||
* Call all on_close() handlers.
|
||||
*/
|
||||
static void do_close() throw();
|
||||
/**
|
||||
* Click or release on window was receivied.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter x: The x-coordinate of the click. May be negative or otherwise out of screen.
|
||||
* Parameter y: The y-coordinate of the click. May be negative or otherwise out of screen.
|
||||
* Parameter buttonmask: Bitfield giving current buttons held:
|
||||
* Bit 0 => Left button is down/held.
|
||||
* Bit 1 => Middle button is down/held.
|
||||
* Bit 2 => Middle button is down/held.
|
||||
*/
|
||||
virtual void on_click(int32_t x, int32_t y, uint32_t buttonmask);
|
||||
/**
|
||||
* Call all on_click() handlers.
|
||||
*/
|
||||
static void do_click(int32_t x, int32_t y, uint32_t buttonmask) throw();
|
||||
/**
|
||||
* Sound mute/unmute status might have been changed.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter unmuted: If true, the sound is now enabled. If false, the sound is now disabled.
|
||||
*/
|
||||
virtual void on_sound_unmute(bool unmuted);
|
||||
/**
|
||||
* Call all on_sound_unmute() handlers.
|
||||
*/
|
||||
static void do_sound_unmute(bool unmuted) throw();
|
||||
/**
|
||||
* Sound device might have been changed.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter dev: The device name sound is now playing (if enabled) from.
|
||||
*/
|
||||
virtual void on_sound_change(const std::string& dev);
|
||||
/**
|
||||
* Call all on_sound_change() handlers.
|
||||
*/
|
||||
static void do_sound_change(const std::string& dev) throw();
|
||||
/**
|
||||
* Emulator mode might have been changed.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter readonly: True if readonly mode is now active, false if now in readwrite mode.
|
||||
*/
|
||||
virtual void on_mode_change(bool readonly);
|
||||
/**
|
||||
* Call all on_mode_change() handlers.
|
||||
*/
|
||||
static void do_mode_change(bool readonly) throw();
|
||||
/**
|
||||
* Autohold on button might have been changed.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter pid: The physical ID of controller (0-7).
|
||||
* Parameter ctrlnum: Physical control number (0-15).
|
||||
* Parameter newstate: True if autohold is now active, false if autohold is now inactive.
|
||||
*/
|
||||
virtual void on_autohold_update(unsigned pid, unsigned ctrlnum, bool newstate);
|
||||
/**
|
||||
* Call all on_autohold_update() handlers.
|
||||
*/
|
||||
static void do_autohold_update(unsigned pid, unsigned ctrlnum, bool newstate) throw();
|
||||
/**
|
||||
* Controller configuration may have been changed.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*/
|
||||
virtual void on_autohold_reconfigure();
|
||||
/**
|
||||
* Call all on_autohold_reconfigure() handlers.
|
||||
*/
|
||||
static void do_autohold_reconfigure() throw();
|
||||
/**
|
||||
* A setting may have changed.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter setting: The setting that has possibly changed.
|
||||
* Parameter value: The new value for the setting.
|
||||
*/
|
||||
virtual void on_setting_change(const std::string& setting, const std::string& value);
|
||||
/**
|
||||
* Call all on_setting_change() handlers.
|
||||
*/
|
||||
static void do_setting_change(const std::string& setting, const std::string& value) throw();
|
||||
/**
|
||||
* A setting has been cleared (but it might have been cleared already).
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter setting: The setting that is now clear.
|
||||
*/
|
||||
virtual void on_setting_clear(const std::string& setting);
|
||||
/**
|
||||
* Call all on_setting_clear() handlers
|
||||
*/
|
||||
static void do_setting_clear(const std::string& setting) throw();
|
||||
/**
|
||||
* A raw frame has been received.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter raw: The raw frame data. 512*512 element array.
|
||||
* Parameter hires: True if in hires mode (512 wide), false if not (256-wide).
|
||||
* Parameter interlaced: True if in interlaced mode (448/478 high), false if not (224/239 high).
|
||||
* Parameter overscan: True if overscan is active, false if not.
|
||||
* Parameter region: One of VIDEO_REGION_* contstants, giving the region this frame is from.
|
||||
*/
|
||||
virtual void on_raw_frame(const uint32_t* raw, bool hires, bool interlaced, bool overscan, unsigned region);
|
||||
/**
|
||||
* Call all on_raw_frame() handlers.
|
||||
*
|
||||
* Calls on_new_dumper() on dumpers that had that not yet called.
|
||||
*/
|
||||
static void do_raw_frame(const uint32_t* raw, bool hires, bool interlaced, bool overscan, unsigned region)
|
||||
throw();
|
||||
/**
|
||||
* A frame has been received.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter _frame: The frame object.
|
||||
* Parameter fps_n: Numerator of current video fps.
|
||||
* Parameter fps_d: Denominator of current video fps.
|
||||
*/
|
||||
virtual void on_frame(struct lcscreen& _frame, uint32_t fps_n, uint32_t fps_d);
|
||||
/**
|
||||
* Call all on_frame() handlers.
|
||||
*
|
||||
* Calls on_new_dumper() on dumpers that had that not yet called.
|
||||
*/
|
||||
static void do_frame(struct lcscreen& _frame, uint32_t fps_n, uint32_t fps_d) throw();
|
||||
/**
|
||||
* A sample has been received.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter l: The left channel sample (16 bit signed).
|
||||
* Parameter r: The right channel sample (16 bit signed).
|
||||
*/
|
||||
virtual void on_sample(short l, short r);
|
||||
/**
|
||||
* Call all on_sample() handlers.
|
||||
*
|
||||
* Calls on_new_dumper() on dumpers that had that not yet called.
|
||||
*/
|
||||
static void do_sample(short l, short r) throw();
|
||||
/**
|
||||
* Dump is ending.
|
||||
*
|
||||
* Calls on_new_dumper() on dumpers that had that not yet called.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*/
|
||||
virtual void on_dump_end();
|
||||
/**
|
||||
* Call all on_dump_end() handlers.
|
||||
*/
|
||||
static void do_dump_end() throw();
|
||||
/**
|
||||
* Sound sampling rate is changing
|
||||
*
|
||||
* The default handler prints warning if dumper flag is set.
|
||||
*
|
||||
* Parameter rate_n: Numerator of the new sampling rate in Hz.
|
||||
* Parameter rate_d: Denominator of the new sampling rate in Hz.
|
||||
*/
|
||||
virtual void on_sound_rate(uint32_t rate_n, uint32_t rate_d);
|
||||
/**
|
||||
* Call all on_sound_rate() methods and save the parameters.
|
||||
*
|
||||
* Calls on_new_dumper() on dumpers that had that not yet called.
|
||||
*/
|
||||
static void do_sound_rate(uint32_t rate_n, uint32_t rate_d) throw();
|
||||
/**
|
||||
* Get the sound rate most recently set by on_sound_rate().
|
||||
*
|
||||
* Returns: The first component is the numerator, the second is the denominator.
|
||||
*/
|
||||
static std::pair<uint32_t, uint32_t> get_sound_rate() throw();
|
||||
/**
|
||||
* Game information is changing.
|
||||
*
|
||||
* The default handler does nothing.
|
||||
*
|
||||
* Parameter gi: The new game info.
|
||||
*/
|
||||
virtual void on_gameinfo(const struct gameinfo_struct& gi);
|
||||
/**
|
||||
* Call all on_gameinfo() handlers and save the gameinfo.
|
||||
*/
|
||||
static void do_gameinfo(const struct gameinfo_struct& gi) throw();
|
||||
/**
|
||||
* Get the gameinfo most recently set by do_gameinfo().
|
||||
*
|
||||
* Returns: The gameinfo.
|
||||
*/
|
||||
static const struct gameinfo_struct& get_gameinfo() throw();
|
||||
/**
|
||||
* Return the dumper flag for this dispatch target.
|
||||
*
|
||||
* The default implementation returns false.
|
||||
*
|
||||
* If dumper flag is set:
|
||||
* - on_sound_rate() default handler prints a warning.
|
||||
* - All dumping related do_* functions triggers calls to to on_new_dumper() on all handlers the next time they
|
||||
* are called.
|
||||
* - Destroying the handler triggers calls to on_destroy_dumper() on all handlers (if on_new_dumper() has been
|
||||
* called).
|
||||
*/
|
||||
virtual bool get_dumper_flag() throw();
|
||||
/**
|
||||
* Notify that a new dumper is joining.
|
||||
*
|
||||
* Parameter dumper: The name of the dumper object.
|
||||
*/
|
||||
virtual void on_new_dumper(const std::string& dumper);
|
||||
/**
|
||||
* Notify that a dumper is leaving.
|
||||
*
|
||||
* Parameter dumper: The name of the dumper object.
|
||||
*/
|
||||
virtual void on_destroy_dumper(const std::string& dumper);
|
||||
/**
|
||||
* Get number of active dumpers.
|
||||
*
|
||||
* Calls on_new_dumper() on dumpers that had that not yet called.
|
||||
*
|
||||
* Returns: The dumper count.
|
||||
*/
|
||||
static unsigned get_dumper_count() throw();
|
||||
/**
|
||||
* Get set of active dumpers.
|
||||
*
|
||||
* Calls on_new_dumper() on dumpers that had that not yet called.
|
||||
*
|
||||
* Returns: The set of dumper names.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
static std::set<std::string> get_dumpers() throw(std::bad_alloc);
|
||||
/**
|
||||
* (Pseudo-)key has been pressed or released.
|
||||
*
|
||||
* Parameter modifiers: The modifier set currently active.
|
||||
* Parameter keygroup: The key group the (pseudo-)key is from.
|
||||
* Parameter subkey: Subkey index within the key group.
|
||||
* Parameter polarity: True if key is being pressed, false if being released.
|
||||
* Parameter name: Name of the key being pressed/released.
|
||||
*/
|
||||
virtual void on_key_event(const modifier_set& modifiers, keygroup& keygroup, unsigned subkey,
|
||||
bool polarity, const std::string& name);
|
||||
/**
|
||||
* Call on_key_event() for all event handlers (or just one if keys are being grabbed).
|
||||
*/
|
||||
static void do_key_event(const modifier_set& modifiers, keygroup& keygroup, unsigned subkey,
|
||||
bool polarity, const std::string& name) throw();
|
||||
/**
|
||||
* Grab all key events.
|
||||
*
|
||||
* While key events are grabbed, do_key_event() only calls on_key_event() for the grabbing object.
|
||||
*/
|
||||
void grab_keys() throw();
|
||||
/**
|
||||
* Ungrab all key events.
|
||||
*
|
||||
* While key events are grabbed, do_key_event() only calls on_key_event() for the grabbing object.
|
||||
*/
|
||||
void ungrab_keys() throw();
|
||||
/**
|
||||
* Get name of target.
|
||||
*/
|
||||
const std::string& get_name() throw();
|
||||
/**
|
||||
* Set window main screen compensation parameters. This is used for mouse click reporting.
|
||||
*
|
||||
* parameter xoffset: X coordinate of origin.
|
||||
* parameter yoffset: Y coordinate of origin.
|
||||
* parameter hscl: Horizontal scaling factor.
|
||||
* parameter vscl: Vertical scaling factor.
|
||||
*/
|
||||
static void do_click_compensation(uint32_t xoffset, uint32_t yoffset, uint32_t hscl, uint32_t vscl);
|
||||
private:
|
||||
static void update_dumpers(bool nocalls = false) throw();
|
||||
bool known_if_dumper;
|
||||
bool marked_as_dumper;
|
||||
std::string target_name;
|
||||
bool notified_as_dumper;
|
||||
bool grabbing_keys;
|
||||
};
|
||||
|
||||
#endif
|
36
manual.lyx
36
manual.lyx
|
@ -4499,5 +4499,41 @@ Finish pending saves before load/quit.
|
|||
Wxwidgets graphics plugin.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
rr0-beta20
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Get rid of win32-crap.[ch]pp.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Move files around a lot.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Get rid of need for host C++ compiler.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Bsnes v084 core.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Refactor inter-component communication.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Fix zero luma.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Fix crash on multiline aliases.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Load/Save settings in wxwidgets gui.
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
||||
|
|
494
src/core/dispatch.cpp
Normal file
494
src/core/dispatch.cpp
Normal file
|
@ -0,0 +1,494 @@
|
|||
#include "core/dispatch.hpp"
|
||||
#include "core/globalwrap.hpp"
|
||||
#include "core/misc.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
|
||||
#define START_EH_BLOCK try {
|
||||
#define END_EH_BLOCK(obj, call) } catch(std::bad_alloc& e) { \
|
||||
OOM_panic(); \
|
||||
} catch(std::exception& e) { \
|
||||
messages << messages << "[dumper " << obj->get_name() << "] Warning: " call ": " << e.what() \
|
||||
<< std::endl; \
|
||||
} catch(int code) { \
|
||||
messages << messages << "[dumper " << obj->get_name() << "] Warning: " call ": Error code #" << code \
|
||||
<< std::endl; \
|
||||
}
|
||||
|
||||
gameinfo_struct::gameinfo_struct() throw(std::bad_alloc)
|
||||
{
|
||||
length = 0;
|
||||
rerecords = "0";
|
||||
}
|
||||
|
||||
std::string gameinfo_struct::get_readable_time(unsigned digits) const throw(std::bad_alloc)
|
||||
{
|
||||
double bias = 0.5 * pow(10, -static_cast<int>(digits));
|
||||
double len = length + bias;
|
||||
std::ostringstream str;
|
||||
if(length >= 3600) {
|
||||
double hours = floor(len / 3600);
|
||||
str << hours << ":";
|
||||
len -= hours * 3600;
|
||||
}
|
||||
double minutes = floor(len / 60);
|
||||
len -= minutes * 60;
|
||||
double seconds = floor(len);
|
||||
len -= seconds;
|
||||
str << std::setw(2) << std::setfill('0') << minutes << ":" << seconds;
|
||||
if(digits > 0)
|
||||
str << ".";
|
||||
while(digits > 0) {
|
||||
len = 10 * len;
|
||||
str << '0' + static_cast<int>(len);
|
||||
len -= floor(len);
|
||||
digits--;
|
||||
}
|
||||
}
|
||||
|
||||
size_t gameinfo_struct::get_author_count() const throw()
|
||||
{
|
||||
return authors.size();
|
||||
}
|
||||
|
||||
std::string gameinfo_struct::get_author_short(size_t idx) const throw(std::bad_alloc)
|
||||
{
|
||||
if(idx >= authors.size())
|
||||
return "";
|
||||
const std::pair<std::string, std::string>& x = authors[idx];
|
||||
if(x.second != "")
|
||||
return x.second;
|
||||
else
|
||||
return x.first;
|
||||
}
|
||||
|
||||
uint64_t gameinfo_struct::get_rerecords() const throw()
|
||||
{
|
||||
uint64_t v = 0;
|
||||
uint64_t max = 0xFFFFFFFFFFFFFFFFULL;
|
||||
for(size_t i = 0; i < rerecords.length(); i++) {
|
||||
if(v < max / 10)
|
||||
//No risk of overflow.
|
||||
v = v * 10 + static_cast<unsigned>(rerecords[i] - '0');
|
||||
else if(v == max / 10) {
|
||||
//THis may overflow.
|
||||
v = v * 10;
|
||||
if(v + static_cast<unsigned>(rerecords[i] - '0') < v)
|
||||
return max;
|
||||
v = v + static_cast<unsigned>(rerecords[i] - '0');
|
||||
} else
|
||||
//Definite overflow.
|
||||
return max;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
globalwrap<std::list<information_dispatch*>> dispatch;
|
||||
uint32_t srate_n = 32000;
|
||||
uint32_t srate_d = 1;
|
||||
struct gameinfo_struct sgi;
|
||||
information_dispatch* exclusive_key = NULL;
|
||||
int32_t vc_xoffset = 0;
|
||||
int32_t vc_yoffset = 0;
|
||||
uint32_t vc_hscl = 1;
|
||||
uint32_t vc_vscl = 1;
|
||||
bool recursive = false;
|
||||
}
|
||||
|
||||
information_dispatch::information_dispatch(const std::string& name) throw(std::bad_alloc)
|
||||
{
|
||||
target_name = name;
|
||||
dispatch().push_back(this);
|
||||
known_if_dumper = false;
|
||||
marked_as_dumper = false;
|
||||
notified_as_dumper = false;
|
||||
grabbing_keys = false;
|
||||
}
|
||||
|
||||
information_dispatch::~information_dispatch() throw()
|
||||
{
|
||||
for(auto i = dispatch().begin(); i != dispatch().end(); ++i) {
|
||||
if(*i == this) {
|
||||
dispatch().erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notified_as_dumper)
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_destroy_dumper(target_name);
|
||||
END_EH_BLOCK(i, "on_destroy_dumper");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_close()
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_close() throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_close();
|
||||
END_EH_BLOCK(i, "on_close");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_click(int32_t x, int32_t y, uint32_t buttonmask)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_click(int32_t x, int32_t y, uint32_t buttonmask) throw()
|
||||
{
|
||||
x = (x - vc_xoffset) / vc_hscl;
|
||||
y = (y - vc_yoffset) / vc_vscl;
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_click(x, y, buttonmask);
|
||||
END_EH_BLOCK(i, "on_click");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_sound_unmute(bool unmuted)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_sound_unmute(bool unmuted) throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_sound_unmute(unmuted);
|
||||
END_EH_BLOCK(i, "on_sound_unmute");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_sound_change(const std::string& dev)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_sound_change(const std::string& dev) throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_sound_change(dev);
|
||||
END_EH_BLOCK(i, "on_sound_change");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_mode_change(bool readonly)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_mode_change(bool readonly) throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_mode_change(readonly);
|
||||
END_EH_BLOCK(i, "on_mode_change");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_autohold_update(unsigned pid, unsigned ctrlnum, bool newstate)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_autohold_update(unsigned pid, unsigned ctrlnum, bool newstate) throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_autohold_update(pid, ctrlnum, newstate);
|
||||
END_EH_BLOCK(i, "on_autohold_update");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_autohold_reconfigure()
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_autohold_reconfigure() throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_autohold_reconfigure();
|
||||
END_EH_BLOCK(i, "on_autohold_reconfigure");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_setting_change(const std::string& setting, const std::string& value)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_setting_change(const std::string& setting, const std::string& value) throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_setting_change(setting, value);
|
||||
END_EH_BLOCK(i, "on_setting_change");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_setting_clear(const std::string& setting)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_setting_clear(const std::string& setting) throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_setting_clear(setting);
|
||||
END_EH_BLOCK(i, "on_setting_clear");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void information_dispatch::on_raw_frame(const uint32_t* raw, bool hires, bool interlaced, bool overscan,
|
||||
unsigned region)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_raw_frame(const uint32_t* raw, bool hires, bool interlaced, bool overscan,
|
||||
unsigned region) throw()
|
||||
{
|
||||
update_dumpers();
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_raw_frame(raw, hires, interlaced, overscan, region);
|
||||
END_EH_BLOCK(i, "on_raw_frame");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_frame(struct lcscreen& _frame, uint32_t fps_n, uint32_t fps_d)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_frame(struct lcscreen& _frame, uint32_t fps_n, uint32_t fps_d) throw()
|
||||
{
|
||||
update_dumpers();
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_frame(_frame, fps_n, fps_d);
|
||||
END_EH_BLOCK(i, "on_frame");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_sample(short l, short r)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_sample(short l, short r) throw()
|
||||
{
|
||||
update_dumpers();
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_sample(l, r);
|
||||
END_EH_BLOCK(i, "on_sample");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_dump_end()
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_dump_end() throw()
|
||||
{
|
||||
update_dumpers();
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_dump_end();
|
||||
END_EH_BLOCK(i, "on_dump_end");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::on_sound_rate(uint32_t rate_n, uint32_t rate_d)
|
||||
{
|
||||
if(!known_if_dumper) {
|
||||
marked_as_dumper = get_dumper_flag();
|
||||
known_if_dumper = true;
|
||||
}
|
||||
if(marked_as_dumper) {
|
||||
messages << "[dumper " << get_name() << "] Warning: Sound sample rate changing not supported!"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::do_sound_rate(uint32_t rate_n, uint32_t rate_d) throw()
|
||||
{
|
||||
update_dumpers();
|
||||
uint32_t g = gcd(rate_n, rate_d);
|
||||
rate_n /= g;
|
||||
rate_d /= g;
|
||||
if(rate_n == srate_n && rate_d == srate_d)
|
||||
return;
|
||||
srate_n = rate_n;
|
||||
srate_d = rate_d;
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_sound_rate(rate_n, rate_d);
|
||||
END_EH_BLOCK(i, "on_sound_rate");
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<uint32_t, uint32_t> information_dispatch::get_sound_rate() throw()
|
||||
{
|
||||
return std::make_pair(srate_n, srate_d);
|
||||
}
|
||||
|
||||
void information_dispatch::on_gameinfo(const struct gameinfo_struct& gi)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_gameinfo(const struct gameinfo_struct& gi) throw()
|
||||
{
|
||||
update_dumpers();
|
||||
try {
|
||||
sgi = gi;
|
||||
} catch(...) {
|
||||
OOM_panic();
|
||||
}
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_gameinfo(sgi);
|
||||
END_EH_BLOCK(i, "on_gameinfo");
|
||||
}
|
||||
}
|
||||
|
||||
const struct gameinfo_struct& information_dispatch::get_gameinfo() throw()
|
||||
{
|
||||
return sgi;
|
||||
}
|
||||
|
||||
bool information_dispatch::get_dumper_flag() throw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void information_dispatch::on_new_dumper(const std::string& dumper)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::on_destroy_dumper(const std::string& dumper)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
unsigned information_dispatch::get_dumper_count() throw()
|
||||
{
|
||||
update_dumpers(true);
|
||||
unsigned count = 0;
|
||||
for(auto& i : dispatch())
|
||||
if(i->marked_as_dumper)
|
||||
count++;
|
||||
if(!recursive) {
|
||||
recursive = true;
|
||||
update_dumpers();
|
||||
recursive = false;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
std::set<std::string> information_dispatch::get_dumpers() throw(std::bad_alloc)
|
||||
{
|
||||
update_dumpers();
|
||||
std::set<std::string> r;
|
||||
try {
|
||||
for(auto& i : dispatch())
|
||||
if(i->notified_as_dumper)
|
||||
r.insert(i->get_name());
|
||||
} catch(...) {
|
||||
OOM_panic();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void information_dispatch::on_key_event(const modifier_set& modifiers, keygroup& keygroup, unsigned subkey,
|
||||
bool polarity, const std::string& name)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_key_event(const modifier_set& modifiers, keygroup& keygroup, unsigned subkey,
|
||||
bool polarity, const std::string& name) throw()
|
||||
{
|
||||
if(exclusive_key) {
|
||||
START_EH_BLOCK
|
||||
exclusive_key->on_key_event(modifiers, keygroup, subkey, polarity, name);
|
||||
END_EH_BLOCK(exclusive_key, "on_key_event");
|
||||
return;
|
||||
}
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_key_event(modifiers, keygroup, subkey, polarity, name);
|
||||
END_EH_BLOCK(i, "on_key_event");
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::grab_keys() throw()
|
||||
{
|
||||
if(grabbing_keys)
|
||||
return;
|
||||
exclusive_key = this;
|
||||
grabbing_keys = true;
|
||||
}
|
||||
|
||||
void information_dispatch::ungrab_keys() throw()
|
||||
{
|
||||
if(!grabbing_keys)
|
||||
return;
|
||||
exclusive_key = NULL;
|
||||
grabbing_keys = false;
|
||||
for(auto& i : dispatch())
|
||||
if(i->grabbing_keys) {
|
||||
exclusive_key = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& information_dispatch::get_name() throw()
|
||||
{
|
||||
return target_name;
|
||||
}
|
||||
|
||||
void information_dispatch::update_dumpers(bool nocalls) throw()
|
||||
{
|
||||
for(auto& i : dispatch()) {
|
||||
if(!i->known_if_dumper) {
|
||||
i->marked_as_dumper = i->get_dumper_flag();
|
||||
i->known_if_dumper = true;
|
||||
}
|
||||
if(i->marked_as_dumper && !i->notified_as_dumper && !nocalls) {
|
||||
for(auto& j : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
j->on_new_dumper(i->target_name);
|
||||
END_EH_BLOCK(j, "on_new_dumper");
|
||||
}
|
||||
i->notified_as_dumper = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void information_dispatch::do_click_compensation(uint32_t xoffset, uint32_t yoffset, uint32_t hscl, uint32_t vscl)
|
||||
{
|
||||
vc_xoffset = xoffset;
|
||||
vc_yoffset = yoffset;
|
||||
vc_hscl = hscl;
|
||||
vc_vscl = vscl;
|
||||
}
|
|
@ -306,4 +306,4 @@ uint32_t gcd(uint32_t a, uint32_t b) throw()
|
|||
}
|
||||
|
||||
std::string bsnes_core_version;
|
||||
std::string lsnes_version = "0-β19";
|
||||
std::string lsnes_version = "0-β20";
|
||||
|
|
Loading…
Add table
Reference in a new issue