MESS keyboard modes

From Ninerpedia
Jump to navigation Jump to search

Keyboard usage on MAME/MESS may be somewhat unintuitive at first sight, but there is some reason behind the things you may observe. It is, however, not so easy to find a "compromise" due to the emulation concept of MAME/MESS.

Emulated keyboard

The emulated keyboard is a set of digital switches which report 0 or 1, according to being released or pressed. In MESS, they are queried just as realized in the real machine, which means as a matrix of switches, arranged in lines and columns. The column is selected by the emulated 9901, and the respective switch status is then sampled on the input line of the emulated 9901.

On the TI console, we have key combinations like FCTN-S or CTRL-W. The actual detection of this combination is done by the key scanning routine inside the console, which is also used in MESS unchanged. So you get two presses, one for the FCTN key, and one for S. This is known as arrow left, but MESS has no idea of that, as this is not its business.

So we need a PC key that maps to the FCTN key (and a PC key that maps to the CTRL key, respectively) so that you get your two-key combination again.

The bad thing about that is that the PC keyboard layout (in particular, localized keyboards) do not match the TI layout. Suppose I want to type an open parenthesis "(". The key scan routine in the TI console expects two keys to be pressed, namely "Shift" and "9". Unfortunately, on my QWERTZ keyboard, this would be the closing parenthesis. On the other hand, everything is good when I want to type "!" as Shift-1 because there is a match. Essentially, when I use my QWERTZ keyboard and I want to type CALL SAY("#NICE TRY"), I actually have to type

CALL SAZ)þ§NICE TRZþ=

I can well understand that this is not really desirable.

We could try some workarounds for this situation in order to still keep the idea of a matrix arrangement of switches without this effect, but not on a multi-system emulator like MAME/MESS which must fit thousands of other systems. The keyboard routine is deep inside the core of MAME.

Natural keyboard

Since there obviously were some people that could not get used to the emulated keyboards, the "natural mode" was conceived. The idea here is what may have come in mind when reading the above explanation.

Instead of turning the keyboard into a set of switches, we take the keycode from the keyboard driver and simulate a set of switches that has been pressed. For example, when Shift-a is pressed, the keycode is 0x41, and the natural mode maps this to "Shift" (as the value comes from the interval of shifted keys) and "a", which means that obviously two switches are actuated.

Let's have a short look at the keyboard definition in the ti99_4x.c driver. I can explain it better with some code:

PORT_START("COL2")  // col 2
  PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C)     PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR('`')
  PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E)     PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(UCHAR_MAMEKEY(UP))
  PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D)     PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
  PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 # ERASE") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')  PORT_CHAR(UCHAR_MAMEKEY(F3))
  PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 * REDO")  PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CHAR(UCHAR_MAMEKEY(F8))
  PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I)     PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR('?')
  PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K)     PORT_CHAR('k') PORT_CHAR('K')
  PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')

This is the group of keys activated when COL2 is selected, which means column 2 in the keyboard matrix. The PORT_BIT describes the bit (line) that is set when the key is pressed. Also, we have negative logic.

The first line says that when the scancode for "c" is received (in emulated mode), this bit is set (to 0, negative logic).

The next parameters are used for the natural mode.

  • PORT_CHAR('c'): When a "c" is received from the keyboard driver, we activate this line, but no modifier key
  • PORT_CHAR('C'): When a "C" is received from the keyboard driver, we activate this line, and also the Shift key.
  • PORT_CHAR('`'): When the backtick is received from the keyboard driver, we activate this line, and also the FCTN line.

For "Cursor left" we can query for UCHAR_MAMEKEY(LEFT).

PORT_START("COL1")  // col 1
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S)   PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(UCHAR_MAMEKEY(LEFT))
...

Hence, this bit is set to 0, when "s" comes from the keyboard driver (no shift), "S" (with Shift), and Cursor Left (with FCTN).

Some observations:

  • As we take the key code from the keyboard driver, the driver has a chance to deliver the key according to the locale. No need to type CALL KEZ anymore, because when I type Y, I can be sure that the proper lines are activated.
  • Since we interact with the keyboard driver and have to iterate through all key definitions each time, the natural keyboard feels sluggish. The emulated keyboard is much more responsive. For that reason I accomodated myself to the emulated mode and feel much happier. :)
  • The natural keyboard mode can only work when the keyboard driver recognizes the keystroke. This entails delivering some keycode (probably from the unicode character set) that corresponds to the key combination.

The last point is a big problem that you already found. We have some key combinations in TI programs like CTRL-W. However, when you press those keys on the PC keyboard, they do not map to a single keycode that can be delivered by the keyboard driver, but only to raw separated scancodes from the keyboard. In other words, we cannot find a suitable PORT_CHAR to be added to the line. Without a recognized keycode, we cannot specify which lines to activate.

Summary

MAME/MESS delivers two keyboard modes which have their pros and cons. Your desire to have a simple access to the "natural" keys (like F1 or Cursor left) and the TI-specific keys like CTRL-W at the same time sounds reasonable, but I don't see how this could be solved inside MAME/MESS without a thorough redesign of the whole core keyboard routine, with the additional constraint that it must be useful for the thousand other drivers.