Merge remote-tracking branch 'origin/rr1-maint'

Conflicts:
	Makefile
	src/lua/core.cpp
	src/lua/lua.cpp
This commit is contained in:
Ilari Liusvaara 2012-03-07 06:19:06 +02:00
commit c3dd13fb3f
25 changed files with 577 additions and 49 deletions

View file

@ -17,7 +17,7 @@ HOSTCC = $(CC)
#Flags.
HOSTCCFLAGS = -std=gnu++0x
CFLAGS = -I$(BSNES_PATH) -std=gnu++0x $(USER_CFLAGS)
LDFLAGS = -lboost_iostreams -lboost_filesystem -lboost_system -lboost_regex -lz $(USER_LDFLAGS)
LDFLAGS = -lboost_iostreams-mt -lboost_filesystem-mt -lboost_system-mt -lboost_regex-mt -lz $(USER_LDFLAGS)
#Platform
GRAPHICS=SDL

View file

@ -1 +1 @@
1-Δ3
1-Δ4ε1

View file

@ -5,6 +5,7 @@
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstdio>
#include <cstdint>
#include <sstream>
#include <iomanip>

View file

@ -76,7 +76,7 @@ void init_special_screens() throw(std::bad_alloc);
/**
* Copy framebuffer to backing store, running Lua hooks if any.
*/
void redraw_framebuffer(lcscreen& torender, bool no_lua = false);
void redraw_framebuffer(lcscreen& torender, bool no_lua = false, bool spontaneous = false);
/**
* Redraw the framebuffer, reusing contents from last redraw. Runs lua hooks if last redraw ran them.
*/

View file

@ -0,0 +1,14 @@
#ifndef _threaddebug__hpp__included__
#define _threaddebug__hpp__included__
#define THREAD_OTHER -1
#define THREAD_MAIN -2
#define THREAD_EMULATION 0
#define THREAD_UI 1
#define THREAD_JOYSTICK 2
void assert_thread(signed shouldbe);
void mark_thread_as(signed call_me);
void init_threaded_malloc();
#endif

View file

@ -14,6 +14,9 @@ bool get_boolean_argument(lua_State* LS, unsigned argindex, const char* fname);
void push_keygroup_parameters(lua_State* LS, const struct keygroup::parameters& p);
extern lua_render_context* lua_render_ctx;
extern controller_frame* lua_input_controllerdata;
extern bool lua_booted_flag;
extern uint64_t lua_idle_hook_time;
extern uint64_t lua_timer_hook_time;
template<typename T>
T get_numeric_argument(lua_State* LS, unsigned argindex, const char* fname)

View file

