Wikifang:Network Translation Patchsite/SpriteManager: Difference between revisions

From Wikifang, a definitive guide to Telefang, Dino Device and Bugsite
Jump to navigation Jump to search
No edit summary
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:
Bugsite's metasprite system is a scriptable SpriteManager which manages the movement of objects on a playfield. These objects need to be managed as a collection of hardware sprites (on systems which support them). In GB retroprogramming parlance these collections of sprites are called metasprites. SpriteManager is Bugsite's implementation of a metasprite system.
Bugsite's metasprite system is a scriptable SpriteManager which manages the movement of objects on a playfield. These objects need to be managed as a collection of hardware sprites (on systems which support them). In GB retroprogramming parlance these collections of sprites are called metasprites. SpriteManager is Bugsite's implementation of a metasprite system.
== Directions ==
Sprites can be said to be ''facing'' a certain direction; and these directions themselves are referred to either by enumerants or input bits. Here's which is which:
{| class="wikitable"
|+ Direction Key
|-
! Direction !! Enumerant !! Input bit
|-
| Right / East || 0 || Bit 4
|-
| Left / West || 1 || Bit 5
|-
| Up / North || 2 || Bit 6
|-
| Down / South || 3 || Bit 7
|}


== Metasprite Data Structure ==
== Metasprite Data Structure ==
Line 16: Line 34:
Bit 1: Metasprite is active, meaning the user is expected to be able to see it. Sprites are usually activated and deactivated by a per-frame clip test; however, sprites can also manually deactivate themselves. Deactivated sprites are processed normally, but they do not create visible hardware sprites on screen.
Bit 1: Metasprite is active, meaning the user is expected to be able to see it. Sprites are usually activated and deactivated by a per-frame clip test; however, sprites can also manually deactivate themselves. Deactivated sprites are processed normally, but they do not create visible hardware sprites on screen.


Bit 2: Metasprite is running an animation. New animations won't be queued, and idle loop scripts won't run, until the animation completes. Stationary animations do not set this flag and are always interruptible animations.
Bit 2: Metasprite is in motion. New animations won't be queued, and choreography scripts won't run, until the animation completes. Stationary animations do not set this flag and are always interruptible animations.


Bit 3: Metasprite has been locked to it's stationary animation.
Bit 3: Metasprite is frozen. Choreography scripts will not run and sprite will consistently repeat it's idle animation.


Bit 4: Metasprite has been locked to it's stationary animation. For some reason, there are two bits with the same effect. It is unknown if one bit has different semantics from the other.
Bit 4: Metasprite is frozen. Choreography scripts will not run and sprite will consistently repeat it's idle animation.
 
For some reason, there are two bits with the same effect of freezing the sprite. It is unknown if one bit has different semantics from the other.
|-
|-
| SpriteY || +$01 || Y coordinate of sprite (16bit)
| SpriteY || +$01 || Y coordinate of sprite (16bit)
Line 30: Line 50:
| AnimAllowed || +$07 || Must be non-zero for animations to run on this sprite.
| AnimAllowed || +$07 || Must be non-zero for animations to run on this sprite.
|-
|-
| FileIndex || +$08 || Offset from the base files for stationary and moving animations.
| Direction || +$08 || Which direction the sprite is facing.
 
The file index appears to be restricted to the following common indices; BugVM instructions that directly set FileIndex will wrap any further values to zero.


{| class="wikitable"
Acts as an offset from the base files for stationary and moving animations. Is not allowed to exceed 3; further values would be meaningless.
|+ Common indices
|-
! Direction !! FileIndex
|-
| Right / East || 0
|-
| Left / West || 1
|-
| Up / North || 2
|-
| Down / South || 3
|}


''See "[[#Directions|Directions]]".''
|-
|-
| FileAnimStationary || +$09 || BugFS file ID containing an animation script to be used for the stationary animation.
| FileAnimStationary || +$09 || BugFS file ID containing an animation script to be used for the stationary animation.
Line 53: Line 60:
| FileAnimMoving || +$0B || BugFS file ID containing an animation script to be used for walk cycles and other sprite-moving animations.
| FileAnimMoving || +$0B || BugFS file ID containing an animation script to be used for walk cycles and other sprite-moving animations.
|-
|-
| IdleTime || +$0D || How many idle frames to continue executing the current IdleInstr.
| ChoreoRepeat || +$0D || How many times to continue executing the current ChoreoInstr.
|-
|-
| IdleInstr || +$0E || The current IdleInstr being executed.
| ChoreoInstr || +$0E || The current choreography instruction being executed.
''See "Idle Loop Instructions".''
 
