Interrupts
The game raises five interrupt lines. A line stays raised until the bot acknowledges it by writing any value to its ACK register, which is the interrupt's name followed by _ACK, such as BONK_ACK.
| Interrupt | Line | Mask | Kind | Raised when |
|---|---|---|---|---|
TIMER |
IP7 | 0x8000 |
Latch | The cycle written to TIMER arrives |
TERRITORY_DISCONNECTED |
IP5 | 0x2000 |
Counter | The opponent's completed trail cuts some of the bot's territory off from its base |
BONK |
IP4 | 0x1000 |
Latch | The bot bonks |
REQUEST_PUZZLE |
IP3 | 0x0800 |
Counter | A requested puzzle arrives in its buffer |
TRAIL_CANCELLED |
IP2 | 0x0400 |
Counter | The bot is canceled |
The mask is the line's bit in both Cause and Status. The kind sets how events add up:
- Latch: one flag. Events while it is raised merge into it, and one ACK clears it.
- Counter: a count of events. Each ACK takes one off, and the line stays raised while the count is above 0.
LAST_TRAIL_CANCEL_REASON holds only the latest reason, however many TRAIL_CANCELLED events are pending.
A write to TIMER sets one target cycle, replacing any earlier one. The line rises at the end of that cycle, or at the end of the current cycle if the target has passed.
Taking an interrupt
#A bot takes an interrupt when Status.IE is set, Status.EXL is clear, and the line's bit is set in both Cause and Status. The simulator reference describes the mechanism. Cause shows the raised lines whether or not interrupts are enabled, so a bot can also poll Cause. This bot enables only the timer line and acknowledges it in its handler:
.text
main:
mfc0 $t1, $12 # Status
li $t2, 0xffff00ff
and $t1, $t1, $t2 # clear every mask bit
ori $t1, $t1, 0x8001 # TIMER line and IE
mtc0 $t1, $12
li $t0, 0xffff0000
lw $t1, 0x1c($t0) # TIMER: the current cycle
addiu $t1, $t1, 50000
sw $t1, 0x1c($t0) # a TIMER interrupt in 50,000 cycles
loop:
j loop
.ktext 0x80000180
lui $k0, 0xffff
sw $zero, 0x6c($k0) # TIMER_ACK
eret