SCI/Specifications/SCI in action/Event handling in SCI

From ScummVM :: Wiki
< SCI‎ | Specifications‎ | SCI in action
Revision as of 04:18, 31 January 2009 by Timofonic (talk | contribs) (Add "Notes" section)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Originally written by Lars Skovlund

This article will deal with the event manager in SCI. Like several other key parts of the interpreter, this one actively communicates with the SCI application. It directly writes to objects of the Event class, but more on that later.

The different input devices are polled differently:

  • The keyboard is typically polled at each timer tick (which is 60 hz).
  • SCI sets up a callback for the PC mouse driver, meaning that the mouse driver "polls itself" and sends information to the interpreter. On non-MS-DOS platforms, this would probably be done in the timer handler.[1]
  • The joystick is only polled when the script wants to.

Some parts of the event mechanism (in particular, keyboard management) are very PC specific, and a conversion will no doubt have to take place on other platforms.

Event types and modifiers

There are three types of events, distinguished by their "type" property. The possible values are listed below; they are laid out as a bitfield to allow for selective event retrieval, see later.

  • 0x00 Null event
  • 0x01 Mouse button event
  • 0x02 Mouse button release event
  • 0x04 Keyboard event
  • 0x40 Movement (joystick) event

This type is returned to the SCI event managers by the input device drivers along with a "message" and a set of "modifiers". This is the basic event structure, although some event types contain extra information. The latter field is a direct copy of the BIOS shift flags, laid out as follows:

  • bit 7 Insert active
  • bit 6 Caps lock active
  • bit 5 Num lock active
  • bit 4 Scroll lock active
  • bit 3 Alt key pressed
  • bit 2 Ctrl key pressed
  • bit 1 Left shift key pressed
  • bit 0 Right shift key pressed

It is obvious, then, that these keys by themselves don't generate any keyboard events. They can, however, be combined with other keys or mouse clicks to produce "shift-click" events, for instance.

The null events

These are generated when a script wants to see an event, but there isn't one to give. The current tick count and mouse position. The tick count, as explained in another document, is the time passed since the interpreter started, measured in 1/60ths of a second. It doesn't seem to be copied into the event object, however.

The mouse events

The mouse position is returned in extra fields in the event record.

If the middle or right button is pressed, this is reflected by the modifiers, in addition to the mouse event. The middle button is translated to the Ctrl key (i.e. set modifiers bit 2), the right button "holds down" both shift keys (setting bits 1 and 0). Every SCI interpreter (at least from 0.000.572 and up) does this, but to my knowledge it is used only in QfG2, where either a shift-click or a right-click is equivalent to typing "look ...".

The keyboard event

The keyboard driver also generates events. When a key is pressed, a keyboard event is generated, with the message field set to the scan code of the pressed key. It should be simple enough, right? Not quite so. The script may want to know if a direction key was pressed, and if so, which. It may call the KMapKeyToDir kernel function for this. KMapKeyToDir takes a keyboard event as input and converts it to a movement event, which is described next.

The movement event

The movement event is only generated by the joystick driver. However, on request, the keyboard driver can convert keyboard events into movement events as described above. The message field is just a direction code, mapped as follows:

8 1 2
7 Center 3
6 5 4

That is, the direction code starts at straight up (code 1), increasing with clockwise movement.

Notes

  1. SCI sets up a callback for the PC mouse driver, meaning that the mouse driver "polls itself" and sends information to the interpreter. On non-MS-DOS platforms, this would probably be done in the timer handler.