''See "[[#Choreography_Instructions|Choreography Instructions]]".''
|-
|-
| IdlePC || +$0F || Pointer to the next idle loop instruction to execute.
| ChoreoPC || +$0F || Pointer to the next choreography instruction to execute.
|-
|-
| IdleScript || +$11 || Pointer to the start point of the current idle loop.
| ChoreoScript || +$11 || Pointer to the start of the current choreography script.
|-
|-
| || +$13 to +$1F || Presumed empty
| || +$13 to +$1F || Presumed empty
Line 72: Line 80:
! Field !! Offset !!  
! Field !! Offset !!  
|-
|-
| || +$00 || Purpose unknown. Zeroed upon initialization.
| Playing || +$00 || Set non-zero when an animation is ready to play.
|-
|-
| Delay || +$01 || Amount of frames to wait until next frame of animation.
| Delay || +$01 || Amount of frames to wait until next frame of animation.
Line 83: Line 91:
|-
|-
| AnimPC || +$07 || Pointer to the next animation instruction to execute.
| AnimPC || +$07 || Pointer to the next animation instruction to execute.
''See "[[#Animation_Script_Instructions|Animation Script Instructions]]".''
|-
|-
| SpriteIndex || +$09 || Index of the metasprite slot that this animation serves.
| SpriteIndex || +$09 || Index of the metasprite slot that this animation serves.
Line 98: Line 108:
Yes, Bugsite has ''two of them''.
Yes, Bugsite has ''two of them''.


=== Idle Loop Instructions ===
=== Choreography Instructions ===
Idle loops are small lists of instructions that dictate how a non-player-controlled sprite, such as an NPC, will move across the screen. Each instruction is preceded by a repeat count; each instruction will execute that many times before moving to the next idle loop. A maximum of one idle instruction will execute per frame, and idle instructions wait for animations to finish before proceeding. Idle loop opcodes do not have operands, and only one flow control instruction.
Choreography scripts are small lists of instructions that dictate how a non-player-controlled sprite, such as an NPC, will move across the screen. Each instruction is preceded by a repeat count; each instruction will execute that many times before moving to the next instruction. A maximum of one choreography instruction will execute per frame, and choreography instructions wait for their triggered animations to finish before proceeding. Choreography opcodes do not have operands, and only one flow control instruction.


Setting a repeat value of 0 causes the loop to stop executing instructions. The current instruction will still execute.
Setting a repeat value of 0 causes the loop to stop executing instructions. The current instruction will still execute; however, the next time the sprite is processed, the stationary animation for it's current direction will play.