@ -68,13 +68,17 @@ struct lua_render_context
void init_lua() throw();
void quit_lua() throw();
void lua_callback_do_paint(struct lua_render_context* ctx) throw();
void lua_callback_do_paint(struct lua_render_context* ctx, bool non_synthethic) throw();
void lua_callback_do_video(struct lua_render_context* ctx) throw();
void lua_callback_do_input(controller_frame& data, bool subframe) throw();
void lua_callback_do_reset() throw();
void lua_callback_do_frame() throw();
void lua_callback_do_frame_emulated() throw();
void lua_callback_do_rewind() throw();
void lua_callback_do_readwrite() throw();
void lua_callback_startup() throw();
void lua_callback_do_idle() throw();
void lua_callback_do_timer() throw();
void lua_callback_pre_load(const std::string& name) throw();
void lua_callback_err_load(const std::string& name) throw();
void lua_callback_post_load(const std::string& name, bool was_state) throw();
@ -85,6 +89,11 @@ void lua_callback_snoop_input(uint32_t port, uint32_t controller, uint32_t index
void lua_callback_quit() throw();
void lua_callback_keyhook(const std::string& key, const struct keygroup::parameters& p) throw();
#define LUA_TIMED_HOOK_IDLE 0
#define LUA_TIMED_HOOK_TIMER 1
uint64_t lua_timed_hook(int timer) throw();
extern bool lua_supported;
extern bool lua_requests_repaint;
extern bool lua_requests_subframe_paint;

View file

@ -11,6 +11,7 @@ public:
{
public:
panel(wxWindow* _parent, unsigned lines);
bool AcceptsFocus () const;
void on_paint(wxPaintEvent& e);
bool dirty;
wxWindow* parent;

View file

@ -2036,6 +2036,43 @@ exec(string command)
Run command as it was entered on the command line
\end_layout
\begin_layout Subsubsection
utime()
\end_layout
\begin_layout Standard
Returns two values.
First is time since some epoch in seconds, the second is microseconds mod
10^6 since that epoch.
\end_layout
\begin_layout Subsubsection
emulator_ready()
\end_layout
\begin_layout Standard
Returns true if emulator has finished booting, false if not (on_startup()
will be issued later).
\end_layout
\begin_layout Subsubsection
set_idle_timeout(number timeout)
\end_layout
\begin_layout Standard
Set number of microseconds to block idle for.
After this timeout has expired, on_idle() will be called once.
\end_layout
\begin_layout Subsubsection
set_timer_timeout(number timeout)
\end_layout
\begin_layout Standard
Set number of microseconds to block timer for.
After this timeout has expired, on_timer() will be called once.
\end_layout
\begin_layout Subsection
Table bit:
\end_layout
@ -2685,6 +2722,32 @@ Uses physical controller numbering.
Gamepad in port 2 is controller 4, not 1!
\end_layout
\begin_layout Subsubsection
input.geta(number controller)
\end_layout
\begin_layout Standard
Get input state for entiere controller.
Returns 13 return values.
\end_layout
\begin_layout Itemize
1st return value: Bitmask: bit i is set if i:th index is nonzero
\end_layout
\begin_layout Itemize
2nd-13th return value: value of i:th index.
\end_layout
\begin_layout Subsubsection
input.seta(number controller, number bitmask, number args...)
\end_layout
\begin_layout Standard
Set state for entiere controller.
args is up to 12 values for indices (overriding values in bitmask if specified).
\end_layout
\begin_layout Subsubsection
input.reset([number cycles])
\end_layout
@ -3199,7 +3262,7 @@ Various callbacks to Lua that can occur.
\end_layout
\begin_layout Subsubsection
Callback: on_paint()
Callback: on_paint(bool not_synth)
\end_layout
\begin_layout Standard
@ -3207,6 +3270,11 @@ Called when screen is being painted.
Any gui.* calls requiring graphic context draw on the screen.
\end_layout
\begin_layout Standard
not_synth is true if this hook is being called in response to received frame,
false otherwise.
\end_layout
\begin_layout Subsubsection
Callback: on_video()
\end_layout
@ -3216,6 +3284,15 @@ Called when video dump frame is being painted.
Any gui.* calls requiring graphic context draw on the video.
\end_layout
\begin_layout Subsubsection
Callback: on_frame_emulated()
\end_layout
\begin_layout Standard
Called when emulating frame has completed and on_paint()/on_video() calls
are about to be issued.
\end_layout
\begin_layout Subsubsection
Callback: on_frame()
\end_layout
@ -3232,6 +3309,14 @@ Callback: on_startup()
Called when the emulator is starting (lsnes.rc and --run files has been run).
\end_layout
\begin_layout Subsubsection
Callback: on_rewind()
\end_layout
\begin_layout Standard
Called when rewind movie to beginning has completed.
\end_layout
\begin_layout Subsubsection
Callback: on_pre_load(string name)
\end_layout
@ -3350,6 +3435,24 @@ Sent when key that has keyhook events requested changes state.
table values in input.raw).
\end_layout
\begin_layout Subsubsection
Callback: on_idle()
\end_layout
\begin_layout Standard
Called when requested by set_idle_timeout(), the timeout has expired and
emulator is waiting.
\end_layout
\begin_layout Subsubsection
Callback: on_timer()
\end_layout
\begin_layout Standard
Called when requested by set_idle_timeout() and the timeout has expired
(regardless if emulator is waiting).
\end_layout
\begin_layout Section
Memory watch expression syntax
\end_layout
@ -5691,5 +5794,41 @@ Wxwidgets: Only bring up ROM patching screen if specifically requested.
Allow configuring some hotkeys.
\end_layout
\begin_layout Subsection
rr1-delta4
\end_layout
\begin_layout Itemize
Lots of code cleanups
\end_layout
\begin_layout Itemize
Fix JMD compression (JMD dumping was broken)
\end_layout
\begin_layout Itemize
Don't crash if Lua C function throws an exception.
\end_layout
\begin_layout Itemize
Support bitmap drawing in Lua.
\end_layout
\begin_layout Itemize
Fix bsnes v085/v086 patches.
\end_layout
\begin_layout Itemize
Improve stability on win32.
\end_layout
\begin_layout Subsection
rr1-delta4epsilon1
\end_layout
\begin_layout Itemize
Don't corrupt movie if movie length is integer multiple of frames per page.
\end_layout
\end_body
\end_document

View file

@ -977,6 +977,26 @@ Print line to message console.
Run command as it was entered on the command line
8.1.3 utime()
Returns two values. First is time since some epoch in seconds,
the second is microseconds mod 10^6 since that epoch.
8.1.4 emulator_ready()
Returns true if emulator has finished booting, false if not
(on_startup() will be issued later).
8.1.5 set_idle_timeout(number timeout)
Set number of microseconds to block idle for. After this timeout
has expired, on_idle() will be called once.
8.1.6 set_timer_timeout(number timeout)
Set number of microseconds to block timer for. After this timeout
has expired, on_timer() will be called once.
8.2 Table bit:
Bitwise logical functions and related.
@ -1316,14 +1336,29 @@ storing value. Notes:
• Uses physical controller numbering. Gamepad in port 2 is
controller 4, not 1!
8.4.3 input.reset([number cycles])
8.4.3 input.geta(number controller)
Get input state for entiere controller. Returns 13 return values.
• 1st return value: Bitmask: bit i is set if i:th index is
nonzero
• 2nd-13th return value: value of i:th index.
8.4.4 input.seta(number controller, number bitmask, number
args...)
Set state for entiere controller. args is up to 12 values for
indices (overriding values in bitmask if specified).
8.4.5 input.reset([number cycles])
Execute reset. If cycles is greater than zero, do delayed reset.
0 (or no value) causes immediate reset.
• Only available with subframe flag false.
8.4.4 input.raw()
8.4.6 input.raw()
Returns table of tables of all available keys and axes. The first
table is indexed by key name (platform-dependent!), and the inner
@ -1347,7 +1382,7 @@ table has the following fields:
• cal_tolerance: Dead zone tolerance. Only meaningful with axis
and pressure types.
8.4.5 input.keyhook(key, state)
8.4.7 input.keyhook(key, state)
Requests that keyhook events to be sent for key (state=true) or
not sent (state=false).
@ -1602,76 +1637,88 @@ initialization. Non-writeable.
Various callbacks to Lua that can occur.
8.10.1 Callback: on_paint()
8.10.1 Callback: on_paint(bool not_synth)
Called when screen is being painted. Any gui.* calls requiring
graphic context draw on the screen.
not_synth is true if this hook is being called in response to
received frame, false otherwise.
8.10.2 Callback: on_video()
Called when video dump frame is being painted. Any gui.* calls
requiring graphic context draw on the video.
8.10.3 Callback: on_frame()
8.10.3 Callback: on_frame_emulated()
Called when emulating frame has completed and
on_paint()/on_video() calls are about to be issued.
8.10.4 Callback: on_frame()
Called on each starting whole frame.
8.10.4 Callback: on_startup()
8.10.5 Callback: on_startup()
Called when the emulator is starting (lsnes.rc and --run files
has been run).
8.10.5 Callback: on_pre_load(string name)
8.10.6 Callback: on_rewind()
Called when rewind movie to beginning has completed.
8.10.7 Callback: on_pre_load(string name)
Called just before savestate/movie load occurs (note: loads are
always delayed, so this occurs even when load was initiated by
lua).
8.10.6 Callback: on_err_load(string name)
8.10.8 Callback: on_err_load(string name)
Called if loadstate goes wrong.
8.10.7 Callback: on_post_load(string name, boolean was_savestate)
8.10.9 Callback: on_post_load(string name, boolean was_savestate)
Called on successful loadstate. was_savestate gives if this was a
savestate or a movie.
8.10.8 Callback: on_pre_save(string name, boolean is_savestate)
8.10.10 Callback: on_pre_save(string name, boolean is_savestate)
Called just before savestate save occurs (note: movie saves are
synchronous and won't trigger these callbacks if called from
Lua).
8.10.9 Callback: on_err_save(string name)
8.10.11 Callback: on_err_save(string name)
Called if savestate goes wrong.
8.10.10 Callback: on_post_save(string name, boolean is_savestate)
8.10.12 Callback: on_post_save(string name, boolean is_savestate)
Called on successful savaestate. is_savestate gives if this was a
savestate or a movie.
8.10.11 Callback: on_quit()
8.10.13 Callback: on_quit()
Called when emulator is shutting down.
8.10.12 Callback: on_input(boolean subframe)
8.10.14 Callback: on_input(boolean subframe)
Called when emulator is just sending input to bsnes core.
Warning: This is called even in readonly mode, but the results
are ignored.
8.10.13 Callback: on_reset()
8.10.15 Callback: on_reset()
Called when SNES is reset.
8.10.14 Callback: on_readwrite()
8.10.16 Callback: on_readwrite()
Called when moving into readwrite mode as result of “set-rwmode”
command (note: moving to rwmode by Lua won't trigger this, as per
recursive entry protection).
8.10.15 Callback: on_snoop(number port, number controller, number
8.10.17 Callback: on_snoop(number port, number controller, number
index, number value)
Called each time bsnes asks for input. The value is the final
@ -1680,12 +1727,22 @@ autofire have been taken into account). Might be useful when
translating movies to format suitable for console verification.
Note: There is no way to modify the value to be sent.
8.10.16 Callback: on_keyhook(string keyname, table state)
8.10.18 Callback: on_keyhook(string keyname, table state)
Sent when key that has keyhook events requested changes state.
Keyname is name of the key (group) and state is the state (same
kind as table values in input.raw).
8.10.19 Callback: on_idle()
Called when requested by set_idle_timeout(), the timeout has
expired and emulator is waiting.
8.10.20 Callback: on_timer()
Called when requested by set_idle_timeout() and the timeout has
expired (regardless if emulator is waiting).
9 Memory watch expression syntax
Memory watch expressions are in RPN (Reverse Polish Notation). At
@ -2786,3 +2843,22 @@ set-axis joystick0axis19 disabled
• Allow configuring some hotkeys.
15.51 rr1-delta4
• Lots of code cleanups
• Fix JMD compression (JMD dumping was broken)
• Don't crash if Lua C function throws an exception.
• Support bitmap drawing in Lua.
• Fix bsnes v085/v086 patches.
• Improve stability on win32.
15.52 rr1-delta4epsilon1
• Don't corrupt movie if movie length is integer multiple of
frames per page.

View file

@ -683,8 +683,10 @@ void controller_frame_vector::resize(size_t newsize) throw(std::bad_alloc)
for(size_t i = pages_needed; i < current_pages; i++)
pages.erase(i);
//Now zeroize the excess memory.
size_t offset = frame_size * (newsize % frames_per_page);
memset(pages[pages_needed - 1].content + offset, 0, CONTROLLER_PAGE_SIZE - offset);
if(newsize < pages_needed * frames_per_page) {
size_t offset = frame_size * (newsize % frames_per_page);
memset(pages[pages_needed - 1].content + offset, 0, CONTROLLER_PAGE_SIZE - offset);
}
frames = newsize;
} else if(newsize > frames) {
//Enlarge movie.

View file

@ -168,7 +168,7 @@ void init_special_screens() throw(std::bad_alloc)
screen_corrupt = lcscreen(&buf[0], 512, 448);
}
void redraw_framebuffer(lcscreen& todraw, bool no_lua)
void redraw_framebuffer(lcscreen& todraw, bool no_lua, bool spontaneous)
{
uint32_t hscl, vscl;
auto g = get_scale_factors(todraw.width, todraw.height);
@ -185,7 +185,7 @@ void redraw_framebuffer(lcscreen& todraw, bool no_lua)
lrc.width = todraw.width * hscl;
lrc.height = todraw.height * vscl;
if(!no_lua)
lua_callback_do_paint(&lrc);
lua_callback_do_paint(&lrc, spontaneous);
ri.fbuf = todraw;
ri.hscl = hscl;
ri.vscl = vscl;
@ -203,7 +203,8 @@ void redraw_framebuffer()
render_info& ri = get_read_buffer();
lcscreen copy = ri.fbuf;
buffering.end_read();
redraw_framebuffer(copy, last_redraw_no_lua);
//Redraws are never spontaneous
redraw_framebuffer(copy, last_redraw_no_lua, false);
}

