From 7dbf5cece42e9d2646522e2d1d3f57a2aeefabb2 Mon Sep 17 00:00:00 2001 From: Nopey Nope Date: Thu, 30 Jan 2020 10:27:03 -0800 Subject: [PATCH] Add and document KeyMapper reloading This is accomplished by clearing all the binds on the events, and then re-parsing the file. This allows batch scripts to change keybindings, and is useful for DOS game menus, who can now change the mappings per-game. ie: config -set sdl mapperfile=~/.dosbox/mario-and-luigi.map or: config -r -conf ~/.dosbox/mario-and-luigi.conf (with a mapperfile=mario-and-luigi.map line in mario-and-luigi.conf) Warning: Because internal changes don't have access to the current_config_path, paths set with config -set are relative to the CWD. Relevant source lines are src/misc/setup.cpp lines 349 and 917 I'm unsure if this interacts well with the CAPS and NUMLOCK code at the bottom of MAPPER_Init, as those now get run every time the mapper reloads. If it does misbehave, those if statements can probably be moved to the MAPPER_StartUp function, although it is called a bit earlier than MAPPER_Init. A natural extension of this would be to add the ability to change the mapperfile from within the MAPPER UI. --- README | 18 ++++++++++++------ src/gui/sdl_mapper.cpp | 30 ++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/README b/README index 03d791be..d287bc74 100644 --- a/README +++ b/README @@ -712,23 +712,25 @@ CONFIG -get "section property" config -set "cpu cycles=10000" 3. To turn EMS memory emulation off: config -set "dos ems=false" - 4. To check which cpu core is being used. + 4. To change the key mappings + config -set "sdl mapperfile=/path/to/mapper-file.map" + 5. To check which cpu core is being used. config -get "cpu core" - 5. To view the list of possible cpu cores: + 6. To view the list of possible cpu cores: config -help cpu core - 6. To change the machine type and restart: + 7. To change the machine type and restart: config -set "machine cga" config -wc -r - 7. To configure the autoexec section to auto-mount a directory at start: + 8. To configure the autoexec section to auto-mount a directory at start: config -axadd "mount c c:\dosgames" "c:" config -wc - 8. To create a specific config file in the config directory: + 9. To create a specific config file in the config directory: config -set "dos ems=false" config -set "cpu cycles=10000" config -set "core dynamic" config -axadd "mount c c:\dosgames" "c:" "cd my_game" "my_game" config -wc my_config.conf - 9. To restart DOSBox from a specific config file in the config directory: + 10. To restart DOSBox from a specific config file in the config directory: config -r -conf my_config.conf LOADFIX [-size] [program] [program-parameters] @@ -1207,6 +1209,10 @@ the configuration file (the mapperfile= entry). At startup, DOSBox will load your mapperfile, if it is present in the DOSBox configuration file. +Additionally, the mapperfile configuration entry can by changed with the CONFIG +program, and will take effect immediately. + config -set "sdl mapperfile=/path/to/mapper-file.map" + =================== 8. Keyboard Layout: diff --git a/src/gui/sdl_mapper.cpp b/src/gui/sdl_mapper.cpp index e424b5e9..1ff6b19b 100644 --- a/src/gui/sdl_mapper.cpp +++ b/src/gui/sdl_mapper.cpp @@ -112,6 +112,7 @@ public: virtual ~CEvent() = default; void AddBind(CBind * bind); + void ClearBinds(); virtual void Active(bool yesno)=0; virtual void ActivateEvent(bool ev_trigger,bool skip_action)=0; virtual void DeActivateEvent(bool ev_trigger)=0; @@ -282,6 +283,12 @@ void CEvent::AddBind(CBind * bind) { bindlist.push_front(bind); bind->event=this; } +void CEvent::ClearBinds() { + for (CBind *bind : bindlist) { + delete bind; + } + bindlist.clear(); +} void CEvent::DeActivateAll(void) { for (CBindList_it bit=bindlist.begin();bit!=bindlist.end();bit++) { (*bit)->DeActivateBind(true); @@ -2137,7 +2144,14 @@ static struct { {0, SDL_SCANCODE_UNKNOWN} }; +static void ClearAllBinds(void) { + for (CEvent *event : events) { + event->ClearBinds(); + } +} + static void CreateDefaultBinds(void) { + ClearAllBinds(); char buffer[512]; Bitu i=0; while (DefaultKeys[i].eventend) { @@ -2230,6 +2244,7 @@ static void MAPPER_SaveBinds(void) { static bool MAPPER_LoadBinds(void) { FILE * loadfile=fopen(mapper.filename.c_str(),"rt"); if (!loadfile) return false; + ClearAllBinds(); char linein[512]; while (fgets(linein,512,loadfile)) { CreateStringBind(linein); @@ -2537,8 +2552,8 @@ void MAPPER_RunInternal() { void MAPPER_Init(void) { InitializeJoysticks(); - CreateLayout(); - CreateBindGroups(); + if (buttons.empty()) CreateLayout(); + if (bindgroups.empty()) CreateBindGroups(); if (!MAPPER_LoadBinds()) CreateDefaultBinds(); for (CButton_it but_it = buttons.begin();but_it!=buttons.end();but_it++) { (*but_it)->BindColor(); @@ -2557,12 +2572,19 @@ void MAPPER_Init(void) { } } +static void ReloadMapper(Section *sec) { + Section_prop const *const section=static_cast(sec); + Prop_path const *const pp = section->Get_path("mapperfile"); + mapper.filename = pp->realpath; + GFX_LosingFocus(); //Release any keys pressed, or else they'll get stuck. + MAPPER_Init(); +} + void MAPPER_StartUp(Section * sec) { Section_prop * section=static_cast(sec); + section->AddInitFunction(&ReloadMapper, true); //runs immediately after this function ends mapper.sticks.num=0; mapper.sticks.num_groups=0; memset(&virtual_joysticks,0,sizeof(virtual_joysticks)); - Prop_path* pp = section->Get_path("mapperfile"); - mapper.filename = pp->realpath; MAPPER_AddHandler(&MAPPER_Run,MK_f1,MMOD1,"mapper","Mapper"); }