{| class='wikitable'
{| class='wikitable'
Line 109: Line 119:
| ENOP $nn || $00-$4F || N/A || Treated as effective NOP by the script interpreter.
| ENOP $nn || $00-$4F || N/A || Treated as effective NOP by the script interpreter.
|-
|-
| INOP $50 || $50 || $33F7 || NOP
| CNOP $50 || $50 || $33F7 || NOP
|-
|-
| INOP $51 || $51 || $33FA || NOP
| CNOP $51 || $51 || $33FA || NOP
|-
|-
| INOP $52 || $52 || $33FD || NOP
| CNOP $52 || $52 || $33FD || NOP
|-
|-
| IDOWN || $53 || $341F || Move sprite down.
| CDOWN || $53 || $341F || Run the sprite's move-down animation.
|-
|-
| IUP || $54 || $3436 || Move sprite up.
| CUP || $54 || $3436 || Run the sprite's move-up animation.
|-
|-
| ILEFT || $55 || $344D || Move sprite left.
| CLEFT || $55 || $344D || Run the sprite's move-left animation.
|-
|-
| IRIGHT || $56 || $3464 || Move sprite down.
| CRIGHT || $56 || $3464 || Run the sprite's move-right animation.
|-
|-
| INOP $57 || $57 || $347B || NOP
| CNOP $57 || $57 || $347B || NOP
|-
|-
| IWAIT || $58 || $3400 || Run the sprite's stationary animation a random number of times, from $0 to $20.
| CWAIT || $58 || $3400 || Run the stationary animation for the sprite's current direction a random number of times, from $0 to $20.


The repeat value of this instruction is ignored.
The repeat value of this instruction is ignored.
|-
|-
| ISTOP || $59 || $341C || Run the sprite's stationary animation.
| CSTOP || $59 || $341C || Run the stationary animation for the sprite's current direction.
|-
|-
| EFGAME $nn || $60-$EF || N/A || Invalid opcodes, will likely crash game.
| EFGAME $nn || $60-$EF || N/A || Invalid opcodes, will likely crash game.
|-
|-
| IHALT || $F0 || $33C0 || Reset the idle loop back to IdleScript.
| CHALT || $F0 || $33C0 || Reset the choreography script back to ChoreoScript.


The repeat value of this instruction is always treated as 0 (e.g. halt).
The repeat value of this instruction is always treated as 0 (e.g. halt).
|-
|-
| IRESET || $F1 || $33E2 || Reset the idle loop back to IdleScript.
| CRESET || $F1 || $33E2 || Reset the choreography script back to ChoreoScript.
|-
|-
| EFGAME $nn || $F2-$FF || N/A || Invalid opcodes, will likely crash game.
| EFGAME $nn || $F2-$FF || N/A || Invalid opcodes, will likely crash game.
|}
|}
''Please keep in mind that directional commands such as CDOWN, CUP, CLEFT, and CRIGHT do not actually move the sprite.'' Instead, they queue the animation script associated with that direction. The animation script itself moves the sprite; it's only by convention that, e.g. CDOWN always executes a script that moves the sprite down two tiles. Furthermore, script execution is predicated upon the target tiles being free; if they are occupied, then the choreography script will halt until that slot becomes free. This has the following consequences:
* The movement path specified by the choreography script will be followed exactly.
* Sprites can get 'stuck' on stationary walls, or even each other.
* NPCs will 'box in' players, never moving until the player moves out of their way, as the player is just another sprite.
Eight choreography script slots exist in memory starting at $2:DC00. Each script storage slot is 128 bytes maximum.


=== Animation Script Instructions ===
=== Animation Script Instructions ===
This scripting engine does the actual job of specifying how a sprite will animate from frame to frame when moving across the screen.
This scripting engine does the actual job of specifying how a sprite will animate from frame to frame when moving across the screen, as well as moving the sprite's origin, reserving space in the movement array, and generating hardware sprites to display. Animation scripts are executed continuously whenever the sprite has been marked as animated (See State field).
 
{| class='wikitable'
|-
! Opcode !! Encoding(s) !! Native Impl. !! Description
|-
| EFGAME $nn || $00-$2F || N/A || Invalid opcodes, will likely crash game.
|-
| SCRNDOWN || $32 || $2A29 || Scroll the screen (e.g. background layer) down one pixel.
|-
| SCRNLEFT || $34 || $2993 || Scroll the screen (e.g. background layer) left one pixel.
|-
| SCRNRIGHT || $36 || $2948 || Scroll the screen (e.g. background layer) right one pixel.
|-
| SCRNUP || $38 || $29DE || Scroll the screen (e.g. background layer) up one pixel.
|-
| RESRVDOWN || $44 || $2AC4 || Mark tile downward as occupied by this sprite.
|-
| RESRVLEFT || $4C || $2BD8 || Mark tile leftward as occupied by this sprite.
|-
| FRAME || $4F || $2C73 || Draw a frame of animation.
 
This instruction takes one operand; a 16b offset from the start of the containing BugFS file with frame data for this instruction.
|-
| RESRVRIGHT || $52 || $2B7C || Mark tile rightward as occupied by this sprite.
|-
| CLRESET || $53 || $2AA5 || Deactivate the sprite and jump back to the start of the animation script.
|-
| RESRVUP || $55 || $2B20 || Mark tile upward as occupied by this sprite.
|-
| WAIT || $57 || $2A77 || Halt animation processing for a certain number of frames.
 
This instruction takes one operand; the number of frames to halt for. It is encoded bias $30 (e.g. the operand minus $30 is what is ultimately stored in Delay).
|-
| MOVDOWN || $64 || $2AD5 || Move the sprite down by 16 pixels, and release prior movement reservations.
|-
| MOVLEFT || $6C || $2BE9 || Move the sprite left by 16 pixels, and release prior movement reservations.
|-
| MOVRIGHT || $72 || $2B8D || Move the sprite right by 16 pixels, and release prior movement reservations.
|-
| RESET || $73 || $2AAD || Jump back to the start of the animation script.
|-
| MOVUP || $75 || $2B31 || Move the sprite up by 16 pixels, and release prior movement reservations.
|}


== Move Permissions ==
== Move Permissions ==