View file

@ -335,6 +335,7 @@ class my_interface : public SNES::Interface
if(stepping_into_save)
messages << "Got video refresh in runtosave, expect desyncs!" << std::endl;
video_refresh_done = true;
lua_callback_do_frame_emulated();
bool region = (SNES::system.region() == SNES::System::Region::PAL);
information_dispatch::do_raw_frame(data, hires, interlace, overscan, region ? VIDEO_REGION_PAL :
VIDEO_REGION_NTSC);
@ -345,7 +346,7 @@ class my_interface : public SNES::Interface
lcscreen ls(data, hires, interlace, overscan, region);
location_special = SPECIAL_FRAME_VIDEO;
update_movie_state();
redraw_framebuffer(ls);
redraw_framebuffer(ls, false, true);
uint32_t fps_n, fps_d;
uint32_t fclocks;
if(region)

View file

@ -3,6 +3,7 @@
#include "core/memorymanip.hpp"
#include "core/misc.hpp"
#include "core/rom.hpp"
#include "core/threaddebug.hpp"
#include "core/window.hpp"
#include "library/sha256.hpp"
@ -248,6 +249,7 @@ bool in_global_ctors()
void reached_main()
{
reached_main_flag = true;
init_threaded_malloc();
}
std::string bsnes_core_version;

