All sprite entities in Faxanadu (dropped items, NPCs, enemies, and bosses) have behavior scripts that define how they move. I'll refer to these as "BScripts" for short. This is a simplified scripting language with the following components: * **Ops:** The base operations a script can perform. This can run an action, switch a behavior, go to a script address, and other things. * **Actions:** Simple actions that can be performed, generally related to movement direction, but also spell-casting * **Behaviors:** Broader behavior routines that perform things like hopping, walking, or flying. # Memory Locations There are a few memory locations relevant to BScripts: | Bank | Address Range | Description | | ---- | ------------- | ---------------------- | | 12 | $A5E7 - $A66A | Behaviors lookup table | | 12 | $A6D8 - $A6E7 | Ops lookup table | | 12 | $A794 - $A7A3 | Actions lookup table | # BScripts Structure BScripts have the following structure: | Script Offset | Size (bytes) | Description | | ------------- | ------------ | ----------- | | 0 | 1 | Op ID | | 1+ | N | Parameters | | ... | | | Scripts will end with an End Script (0xFF) or Go To (0x05 + address). # Ops Operations are identified by a number between 0 and 7, and a special value 0xFF. Implementations are all in Bank 12. Here's a quick summary of the ops: | Op ID | Name | Parameters | Implementation Address | | ----- | --------------- | ----------- | ---------------------- | | $00 | Switch Behavior | 2 (2 bytes) | $A6FF | | $01 | | | $A72C | | $02 | Run Action | 1 (1 byte) | $A772 | | $03 | | | $A7E5 | | $04 | | | $A86E | | $05 | Go To | 1 (2 bytes) | $A74C | | $06 | | | $A84F | | $07 | | | $A6E8 | | $FF | End Script | 0 | N/A | # Actions Actions are simple movement or attack changes in a sprite that may be invoked in-between behaviors. They do not take any parameters. Implementations are all in Bank 12. Here's a quick summary of the actions: | Action ID | Name | Implementation Address | | --------- | ------------------------- | ---------------------- | | $00 | Face player (X) | $867B | | $01 | Flip X direction | $8407 | | $02 | Face player (Y) | $8691 | | $03 | Flip Y direction | $8410 | | $04 | Randomly flip X direction | $A7AD | | $05 | Randomly flip Y direction | $A7C9 | | $06 | Fly upward | $A7A4 | | $07 | Cast magic | $9239 | # Behaviors Behaviors are more detailed code paths that make up the bulk of most sprites' overall logic. They may take any number of parameters (but always at least 1 — an arbitrary data value), and work with various bits of state in memory. Implementations are all in Bank 12. Here's a quick summary of the behaviors: | Behavior ID | Name | Parameters | Implementation Address | | ----------- | ------------------ | ----------- | ---------------------- | | $00 | Walk Toward Player | 3 (3 bytes) | $A8FC | | $01 | Wait | 1 (1 byte) | $A98B | | $02 | | | $8D0A | | $03 | | | $9E6D | | $04 | Walk Forward | 3 (3 bytes) | $A941 | | $05 | _No-op_ | 1 (1 byte) | $A6AE | | $06 | | | | | $07 | | | | | $08 | | | | | $09 | Hop | 4 (4 bytes) | $A9DE | | $0A | | | | | $0B | _No-op_ | 1 (1 byte) | $A6AE | | $0C | | | | | $0D | | | | | $0E | | | | | $0F | | | | | $10 | | | | | $11 | | | | | $12 | | | | | $13 | | | | | $14 | | | | | $15 | | | | | $16 | | | | | $17 | | | | | $18 | | | | | $19 | | | | | $1A | | | | | $1B | | | | | $1C | | | | | $1D | | | | | $1E | | | | | $1F | | | | | $20 | | | | | $21 | | | | | $22 | | | | | $23 | | | | | $24 | | | | | $25 | | | | | $26 | | | | | $27 | | | | | $28 | | | | | $29 | | | | | $2A | | | | | $2B | | | | | $2C | | | | | $2D | | | | | $2E | | | | | $2F | | | | | $30 | | | | | $31 | | | | | $32 | | | | | $33 | | | | | $34 | | | | | $35 | | | | | $36 | | | | | $38 | | | | | $39 | | | | | $3A | | | | | $3B | | | | | $3C | | | | | $3D | | | | | $3E | | | | | $3F | | | | | $40 | | | | | $41 | | | | ## Behavior $01: Walk Toward Player **Function Address:** $A8FC **Arguments:** 1. Number of ticks to walk 2. Per-tick X fractional distance (1 byte) 3. Per-tick X full distance (1 byte) Walks a pre-set distance toward the player. ## Behavior $09: Hop **Function Address:** $A9DE **Arguments:** 1. Data value (unused) 2. X fractional movement for hop (1 byte) 3. X full movement for hop (1 byte) 4. Hop mode (1 byte) Hops up and then down, optionally moving in an X direction at the same time. The following hop modes are supported: | Hop Mode | Jump Strength | Gravity Index | Start Tick Value | Ground Tick Value | | -------- | ------------- | ------------- | ---------------- | ----------------- | | 0 | 4 | 2 | $40 (64) | $C0 (192) | | 1 | 5 | 3 | $20 (32) | $60 (96) | | 2 | 6 | 4 | $10 (16) | $30 (48) | | 3 | 7 | 5 | $08 (8) | $18 (24) | | 4 | 7 | 4 | $10 (16) | $30 (48) | The Gravity Index is used for two things: 1. A gravity calculation for falling 2. A peak tick lookup table, to determine whether it's time to flip the Y direction (from jumping to falling). The peak tick lookup table (not all values are used by this behavior — it's shared with others). | Index | Value | | ----- | ----- | | 0 | $FF | | 1 | $7F | | 2 | $3F | | 3 | $1F | | 4 | $0F | | 5 | $07 | | 6 | $03 | | 7 | $01 |