Latest revision as of 22:10, 23 December 2017

Bugsite's metasprite system is a scriptable SpriteManager which manages the movement of objects on a playfield. These objects need to be managed as a collection of hardware sprites (on systems which support them). In GB retroprogramming parlance these collections of sprites are called metasprites. SpriteManager is Bugsite's implementation of a metasprite system.

Directions[edit]

Sprites can be said to be facing a certain direction; and these directions themselves are referred to either by enumerants or input bits. Here's which is which:

Direction Key
Direction Enumerant Input bit
Right / East 0 Bit 4
Left / West 1 Bit 5
Up / North 2 Bit 6
Down / South 3 Bit 7

Metasprite Data Structure[edit]

Each metasprite consists of a metasprite struct and, if animated, an optional scripting context. Both data structures exist as an array of 8 slots at $C700 and $C800, respectively. The offsets of each structure are as follows:

Metasprite Struct Fields
Field Offset
State +$00 A bitmask of various sprite properties.

Bit 0: Metasprite slot is initialized and valid. If this bit is clear, the slot can be treated as unused and overwritten with a new metasprite.

Bit 1: Metasprite is active, meaning the user is expected to be able to see it. Sprites are usually activated and deactivated by a per-frame clip test; however, sprites can also manually deactivate themselves. Deactivated sprites are processed normally, but they do not create visible hardware sprites on screen.

Bit 2: Metasprite is in motion. New animations won't be queued, and choreography scripts won't run, until the animation completes. Stationary animations do not set this flag and are always interruptible animations.

Bit 3: Metasprite is frozen. Choreography scripts will not run and sprite will consistently repeat it's idle animation.

Bit 4: Metasprite is frozen. Choreography scripts will not run and sprite will consistently repeat it's idle animation.

For some reason, there are two bits with the same effect of freezing the sprite. It is unknown if one bit has different semantics from the other.

SpriteY +$01 Y coordinate of sprite (16bit)
SpriteX +$03 X coordinate of sprite (16bit)
MovePerms +$05 Pointer into the move permissions array which references the sprite's current location.
AnimAllowed +$07 Must be non-zero for animations to run on this sprite.
Direction +$08 Which direction the sprite is facing.

Acts as an offset from the base files for stationary and moving animations. Is not allowed to exceed 3; further values would be meaningless.

See "Directions".

FileAnimStationary +$09 BugFS file ID containing an animation script to be used for the stationary animation.
FileAnimMoving +$0B BugFS file ID containing an animation script to be used for walk cycles and other sprite-moving animations.
ChoreoRepeat +$0D How many times to continue executing the current ChoreoInstr.
ChoreoInstr +$0E The current choreography instruction being executed.

See "Choreography Instructions".

ChoreoPC +$0F Pointer to the next choreography instruction to execute.
ChoreoScript +$11 Pointer to the start of the current choreography script.
+$13 to +$1F Presumed empty

If a sprite is animated, the corresponding slot in the scripting context array will also run.

Animation Script Context Fields
Field Offset
Playing +$00 Set non-zero when an animation is ready to play.
Delay +$01 Amount of frames to wait until next frame of animation.
FileBank +$02 ROM bank of the start of the script's BugFS file.
FilePtr +$03 ROM pointer of the start of the script's BugFS file.
AnimScript +$05 Pointer to start of the current animation script.
AnimPC +$07 Pointer to the next animation instruction to execute.

See "Animation Script Instructions".

SpriteIndex +$09 Index of the metasprite slot that this animation serves.

In all known instances, the script context slot index matches the metasprite it serves, even though it's not strictly necessary.

SpritePtr +$0A Pointer to the metasprite slot that this animation serves.

This appears to be strictly a convenience feature; the sprite pointer can be generated from the index using four instructions.

+$0C to +$0F Presumed empty

Sprite Script Engines[edit]

Yes, Bugsite has two of them.

Choreography Instructions[edit]

Choreography scripts are small lists of instructions that dictate how a non-player-controlled sprite, such as an NPC, will move across the screen. Each instruction is preceded by a repeat count; each instruction will execute that many times before moving to the next instruction. A maximum of one choreography instruction will execute per frame, and choreography instructions wait for their triggered animations to finish before proceeding. Choreography opcodes do not have operands, and only one flow control instruction.

Setting a repeat value of 0 causes the loop to stop executing instructions. The current instruction will still execute; however, the next time the sprite is processed, the stationary animation for it's current direction will play.