View file

@ -470,14 +470,15 @@ long movie_logic::new_frame_starting(bool dont_poll) throw(std::bad_alloc, std::
controller_frame c = update_controls(false);
if(!mov.readonly_mode()) {
mov.set_controls(c);
if(dont_poll)
if(!dont_poll)
mov.set_all_DRDY();
if(c.reset()) {
auto g = c.delay();
long hi = g.first, lo = g.second;
mov.commit_reset(hi * 10000 + lo);
}
}
} else if(!dont_poll)
mov.set_all_DRDY();
return mov.get_reset_status();
}

View file

@ -277,6 +277,7 @@ void do_load_beginning() throw(std::bad_alloc, std::runtime_error)
our_movie.rtc_second = our_movie.movie_rtc_second;
our_movie.rtc_subsecond = our_movie.movie_rtc_subsecond;
redraw_framebuffer(screen_nosignal);
lua_callback_do_rewind();
} catch(std::bad_alloc& e) {
OOM_panic();
} catch(std::exception& e) {

91
src/core/threaddebug.cpp Normal file
View file

@ -0,0 +1,91 @@
#include "core/threaddebug.hpp"
#include "core/window.hpp"
#define DESIGNATED_THREADS 16
namespace
{
volatile thread_id* threads[DESIGNATED_THREADS];
volatile bool thread_marked;
mutex* malloc_mutex;
}
void assert_thread(signed shouldbe, const std::string& desc)
{
#ifndef DISABLE_THREAD_ASSERTIONS
if(shouldbe < 0 || shouldbe >= DESIGNATED_THREADS) {
std::cerr << "WARNING: assert_thread(" << shouldbe << ") called." << std::endl;
return;
}
if(!thread_marked)
return;
thread_id* t = const_cast<thread_id*>(threads[shouldbe]);
if(!t || !t->is_me())
std::cerr << "WARNING: " << desc << ": Wrong thread!" << std::endl;
#endif
}
void mark_thread_as(signed call_me)
{
#ifndef DISABLE_THREAD_ASSERTIONS
if(call_me < 0 || call_me >= DESIGNATED_THREADS) {
std::cerr << "WARNING: mark_thread_as(" << call_me << ") called." << std::endl;
return;
}
thread_marked = true;
threads[call_me] = &thread_id::me();
#endif
}
#ifdef MAKE_MALLOC_THREADSAFE
void init_threaded_malloc()
{
if(!malloc_mutex)
malloc_mutex = &mutex::aquire();
}
extern "C"
{
void* __real_malloc(size_t);
void* __real_calloc(size_t, size_t);
void* __real_realloc(void*, size_t);
void __real_free(void*);
void* __wrap_malloc(size_t block)
{
if(!malloc_mutex)
return __real_malloc(block);
mutex::holder(*malloc_mutex);
return __real_malloc(block);
}
void* __wrap_calloc(size_t count, size_t size)
{
if(!malloc_mutex)
return __real_calloc(count, size);
mutex::holder(*malloc_mutex);
return __real_calloc(count, size);
}
void* __wrap_realloc(void* block, size_t size)
{
if(!malloc_mutex)
return __real_realloc(block, size);
mutex::holder(*malloc_mutex);
return __real_realloc(block, size);
}
void __wrap_free(void* block)
{
if(!malloc_mutex)
return __real_free(block);
mutex::holder(*malloc_mutex);
return __real_free(block);
}
}
#else
void init_threaded_malloc()
{
}
#endif

View file

@ -1,10 +1,12 @@
#include "core/command.hpp"
#include "core/dispatch.hpp"
#include "core/framerate.hpp"
#include "lua/lua.hpp"
#include "core/misc.hpp"
#include "core/render.hpp"
#include "core/window.hpp"
#include "library/string.hpp"
#include "library/minmax.hpp"
#include <fstream>
#include <iostream>
@ -118,6 +120,8 @@ keypress::keypress(modifier_set mod, keygroup& _key, keygroup& _key2, short _val
namespace
{
bool queue_function_run = false;
function_ptr_command<> identify_key("show-plugins", "Show plugins in use",
"Syntax: show-plugins\nShows plugins in use.\n",
[]() throw(std::bad_alloc, std::runtime_error) {
@ -381,6 +385,7 @@ namespace
if(k.key2)
k.key2->set_position(k.value, k.modifiers);
queue_lock->lock();
queue_function_run = true;
}
//Flush commands.
while(!commands.empty()) {
@ -389,6 +394,7 @@ namespace
queue_lock->unlock();
command::invokeC(c);
queue_lock->lock();
queue_function_run = true;
}
//Flush functions.
while(!functions.empty()) {
@ -398,6 +404,7 @@ namespace
f.first(f.second);
queue_lock->lock();
++functions_executed;
queue_function_run = true;
}
queue_condition->signal();
} catch(std::bad_alloc& e) {
@ -409,28 +416,62 @@ namespace
if(!unlocked)
queue_lock->unlock();
}
uint64_t on_idle_time;
uint64_t on_timer_time;
void reload_lua_timers()
{
on_idle_time = lua_timed_hook(LUA_TIMED_HOOK_IDLE);
on_timer_time = lua_timed_hook(LUA_TIMED_HOOK_TIMER);
queue_function_run = false;
}
}
#define MAXWAIT 10000
#define MAXWAIT 5000000ULL
void platform::flush_command_queue() throw()
{
reload_lua_timers();
queue_function_run = false;
if(modal_pause || normal_pause)
freeze_time(get_utime());
init_threading();
bool run_idle = false;
while(true) {
uint64_t now = get_utime();
if(now >= on_timer_time) {
lua_callback_do_timer();
reload_lua_timers();
}
if(run_idle) {
lua_callback_do_idle();
reload_lua_timers();
run_idle = false;
}
mutex::holder h(*queue_lock);
internal_run_queues(true);
if(!pausing_allowed)
break;
uint64_t now = get_utime();
if(queue_function_run)
reload_lua_timers();
now = get_utime();
uint64_t waitleft = 0;
waitleft = (now < continue_time) ? (continue_time - now) : 0;
waitleft = (modal_pause || normal_pause) ? MAXWAIT : waitleft;
waitleft = (waitleft > MAXWAIT) ? MAXWAIT : waitleft;
if(waitleft > 0)
queue_condition->wait(waitleft);
else
waitleft = min(waitleft, static_cast<uint64_t>(MAXWAIT));
if(waitleft > 0) {
if(now >= on_idle_time) {
run_idle = true;
waitleft = 0;
}
if(on_idle_time >= now)
waitleft = min(waitleft, on_idle_time - now);
if(on_timer_time >= now)
waitleft = min(waitleft, on_timer_time - now);
if(waitleft > 0)
queue_condition->wait(waitleft);
} else
break;
//If we had to wait, check queues at least once more.
}
@ -445,18 +486,41 @@ void platform::set_paused(bool enable) throw()
void platform::wait(uint64_t usec) throw()
{
reload_lua_timers();
continue_time = get_utime() + usec;
init_threading();
bool run_idle = false;
while(true) {
uint64_t now = get_utime();
if(now >= on_timer_time) {
lua_callback_do_timer();
reload_lua_timers();
}
if(run_idle) {
lua_callback_do_idle();
run_idle = false;
reload_lua_timers();
}
mutex::holder h(*queue_lock);
internal_run_queues(true);
uint64_t now = get_utime();
if(queue_function_run)
reload_lua_timers();
now = get_utime();
uint64_t waitleft = 0;
waitleft = (now < continue_time) ? (continue_time - now) : 0;
waitleft = (waitleft > MAXWAIT) ? MAXWAIT : waitleft;
if(waitleft > 0)
queue_condition->wait(waitleft);
else
waitleft = min(static_cast<uint64_t>(MAXWAIT), waitleft);
if(waitleft > 0) {
if(now >= on_idle_time) {
run_idle = true;
waitleft = 0;
}
if(on_idle_time >= now)
waitleft = min(waitleft, on_idle_time - now);
if(on_timer_time >= now)
waitleft = min(waitleft, on_timer_time - now);
if(waitleft > 0)
queue_condition->wait(waitleft);
} else
return;
}
}

View file

@ -1,5 +1,6 @@
#include "core/command.hpp"
#include "lua/internal.hpp"
#include "core/framerate.hpp"
#include "core/window.hpp"
namespace
@ -45,4 +46,27 @@ namespace
command::invokeC(text);
return 0;
});
function_ptr_luafun lua_booted("emulator_ready", [](lua_State* LS, const std::string& fname) -> int {
lua_pushboolean(LS, lua_booted_flag ? 1 : 0);
return 1;
});
function_ptr_luafun lua_utime("utime", [](lua_State* LS, const std::string& fname) -> int {
uint64_t t = get_utime();
lua_pushnumber(LS, t / 1000000);
lua_pushnumber(LS, t % 1000000);
return 2;
});
function_ptr_luafun lua_idle_time("set_idle_timeout", [](lua_State* LS, const std::string& fname) -> int {
lua_idle_hook_time = get_utime() + get_numeric_argument<uint64_t>(LS, 1, fname.c_str());
return 0;
});
function_ptr_luafun lua_timer_time("set_timer_timeout", [](lua_State* LS, const std::string& fname) -> int {
lua_timer_hook_time = get_utime() + get_numeric_argument<uint64_t>(LS, 1, fname.c_str());
return 0;
});
}

