-
Notifications
You must be signed in to change notification settings - Fork 0
Event Runtime
Navigation: Home - Game systems - Event Runtime
Single reference for how the Amiga executable loads, triggers, and interprets
event.dat scripts. File layout is in 06-event-dat-format.md;
opcode semantics in 07-event-script-opcodes.md.
| Address | Label | Role |
|---|---|---|
0x92F2 |
event_dat_loader |
Copy current location record into A4-$47C8 (max 2220 bytes) |
0x1754A |
event_system_init |
Scan triplet table; compute string anchor + script start |
0x175E2 |
event_tile_scanner |
Match party tile + cond flags; dispatch matching event id |
0x17262 |
event_handler_pool_seek |
Skip N 0xFF-delimited records in script pool |
0x172BC |
(era gate) | Compare era_low vs cached attrib+0x0F before VM runs |
0x172CA |
event_script_interpreter |
Opcode dispatch via table @ 0x17494
|
0x1750C |
event_script_fetch_next |
Read next byte; loop or cleanup on 0xFF
|
0x155BE |
(read helper) |
work_buf[parse_pos++] — script byte fetch |
0x157FC |
event_token_skip_helper |
Skip N tokens using length table @ A4-$6CC8
|
0x15884 |
event_text_resolve_u8 |
Map u8 string index → string table pointer |
0x171AC |
event_script_cleanup |
End script (OP_0F, 0xFF, abort) |
0x1280 |
main scheduler | If tile runtime < $80 and pending latch → scanner thunk |
Thunk JSR -$7D3A(A4) from the main loop reaches 0x175E2 (vector @ $25C6E).
-
screen_mode_id = A4-$79F2(byte). - Index header:
entry = header[screen_mode_id](6 bytes/entry, BE offset + BE length). - Clamp length to
0x8AC; memcpy intoA4-$47C8(event_work_buf). - Blob pointer from
A4-$1108(event_blob).
Locations 0–59 align with map.dat / attrib.dat screens. Locations 60–70
use the same index but hold global quest banks, castle blobs, and meta reference
text (see inventory in EXTRACTED/event_location_inventory.json).
Walk work_buf from offset 0:
- Read 3-byte triplets
(pos, event, cond)until00 00 00. - Store terminator index in
A4-$7954(event_script_anchor). - Read LE u16 at terminator → add to anchor → final string-table base in
$7954. - Store
terminator + 5inA4-$5C44(event_script_start).
If no 00 00 00 group exists (locations 63, 65, 68), init never completes
normally — those records use the queued dispatch path instead.
Each pending step:
context = byte_table_6BE6[ facing_index_55D7 ]
party_tile = (coord_a << 4) | coord_b // Y in high nibble, X in low
if event_script_anchor == $FFFF → call 0x1754A
parse_pos = event_script_start
for each triplet (pos, event_id, cond):
if pos != party_tile → continue
if (cond & context) == 0 → continue
pool_seek(event_id) → optional era gate → interpreter
clear triplet bytes (one-shot)
if queued_event_id != $FF:
rebuild anchor from work_buf[0..1] as BE u16; seek queued id; re-init
if left trigger tile → clear visited bit7 + tile_rt bit7
else → pending_event_latch = 1
Condition flags (triplet byte 2, AND-masked with context_mask_tbl[facing_index]):
| Value | Meaning |
|---|---|
0x10 |
DIR_W? (west-facing context) |
0x20 |
DIR_S? (south-facing context) |
0x40 |
DIR_E? (east-facing context) |
0x80 |
DIR_N? (north-facing context; also used for ENTER tiles) |
0xC0 |
DIR_N? + DIR_E? |
0xF0 |
ANY_DIR (all four facing bits set) |
context_mask_tbl @ A4-$6BE6 (ghidra mm2_data_00.bin off 0x1418):
[0x10, 0, 0x20, 0, 0x40, 0, 0x80, 0] indexed by facing index 0/2/4/6 (W/S/E/N).
There is no “match all facings” cond byte — 0x10 door labels require west-facing only.
172CA: op = read_script_byte()
dispatch jump_table[0x17494][op] // op in 0..0x32
1750C: if op == 0xFF → cleanup
if script_abort → exit
goto 172CA
1748C: script_abort = 1
Invalid opcode (>= 0x33) branches to 0x1748C.
-
Screen gate @
0x172BC:era_low(A4-$79B5) must equal cachedattrib.datbyte0x0Ffor the current screen (A4-$A9F5). -
Script ops
OP_22/OP_23: range-check era or day-of-year intocond_flag(A4-$7951).
Anchor A4 = $7FFE. Canonical signed offsets (see mm2_gamestate.h).
| Offset | Field | Notes |
|---|---|---|
-$79F2 |
screen_mode_id |
Indexes event.dat header |
-$79F1 |
coord_b |
Party X (column) |
-$79F0 |
coord_a |
Party Y (row) |
-$7956 |
event_parse_pos |
Script PC in work buf |
-$7954 |
event_script_anchor |
String base; $FFFF = need init |
-$7952 |
pending_event_latch |
Set on movement; cleared @ 0x1280 |
-$7951 |
cond_flag |
Predicate result; gates OP_10/11 |
-$7950 |
exit_flags |
ESC / modal bits |
-$79EA |
script_abort |
Set by OP_29 / invalid op |
-$79B5 |
era_low |
Current era index |
-$79B1 |
last_move_key |
'N'/'S'/'E'/'W' |
| Offset | Field | Notes |
|---|---|---|
-$5C44 |
event_script_start |
Restored to parse_pos each scan |
-$5D46 |
queued_event_id |
$FF = none; path @ 0x176B6 |
-$5D42 |
saved_cond_flag |
OP_26/27 party select |
-$5D44 |
string_walk_index |
String resolver @ 0x15884 |
| Offset | Field | Notes |
|---|---|---|
-$55D7 |
facing_index |
0/2/4/6 → context table |
-$55D6 |
tile_runtime_flags |
Bit7 active event; <$80 allows scanner |
-$55C8 |
event_busy_sentinel |
$FF during script |
-$55BA |
tile_table_a |
OP_21 writes |
-$54BA |
tile_visited_flags |
OP_14 clears bit7 |
-$6BE6 |
context_mask_tbl |
Facing → cond context byte |
| Offset | Field | Size |
|---|---|---|
-$47C8 |
event_work_buf |
2220 |
-$6CC8 |
opcode_len_tbl |
256×16-bit deltas |
-$1108 |
event_blob |
ptr → event.dat |
-$110C |
map_blob |
ptr → map.dat |
-$A9F5 |
attrib_era_gate_cache |
byte |
Helper @ 0x157FC for OP_10, OP_11, OP_2B:
- Read count byte N.
- Repeat N times: read token byte B at parse_pos;
parse_pos += word_table[B].
Table is indexed as word[B×2] (68000 move.w (a0,d1.l), d0 after asl.l #1).
Dump / rebuild: python tools/dump_event_token_table.py.
| Tool | Purpose |
|---|---|
tools/decode_event.py |
Decode, decompile, predicates, consumed items |
tools/event_location_inventory.py |
JSON inventory of 71 locations |
tools/validate_event_map.py |
Triplet vs map collision 0x80 check |
tools/mm2_event_sim/ |
Interactive TUI simulator |
EXTRACTED/decomp/mm2_event_codec.{h,c} |
C load/decode/encode |
- 14-game-state-struct.md — full A4 workspace
- 21-map-dat-format.md — collision event bit
-
12-attrib-dat-format.md — era gate byte
0x0F
- Docs Wiki Hub ← full doc index
- Getting Started ← read this first
- Overview
- Workspace Notes
- Open Questions
- Full Analysis
- Game Remake
- Startup and Init
- Runtime Memory Map
- Main Loop and Map
- Exploration Input and Options
- Party and Session
- Game State Struct
- Data Hunk mm2 data 00
- Time Era Calendar
- GFX Loading
- ANM TV Format
- PC DOS graphics
- SNES graphics
- 3D View and Game Screen
- Amiga 3D Render Process
- Scripted Scene Graphics
- Event Graphics Opcodes
- Title Screen Assets
- Title Screen Animation
- Format inventory
- items.dat
- monsters.dat
- roster.dat
- attrib.dat
- map.dat
- spells & item use
- event.dat
- Events by location ← 71 maps
- Events hub (numbered)
- Event Script Opcodes
-
Event Script DSL ←
.mm2evtauthoring - Event Text Rendering
- Event Graphics Opcodes
- Combat Overview
- Combat System
- Encounter Tables
- Spell Cast ASM
- monsters.dat abilities
- Spells and item use
- Amiga audio in exe ← Paula / DATA / remake
- Controls: Sounds / Walk Beep
- MM2 music format (superseded)
- Title/death audio paths (superseded)
- Known songs catalog (superseded)
- Town Services
- Spell Sources
- Character Mechanics
- Skills and Hirelings
- Commerce Formulas
- Commerce World Services
- Mount Farview Class Quest
- Class Quest HP Bug
- Event Runtime
- Event to String Path
- Embedded Exe Strings
- Copy Protection
- Time Era Calendar
- Game State Struct
- MM1 Overview ← hub + decode status
- MM1 MAZEDATA format
- MM1 to MM2 outdoor
- MM1 WALLPIX by sector
- MM1 art & graphics
- MM1 items / monsters (status)
- MM1 map walker ↗
- MM1 2D maps gallery
- MM1 WALLPIX gallery