Merge branch 'rr1-maint'

This commit is contained in:
Ilari Liusvaara 2012-05-15 12:05:29 +03:00
commit 48dbce5bfa
10 changed files with 264 additions and 7 deletions

View file

@ -386,7 +386,6 @@ private:
std::map<size_t, page> memory; std::map<size_t, page> memory;
}; };
/** /**
* Clip range inside another. * Clip range inside another.
* *

View file

@ -38,6 +38,12 @@
#define SPECIAL_LEFT 0x4000000CUL #define SPECIAL_LEFT 0x4000000CUL
//Right. //Right.
#define SPECIAL_RIGHT 0x4000000DUL #define SPECIAL_RIGHT 0x4000000DUL
//Left word.
#define SPECIAL_LEFT_WORD 0x4000000EUL
//Right word.
#define SPECIAL_RIGHT_WORD 0x4000000FUL
//Delete word.
#define SPECIAL_DELETE_WORD 0x40000010UL
//Pressed mask. //Pressed mask.
#define PRESSED_MASK 0x80000000UL #define PRESSED_MASK 0x80000000UL
@ -193,6 +199,12 @@ struct commandline_model
* Enable command line. * Enable command line.
*/ */
void enable() throw(); void enable() throw();
/**
* Enable command line with specific command.
*
* Parameter cmd: The command template.
*/
void enable(const std::string& cmd) throw();
/** /**
* Repaint to SDL surface. * Repaint to SDL surface.
* *
@ -421,6 +433,8 @@ void notify_emulator_exit();
* The user interface loop. Call in UI thread. notify_emulator_exit() causes this to return. * The user interface loop. Call in UI thread. notify_emulator_exit() causes this to return.
*/ */
void ui_loop(); void ui_loop();
/**
* Save the config.
*/
void lsnes_sdl_save_config();
#endif #endif

View file

@ -1565,6 +1565,14 @@ scroll-down
Scroll messages window forward one screenful. Scroll messages window forward one screenful.
\end_layout \end_layout
\begin_layout Subsubsection
prompt-command <command>
\end_layout
\begin_layout Standard
Enter command prompt, with prompt prepopulated with specified command.
\end_layout
\begin_layout Section \begin_layout Section
Settings Settings
\end_layout \end_layout

View file

@ -765,6 +765,11 @@ Scroll messages window back one screenful.
Scroll messages window forward one screenful. Scroll messages window forward one screenful.
6.12.7 prompt-command <command>
Enter command prompt, with prompt prepopulated with specified
command.
7 Settings 7 Settings
7.1 Core settings 7.1 Core settings

View file

@ -1,5 +1,5 @@
ifeq ($(GRAPHICS), SDL) ifeq ($(GRAPHICS), SDL)
OBJECTS = commandline.$(OBJECT_SUFFIX) drawprim.$(OBJECT_SUFFIX) graphicsfn.$(OBJECT_SUFFIX) keyboard.$(OBJECT_SUFFIX) main.$(OBJECT_SUFFIX) thread.$(OBJECT_SUFFIX) status.$(OBJECT_SUFFIX) OBJECTS = commandline.$(OBJECT_SUFFIX) drawprim.$(OBJECT_SUFFIX) graphicsfn.$(OBJECT_SUFFIX) keyboard.$(OBJECT_SUFFIX) main.$(OBJECT_SUFFIX) thread.$(OBJECT_SUFFIX) status.$(OBJECT_SUFFIX) savesettings.$(OBJECT_SUFFIX)
SDL_CFLAGS += $(shell $(CROSS_PREFIX)sdl-config --cflags) SDL_CFLAGS += $(shell $(CROSS_PREFIX)sdl-config --cflags)
SDL_LDFLAGS += $(shell $(CROSS_PREFIX)sdl-config --libs) SDL_LDFLAGS += $(shell $(CROSS_PREFIX)sdl-config --libs)
else else

View file