View file

@ -4,11 +4,15 @@
struct lua_State { int x; };
lua_function::lua_function(const std::string& name) throw(std::bad_alloc) {}
lua_function::~lua_function() throw() {}
void lua_callback_do_paint(struct lua_render_context* ctx) throw() {}
void lua_callback_do_paint(struct lua_render_context* ctx, bool nonsynth) throw() {}
void lua_callback_do_video(struct lua_render_context* ctx) throw() {}
void lua_callback_do_input(controller_frame& data, bool subframe) throw() {}
void lua_callback_do_reset() throw() {}
void lua_callback_do_frame() throw() {}
void lua_callback_do_frame_emulated() throw() {}
void lua_callback_do_rewind() throw() {}
void lua_callback_do_idle() throw() {}
void lua_callback_do_timer() throw() {}
void lua_callback_do_readwrite() throw() {}
void lua_callback_startup() throw() {}
void lua_callback_pre_load(const std::string& name) throw() {}
@ -22,9 +26,14 @@ void lua_callback_quit() throw() {}
void lua_callback_keyhook(const std::string& key, const struct keygroup::parameters& p) throw() {}
void init_lua() throw() {}
void quit_lua() throw() {}
uint64_t lua_timed_hook(int timer) throw() { return 0x7EFFFFFFFFFFFFFFULL; }
bool lua_requests_repaint = false;
bool lua_requests_subframe_paint = false;
bool lua_supported = false;
uint64_t lua_idle_hook_time = 0x7EFFFFFFFFFFFFFFULL;
uint64_t lua_timer_hook_time = 0x7EFFFFFFFFFFFFFFULL;
#endif
char SYMBOL_3263572374236473826587375832743243264346;

