;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DKC Barrel (1.0) ; By Sonikku ; ; The barrel object from Donkey Kong Country. ; When A or B is pressed, Mario launches in the direction that ; the sprite was facing. ; ; Have a BARREL of fun with this. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; sprite data ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; init JSL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dcb "INIT" LDA #$01 STA $157C,x STZ $C2,x RTL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; main sprite JSL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dcb "MAIN" PHB ; \ PHK ; | main sprite function, just calls local subroutine PLB ; | JSR START_HB_CODE ; | PLB ; | RTL ; / ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; main sprite routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;*******The list of values below are indexed by the sprites current frame.****** MARIOSPDY dcb $90,$D0,$00,$40,$50,$40,$00,$D0 ; Speed of Mario when shot vertically. MARIOSPDX dcb $00,$40,$40,$40,$00,$D0,$B0,$D0 ; Speed of Mario when shot horizontally. MARIODIR dcb $00,$01,$01,$01,$01,$00,$00,$00 ; Direction of Mario when shot. MARIOPOSE dcb $0B,$0C,$0C,$24,$24,$24,$0C,$0C ; Pose of Mario when shot. ;*************************************************************************************** CENTERSPD dcb $B0,$50 ; Speed at which Mario centers when touching the sprite. Changing these values not reccomended. RETURN RTS START_HB_CODE JSR SUB_GFX LDA $9D BNE RETURN JSR SUB_OFF_SCREEN_X0 LDA $14C8,x CMP #$08 BNE RETURN LDA $1540,x BNE FLYING JSL $01A7DC BCC RETURN LDA #$05 STA $1497 PHX LDX #$0C LOOP LDA $7FAB9E,x CMP $7FAB9E,x BNE DONE STZ $1540,x TXA BEQ DONE DEX BRA LOOP DONE PLX INC $1570,x LDA $1570,x LSR A LSR A LSR A AND #$07 STA $C2,x LDA #$FF STA $78 STZ $7D STZ $7B JSR SUB_HORZ_POS TYA LDA $7B CLC ADC CENTERSPD,y STA $7B LDA $D8,x SEC SBC #$16 STA $96 LDA $14D4,x SBC #$00 STA $97 LDA $16 AND #$80 BEQ RETURN STZ $140D LDA #$09 STA $1DFC LDA #$30 STA $1540,x RTS FLYING LDA $77 BNE STOPFLY LDY $C2,x LDA MARIOSPDY,y STA $7D LDA MARIOSPDX,y STA $7B LDA MARIODIR,y STA $76 LDA MARIOPOSE,y STA $72 RTS STOPFLY STZ $1540,x RTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; graphics routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TILEMAP dcb $80,$82,$A0,$A2 dcb $84,$86,$A4,$A6 dcb $88,$8A,$A8,$AA dcb $8C,$8E,$AC,$AE dcb $C0,$C2,$E0,$E2 dcb $C4,$C6,$E4,$E6 dcb $C8,$CA,$E8,$EA dcb $CC,$CE,$EC,$EE X_OFFSET dcb $FF,$FF,$FF,$FF,$F8,$08,$F8,$08 Y_OFFSET dcb $F9,$F9,$09,$09 SUB_GFX JSR GET_DRAW_INFO ; sets y = OAM offset LDA $157C,x ; \ $02 = direction ASL A ASL A STA $02 ; / LDA $C2,x ASL A ASL A STA $03 PHX LDX #$03 LOOP_START PHX TXA CLC ADC $02 TAX LDA X_OFFSET,x CLC ADC $00 ; \ tile x position = sprite y location ($01) STA $0300,y ; / PLX LDA Y_OFFSET,x CLC ADC $01 ; \ tile y position = sprite x location ($00) STA $0301,y ; / PHX TXA CLC ADC $03 TAX LDA TILEMAP,x STA $0302,y PLX PHX LDX $15E9 LDA $15F6,x ; tile properties xyppccct, format LDX $02 ; \ if direction == 0... BNE NO_FLIP ; | ORA #$40 ; / ...flip tile NO_FLIP ORA $64 ; add in tile priority of level STA $0303,y ; store tile properties PLX INY ; \ increase index to sprite tile map ($300)... INY ; | ...we wrote 1 16x16 tile... INY ; | ...sprite OAM is 8x8... INY ; / ...so increment 4 times DEX BPL LOOP_START PLX LDY #$02 ; \ 460 = 2 (all 16x16 tiles) LDA #$03 ; | A = (number of tiles drawn - 1) JSL $01B7B3 ; / don't draw if offscreen RTS ; return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $B760 - graphics routine helper - shared ; sets off screen flags and sets index to OAM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;org $03B75C TABLE1 dcb $0C,$1C TABLE2 dcb $01,$02 GET_DRAW_INFO STZ $186C,x ; reset sprite offscreen flag, vertical STZ $15A0,x ; reset sprite offscreen flag, horizontal LDA $E4,x ; \ CMP $1A ; | set horizontal offscreen if necessary LDA $14E0,x ; | SBC $1B ; | BEQ ON_SCREEN_X ; | INC $15A0,x ; / ON_SCREEN_X LDA $14E0,x ; \ XBA ; | LDA $E4,x ; | REP #$20 ; | SEC ; | SBC $1A ; | mark sprite invalid if far enough off screen CLC ; | ADC.W #$0040 ; | CMP.W #$0180 ; | SEP #$20 ; | ROL A ; | AND #$01 ; | STA $15C4,x ; / BNE INVALID ; LDY #$00 ; \ set up loop: LDA $1662,x ; | AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice BEQ ON_SCREEN_LOOP ; | else, go through loop once INY ; / ON_SCREEN_LOOP LDA $D8,x ; \ CLC ; | set vertical offscreen if necessary ADC TABLE1,y ; | PHP ; | CMP $1C ; | (vert screen boundry) ROL $00 ; | PLP ; | LDA $14D4,x ; | ADC #$00 ; | LSR $00 ; | SBC $1D ; | BEQ ON_SCREEN_Y ; | LDA $186C,x ; | (vert offscreen) ORA TABLE2,y ; | STA $186C,x ; | ON_SCREEN_Y DEY ; | BPL ON_SCREEN_LOOP ; / LDY $15EA,x ; get offset to sprite OAM LDA $E4,x ; \ SEC ; | SBC $1A ; | $00 = sprite x position relative to screen boarder STA $00 ; / LDA $D8,x ; \ SEC ; | SBC $1C ; | $01 = sprite y position relative to screen boarder STA $01 ; / RTS ; return INVALID PLA ; \ return from *main gfx routine* subroutine... PLA ; | ...(not just this subroutine) RTS ; / ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; off screen processing code - shared ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;org $03B83B TABLE3 dcb $40,$B0 TABLE6 dcb $01,$FF TABLE4 dcb $30,$C0,$A0,$80,$A0,$40,$60,$B0 TABLE5 dcb $01,$FF,$01,$FF,$01,$00,$01,$FF SUB_OFF_SCREEN_X0 LDA #$06 ; \ entry point of routine determines value of $03 BRA STORE_03 ; | SUB_OFF_SCREEN_X1 LDA #$04 ; | BRA STORE_03 ; | SUB_OFF_SCREEN_X2 LDA #$02 ; | STORE_03 STA $03 ; | BRA START_SUB ; | SUB_OFF_SCREEN_X3 STZ $03 ; / START_SUB JSR SUB_IS_OFF_SCREEN ; \ if sprite is not off screen, return BEQ RETURN_2 ; / LDA $5B ; \ goto VERTICAL_LEVEL if vertical level AND #$01 ; | BNE VERTICAL_LEVEL ; / LDA $D8,x ; \ CLC ; | ADC #$50 ; | if the sprite has gone off the bottom of the level... LDA $14D4,x ; | (if adding 0x50 to the sprite y position would make the high byte >= 2) ADC #$00 ; | CMP #$02 ; | BPL ERASE_SPRITE ; / ...erase the sprite LDA $167A,x ; \ if "process offscreen" flag is set, return AND #$04 ; | BNE RETURN_2 ; / LDA $13 ; \ AND #$01 ; | ORA $03 ; | STA $01 ; | TAY ; / LDA $1A CLC ADC TABLE4,y ROL $00 CMP $E4,x PHP LDA $1B LSR $00 ADC TABLE5,y PLP SBC $14E0,x STA $00 LSR $01 BCC LABEL20 EOR #$80 STA $00 LABEL20 LDA $00 BPL RETURN_2 ERASE_SPRITE LDA $14C8,x ; \ if sprite status < 8, permanently erase sprite CMP #$08 ; | BCC KILL_SPRITE ; / LDY $161A,x CPY #$FF BEQ KILL_SPRITE LDA #$00 STA $1938,y KILL_SPRITE STZ $14C8,x ; erase sprite RETURN_2 RTS ; return VERTICAL_LEVEL LDA $167A,x ; \ if "process offscreen" flag is set, return AND #$04 ; | BNE RETURN_2 ; / LDA $13 ; \ only handle every other frame?? LSR A ; | BCS RETURN_2 ; / AND #$01 STA $01 TAY LDA $1C CLC ADC TABLE3,y ROL $00 CMP $D8,x PHP LDA.W $001D LSR $00 ADC TABLE6,y PLP SBC $14D4,x STA $00 LDY $01 BEQ LABEL22 EOR #$80 STA $00 LABEL22 LDA $00 BPL RETURN_2 BMI ERASE_SPRITE SUB_IS_OFF_SCREEN LDA $15A0,x ; \ if sprite is on screen, accumulator = 0 ORA $186C,x ; | RTS ; / return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SUB_HORZ_POS ; This routine determines which side of the sprite Mario is on. It sets the Y register ; to the direction such that the sprite would face Mario ; It is ripped from $03B817 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SUB_HORZ_POS LDY #$00 ;A:25D0 X:0006 Y:0001 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1020 VC:097 00 FL:31642 LDA $94 ;A:25D0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZCHC:1036 VC:097 00 FL:31642 SEC ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1060 VC:097 00 FL:31642 SBC $E4,x ;A:25F0 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizCHC:1074 VC:097 00 FL:31642 STA $0F ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1104 VC:097 00 FL:31642 LDA $95 ;A:25F4 X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1128 VC:097 00 FL:31642 SBC $14E0,x ;A:2500 X:0006 Y:0000 D:0000 DB:03 S:01ED P:envMXdiZcHC:1152 VC:097 00 FL:31642 BPL SPR_L16 ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1184 VC:097 00 FL:31642 INY ;A:25FF X:0006 Y:0000 D:0000 DB:03 S:01ED P:eNvMXdizcHC:1200 VC:097 00 FL:31642 SPR_L16 RTS ;A:25FF X:0006 Y:0001 D:0000 DB:03 S:01ED P:envMXdizcHC:1214 VC:097 00 FL:31642