Opcode Encoding(s) Native Impl. Description
ENOP $nn $00-$4F N/A Treated as effective NOP by the script interpreter.
CNOP $50 $50 $33F7 NOP
CNOP $51 $51 $33FA NOP
CNOP $52 $52 $33FD NOP
CDOWN $53 $341F Run the sprite's move-down animation.
CUP $54 $3436 Run the sprite's move-up animation.
CLEFT $55 $344D Run the sprite's move-left animation.
CRIGHT $56 $3464 Run the sprite's move-right animation.
CNOP $57 $57 $347B NOP
CWAIT $58 $3400 Run the stationary animation for the sprite's current direction a random number of times, from $0 to $20.

The repeat value of this instruction is ignored.

CSTOP $59 $341C Run the stationary animation for the sprite's current direction.
EFGAME $nn $60-$EF N/A Invalid opcodes, will likely crash game.
CHALT $F0 $33C0 Reset the choreography script back to ChoreoScript.

The repeat value of this instruction is always treated as 0 (e.g. halt).

CRESET $F1 $33E2 Reset the choreography script back to ChoreoScript.
EFGAME $nn $F2-$FF N/A Invalid opcodes, will likely crash game.

Please keep in mind that directional commands such as CDOWN, CUP, CLEFT, and CRIGHT do not actually move the sprite. Instead, they queue the animation script associated with that direction. The animation script itself moves the sprite; it's only by convention that, e.g. CDOWN always executes a script that moves the sprite down two tiles. Furthermore, script execution is predicated upon the target tiles being free; if they are occupied, then the choreography script will halt until that slot becomes free. This has the following consequences:

  • The movement path specified by the choreography script will be followed exactly.
  • Sprites can get 'stuck' on stationary walls, or even each other.
  • NPCs will 'box in' players, never moving until the player moves out of their way, as the player is just another sprite.

Eight choreography script slots exist in memory starting at $2:DC00. Each script storage slot is 128 bytes maximum.

Animation Script Instructions[edit]

This scripting engine does the actual job of specifying how a sprite will animate from frame to frame when moving across the screen, as well as moving the sprite's origin, reserving space in the movement array, and generating hardware sprites to display. Animation scripts are executed continuously whenever the sprite has been marked as animated (See State field).

Opcode Encoding(s) Native Impl. Description
EFGAME $nn $00-$2F N/A Invalid opcodes, will likely crash game.
SCRNDOWN $32 $2A29 Scroll the screen (e.g. background layer) down one pixel.
SCRNLEFT $34 $2993 Scroll the screen (e.g. background layer) left one pixel.
SCRNRIGHT $36 $2948 Scroll the screen (e.g. background layer) right one pixel.
SCRNUP $38 $29DE Scroll the screen (e.g. background layer) up one pixel.
RESRVDOWN $44 $2AC4 Mark tile downward as occupied by this sprite.
RESRVLEFT $4C $2BD8 Mark tile leftward as occupied by this sprite.
FRAME $4F $2C73 Draw a frame of animation.

This instruction takes one operand; a 16b offset from the start of the containing BugFS file with frame data for this instruction.

RESRVRIGHT $52 $2B7C Mark tile rightward as occupied by this sprite.
CLRESET $53 $2AA5 Deactivate the sprite and jump back to the start of the animation script.
RESRVUP $55 $2B20 Mark tile upward as occupied by this sprite.
WAIT $57 $2A77 Halt animation processing for a certain number of frames.

This instruction takes one operand; the number of frames to halt for. It is encoded bias $30 (e.g. the operand minus $30 is what is ultimately stored in Delay).

MOVDOWN $64 $2AD5 Move the sprite down by 16 pixels, and release prior movement reservations.
MOVLEFT $6C $2BE9 Move the sprite left by 16 pixels, and release prior movement reservations.
MOVRIGHT $72 $2B8D Move the sprite right by 16 pixels, and release prior movement reservations.
RESET $73 $2AAD Jump back to the start of the animation script.
MOVUP $75 $2B31 Move the sprite up by 16 pixels, and release prior movement reservations.

Move Permissions[edit]

Bugsite handles collision detection with an array covering the whole of WRAM6; with a backup copy at WRAM7 for restoring old data in the array.

The array appears to exclusively bit 7 zero for unoccupied tiles and bit 7 one for occupied tiles. This is a rather inefficient use of working memory, even with the GBC's copious amounts of it; though it's unknown if the lower 7 bits of each tile byte stores flags or data other than the occupation state of the tile.