Improve input handling of special keys #13
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
At first I noticed that F5 key used to reset the wind at the start of the custom cup doesn't work also (and this was basically the reason version 3.13 was created — oops). So I've added a line of code to fix that.
Then I realized that other F keys should be possible to assign in key setup and that is broken too. So I've added a few more lines to fix that.
Then I noticed that it's also not possible to move the start gate up in practice using the + key not on the keypad, but the one accesed by Shift+=, even though it was possible in the DOS version. Then I've noticed that not only Shift, Num Lock etc. work in "press any key"-like situations (where they didn't in the DOS version), but also are ignored by the game altogether when it comes to detection of which key was pressed. 🤕 (While looking into the code I've also noticed that the game supports a few key combos I don't remember to be documented, and I find them cool actually. But that means they also need to be supported.)
And finally I remembered that we should be also allowing some of the punctuation marks in the player name field for example. So this issue needed a thorough solution.
I've did some investigation and research.
My understanding now is that while BIOS keycodes differentiated between charcodes and scancodes on the keyboard, SDL differentiates between keycodes and scancodes. So if we press a key normally, and with Caps Lock on/Shift held, that would at all times be the same scancode, but two different charcodes (lower- and uppercase) in DOS, and on SDL one keycode but with three different modifier statuses. And not only we need to convert keycode value from Unicode to ANSI for the game to interpret it correctly, the scancodes on SDL are different too, since they use USB and not BIOS list. That would be complicated enough, but since we don't get the actual charcode on SDL, we also don't even know what character to print when Shift is used eg. with number row, since there is no information about keyboard layout used.
So a proper fix would require in my opinion reworking the game input handling mechanics, so that in case of steering input we always depend on (USB) scancode, and in text input scenario we should probably depend on the SDL Text Input handling mechanisms.
That would probably be quite intrusive to the game's code, so for now I've prepared a solution which cuts some corners, but is contained fully within the
SDLPort.WaitForKeyPress
procedure and works in general. Most importantly I had to assume a keyboard layout as a base for conversion of characters with the Shift modifier key. We don't need to be afraid of game receiving uppercased input now however, since that was a feature baked into BIOS keyboard handling and the game had to deal with it already. I've chosen US QWERTY trying to cover as many users as possible, I guess it's still better than not working at all. I didn't bother with setting the correct scancode for regular letters and punctuation — apart from special keys with charcode 0, the game only processes the scancode when saving and reading the key setup, but never really depends on the value. But I left the code to set it which was already there, since that is technically a more correct way to emulate the BIOS functionality. I've also modifiedSDLPort.KeyPressed
so that pressing the modifier keys alone doesn't trigger anything, in line with DOS version.I've conducted some behavioral testing between the DOS version and this patch, and on the surface it seems to work the same way now. Concerning processing of national characters, the
a with ring above
ando with diaeresis
comments were swapped, so while I was at it I also added the rest of characters supported by the game as well.