@ -7,6 +7,34 @@ namespace
{ {
volatile uint32_t autorepeat_first = 10; volatile uint32_t autorepeat_first = 10;
volatile uint32_t autorepeat_subsequent = 4; volatile uint32_t autorepeat_subsequent = 4;
bool is_whitespace(uint32_t cp)
{
switch(cp) {
case 12:
case 32:
case 9:
case 0x1680:
case 0x180E:
case 0x2000:
case 0x2001:
case 0x2002:
case 0x2003:
case 0x2004:
case 0x2005:
case 0x2006:
case 0x2007:
case 0x2008:
case 0x2009:
case 0x200A:
case 0x2028:
case 0x205F:
case 0x3000:
return true;
default:
return false;
};
}
} }
commandline_model::commandline_model() throw() commandline_model::commandline_model() throw()
@ -91,6 +119,31 @@ std::string commandline_model::key(uint32_t k) throw(std::bad_alloc)
return ""; return "";
delete_codepoint(cursor_pos); delete_codepoint(cursor_pos);
return ""; return "";
case SPECIAL_LEFT_WORD:
while(cursor_pos > 0 && (cursor_pos == codepoints.size() || isspace(codepoints[cursor_pos])))
cursor_pos--;
while(cursor_pos > 0 && (cursor_pos == codepoints.size() || !isspace(codepoints[cursor_pos])))
cursor_pos--;
//If the previous position is whitespace, back off to it.
while(cursor_pos > 0 && isspace(codepoints[cursor_pos - 1]))
cursor_pos--;
return "";
case SPECIAL_RIGHT_WORD:
while(cursor_pos < codepoints.size() && isspace(codepoints[cursor_pos]))
cursor_pos++;
while(cursor_pos < codepoints.size() && !isspace(codepoints[cursor_pos]))
cursor_pos++;
return "";
case SPECIAL_DELETE_WORD:
while(cursor_pos > 0 && !isspace(codepoints[cursor_pos - 1])) {
delete_codepoint(cursor_pos - 1);
cursor_pos--;
}
while(cursor_pos > 0 && isspace(codepoints[cursor_pos - 1])) {
delete_codepoint(cursor_pos - 1);
cursor_pos--;
}
return "";
case 0: case 0:
case PRESSED_MASK: case PRESSED_MASK:
//Eh? //Eh?
@ -145,6 +198,35 @@ bool commandline_model::overwriting() throw()
return overwrite_mode; return overwrite_mode;
} }
void commandline_model::enable(const std::string& cmd) throw()
{
enable();
unsigned left = 0;
unsigned tmp = 0;
for(size_t itr = 0; itr < cmd.length(); itr++) {
unsigned char ch = cmd[itr];
if(ch < 128)
codepoints.push_back(ch);
else if(left) {
left--;
tmp = tmp * 64 + (ch & 0x3F);
if(!left)
codepoints.push_back(tmp);
} else if(ch < 192) {
} else if(ch < 224) {
left = 1;
tmp = ch & 0x1F;
} else if(ch < 240) {
left = 2;
tmp = ch & 0x0F;
} else if(ch < 248) {
left = 3;
tmp = ch & 0x07;
}
}
cursor_pos = codepoints.size();
}
void commandline_model::enable() throw() void commandline_model::enable() throw()
{ {
if(enabled_flag) if(enabled_flag)

View file

@ -69,6 +69,9 @@ namespace
SDL_TimerID timer_id; SDL_TimerID timer_id;
//Timer IRQ counter. Used by identify key stuff. //Timer IRQ counter. Used by identify key stuff.
volatile unsigned timer_irq_counter; volatile unsigned timer_irq_counter;
//Delayed command to start.
bool delayed_cmd_active;
std::string delayed_cmd;
void sigalrm_handler(int s) void sigalrm_handler(int s)
{ {
@ -270,6 +273,13 @@ namespace
platform::queue(emu_handle_identify, NULL, false); platform::queue(emu_handle_identify, NULL, false);
} }
function_ptr_command<const std::string&> exec_command_prefix("prompt-command",
"Prompt for command", "Syntax: prompt-command <prefix>\nPrompts command with specified text.\n",
[](const std::string& line) throw(std::bad_alloc, std::runtime_error) {
delayed_cmd = line;
delayed_cmd_active = true;
});
//Handle QUIT in normal state. //Handle QUIT in normal state.
void ui_handle_quit_signal() void ui_handle_quit_signal()
{ {
@ -307,7 +317,7 @@ void ui_loop()
{ {
ui_mutex->lock(); ui_mutex->lock();
int r = SDL_PollEvent(&e); int r = SDL_PollEvent(&e);
if(!repaint_in_flight && !timer_triggered && !r) { if(!repaint_in_flight && !timer_triggered && !delayed_cmd_active && !r) {
ui_mutex->unlock(); ui_mutex->unlock();
usleep(2000); usleep(2000);
continue; continue;
@ -386,9 +396,13 @@ void ui_loop()
switch(special_mode) { switch(special_mode) {
case SPECIALMODE_NORMAL: case SPECIALMODE_NORMAL:
//Enable command line if needed. //Enable command line if needed.
if(iskbd && kbdkey == SDLK_ESCAPE) { if((iskbd && kbdkey == SDLK_ESCAPE) || delayed_cmd_active) {
if(!cmdline.enabled() && !polarity) { if(!cmdline.enabled() && !polarity) {
if(delayed_cmd_active)
cmdline.enable(delayed_cmd);
else
cmdline.enable(); cmdline.enable();
delayed_cmd_active = false;
commandline_updated = true; commandline_updated = true;
special_mode = SPECIALMODE_COMMAND; special_mode = SPECIALMODE_COMMAND;
platform::set_modal_pause(true); platform::set_modal_pause(true);

View file

@ -306,6 +306,46 @@ uint32_t get_command_edit_operation(SDL_Event& e, bool enable)
//Everything except keyboard is no-op. //Everything except keyboard is no-op.
if(e.type != SDL_KEYDOWN && e.type != SDL_KEYUP) if(e.type != SDL_KEYDOWN && e.type != SDL_KEYUP)
return SPECIAL_NOOP; return SPECIAL_NOOP;
//Keys with CTRL held.
if(e.key.keysym.mod & KMOD_CTRL) {
switch(e.key.keysym.sym) {
case 'A': case 'a':
return SPECIAL_HOME | press;
case 'B': case 'b':
return SPECIAL_LEFT | press;
case 'D': case 'd':
return SPECIAL_DELETE | press;
case 'E': case 'e':
return SPECIAL_END | press;
case 'F': case 'f':
return SPECIAL_RIGHT | press;
case 'P': case 'p':
return SPECIAL_UP | press;
case 'N': case 'n':
return SPECIAL_DOWN | press;
case SDLK_LEFT:
return SPECIAL_LEFT_WORD | press;
case SDLK_RIGHT:
return SPECIAL_RIGHT_WORD | press;
case 'W': case 'w':
return SPECIAL_DELETE_WORD | press;
default:
return SPECIAL_NOOP;
};
}
//Keys with ALT held.
if(e.key.keysym.mod & KMOD_ALT) {
switch(e.key.keysym.sym) {
case 'B': case 'b':
return SPECIAL_LEFT_WORD | press;
case 'D': case 'd':
return SPECIAL_DELETE_WORD | press;
case 'F': case 'f':
return SPECIAL_RIGHT_WORD | press;
default:
return SPECIAL_NOOP;
};
}
//Escape is special. //Escape is special.
if(e.key.keysym.sym == SDLK_ESCAPE) if(e.key.keysym.sym == SDLK_ESCAPE)
return (e.type == SDL_KEYUP) ? SPECIAL_NAK : SPECIAL_NOOP; return (e.type == SDL_KEYUP) ? SPECIAL_NAK : SPECIAL_NOOP;

View file

@ -210,6 +210,7 @@ int main(int argc, char** argv)
fatal_error(); fatal_error();
return 1; return 1;
} }
lsnes_sdl_save_config();
rrdata::close(); rrdata::close();
platform::quit(); platform::quit();
quit_lua(); quit_lua();

View file

@ -0,0 +1,94 @@
#include "core/command.hpp"
#include "core/controller.hpp"
#include "core/dispatch.hpp"
#include "core/framerate.hpp"
#include "lua/lua.hpp"
#include "core/mainloop.hpp"
#include "core/misc.hpp"
#include "core/moviedata.hpp"
#include "core/rom.hpp"
#include "core/rrdata.hpp"
#include "core/settings.hpp"
#include "core/window.hpp"
#include "library/zip.hpp"
namespace
{
void write_configuration(const std::string& cfg)
{
std::ofstream cfgfile(cfg.c_str());
//Joystick axis.
for(auto i : keygroup::get_axis_set()) {
keygroup* k = keygroup::lookup_by_name(i);
auto p = k->get_parameters();
cfgfile << "set-axis " << i << " ";
switch(p.ktype) {
case keygroup::KT_DISABLED: cfgfile << "disabled"; break;
case keygroup::KT_AXIS_PAIR: cfgfile << "axis"; break;
case keygroup::KT_AXIS_PAIR_INVERSE: cfgfile << "axis-inverse"; break;
case keygroup::KT_PRESSURE_M0: cfgfile << "pressure-0"; break;
case keygroup::KT_PRESSURE_MP: cfgfile << "pressure-+"; break;
case keygroup::KT_PRESSURE_0M: cfgfile << "pressure0-"; break;
case keygroup::KT_PRESSURE_0P: cfgfile << "pressure0+"; break;
case keygroup::KT_PRESSURE_PM: cfgfile << "pressure+-"; break;
case keygroup::KT_PRESSURE_P0: cfgfile << "pressure+0"; break;
};
cfgfile << " minus=" << p.cal_left << " zero=" << p.cal_center << " plus=" << p.cal_right
<< " tolerance=" << p.cal_tolerance << std::endl;
}
//Settings.
for(auto i : setting::get_settings_set()) {
if(!setting::is_set(i))
cfgfile << "unset-setting " << i << std::endl;
else
cfgfile << "set-setting " << i << " " << setting::get(i) << std::endl;
}
//Aliases.
for(auto i : command::get_aliases()) {
std::string old_alias_value = command::get_alias_for(i);
while(old_alias_value != "") {
std::string aliasline;
size_t s = old_alias_value.find_first_of("\n");
if(s < old_alias_value.length()) {
aliasline = old_alias_value.substr(0, s);
old_alias_value = old_alias_value.substr(s + 1);
} else {
aliasline = old_alias_value;
old_alias_value = "";
}
cfgfile << "alias-command " << i << " " << aliasline << std::endl;
}
}
//Keybindings.
for(auto i : keymapper::get_bindings()) {
std::string i2 = i;
size_t s = i2.find_first_of("|");
size_t s2 = i2.find_first_of("/");
if(s > i2.length() || s2 > s)
continue;
std::string key = i2.substr(s + 1);
std::string mod = i2.substr(0, s2);
std::string modspec = i2.substr(s2 + 1, s - s2 - 1);
std::string old_command_value = keymapper::get_command_for(i);
if(mod != "" || modspec != "")
cfgfile << "bind-key " << mod << "/" << modspec << " " << key << " "
<< old_command_value << std::endl;
else
cfgfile << "bind-key " << key << " " << old_command_value << std::endl;
}
}
}
void lsnes_sdl_save_config()
{
std::string cfg = get_config_path() + "/lsnes.rc";
std::string cfgn = cfg + ".new";
write_configuration(cfg + ".new");
#if defined(_WIN32) || defined(_WIN64) || defined(TEST_WIN32_CODE)
//Grumble, Windows seemingly can't do this atomically.
remove(cfg.c_str());
#endif
rename(cfgn.c_str(), cfg.c_str());
}