Event Codes Reference
Firmware Event Codes Reference
The KN5000 firmware uses a hierarchical event dispatch system to communicate between UI components, DISK MENU handlers, and extension ROMs. Events are 32-bit codes dispatched via SendEvent (synchronous) or PostEvent (asynchronous queue). This page documents all known event codes, their dispatch paths, and how they interact with the handler chain.
Freshness policy: This page must be updated whenever new event codes are discovered during reverse engineering or homebrew development. See Documentation Freshness Policy below.
Event Code Format
Event codes are 32-bit values with a structured layout:
0x01E0009C
├── 0x01E0 = Event port/category prefix
└── 0x009C = Event number within that category
The prefix determines which dispatch layer handles the event:
| Prefix | Category | Dispatch Layer | Description |
|---|---|---|---|
0x01E0 |
Lifecycle / Object | ClassProc → ObjectProc → InheritedProc | Object lifecycle, getters, activation |
0x01C0 |
Request / Action | Record function directly | Button presses, UI actions, initialization |
0x01E4 |
Grid/Check Response | UI widget system | Widget state query responses |
Dispatch Architecture
Event arrives (via SendEvent or PostEvent queue)
│
▼
SendEvent (0xFA9660)
│ Saves global state, looks up handler from object table
│ Calls handler function (typically ClassProc)
│
▼
ClassProc (0xFA44E2) ─── Layer 1: Simple Getters & Specials
│ Handles: 0x01E00000-0x01E00007 (getters via jump table)
│ 0x01E0000D (keypress), 0x01E0000E (input)
│ 0x01E0000F (return immediately)
│ 0x01E00015 (return config pointer)
│
│ Everything else falls through to:
▼
ObjectProc (0xFA3D85) ─── Layer 2: Lifecycle Events
│ Handles: 0x01E00010-0x01E00023 (20 lifecycle cases)
│ via jump table at 0xEAA8A4
│
│ Everything else falls through to:
▼
InheritedProc (0xFA4409) ─── Layer 3: Handler Chain
│ Follows "next handler" chain in data record (+0x04)
│ Calls chained handler's implementation function
│
▼
Record Function (implementation) ─── Layer 4: Handler-Specific
│ Called by SendEvent (step 9) for ALL events
│ Receives: XWA=object_id, XBC=event_code, XDE=param
│ This is where extension ROM handlers intercept events
│
▼
Default Handler (workspace[0x0E0A][0x00DC])
Handles remaining lifecycle management if delegated
Key insight: The record function (Layer 4) receives ALL events, regardless of which layer processed them first. For extension ROMs, the record function is the primary interception point.
Known Event Codes
ClassProc Getter Events (0x01E00000-0x01E00007)
Handled by ClassProc’s jump table at 0xEAA8F8. These are fast property queries.
| Code | Name | Handler | Return Value |
|---|---|---|---|
0x01E00000 |
EVT_IDENTITY |
ClassProc_Event_LoadFromWA | Returns XWA unchanged (identity query) |
0x01E00001 |
EVT_GET_HL |
ClassProc_Event_LoadFromHL | Returns *(XHL) |
0x01E00002 |
EVT_GET_IZ |
ClassProc_Event_LoadFromIZ | Returns *(XIZ) |
0x01E00003 |
EVT_GET_CONFIG |
ClassProc_Event_LoadFromOffset | Returns *(XHL+0x0C) |
0x01E00004 |
EVT_GETTER_4 |
(complex) | Linked object operation |
0x01E00005 |
EVT_GETTER_5 |
(complex) | Linked object operation |
0x01E00006 |
EVT_GETTER_6 |
(complex) | Linked object operation |
0x01E00007 |
EVT_GETTER_7 |
(complex) | Linked object operation |
ClassProc Special Events
| Code | Name | Dispatch | Description |
|---|---|---|---|
0x01E0000D |
EVT_KEYPRESS |
ClassProc special | Keypress handling |
0x01E0000E |
EVT_INPUT |
ClassProc special | Other input event |
0x01E0000F |
EVT_RETURN_ZERO |
ClassProc special | Returns immediately (no-op) |
0x01E00015 |
EVT_GET_CONFIG_2 |
ClassProc special | Returns *(XHL+0x0C) |
ObjectProc Lifecycle Events (0x01E00010-0x01E00023)
Handled by ObjectProc’s jump table at 0xEAA8A4. These manage object lifecycle (creation, destruction, state changes). Each maps to a specific lifecycle phase.
| Code | Name | Description |
|---|---|---|
0x01E00010 |
EVT_LIFECYCLE_10 |
Lifecycle phase 0x10 |
0x01E00011 |
EVT_LIFECYCLE_11 |
Lifecycle phase 0x11 |
0x01E00012 |
EVT_LIFECYCLE_12 |
Lifecycle phase 0x12 |
0x01E00013 |
EVT_LIFECYCLE_13 |
Lifecycle phase 0x13 |
0x01E00014 |
EVT_REDRAW |
UI redraw / refresh (observed during DISK MENU open and selection) |
0x01E00015 |
EVT_LIFECYCLE_15 |
Lifecycle phase 0x15 (also ClassProc special) |
0x01E00016 |
EVT_LIFECYCLE_16 |
Lifecycle phase 0x16 |
| … | … | Phases 0x17-0x22 (not yet individually documented) |
0x01E00023 |
EVT_LIFECYCLE_23 |
Lifecycle phase 0x23 (last) |
DISK MENU Selection Events (0x01C0xxxx)
These are request/action events that reach the record function directly. They are the primary events extension ROMs should intercept.
| Code | Name | Context | Description |
|---|---|---|---|
0x01C00001 |
EVT_MENU_OPEN |
DISK MENU opens | Sent when the DISK MENU screen is displayed |
0x01C00002 |
EVT_SELECT_CONFIRM |
Entry selected | Part of the selection sequence after button press |
0x01C00008 |
EVT_ACTIVATE |
Entry selected | Primary activation event from button press. Intercept this to detect DISK MENU selection. |
0x01C0000F |
EVT_INIT_HOOK |
Menu initialized | Custom initialization hook (HDAE5000 intercepts this specifically) |
0x01C00039 |
EVT_BUTTON_FOCUS |
Entry selected | Button focus/navigation event during selection |
Activation Events
| Code | Name | Source | Description |
|---|---|---|---|
0x01C00008 |
EVT_ACTIVATE |
Button press | Sent by firmware when user selects a DISK MENU entry via LCD panel button. This is the event to intercept for button-press activation. |
0x01E0009C |
EVT_POST_ACTIVATE |
PostEvent injection | Sent by FileIO_DiskRemoved via PostEvent(0x00600002, 0x01E0009C, 0). Used for programmatic activation. Falls through ClassProc → ObjectProc → InheritedProc chain. |
Display/Memory Allocation Events
Used by Alloc_Memory functions to query display parameters:
| Code | Name | Return Value | Description |
|---|---|---|---|
0x01E000A1 |
EVT_ALLOC_DATA_PTR |
ROM pointer | Returns palette/graphics data pointer |
0x01E000A2 |
EVT_ALLOC_WIDTH |
0x140 (320) | Returns display width |
0x01E000A3 |
EVT_ALLOC_HEIGHT |
0xF0 (240) | Returns display height |
Grid/Check Widget Events (0x01E4xxxx)
Used by the UI widget system for checkbox and grid controls:
| Code | Name | Description |
|---|---|---|
0x01E40008 |
EVT_GRIDCHECK_RESP_A |
Grid/Check widget response variant A |
0x01E40009 |
EVT_GRIDCHECK_RESP_A2 |
Grid/Check widget response variant A2 |
0x01E4000A |
EVT_GRIDCHECK_RESP_B |
Grid/Check widget response variant B |
0x01E4000B |
EVT_GRIDCHECK_RESP_B2 |
Grid/Check widget response variant B2 |
Initialization/Callback Events
Used in Boot_Init and Frame_Handler for display initialization:
| Code | Name | Context | Description |
|---|---|---|---|
0x01C00016 |
EVT_HD_INIT_PARAMS |
Boot_Init | Hard disk initialization parameters |
0x01CA0000 |
EVT_DISPLAY_CALLBACK |
Frame_Handler | Display callback identifier |
0x01CA0004 |
EVT_DISPLAY_UPDATE |
Frame_Handler | Display state update callback |
Object State Query Events
| Code | Name | Description |
|---|---|---|
0x01E0008F |
EVT_OBJECT_STATE_QUERY |
Queries object state, used by GridCheck widget system |
0x01C0000D |
EVT_POST_INIT |
Posted by HDAE5000 after 0x01C0000F custom init |
0x01C00013 |
EVT_CPANEL_EVENT |
Control panel event code (referenced in control-panel-protocol.md) |
Event Queue (PostEvent)
PostEvent (0xFAD61F) enqueues events for asynchronous dispatch:
Queue base: 0x02BC34
Entry size: 12 bytes
Max entries: 1,024 (indices 0x0000-0x03FF)
Write index: 0x02EC36 (16-bit)
Counter: 0x02F840
Entry layout:
+0x00 4 bytes Target object ID (e.g., 0x016A0005)
+0x04 4 bytes Event code (e.g., 0x01E0009C)
+0x08 4 bytes Parameter
Events are dequeued by the main event loop and dispatched via SendEvent.
DISK MENU Activation Flow
The complete sequence when a user selects a DISK MENU entry by pressing a panel button:
1. User presses RIGHT 5 button on LCD panel
2. Control panel HLE sends scan code via SC1 serial
3. Firmware interprets button as DISK MENU selection
4. SendEvent dispatches events to registered handler:
Step 1: EVT_ACTIVATE (0x01C00008)
→ ClassProc → ObjectProc → InheritedProc → Record function
→ Mines_Handler intercepts: sets GAME_ACTIVE=1, skips delegation
Step 2: EVT_BUTTON_FOCUS (0x01C00039)
→ Delegated to default handler (Mines_Handler doesn't intercept)
Step 3: EVT_SELECT_CONFIRM (0x01C00002)
→ Delegated to default handler
Step 4: EVT_REDRAW (0x01E00014)
→ Handled by ObjectProc lifecycle, then delegated
5. Next Frame_Handler call detects GAME_ACTIVE=1
6. C runtime initialized, main() called
7. Game renders minesweeper board to VRAM
For comparison, programmatic activation via PostEvent:
1. FileIO_DiskRemoved calls PostEvent(0x00600002, 0x01E0009C, 0)
2. Main loop dequeues event
3. SendEvent(slot[+0x00], 0x01E0009C, 0)
4. ClassProc: not a getter → ObjectProc
5. ObjectProc: not in 0x10-0x23 range → InheritedProc
6. InheritedProc: follows handler chain
7. Record function (Mines_Handler) intercepts: sets GAME_ACTIVE=1
Implementing Event Handlers
For homebrew extension ROMs that register handlers via RegisterObjectTable:
// Pseudo-code for a handler record function
void My_Handler(uint32_t object_id, uint32_t event_code, uint32_t param) {
switch (event_code) {
case 0x01C00008: // Button-press activation (DISK MENU selection)
GAME_ACTIVE = 1;
return; // Skip delegation to prevent default handler UI
case 0x01E0009C: // Programmatic activation (PostEvent injection)
GAME_ACTIVE = 1;
return; // Skip delegation
default:
// Delegate everything else to default handler
call_default_handler(object_id, event_code, param);
break;
}
}
Assembly implementation (TLCS-900, from the Mines project):
Mines_Handler:
push xix
push xiz
; Check for DISK MENU selection event
ld xix, 0x01C00008
cp xbc, xix
jr z, .activate
; Check for PostEvent activation
ld xix, 0x01E0009C
cp xbc, xix
jr z, .activate
; Delegate to default handler
ld xiz, (WORKSPACE_PTR)
add xiz, 0x0E0A
ld xiz, (xiz)
add xiz, 0x00DC
ld xix, (xiz)
call (xix)
jr .done
.activate:
; Set game active flag
ld xhl, GAME_ACTIVE
ld xwa, 0x00000001
ld (xhl), xwa
; Fall through to .done (skip default handler)
.done:
pop xiz
pop xix
ret
Documentation Freshness Policy
This event codes reference and the following related documentation must be updated whenever new event codes are discovered or existing codes are better understood:
- This page (
event-codes.md) – Add new codes, update descriptions, correct dispatch paths - HDAE5000 Homebrew Development – Update handler examples and activation flow
- ROM disassembly (
~/devel/kn5000-roms-disasm/) – Update symbolic names (EVT_*constants) in assembly source - Symbol reference files – Keep
hdae5000_symbols_reference.txtandmaincpu_symbols_reference.txtin sync with assembly
See also: HDAE5000 Homebrew Development for the full handler registration and dispatch system documentation.