MMIO registers
Every register is a 32-bit word. Access is R (read with lw), W (written with sw) or RW.
| Register | Address | Access | Meaning |
|---|---|---|---|
VELOCITY |
0xffff0010 |
RW | The velocity, -10 to 10. Writes are clamped to that range |
ANGLE |
0xffff0014 |
RW | Read: the heading, 0 to 359. Write: stages an angle from -360 to 360 for ANGLE_CONTROL, and other values are ignored |
ANGLE_CONTROL |
0xffff0018 |
W | 0 turns by the staged angle, 1 sets the heading to it, and other values are ignored |
TIMER |
0xffff001c |
RW | Read: the current cycle. Write: requests a TIMER interrupt at that cycle |
BOT_X |
0xffff0020 |
R | The bot's x in pixels |
BOT_Y |
0xffff0024 |
R | The bot's y in pixels |
OTHER_X |
0xffff00a0 |
R | The opponent's x in pixels, or -1 in a one-bot match |
OTHER_Y |
0xffff00a4 |
R | The opponent's y in pixels, or -1 in a one-bot match |
BASE_LOCATION |
0xffff0044 |
R | The center of the bot's base in pixels: x in the upper 16 bits, y in the lower 16 |
BASE_OTHER_LOCATION |
0xffff0048 |
R | The center of the other base, packed the same way |
SEARCH_FIELD |
0xffff00dc |
W | Copies the field map to the address written |
FIELD_MAP_BYTES |
0xffff00c0 |
R | The size of the field map, 900 |
NUM_PAINT |
0xffff0040 |
R | The paint left |
TRAIL_LENGTH |
0xffff00c4 |
R | The tiles in the bot's unfinished trail |
LAST_TRAIL_CANCEL_REASON |
0xffff00c8 |
R | The latest cancellation reason |
LAST_CLAIMED_TILES |
0xffff00cc |
R | The tiles the latest completed trail gained |
SCORES_REQUEST |
0xffff1018 |
W | Writes the bot's score, then the opponent's, as two words at the address written |
REQUEST_PUZZLE |
0xffff00d0 |
W | Requests a puzzle for the buffer at the address written |
CURRENT_PUZZLE |
0xffff00b8 |
RW | Write: selects the puzzle for SUBMIT_SOLUTION, numbered from 0 in request order. Read: the selection, -1 before the first write |
AVAIL_PUZZLES |
0xffff00b4 |
R | The puzzle requests accepted so far |
SUBMIT_SOLUTION |
0xffff00d4 |
W | Submits the solution at the address written for the selected puzzle |
TIMER_ACK |
0xffff006c |
W | Acknowledges TIMER |
BONK_ACK |
0xffff0060 |
W | Acknowledges BONK |
REQUEST_PUZZLE_ACK |
0xffff00e4 |
W | Acknowledges one REQUEST_PUZZLE |
TRAIL_CANCELLED_ACK |
0xffff00e8 |
W | Acknowledges one TRAIL_CANCELLED |
TERRITORY_DISCONNECTED_ACK |
0xffff00ec |
W | Acknowledges one TERRITORY_DISCONNECTED |
MMIO_STATUS |
0xffff204c |
R | The status of the last game command |
PRINT_INT |
0xffff0080 |
W | Prints the value in signed decimal |
PRINT_HEX |
0xffff0088 |
W | Prints the value in lowercase hexadecimal |
PRINT_FLOAT |
0xffff0084 |
W | Prints the value as a single-precision float with six decimals |
Each print register writes the value and a newline to the bot's Console tab in the debugger. The print registers also work under tournament rules.
These accesses raise a data bus error:
- A byte or halfword access to a register
- A read of a W register or a write to an R register
- An access to an address from
0xffff0000up with no register
Under tournament rules, a data bus error crashes the bot.
Buffer pointers
#Four registers take the address of a buffer in the bot's memory:
| Register | Buffer size | Word-aligned |
|---|---|---|
SEARCH_FIELD |
900 bytes | No |
SCORES_REQUEST |
8 bytes | Yes |
REQUEST_PUZZLE |
268 bytes | Yes |
SUBMIT_SOLUTION |
num_rows * num_cols bytes of the selected puzzle |
No |
The whole buffer must lie in the data segment, from 0x10000000 to the current end of the heap, or in the stack area, from 0x7ff00000 to 0x7fffffff. A buffer that breaks these rules sets MMIO_STATUS to BAD_ADDRESS, and the game writes nothing and queues no puzzle.
MMIO_STATUS
#Writes to CURRENT_PUZZLE, REQUEST_PUZZLE, SUBMIT_SOLUTION, SEARCH_FIELD, REQUEST_PUZZLE_ACK, TRAIL_CANCELLED_ACK and TERRITORY_DISCONNECTED_ACK set MMIO_STATUS, and so does a SCORES_REQUEST with a bad buffer.
| Value | Name | Meaning |
|---|---|---|
| 0 | OK |
The command succeeded |
| 1 | WRONG_SOLUTION |
The solution leaves a cell above 0 or has a press amount of num_colors or more, the puzzle is already solved, or CURRENT_PUZZLE names no requested puzzle |
| 2 | BAD_ADDRESS |
The buffer breaks the buffer pointer rules |
| 3 | TOO_MANY_PUZZLES |
The bot has already requested 2,000 puzzles |
Field map
#SEARCH_FIELD writes one byte per tile, 900 bytes in row-major order: the tile in row r and column c is byte r * 30 + c. Owners and trails are relative to the bot that asks.
| Bits | Field | Values |
|---|---|---|
| 0-1 | Owner | 0 nobody, 1 the asking bot, 2 the opponent |
| 2-3 | Trail | 0 none, 1 the asking bot's, 2 the opponent's |
| 4 | Wall | 1 for a wall |
| 5 | Home | 1 for a home-base tile. The owner bits say whose |
| 6-7 | Reserved | Always 0 |
For example, the asking bot reads its own base tiles as 0x21 and the opponent's as 0x22.