View file

@ -1,4 +1,4 @@
#include "core/lua-int.hpp"
#include "lua/internal.hpp"
#include "core/render.hpp"
#include "lua/bitmap.hpp"
#include <vector>
@ -48,7 +48,7 @@ namespace
delete p;
}
void operator()(struct screen& scr) throw()
template<bool T> void composite_op(struct screen<T>& scr) throw()
{
size_t pallim = 0;
size_t w, h;
@ -74,7 +74,7 @@ namespace
clip_range(scr.originx, scr.width, x, xmin, xmax);
clip_range(scr.originy, scr.height, y, ymin, ymax);
for(int32_t r = ymin; r < ymax; r++) {
uint32_t* rptr = scr.rowptr(y + r + scr.originy);
typename screen<T>::element_t* rptr = scr.rowptr(y + r + scr.originy);
size_t eptr = x + xmin + scr.originx;
if(b)
for(int32_t c = xmin; c < xmax; c++, eptr++) {
@ -87,6 +87,8 @@ namespace
b2->object()->pixels[r * b2->object()->width + c].apply(rptr[eptr]);
}
}
void operator()(struct screen<false>& x) throw() { composite_op(x); }
void operator()(struct screen<true>& x) throw() { composite_op(x); }
private:
int32_t x;
int32_t y;

View file

@ -26,6 +26,38 @@ namespace
return 1;
});
function_ptr_luafun iseta("input.seta", [](lua_State* LS, const std::string& fname) -> int {
if(!lua_input_controllerdata)
return 0;
short val;
unsigned controller = get_numeric_argument<unsigned>(LS, 1, fname.c_str());
if(controller >= MAX_PORTS * MAX_CONTROLLERS_PER_PORT)
return 0;
uint64_t base = get_numeric_argument<uint64_t>(LS, 2, fname.c_str());
for(unsigned i = 0; i < MAX_CONTROLS_PER_CONTROLLER; i++) {
val = (base >> i) & 1;
get_numeric_argument<short>(LS, i + 3, val, fname.c_str());
lua_input_controllerdata->axis(controller, i, val);
}
return 0;
});
function_ptr_luafun igeta("input.geta", [](lua_State* LS, const std::string& fname) -> int {
if(!lua_input_controllerdata)
return 0;
unsigned controller = get_numeric_argument<unsigned>(LS, 1, fname.c_str());
if(controller >= MAX_PORTS * MAX_CONTROLLERS_PER_PORT)
return 0;
uint64_t fret = 0;
for(unsigned i = 0; i < MAX_CONTROLS_PER_CONTROLLER; i++)
if(lua_input_controllerdata->axis(controller, i))
fret |= (1ULL << i);
lua_pushnumber(LS, fret);
for(unsigned i = 0; i < MAX_CONTROLS_PER_CONTROLLER; i++)
lua_pushnumber(LS, lua_input_controllerdata->axis(controller, i));
return MAX_CONTROLS_PER_CONTROLLER + 1;
});
function_ptr_luafun ireset("input.reset", [](lua_State* LS, const std::string& fname) -> int {
if(!lua_input_controllerdata)
return 0;

View file

@ -15,6 +15,9 @@ extern "C" {
#include <lualib.h>
}
uint64_t lua_idle_hook_time = 0x7EFFFFFFFFFFFFFFULL;
uint64_t lua_timer_hook_time = 0x7EFFFFFFFFFFFFFFULL;
namespace
{
globalwrap<std::map<std::string, lua_function*>> functions;
@ -166,6 +169,7 @@ void push_keygroup_parameters(lua_State* LS, const struct keygroup::parameters&
lua_render_context* lua_render_ctx = NULL;
controller_frame* lua_input_controllerdata = NULL;
bool lua_booted_flag = false;
namespace
{
@ -334,12 +338,13 @@ namespace
}
}
void lua_callback_do_paint(struct lua_render_context* ctx) throw()
void lua_callback_do_paint(struct lua_render_context* ctx, bool non_synthetic) throw()
{
if(!callback_exists("on_paint"))
return;
lua_render_ctx = ctx;
run_lua_cb(0);
push_boolean(non_synthetic);
run_lua_cb(1);
lua_render_ctx = NULL;
}
@ -366,6 +371,36 @@ void lua_callback_do_frame() throw()
run_lua_cb(0);
}
void lua_callback_do_rewind() throw()
{
if(!callback_exists("on_rewind"))
return;
run_lua_cb(0);
}
void lua_callback_do_idle() throw()
{
lua_idle_hook_time = 0x7EFFFFFFFFFFFFFFULL;
if(!callback_exists("on_idle"))
return;
run_lua_cb(0);
}
void lua_callback_do_timer() throw()
{
lua_timer_hook_time = 0x7EFFFFFFFFFFFFFFULL;
if(!callback_exists("on_timer"))
return;
run_lua_cb(0);
}
void lua_callback_do_frame_emulated() throw()
{
if(!callback_exists("on_frame_emulated"))
return;
run_lua_cb(0);
}
void lua_callback_do_readwrite() throw()
{
if(!callback_exists("on_readwrite"))
@ -375,6 +410,7 @@ void lua_callback_do_readwrite() throw()
void lua_callback_startup() throw()
{
lua_booted_flag = true;
if(!callback_exists("on_startup"))
return;
run_lua_cb(0);
@ -505,6 +541,21 @@ void quit_lua() throw()
lua_close(lua_initialized);
}
#define LUA_TIMED_HOOK_IDLE 0
#define LUA_TIMED_HOOK_TIMER 1
uint64_t lua_timed_hook(int timer) throw()
{
switch(timer) {
case LUA_TIMED_HOOK_IDLE:
return lua_idle_hook_time;
case LUA_TIMED_HOOK_TIMER:
return lua_timer_hook_time;
}
}
bool lua_requests_repaint = false;
bool lua_requests_subframe_paint = false;
bool lua_supported = true;

View file

@ -289,7 +289,7 @@ void handle_wx_keyboard(wxKeyEvent& e, bool polarity)
modifier_set mset;
modifier_entry* m = modifiers;
while(m->name) {
if((keyc & m->mod) == m->mod) {
if((mods & m->mod) == m->mod) {
mset.add(*m->allocated);
}
m++;

View file

@ -15,6 +15,10 @@ wxwin_status::panel::panel(wxWindow* _parent, unsigned lines)
this->Connect(wxEVT_PAINT, wxPaintEventHandler(wxwin_status::panel::on_paint), NULL, this);
}
bool wxwin_status::panel::AcceptsFocus () const
{
return false;
}
wxwin_status::wxwin_status()
: wxFrame(NULL, wxID_ANY, wxT("lsnes: Status"), wxDefaultPosition, wxSize(-1, -1),