Toribash
Original Post
[CONC/WIP] Library Modification
Concept

This is probably best explained in the order that I myself discovered it.

A few weeks ago I got somewhat annoyed at the key-bindings Toribash uses, as I use a non-QWERTY layout and certain keys were inconveniently overlapping. I searched for a solution and could find none that worked very well.

I had previously looked into both using AHK, which was utterly cumbersome and couldn't properly detect the state of the game (in/out of chat). I then turned to the Lua scripting system that is available in Toribash and promptly found that you can't actually override key-bindings with the provided functions (at least to the best of my knowledge).

At this point I decided I'd have to come up with something a little more involved if I wanted to solve this problem. My first possible solution came when I did a little probing of the Toribash game client with cheat engine and found the memory location of the boolean variable that stored whether the keyboard was in control of the tori or in chat/menu. I started trying to write an AHK script that would use the ReadMemory function provided by WINAPI to get the keyboard control state.

However, I shortly abandoned that idea due to my severe dislike of the AHK language and because I'd thought of another more extensible method of using the ReadMemory function. This idea was to extend the in-game Lua functionality with the the ability to call ReadMemory. Now, I stumbled around for a while trying to figure out exactly how I'd go about loading functions into the Lua module; I at first thought you could load an external library containing the functions from within a Lua script. I did however eventually realise (at least this is how I believe it works) that extended functionality had to be compiled in with the Lua interpreter.

This leads me to my current proposal for modification: as all of the libraries that Toribash uses are open-source they can be easily modified and recompiled with added functionality. For example the Lua library can be modified with memory read/write functionality, high performance functions for specific tasks, and possibly, though I'm not entirely sure of how one would implement it, access to the functions within the Toribash client.


WIP


Getting back to my original problem of the key mapping. After a little bit of research and testing I figured out that Toribash uses the SDL library for keyboard input when controlling the tori. More specifically it uses the SDL_KeyboardEvent for this purpose, but not for menu/chat text input (I'm guessing it uses the SDL_TextInputEvent). After some poking around I found the section of code that SDL uses to generate the event structure that it sends back to the calling module.

This is where it gets a little complicated. The SDL library creates and manages the window that Toribash exists within. When a key is pressed a scancode is generated which is then passed as an event to the window by the operating system. The SDL library then converts this scancode to an SDL scancode, adds the scancode to the event structure, then does a lookup with the SDL scancode to find its matching SDL keycode, and adds this keycode to the event structure before passing the structure back up the calling chain and eventually to the calling module, in this case the Toribash client (I've omitted some details such as how it handles modifier keys, etc.).

After a little bit of testing with a slightly modified SDL library I found that the client uses the scancode for some of the key-bindings (main control WASDZXC, etc.) while it uses the keycode for others (recording, menu shortcuts, etc.). This leads to problems because the keycode lookup is done against your current keyboard layout, so sometimes two different scancodes and keycodes can end up on the same key (which happens with the layout I use). The first step in fixing the key-bindings was to change how the event structure was built such that the keycode lookup was done against the default layout (QWERTY) rather than the your current one, thus each pair of keycode and scancode map to the same physical key on the keyboard.

The next step was simply to create an array that could be used to map one scancode to another and then write a function that would read a custom mapping into the array from a file. This function is then called when the keyboard is initialised and the scancode is mapped just before the event structure is built.

As of this moment the patch for the SDL library is fully functional, but a small standalone application to generate the scancode mapping file is still in development.

Here's the diff patch for SDL_keyboard.c in SDL version 2.0.3 (http://www.libsdl.org/download-2.0.php), the default scancode mapping file, and a basic outline of the mapping file so that you can edit it by hand for testing.

SDL_keyboard.c.diff


keybindings.cfg


Explanation for keybindings.cfg



I'll be posting up the source and binary for the keybindings generator as well as the binary for a modified SDL2.dll when the generator is complete.
Hmm interesting.

In theory you could bind key/mouse events to other input-methods; like say a game controller, right?
...