Code;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Homing Pipe Cannon
; by MarioFanGamer
;
; This sprite is a recreation of a barrel cannon from
; Donkey Kong Country 3 which will follow the player
; once entered until the latter lands on the ground.
; It is blocked by walls which allows you to limit its
; movement.
; Do note that you still can shoot fireballs and use the
; cape you implement patches which disable them under
; certain situations.
;
; Using extra bytes: No
;
; Extra property byte 1: Vertical speed of the player
; when getting shot.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; If using the disable fireball flag patch,
; set that one to the freeRAM set in the patch
!DisableFireballs = 0
!ShootSound = $09 ; The sound to play when you get shot
!ShootBank = $1DFC|!addr ;
!PrepareShootTime = $10 ; The time the cannon awaits in the prepare state
; Graphics
Tiles:
db $80,$85,$87,$89
XOffsets:
db $00,$10,$00,$10
YOffsets:
db $00,$00,$10,$10
; Internal defines
; The state of the cannon
!CannonState = !C2
; 0: Stationary but ready
; 1: Prepare to shoot
; 2: Following the player
; How long must the cannon wait until it can catch the player?
!TimerDisable = !1540
; This is simply used to run the desired interaction points
; The sprite itself doesn't apply any kind of movement on its own.
DummySpeed:
db $10,$F0
print "MAIN ",pc
PHB
PHK
PLB
JSR Main
PLB
RTL
Main:
JSR Graphics ; Graphics
LDA !14C8,x ; Default stuff.
EOR #$08 ;
ORA $9D ;
BNE .Return ;
;
%SubOffScreen() ; A is already zero.
;
LDA !CannonState,x ; Get current cannon state.
DEC ;
BEQ .PrepareShoot ; If Mario is in cannon...
DEC ;
BNE .NotMoving ; If cannon isn't moving...
;
LDA $72 ; Stop cannon if player is on ground.
BNE .InAir ;
STZ !CannonState,x ;
.InAir: ;
;
; LDA !B6,x ;
; BPL .NormalPos ;
; LDA !E4,x ;
; PHA ;
; SEC : SBC #$01 ;
; STA !E4,x ;
; LDA !14E0,x ;
; PHA ;
; SBC #$00 ;
; STA !14E0,x ;
; .NormalPos: ;
;
JSL $019138|!bank ; Run block interaction.
;
LDY #$00 ; SubHorzPos with offset.
LDA !14E0,x ;
XBA ;
LDA !E4,x ;
REP #$20 ;
CLC : ADC #$0010 ; Centre of sprite
STA $00 ;
LDA $94 ;
CLC : ADC #$0008 ; Centre of Mario
CMP $00 ;
SEP #$20 ;
BCS .RightOfCannon ;
INY ;
.RightOfCannon: ;
;
LDA DummySpeed,y ; Set speed so interaction points run.
STA !B6,x ; (Speed doesn't get actually applied, btw.)
;
LDA !1588,x ; Is the cannon blocked in a direction?
AND #$03 ;
BNE .NotMoving ; If so, don't move it.
;
LDA $94 ;
SEC : SBC #$08 ; Mario's position offset
STA !E4,x ;
LDA $95 ;
SBC #$00 ;
STA !14E0,x ;
;
.NotMoving: ;
LDA !TimerDisable,x ;
BNE .NoInteraction ;
JSL $01A7DC|!bank ;
BCC .NoInteraction ;
LDA #$01 ; Set state
STA !CannonState,x ;
LDA #!PrepareShootTime ; Timer until cannon shoots
STA !TimerDisable,x ;
JSR SpawnContactGraphics; Like in DKC3!
.NoInteraction: ;
.Return: ;
RTS ;
;
.PrepareShoot: ;
LDA #$FF ; Hide player (and Yoshi even not riding...)
STA $78 ;
;
LDA !D8,x ; Put player in cannon
SEC : SBC #$0B ;
STA $96 ;
LDA !14D4,x ;
SBC #$00 ;
STA $97 ;
LDA !E4,x ;
CLC : ADC #$08 ;
STA $94 ;
LDA !14E0,x ;
ADC #$00 ;
STA $95 ;
;
STZ $7B ; Remove speed of player.
STZ $7D ;
;
if !DisableFireballs ;
LDA #$01 ; Disable fireball shooting if possible.
STA !DisableFireballs ;
endif ;
;
LDA !TimerDisable,x ; Ready to shoot?
BNE .Return2 ;
;
LDA #$10 ; Prevent cannon from catching the player
STA !TimerDisable,x ; right after shooting
;
LDA !extra_prop_1,x ; Give it some speed!
STA $7D ;
INC !CannonState,x ; Set cannon to moving.
;
LDA #!ShootSound ; Cannon shot sound
STA !ShootBank ;
;
if !DisableFireballs ;
STZ !DisableFireballs ; Enable shooting fireballs
endif ;
;
LDA #$0B ; Set Mario to jumping frame.
STA $72 ;
;
LDA #$08 ; Spawn some appropriate smoke.
STA $00 ;
LDA #$F8 ;
STA $01 ;
LDA #$1B ;
STA $02 ;
LDA #$01 ;
%SpawnSmoke() ;
.Return2: ;
RTS ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Simple 32x32 GFX routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Graphics: ;
%GetDrawInfo() ;
;
LDA !15F6,x ; Get sprite properties with level mode priority.
ORA $64 ;
STA $02 ;
;
LDX #$03 ;
.Loop ;
LDA $00 ; Code is really self-explanatory
CLC : ADC XOffsets,x ; Especially since the graphics are static
STA $0300|!addr,y ;
LDA $01 ;
CLC : ADC YOffsets,x ;
STA $0301|!addr,y ;
LDA Tiles,x ;
STA $0302|!addr,y ;
LDA $02 ;
STA $0303|!addr,y ;
INY #4 ;
DEX ;
BPL .Loop ;
;
LDX $15E9|!addr ; Restore sprite index
LDY #$02 ; 16x16 tiles
LDA #$03 ; Four objects
%FinishOAMWrite() ;
RTS ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Spawn contact graphics
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SpawnContactGraphics: ;
LDY #$03 ; Loop through every smoke slot
.Loop ;
LDA $17C0|!addr,y ;
BEQ .EmptySlot ;
DEY ;
BPL .Loop ;
RTS ;
;
.EmptySlot: ;
LDA #$02 ; Set type (contact graphics)
STA $17C0|!addr,y ;
LDA $D3 ; Offset graphics
CLC : ADC #$10 ;
STA $17C4|!addr,y ;
LDA $D1 ;
STA $17C8|!addr,y ;
LDA #$08 ; Set duration
STA $17CC|!addr,y ;
RTS ;