techcompliant / TC-Specs

Specifications for in-game computer design
27 stars 14 forks source link

Keyboard handling #26

Open Yamakaky opened 8 years ago

Yamakaky commented 8 years ago

https://github.com/techcompliant/TC-Specs/blob/master/Input/keyboard.md

How do we handle non-QWERTY keyboards? On my AZERTY keyboard, 0-9 is entered by pressing Shift. Same thing for all the symbols. Additionally, I'm not sure that "ASCII letters are uppercase when either shift or control are held down." is sound. In the real world, it's the OS which converts from key code to ascii using a QWERTY or ASCII charmap. I see two solutions:

jameskirkwood commented 8 years ago

For what it's worth, in Notch's leaked emulator, ASCII characters were added to the buffer when the OS sent a keyTyped event to a Java KeyListener, or when a keyPressed event corresponding to any of {Backspace, Return, Insert or Delete} was sent. This meant the buffer held the typed characters (or Insert/Delete key down events), not necessarily the pressed keys, and holding control prevented characters from being buffered at all. However it seems orlof's DCPU-Admiral relies on the Control key itself being buffered along with combined keys.

keyPressed and keyReleased events were used to track key states. Strangely, Control, Alt and AltGr all map to "Control" and alphabetical keys map to lower case ASCII letters only, but I presume others would agree that both upper and lower case ASCII should be usable to poll keys.

Of course, I'm not suggesting TC should implement it the same way, but it does highlight how much room for interpretation there is in the original specification I suppose.

paultech commented 8 years ago

Take into account the existing bug also for keyboard - https://github.com/techcompliant/TC/issues/12

@andyleap @Meisaka Input?

andyleap commented 8 years ago

Big question is: how much do we want to break existing compatibility? There's programs that rely on the current functionality... It'd be possible to add a new interrupt code to get an "unmapped" key? I don't want to go all the way to "real world", though, as that's a bit complex/pointless. One thought is to take advantage of the 16 bit words and have lower byte be the key pressed, and then have the upper byte be bitmask of "modifier buttons"

paultech commented 8 years ago

@orlof @azertyfun @MadMockers @alfie275 @Blecki can we break compatibility with your existing software packages made available to TC? I see the biggest hurdle to this being TC is unavailable to test at this time and we'd break support for using other emulators in the interim

andyleap commented 8 years ago

unless we add additional interrupts, the emulator will be, technically, still compliant, as it isn't involved with key mapping. All we'd really need to do is tweak ICIClient to match. I can take care of that, if need be, and put out a windows build of it (it was a bit of frustration to build it).

Yamakaky commented 8 years ago

As for cFrOSt, I think we are OK

paultech commented 8 years ago

Sorry @Yamakaky I didn't notice your involvement with cFrost or I would of @'ed you also!

azertyfun commented 8 years ago

Additionally, even back then it was kind of hit-and-miss. I remember being unable to use programs on 0x10co.de for example.

Yamakaky commented 8 years ago

That's OK, I'm more into my emu for now ^^ There is also @l3nn0x and @vaasref

MadMockers commented 8 years ago

My view is it would be best be to extend the keyboard spec without changing the behaviour of the existing keyboard interrupts if there are going to be major changes. I think following what Notch's emulator originally did is ideal. The OS (as in the real OS that is running TC) can do the hard work of converting scan codes to a character, and then that gets fed into the keyboard buffer. This is probably the easiest way to support everyone in my view. AFAIK this is how most implementations have worked up until now anyway.

andyleap commented 8 years ago

I think the current behavior doesn't even match notch's emulator. We're kinda at the point of "if we keep going, it will make changing much more painful". One thought is to add an additional interrupt, and make it a "Get raw code" interrupt, with a shared buffer between the 2, so a program can choose to either get the "decoded" version of a letter, like shift+a yielding 'A', or a raw version, where shift+a may yield 0x0161 (that's 0x61 in the lower byte, for 'a', and 0x01 in the upper byte as a bitmask saying "shift was held").

Yamakaky commented 8 years ago

Basically, we have to cases. You may want to get the raw keys (think game controls) or the ascii letters (like a shell).

jameskirkwood commented 8 years ago

There is also the question of whether key repeat ("typematic") should be generated by the OS (as in Notch's emulator), the keyboard emulator, or by the DCPU program if needed (or even made configurable by the player, or DCPU program).

orlof commented 8 years ago

Admiral currently expects that all keys from 0x10 to 0x83 can be read from buffer with a=1. Admiral relies that with my keyboard shift+a yields A and shift+1 yields !

Admiral never expects to receive CTRL or SHIFT from buffer.

I did experience with key repeat, but typically my DASM was unable to process the keys fast enough and it caused a lot of problems.

Sidenote: After reading a key from buffer, Admiral's getchar uses a=2, b=0x91 interrupt to explicitly query CTRL button state and set it as the 15th bit of the key. e.g. CTRL+SHIFT+a should yield 0x41 from buffer and after CTRL masking it comes out as 0x8041 from my getchar.

Blecki commented 8 years ago

@paultech pretty much nailed it. The problem is nothing to test with. The default keyboard implementation is stupid IMO. It would not be hard to adapt, just, no way to test.

jameskirkwood commented 8 years ago

Oops, sorry @orlof, not sure how I got that wrong (it was ages ago that I tested it). The reason Admiral didn't seem to work on Lettuce (nor my unreleased emulator) was that it expects capital letters to be buffered while the control key is held, as per TC's current spec. (Holding both shift and control works though.)