When the event broker sends an event notification, it uses its own event messages, which it creates as necessary. After the event broker creates an event message, it copies the information into the message's data block. The information contains a report of the status of each event type that matches a set bit in either the listener of the trigger or capture masks. You can think of the event message data block as a snapshot of the status of all listener-specified events during the field. Only events specified in the trigger mask can trigger the snapshot, but the status of all events specified in either mask is reported in the message.
For example, consider a listener that specifies the "Gun Button Pressed" event type in its trigger mask, and the "Control Button Update" and "Keyboard Update" event types in its capture mask. When any gun attached to the control port is pressed during a field, the event broker prepares an event message for the listener. The event message's data field reports a gun button press and the status of the Control Button Update and Keyboard Update events (indicating whether or not either of those events occurred during the field). If the "gun button pressed" event had not occurred, the event broker would not have sent an event message to the listener, even if keyboard or controller pad button updates occurred, because those event types were in the capture mask but not in the trigger mask.
GetMsg()
call. The listener can then read the message's data block (described in Reading an Event Message Data Block below), and either act on the data or store it for later use.
After a listener has processed the event data in an event message, the listener must reply to the event broker. Its reply tells the event broker that the event message is once again free for use. If the listener does not reply to an event message, the event broker assumes that the message was not processed. Each unprocessed event message is one element in the listener's event queue. When the number of unprocessed event messages exceeds the maximum event queue depth, the event broker stops reporting events to the listener. Consequently, the listener loses events until it can process and free up messages in its queue. If the listener asks to be notified of an event queue overflow, the event broker reports it as soon as an event message is free. The update event types (EB_ControlButtonUpdate
, EB_MouseUpdate
, and so on) are all reported as occurring, because an event queue overflow is considered an update.
To reply to an event message and return it to the event broker, a listener uses the ReplyMsg()
call. Always pass NULL as the data pointer, and 0 as the data size parameter to ReplyMsg()
.
Reading an Event Message Data Block
When a listener receives an event message from the event broker, a pointer to the event data block is in the msg_DataPtr
field of the message structure, and the size in bytes of the data block in the msg_DataSize
field. To interpret the event data stored in the event message, the listener task must be able to read the data structures used in the data block.
EB_EventRecord
and follows with one or more EventFrame
structures, each containing the report of a single event. (Each event report is called an event frame.) The final structure in the data block is a degenerate EventFrame data structure, which indicates the end of the event frames.
typedef struct EventFrame
{
uint32 ef_ByteCount; /* total size of EventFrame */
uint32 ef_SystemID; /* 3DO machine ID, or 0=local */
uint32 ef_SystemTimeStamp; /* event-count timestamp */
int32 ef_Submitter; /* Item of event sender, or 0 */
uint8 ef_EventNumber; /* event code, [0,255] */
uint8 ef_PodNumber; /* CP pod number, or 0 */
uint8 ef_PodPosition; /* CP position on daisychain, or 0 */
uint8 ef_GenericPosition; /* Nth generic device of type, or 0 */
uint8 ef_Trigger; /* 1 for trigger, 0 for capture */
uint8 rfu1[3];
uint32 rfu2;
uint32 ef_EventData[1]; /* first word of event data */
} EventFrame;
ef_ByteCount
gives the total size of the EventFrame
in bytes. Because the event data at the end of the frame varies in size depending on the event, this value changes from frame to frame.
ef_SystemID
reports the ID number of the 3DO unit where this event occurred. This value is useful if two or more 3DO units are linked together (as they might be for networked games). If the event occurred on the local 3DO unit, this value is set to 0.
ef_SystemTimeStamp
is the exact system time the event broker recorded this event. This time value corresponds to the current vblank count value as provided by the timer device's TIMER_UNIT_VBLANK
unit.
ef_Submitter
gives the item number of the event sender. This value is important when multiple listener tasks tied into the event broker send events to each other. This item number is the item number of the sending task. If the event comes from a pod and not a task, this field is set to 0.
ef_EventNumber
is an event code from 0 to 255 that identifies the generic type of event. These event types are the same as the event types identified within a configuration event mask. The include file event.h defines a constant for each type as shown in Table 2.
ef_PodNumber
gives the unique pod number of the pod where an event originated. This number is constant and is assigned when a pod is first plugged into the 3DO unit. It does not change if the pod changes its position in the control port daisy chain. This value is set to 0 if the event did not originate in a pod (for example, an event generated by another task or the CD-ROM drive).
ef_PodPosition
gives the position of the event-reporting pod in the control port daisy chain. Numbering starts with 1 for the first pod, and continues consecutively the further the chain extends from the 3DO unit. If the event did not originate in a pod, this value is set to 0.
ef_GenericPosition
, gives the daisy-chain position of the event-reporting pod among identical generic device types in the daisy chain. A generic device type is a functional description of the pod or part of the pod, and currently includes the following defined types:
POD_IsControlPad
POD_IsMouse
POD_IsGun
POD_IsGlassesCtlr
POD_IsAudioCtlr
POD_IsKeyboard
POD_IsLightGun
POD_IsStick
POD_IsIRController
ef_Trigger
identifies an event as one that triggered the event notification or as a captured event that did not trigger the notification. If the value is 1, the event was a triggering event; if the value is 0, the event is a captured event.
ef_EventData
is the first word of a data structure that contains data about an event. The rest of the data structure follows this field in memory. The definition of the data structure depends entirely on the generic device where the event occurred. The data structures are described in Reading Event Data.
ef_ByteCount
field. The rest of the EventFrame data structure cannot be present.
Reading Event Data
The event data array at the end of each full event frame is a data structure that determines the type of device reporting the event. For example, an event occurring on a controller pad uses a structure designed to report control pad data. An event occurring on a mouse uses a structure designed to report mouse data.
ControlPadEventData
, defined in event.h as follows:
typedef struct ControlPadEventData
{
uint32 cped_ButtonBits; /* left justified, zero fill */
} ControlPadEventData;
cped_ButtonBits
contains a value whose bits tell the status of each controller pad button during the field. The constants defining these flag bits are as follows:
ControlDown
- the down arm of the joypad cross.
ControlUp
- the up arm of the joypad cross.
ControlRight
- the right arm of the joypad cross.
ControlLeft
-the left arm of the joypad cross.
ControlA
-the A button.
ControlB
- the B button.
ControlC
- the C button.
ControlStart
- the P (play/pause) button.
ControlX
-the X (stop) button.
ControlLeftShift
- the left shift button.
ControlRightShift
- the right shift button.
EVENTNUM_ControlButtonPressed
event, 1 means the button was pressed since the last field, 0 means the button was not pressed.
EVENTNUM_ControlButtonReleased
event, 1 means the button was released since the last field, 0 means the button was not released.
EVENTNUM_ControlButtonUpdat
event, 1 means the button is down; 0 means the button is up.
EVENTNUM_ControlButtonArrived
event, 1 means the button is down; 0 means the button is up.
MouseEventData
, defined in event.h as follows:
typedef struct MouseEventData
{
uint32 med_ButtonBits; /* left justified, zero fill */
int32 med_HorizPosition;
int32 med_VertPosition;
} MouseEventData;
med_ButtonBits
contains a value whose bits tell which mouse button (or buttons) generated the event. The constants defining these flag bits are as follows:
MouseLeft
- the left mouse button.
MouseMiddle
- the middle mouse button.
MouseRight
- the right mouse button.
MouseShift
- the mouse's shift button.
EVENTNUM_MouseButtonPressed
event, 1 means the button was pressed since the last field; 0 means the button was not pressed.
EVENTNUM_MouseButtonReleased
event; 1 means the button was released since the last field, 0 means the button was not released.
EVENTNUM_MouseUpdate
evenly; 1 means the button is down, a 0 means the button is up.
EVENTNUM_MouseDataArrived
event; 1 means the button is down, a 0 means the button is up.
EVENTNUM_MouseMoved
event; 1 means the button is down, 0 means the button is up.
med_HorizPosition
and med_VertPosition
report the mouse's current position in absolute space. That position is reckoned from an origin (0,0) that is set when the mouse is first plugged in, and uses units that will typically (depending on the mouse) measure 100, 200, or 400 increments per inch. It is up to the task to interpret the absolute position of the mouse to a pointer position on the display.
typedef struct LightGunEventData
{
uint32 lged_ButtonBits; /* left justified, zero fill */
uint32 lged_Counter; /*cunter at top-center of hit */
uint32 lged_LinePulseCount; /* # of scan lines which were hit */
} LightGunEventData;
lged_ButtonBits
contains a value whose bits tell the state of the various triggers, buttons, and other pushable or flippable controls on a light gun. Most light guns have one trigger and one auxiliary button. The only flag bit currently defined for this field is:
LightGunTrigger
- the main light gun trigger.
lged_Counter
contains a value which specifies the number of times that the light gun's internal clock (nominally 20 MHz) counted up, between the time it was reset (during vertical blanking) and the time that the light gun's optical sensor "saw" a flash of light from the display as the display's electron beam passed through its field of view. The beam travels left to right along each line, and downwards from line to line.
lged_LinePulseCount
contains the value 0 if the light gun sensor did not detect a sufficiently strong pulse of light while scanning the video field. In this case, the lged_Counter
value may or may not be valid. If the light gun sensor detected a sufficiently strong pulse of light, lged_LinePulseCount
contains a nonzero value. Some light guns can actually count the number of successive horizontal scan lines during a pulse and return that value in this field. For light guns of this sort, the lged_LinePulseCount
is considered a "quality of signal" indicator. Other light guns simply return a constant value (typically 15) to indicate that their sensor detected at least one pulse that was strong enough to trip the sensor.
StickEventData
, defined in event.h as follows:
typedef struct StickEventData
{
uint32 stk_ButtonBits; /* left justified, zero fill */
int32 stk_HorizPosition;
int32 stk_VertPosition;
int32 stk_DepthPosition;
} StickEventData;
stk_ButtonBits
contains a value that identifies which joystick button (or buttons) generated the event. The constants defining these flag bits are as follows:
StickCapability
- the AND of Stick4Way
and StickTurbulence.
Stick4Way
- determines how many buttons the stick has.
StickTurbulence
- indicates whether or not the stick understands output commands.
StickButtons
- the stick buttons.
StickFire
- the joystick was fired.
StickA
- the A button.
StickB
- the B button.
StickC
- the C button.
StickUp
- the up button of the stick.
StickDown
- the down button of the stick.
StickRight
- the right button of the stick.
StickLeft
- the left button of the stick.
StickPlay
- the play button of the stick.
StickStop
- the stop button of the stick.
StickLeftShift
- the left-shift button of the stick.
StickRightShift
- the right-shift button of the stick.
stk_HorizPosition
, stk_VertPosition
, and stk_DepthPosition
contain binary numbers and return a value between 0 through 1023. A value of 0 means the joystick is pushed left or all of the way down. A value of 1023 means the joystick is pushed right or all the way up. Keep in mind that some joysticks cannot go all the way to 0 or 1023.
EVENTNUM_DeviceOnline
or EVENTNUM_DeviceOffline
respectively, the DeviceStateEventData structure contains the Item number of the device, and the unit number within the device that has gone on-line or off-line. The DeviceStateEventData
structure is defined as follows:
typedef struct DeviceStateEventData
{
Item dsed_DeviceItem;
uint32 dsed_DeviceUnit;
} DeviceStateEventData;
EVENTNUM_FilesystemMounted
, EVENTNUM_FilesystemDismounted
, or EVENTNUM_FilesystemOffline
, the FileSystemEventData structure contains the Item number of the Filesystem node, and the name of the filesystem which is changing state. The FileSystemEventData structure is defined as follows:
typedef struct FilesystemEventData
{
Item fsed_FilesystemItem;
char fsed_Name[FILESYSTEM_MAX_NAME_LEN];
} FilesystemEventData;