Download the sprites featured in the docs here: Test suite
This kind of sprites are found exclusively whenever the player hits a block and there is a small image bouncing up and down at the block's position and might change the Map16 tile into another tile number.
Programming a bounce sprite just requires a file inside of misc_sprites/bounce
folder, then you can start writing code inside of your ASM file.
Bounce sprites generally don't have a lot of code going on and you can just call a few routines and call it a day, this results in rather short sprite codes, which is great at keeping the insert size down.
Example of a bounce sprite:
print "MAIN", pc
lda #$02 ; yxppccct properties
sta !bounce_properties,x
lda #$2A ; tile number
%BounceGenericDraw()
lda $9D
bne not_done
init:
lda !bounce_init,x
bne no_init
inc !bounce_init,x
%EraseCoinAbove()
%InvisibleMap16()
%SetMarioSpeed()
no_init:
%UpdatePos()
%BounceSetSpeed()
lda !bounce_timer,x
bne not_done
%RevertMap16()
stz !bounce_num,x
not_done:
rtl
This recreates the gray question mark block from the gif in the PIXI thread and as it was explained earlier, the code is rather short.
As any other sprite, bounce blocks require starting their code with the print "MAIN", pc
line, which is used by PIXI to determine where the code will start running. Also this code has the proper data bank set before being executed, so no need for any kind of wrapper.
Then it's up to you to know if you draw the sprite's graphics or wait until later, in the example above we're drawing them first, then executing the rest of the logic.
Bounce sprites can have init routines, but they're tied to a RAM address (!bounce_init
) which is used as a flag. In the init routine it's 100% expected that the bounce sprite deletes the Map16 image, give mario proper bounce speeds depending on the direction on which the bounce sprite is going to move and erase coins above it if applicable.
Out of the init routine and while the game is running normally (not paused), the bounce sprite should update its position and speed values and check if the sprite is done being processed.
When the sprite is done being processed, it must revert the Map16 tile it created to something else saved in its RAM or a constant value that's valid for $9C and set its sprite number to 0.
There are several routines included here, in this table you'll find some info about them, more details in their respective files at the routines
folder.
Routine/Macro | Description |
---|---|
%BounceGenericDraw() |
Draws a single 16x16 tile at bounce sprite's coordinates. |
%BounceGetDrawInfo() |
Gets misc information of the bounce sprite to draw it on screen and handle offscreen situations. |
%BounceChangeMap16() |
Changes the Map16 tile the bounce sprite is currently touching. You're better off using either %RevertMap16() or %InvisibleMap16() . |
%RevertMap16() |
Calls %BounceChangeMap16() Changes the Map16 tile the bounce sprite is touching with whatever value is in !bounce_map16_tile . |
%InvisibleMap16() |
Calls %BounceChangeMap16() Changes the Map16 tile the bounce sprite is touching with an invisible solid block. |
%SetSpeed() |
Shortcut for %BounceSetSpeed() . Updates the speed values in the bounce sprite. Meant to be called every frame. |
%SetMarioSpeed() |
Shortcut for %BounceSetMarioSpeed() . Updates the player's speed values to reflect them touching the bounce sprite. |
%UpdatePos() |
Shortcut for %BounceUpdatePos() . Updates the bounce sprite's position based on its X and Y speed values. |
%EraseCoinAbove() |
Deletes a coin Map16 tile above the activated block. This isn't a routine per se, it's just a macro inside of _header.asm |
%SetupCoords() |
Sets up the origin coordinates for the generic spawn routines. It's called automatically within other macros. |
%SpawnExtendedAlt() |
Calls %SpawnExtendedGeneric() . Generic routine to spawn a Extended Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnExtended() |
%SpawnSmokeAlt() |
Calls %SpawnSmokeGeneric() . Generic routine to spawn a Smoke Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnSmoke() |
%SpawnCluster() |
NOT IN PIXI YET. |
%SpawnMinorExtended() |
Calls %SpawnMinorExtendedGeneric() . Generic routine to spawn a Minor Extended Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnSpinningCoin() |
Calls %SpawnSpinningCoinGeneric() . Generic routine to spawn a Spinning Coin Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnScore() |
Calls %SpawnScoreGeneric() . Generic routine to spawn a Score Sprite (ID given in A) from the sprite's origin plus an offset. |
This sprite type is generally seen as the particle system of the game. They can be used to have certain minor effects on things to give them more impact or give feedback on what's happening, such as the Turn Block particles that are generated when the player is big and spin jumps on them.
Programming a minor extended sprite just requires a file inside of misc_sprites/minorextended
folder, then you can start writing code inside of your ASM file.
Minor extended sprites generally should have fairly simple codes to keep them as fast as possible, they also not require a very strict procedure on what should happen inside of them.
Example of a minor extended sprite:
print "MAIN",pc
lda $9D
bne .skip
lda $13
and #$03
beq .no_update_x
%SpeedXFast()
.no_update_x
%SpeedYFast()
lda $13
and #$03
bne .no_update_gravity
inc !minor_extended_y_speed,x
.no_update_gravity
.skip
%MinorExtendedGetDrawInfo()
bcc .end
lda $00
sta $0200|!addr,y
lda $01
sta $0201|!addr,y
lda #$40 ; force tile number
sta $0202|!addr,y
lda !minor_extended_timer,x
tax
eor .props,x
ora #$02
ora $64
sta $0203|!addr,y
ldx $1698|!addr
tya
lsr #2
tay
lda #$02
ora $02
sta $0420|!addr,y
.end
rtl
.props
db $00,$00,$80,$80,$80,$C0,$40,$00
This recreates the gray turn block particle from the gif at the thread, the code doesn't have a lot happening besides fairly standard stuff.
As any other sprite, bounce blocks require starting their code with the print "MAIN", pc
line, which is used by PIXI to determine where the code will start running. Also this code has the proper data bank set before being executed, so no need for any kind of wrapper.
Since minor extended sprites are just images moving around, you just need to take care of drawing them in place, most of the logic would probably be at your graphics routine to make their images a little bit more dynamic.
Minor extended sprites offer two ways of updating their X/Y position and handling their speed values, a fast and inaccurate version and a slow but accurate version. The fast speed handling treats speed values as 1 speed value = 1 px per frame
, which means that for every unit in !minor_extended_x_speed
or !minor_extended_y_speed
will travel 1 pixel. The slow one treats its speed value the same way regular sprites treat theirs, 1 speed value = 1/16th of a pixel per frame
, which results in fairly smooth trajectories but in slower code. It's up to you to decide which one fits the best on your sprites. Also, this sprite type doesn't have any gravity routines, so it's also up to you to handle that as well.
There are several routines included here, in this table you'll find some info about them, more details in their respective files at the routines
folder.
Routine/Macro | Description |
---|---|
%MinorExtendedGetDrawInfo() |
Gets misc information of the minor extended sprite to draw it on screen and handle offscreen situations. |
%SpeedX() |
Calls %MinorExtendedSpeed() . Updates the X position of the sprite based on its speed using the slow algorithm (1 unit = 1/16th px/frame). |
%SpeedXFast() |
Calls %MinorExtendedSpeed() . Updates the X position of the sprite based on its speed using the fast algorithm (1 unit = 1 px/frame). |
%SpeedY() |
Calls %MinorExtendedSpeed() . Updates the Y position of the sprite based on its speed using the slow algorithm (1 unit = 1/16th px/frame). |
%SpeedYFast() |
Calls %MinorExtendedSpeed() . Updates the Y position of the sprite based on its speed using the fast algorithm (1 unit = 1 px/frame). |
%SetupCoords() |
Sets up the origin coordinates for the generic spawn routines. It's called automatically within other macros. |
%SpawnExtendedAlt() |
Calls %SpawnExtendedGeneric() . Generic routine to spawn a Extended Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnExtended() |
%SpawnSmokeAlt() |
Calls %SpawnSmokeGeneric() . Generic routine to spawn a Smoke Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnSmoke() |
%SpawnCluster() |
NOT IN PIXI YET. |
%SpawnMinorExtended() |
Calls %SpawnMinorExtendedGeneric() . Generic routine to spawn a Minor Extended Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnSpinningCoin() |
Calls %SpawnSpinningCoinGeneric() . Generic routine to spawn a Spinning Coin Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnScore() |
Calls %SpawnScoreGeneric() . Generic routine to spawn a Score Sprite (ID given in A) from the sprite's origin plus an offset. |
Smoke sprites are a minor sprite system that handles drawing sprite images over most of the sprite types in the game. They have a very limited amount of slots available, so you can't really spam them.
Programming a smoke sprite just requires a file inside of misc_sprites/smoke
folder, then you can start writing code inside of your ASM file.
Smoke sprites are a super simple and quick sprite type, generally used for smoke particle effects. They have very limited RAM tables and usually they're static on the screen. They also don't have high bytes for their positions, so they can't handle offscreen situations very well.
Example of a smoke sprite:
print "MAIN", pc
main:
lda !smoke_timer,x
bne .process
stz !smoke_num,x
rtl
.process
ldy $9D
bne .no_update_timer
dec !smoke_timer,x
.no_update_timer
.draw
lda #$0E
sta $02
lda !smoke_timer,x
asl #5
and #$40
ora $64
sta $03
lda #$02
sta $04
%SmokeGenericDraw()
.return
rtl
As any other sprite, smoke sprites require starting their code with the print "MAIN", pc
line, which is used by PIXI to determine where the code will start running. Also this code has the proper data bank set before being executed, so no need for any kind of wrapper.
There are several routines included here, in this table you'll find some info about them, more details in their respective files at the routines
folder.
Routine/Macro | Description |
---|---|
%SetupCoords() |
Sets up the origin coordinates for the generic spawn routines. It's called automatically within other macros. |
%SpawnExtendedAlt() |
Calls %SpawnExtendedGeneric() . Generic routine to spawn a Extended Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnExtended() |
%SpawnSmokeAlt() |
Calls %SpawnSmokeGeneric() . Generic routine to spawn a Smoke Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnSmoke() |
%SpawnCluster() |
NOT IN PIXI YET. |
%SpawnMinorExtended() |
Calls %SpawnMinorExtendedGeneric() . Generic routine to spawn a Minor Extended Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnSpinningCoin() |
Calls %SpawnSpinningCoinGeneric() . Generic routine to spawn a Spinning Coin Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnScore() |
Calls %SpawnScoreGeneric() . Generic routine to spawn a Score Sprite (ID given in A) from the sprite's origin plus an offset. |
print "MAIN", pc
lda $9D
bne .draw
lda !score_y_speed,x
bne .alive
stz !score_num,x
rtl
.alive
dec !score_y_speed,x
cmp #$2A
bne .skip_reward
.give_reward
lda $0F48|!addr
clc
adc.b #10
cmp.b #90
bcc .not_max
lda.b #99
.not_max
sta $0F48|!addr
lda #$01
sta $1DFC|!addr
.skip_reward
.handle_movement
%UpdateYPos()
.draw
lda #$44
sta $07
lda #$EF
sta $08
lda #$00
sta $09
lda #$08
sta $0A
%ScoreGenericDraw()
rtl
As any other sprite, score sprites require starting their code with the print "MAIN", pc
line, which is used by PIXI to determine where the code will start running. Also this code has the proper data bank set before being executed, so no need for any kind of wrapper.
There are several routines included here, in this table you'll find some info about them, more details in their respective files at the routines
folder.
Routine/Macro | Description |
---|---|
%SetupCoords() |
Sets up the origin coordinates for the generic spawn routines. It's called automatically within other macros. |
%SpawnExtendedAlt() |
Calls %SpawnExtendedGeneric() . Generic routine to spawn a Extended Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnExtended() |
%SpawnSmokeAlt() |
Calls %SpawnSmokeGeneric() . Generic routine to spawn a Smoke Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnSmoke() |
%SpawnCluster() |
NOT IN PIXI YET. |
%SpawnMinorExtended() |
Calls %SpawnMinorExtendedGeneric() . Generic routine to spawn a Minor Extended Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnSpinningCoin() |
Calls %SpawnSpinningCoinGeneric() . Generic routine to spawn a Spinning Coin Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnScore() |
Calls %SpawnScoreGeneric() . Generic routine to spawn a Score Sprite (ID given in A) from the sprite's origin plus an offset. |
print "MAIN", pc
lda $9D
bne .draw
%UpdateYPos()
lda !spinning_coin_y_speed,x
clc
adc #$03
sta !spinning_coin_y_speed,x
cmp #$20
bmi .draw
.erase
stz $00
stz $01
lda.b #$00+!ScoreOffset
%SpawnScore()
lda !spinning_coin_layer,x
sta !score_layer,y
stz $00
stz $01
lda #$10
sta $02
lda !spinning_coin_layer,x
lsr
php
lda !spinning_coin_x_low,x
bcc .no_layer_2_x
sbc $26
.no_layer_2_x
sta $04
lda !spinning_coin_y_low,x
plp
bcc .no_layer_2_y
sbc $28
.no_layer_2_y
sta $06
lda #$05
xba
%SpawnSmokeGeneric()
stz !spinning_coin_num,x
rtl
.draw
;draw routine ommited, check the actual file for it (too long)
There are several routines included here, in this table you'll find some info about them, more details in their respective files at the routines
folder.
Routine/Macro | Description |
---|---|
%SetupCoords() |
Sets up the origin coordinates for the generic spawn routines. It's called automatically within other macros. |
%SpawnExtendedAlt() |
Calls %SpawnExtendedGeneric() . Generic routine to spawn a Extended Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnExtended() |
%SpawnSmokeAlt() |
Calls %SpawnSmokeGeneric() . Generic routine to spawn a Smoke Sprite (ID given in A) from the sprite's origin plus an offset. An alternative and generic version of %SpawnSmoke() |
%SpawnCluster() |
NOT IN PIXI YET. |
%SpawnMinorExtended() |
Calls %SpawnMinorExtendedGeneric() . Generic routine to spawn a Minor Extended Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnSpinningCoin() |
Calls %SpawnSpinningCoinGeneric() . Generic routine to spawn a Spinning Coin Sprite (ID given in A) from the sprite's origin plus an offset. |
%SpawnScore() |
Calls %SpawnScoreGeneric() . Generic routine to spawn a Score Sprite (ID given in A) from the sprite's origin plus an offset. |