Code;========================================================================================================================
;The Ultimate n00b sprite
;Coded by Nesquik Bunny - heavily optimized by Blind Devil
;Please credit if used
;
;A highly customizable boss with configurable health and actions. This boss can have up to 35ish (!) different actions, and
;can change actions depending on his health. See below for configurations and the readme for more detailed info.
;========================================================================================================================
!Health = 10 ; Health the sprite has (in decimal!). Can be anywhere between 0-99. Don't be silly, though.
!FaceMario = 1 ; Initially face Mario? 0 = no, 1 = yes.
!AnimationSpd = 2 ; Speed for sprite's animation.
; 0 = slow, 1 = medium (like most sprites), 2 = fast (like Fuzzy/Mega Mole).
!HurtSFX = $20 ; Sound effect for when the boss gets stomped/attacked.
!HurtPort = $1DF9 ; Port used for above SFX.
!Gravity = $00 ; Y speed for the sprite if setting custom gravity behavior on.
; 00 makes it float in the air (doesn't rise nor fall)
; Suggested value: any value from 00-50.
; 10 = low gravity.
; 50 = high gravity.
!Ledges = 0 ; Does your sprite stay on ledges? If it jumps/floats, it's advised to change this to 0.
; 0 = no, 1 = yes.
!DeathType = 2 ; Type of Death:
; 0 = Fall down, as if killed by star
; 1 = Disappear in a puff of smoke.
; 2 = Explosion (bob-omb) style.
!DoFlash = 1 ; Does the sprite "flash" when it gets hurt? Flashes through colors and cannot be in
; contact if it does.
; 0 = no, 1 = yes.
!ExitType = 0 ; Type of exit when sprite dies:
; 0 = Goal sphere style, normal exit (no walking).
; 1 = Goal sphere style, secret exit (walking).
; 2 = Teleport to whatever in the screen exit.
; 3 = Fade to OW. (Exit specified below).
; Anything else = do nothing. Useful if not using sprite as a boss, but as a regular sprite.
!ExitSong = $03 ; Type of music when boss is defeated (only applicable if !Exit is 0-2)
; You will likely have to change this if using AMK.
!OWExit = 1 ; If using !Exit as option 3, to fade to the OW...
; 0 = Side exit (trigger no events), 1 = normal exit, 2 = secret exit.
!NormalSprite = $00 ; Normal sprite to generate (if generating one).
!CustomSprite = $02 ; Custom sprite to generate.
; NOTE: Generating a custom sprite that doesn't exist will (probably) result in a crash.
SPRITE_TO_GEN: ; For generating random normal sprites, write the sprite numbers here.
db $0D,$0F,$10,$09
!RandTableSize = $03 ; Size for above table, -1.
!SpawnSound = $09 ; Sound to play when a normal/random normal/custom sprite is spawned.
!SpawnPort = $1DFC ; Port used for above SFX.
!SprAimSpd = $18 ; Speed to spawn sprites aimed ath the player (applicable if using JSR AimSpr right after a sprite spawning routine)
!INITSTAT = $01 ; STATUS for above sprites. For stationary shells, make this 09 etc.
; See !14C8,x in the RAM Map for all states.
!StunTimerA = $20 ; How long the sprite stuns the ground, in frames (applicable if using JSR Strong)
!StunTimerB = $40 ; How long the sprite stuns the ground in frames (applicable if using JSR Strong2)
!JumpHeight = $D0 ; New Jump height for the player if poisoned. $FF = mimimum, 80 = maximum.
; Advisable - A0-E0
!PoTimer = $03 ; Time to poison Mario, in seconds (if using JSR Poison).
!Speed = $18 ; Speed Mario gets when poisoned. 00 = No speed at all, 26 = Max running speed.
; Advisable values = 15-20.
!Col = 1 ; Have a green face when Mario is poisoned? 0 = no, 1 = yes.
; NOTES:
; IF NEAR THE STATUS BAR (TOP), THE COLORS REVERT TO NORMAL
; SAME IF THE PLAYER PAUSES.
; THIS AFFECTS COLORS 86,89, 8C and 8E only.
; IT ALSO DOESN'T WORK ON SA-1.
!High = $45 ; Color for Mario's face when poisoned.
!Low = $0E ; 4 digit SNES RGB values, like this:
; XXYY <- YY is !High, and XX is Low.
!High2 = $B6
!Low2 = $30 ; Color for Mario's pants.
!FireballHealth = 1 ; Can your sprite be hurt by fireballs?
; 0 = no, 1 = yes.
!UseMultiplier = 1 ; If your boss can be hurt by fireballs, should Mario shoot 3 fireballs at him
; before decrementing his actual HP? (tl;dr: fire HP = HP*3)
; 0 = no, 1 = yes.
!CapeHealth = 1 ; Can your sprite be hurt by cape spins?
; 0 = no, 1 = yes.
!DisableFlight = 0 ; Disable cape flight during the boss battle?
; 0 = don't disable, 1 = disable.
!ExSound = $26 ; Sound to play when either a bone or hammer is thrown.
!ExPort = $1DF9 ; Port used for above SFX.
!PTimer = $88 ; Timer, in fourth frames, for P-switch (if it's activated).
!FTimer = $4F ; How long the sprite flashes when hit, in frames.
!Dark = $0B ; Screen brightness to use when using JSR Dark.
!Dark2 = $07 ; Screen brightness to use when using JSR Dark2.
; Can be from 00-0F.
; 0F - default brightness, 00 = Completely black (not recommended).
!Spinjumpable = 1 ; Should the sprite be spinjumpable?
; If not, even a spinjump will hurt Mario if not using JSR JumpHurt.
; 0 = no, 1 = yes.
!PushPlayer = 1 ; "Push" Mario back after jumping on the sprite?
; 0 = no, 1 = yes.
!RiseLoc = $00F0 ; If making your sprite rise at a certain hitpoint (JSR Rise)
; ..specify the height at which it should stop.
; Below values are most common ones in case your boss is located in the bottom subscreen boundary of an horizontal level:
; 0145 = 40% up of the screen.
; 0130 = Halfway up the screen.
; 0115 = 2/3 up screen.
; 00F0 = Right below the status bar.
; Must be 4 digits, otherwise the game will crash!
!RiseSpeed = $E0 ; Speed at which the sprite rises.
; 80 - Extremely fast.
; FF - Slowest.
; Suggested: A0-E0.
!DropSpeed = $16 ; If making your sprite drop again, specify the speed..
; ..at which it falls down.
; 01 = slowest, 7F = extremely fast.
; Suggested values: 10-40.
; NOTE, it stops when it touches the ground.
!Invulnerangry = 1 ; Should the sprite be immune to attacks if on angry state (if using JSR Ramming)?
; If so, thrown items and stomps will hit, but won't take any effect.
; 0 = no, 1 = yes.
!RamSpd = $30 ; Speed to use for sprite when it's about to ram a wall (if using JSR Ramming).
; 01 = slowest, 7F = extremely fast.
; Suggested values: 28-48.
!AngryProp = $08 ; Palette/properties the sprite will use when on angry state (if using JSR Ramming), YXPPCCCT format.
!PushMario = $22 ; Speed to knockback Mario if the sprite touches him. (Only applicable if doing JSR Push).
!YPush = $D5 ; Upwards knockback speed if sprite hurts Mario.
;If making your sprite chase Mario..
MaxAcceleration: db $10,$F0 ; Maximum X speeds the sprite can chase.
MaxAccelerationY: db $10,$F0 ; Maximum Y speeds the sprite can chase.
AccelerationX: db $02,$FE ; Acceleration for X speed.
AccelerationY: db $02,$FE ; Acceleration for Y speed.
;If using messages, read below:
!Msg1T = $01 ; Message one type. 01 = Message one, 02 = Message two.
!Msg2T = $01 ; Same for the second message.
!Msg1L = $00 ; Level of first message.
!Msg2L = $29 ; Level of second message.
;These can be quite tricky. Up to level 24 = 24, but then it's 25 for level 101. 101 = 25, 102 = 26, 103 = 27, 104 = 28,
;105 = 29, 106 = 2A, 107 = 2B etc.
; Level 00 = 00
; Level 1A = 1A
; Level 20 = 20
; etc.
; Level 24 = 24
; Level 101 = 25 ; After level 24 comes level 101, so that becomes 25.
; Level 102 = 26
; Level 103 = 27.
;================================================================
;Status Bar Stuff Here!
;================================================================
!A = $0A : !B = $0B : !C = $0C : !D = $0D : !E = $0E : !F = $0F : !G = $10 : !H = $11 : !I = $12 : !J = $13 : !K = $14
!L = $15 : !M = $16 : !N = $17 : !O = $18 : !P = $19 : !Q = $1A : !R = $1B : !S = $1C : !T = $1D : !U = $1E : !V = $1F
!W = $20 : !X = $21 : !Y = $22 : !Z = $23
!ShowTiles = 0 ; Draw <Name>x<HP> on status bar? (E.g. SMWCx10)
; 0 = no, 1 = yes.
NameTable:
db !S,!M,!W,!C ; Name of boss. Write like this: !A for A, !F for F, !Q for Q etc.
; MUST PUT THE ! AND COMMA (,) after each letter except the last one.
; The db at the beginning is important, don't touch that.
; db !F,!A,!I,!L will write "FAIL".
!NameSize = $03 ; The number of letters you wrote for your boss -1. For example, If my boss was called
; LOL, I would put a 02 here (3-1). (NOTE: must be 2 digit, so for 04 write 04, not 4)
!Position = $0EF9 ; Position to draw tiles to.
; Can be anywhere from $0EF9-$0F2F. See 1024's status bar for reference.
;================================================================
;Graphics Defines!
;================================================================
;Notes:
;This is a 32x32 Boss, so it has 4 tiles - Top Left, Top Right, Bottom Left and Bottom Right.
;BlindEdit: the previous method for non-animated tiles was bad and wasted space so it went bust. So, by default,
;it will always animate between frames. If you want frames to not animate, change the respective animation
;frames to the same values.
;For each 16x16 tile (Top Right, Top Left etc.) , you specify the top-left part of that 16x16 tile. For example, the Mushroom
;is a 16x16 tile. In the 8x8 editor it's tile 0x324. So you would right the last 2 digits - 24 for that and the whole 16x16
;gets drawn. Similarly, the fire flower graphic would be 26.
;NOTE: IF YOU CHOOSE "use second graphics page" in the CFG editor (which is set by default), it'll use tiles from SP3 and SP4.
;Frames for Animate (default):
!TopLeft = $CC
!TopRight = $CE
!BottomLeft = $EC
!BottomRight = $EE
!WalkTopLeft = $C8
!WalkTopRight = $CA
!WalkBottomLeft = $E8
!WalkBottomRight = $EA
;If using more animation frames in the sprite, specify them here:
;NOTE: To use them, use JSR Animate2 and JSR Animate3 in your sprite STATES.
;Frames for Animate2:
!TopLeft2 = $CC
!TopRight2 = $CE
!BottomLeft2 = $EC
!BottomRight2 = $EE
!WalkTopLeft2 = $8A
!WalkTopRight2 = $8C
!WalkBottomLeft2 = $AA
!WalkBottomRight2 = $AC
;Frames for Animate3:
!TopLeft3 = $CA
!TopRight3 = $CC
!BottomLeft3 = $EA
!BottomRight3 = $EC
!WalkTopLeft3 = $CA
!WalkTopRight3 = $CC
!WalkBottomLeft3 = $EA
!WalkBottomRight3 = $EC
;================================================================
;Sprite X Speeds Are Configurable Here!
;================================================================
; Notes:
; If your sprite has 6HP, you need to write to the first 7 values of the table only (00-06), if it has 3 HP, write to the first 4 values of the table etc.
; Slowest speed is 01 and fastest is 7F. It's recommended to not go higher than 25 as it gets very fast from there onwards.
; 00 is stationary i.e. the sprite doesn't move.
; First value in the table is for 00 HP, last value is for 99 HP. Writing to values not used doesn't have any affect.
Tbl1R: db $00,$11,$11,$12,$14,$10,$00,$13,$18,$14,$10 ; 00-10
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 11-21
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 22-32
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 33-43
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 44-54
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 55-65
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 66-76
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 77-87
db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF ; 88-98
db $FF ; 99
;===================;
; Pointers ;
;===================;
MainPointer:
LDA !1528,x ;load boss HP
JSL $0086DF|!BankB ;call 2-byte pointer subroutine
dw STATE0 ; Dead state. Don't use for actions (only RTS)
dw STATE1 ; 01, last hit point.
dw STATE2 ; 02, 2 hit points left ..
dw STATE3 ; 03, 3rd last hit point.
dw STATE4 ; 04, etc.
dw STATE5 ; 05
dw STATE6 ; 06
dw STATE7 ; 07
dw STATE8 ; NOTE! MAKE SURE YOU HAVE AS MANY DWS AS YOUR BOSS HP, OTHERWISE YOU MIGHT GET PROBLEMS!
dw STATE9
dw STATE10
;Here, for every state, you should call the boss actions (specified below), and you can potentially write your own codes kinda like uberASM.
;Codes will run every frame per state.
;And make sure you use one boss hurt subroutine per state, or else the boss will be intangible/invincible.
STATE10:
JSR Push
JSR Ramming
JSR AnyHurt
JSR HammerA
RTS
STATE9:
JSR Push
JSR Ramming
JSR AnyHurt
JSR HammerA
RTS
STATE8:
JSR Push
JSR GenCSpr
JSR AimSpr
JSR HammerA
JSR Strong2
JSR AnyHurt
RTS
STATE7:
JSR Push
JSR JumpC
JSR Strong2
JSR AnyHurt
JSR HammerA
RTS
STATE6:
JSR Push
JSR Strong2
JSR HammerA
JSR AnyHurt
RTS
STATE5:
JSR Push
JSR HammerA
JSR Strong2
JSR AnyHurt
JSR Roar
RTS
STATE4:
JSR Push
JSR HammerA
JSR Strong2
JSR AnyHurt
RTS
STATE3:
JSR Push
JSR JumpA
JSR HammerB
JSR AnyHurt
RTS
STATE2:
JSR Push
JSR HammerB
JSR JumpA
JSR Strong2
JSR AnyHurt
RTS
STATE1:
JSR Push
JSR HammerB
JSR JumpA
JSR SpitFire
JSR SpitFire
JSR SpitFire
JSR Follow
JSR AnyHurt
RTS
STATE0: ;this is dead state, no actions required.
JSR PSwitch ; Makes the sprite turn on the P-switch.
RTS
;==================================================================
;OPTION POINTERS ARE HERE!
;Possible Options:
;==================================================================
;JSR AnyHurt ; Makes the sprite get hurt by jumping on it or if something is thrown at him. Don't use other hurt options in the same state.
;JSR JumpHurt ; Makes the sprite get hurt ONLY by jumping on it. Don't use other hurt options in the same state.
;JSR ThrowHurt ; Makes the sprite get hurt ONLY if something is thrown at him. Don't use other hurt options in the same state.
;JSR Ramming ; Makes the sprite become angry, changing its colors, and faster after turning around 3 times. When he hits a wall, will shake the ground.
;JSR ClearRamming ; Use this if you want to disable the ramming state. If not properly disabled, the sprite may get stuck at an angry state.
;JSR SpitFire ; Makes the sprite spit fireballs (extended sprite) at Mario, like Reznor/Venus plants. Can be used more than once in a same state.
;JSR Roar ; Roars and throws a bunch of hammers at once.
;JSR GenParaBomb ; This will make the sprite generate para-bombs.
;JSR GenFire ; This will make the sprite generate bowser statue flames from the right side of the screen.
;JSR GenBullets ; This will make the sprite generate bullets from the left side of the screen.
;JSR LoopyLight ; Makes the screen loop through brightness, so the screen revolves around brightness and darkness.
; NOTE! DO NOT USE THIS IN THE FIRST SPRITE STATE (WHEN HE HAS FULL HP), THIS CAN MESS UP THE MOSAIC
; EFFECT IF YOU DO SO! (If you've disabled it, I guess it's fine though.)
; This is kind of a stupid option, but I added it anyways, because I was bored >_>
;JSR Push ; When Mario touches the sprite, will hurt him and knock him away.
;JSR Animate2 ; Makes the sprite use different tilemaps as defined previously in this file.
;JSR Animate3 ; Makes the sprite use different tilemaps as defined previously in this file.
;JSR Animate ; Use this to make the sprite change back to its default tilemaps.
;JSR WavyMotion ; Makes the sprite move up and down in a wavy motion.
;JSR BoneA ; Makes the sprite throw a bone.
;JSR BoneB ; Makes the sprite throw a bone more frequently.
;JSR HammerA ; Makes the sprite throw a hammer.
;JSR HammerB ; Makes the sprite throw a hammer more frequently.
;JSR Rise ; Makes the sprite rise up to a configurable height (see top of file for height and rise speed).
;JSR Drop ; Makes the sprite drop down to the ground (see top of file for drop speed).
;JSR JumpA ; Makes the sprite jump every 4 seconds.
;JSR JumpB ; Makes the sprite jump every 3 seconds.
;JSR JumpC ; Makes the sprite jump every 2 seconds.
;JSR Strong ; Makes the sprite shake the ground after jumping (only applies if jumping).
;JSR Strong2 ; Same as Strong, but shakes the ground for more time.
;JSR OnOff ; Makes the sprite flip the ON/OFF status to OFF.
;JSR PSwitch ; Makes the sprite turn on the P-switch.
;JSR Follow ; Makes the sprite face Mario all the time.
;JSR Chase ; Use this to make the sprite chase Mario in all directions, similar to a Phanto.
;JSR NoChase ; Use this to clear out the chase effect. NEEDED if you want to cancel out the chase effect.
;JSR GenNSpr ; Makes the sprite throw a normal sprite (configured at the top of the file) at Mario.
;JSR GenCSpr ; Makes the sprite throw a custom sprite (configured at the top of the file) at Mario.
;JSR RandSpr ; Makes the sprite throw a random regular SMW sprite.
;JSR AimSpr ; Makes thrown sprites to be spawned aimed at Mario.
; Should be used *right after* 'JSR GenNSpr', 'JSR GenCSpr' or 'JSR RandSpr'
;JSR Dark ; Darkens the screen.
;JSR Dark2 ; Darkens the screen using a different value.
;JSR Bright ; Makes the screen brightness back to normal (if you want it normal again).
;JSR Msg ; Makes the sprite play a message. Note: recommended you use this only once, because it's the same message.
;JSR Msg2 ; Makes the sprite play another message. Note: recommended you use this only once, because it's the same message.
;JSR Inv ; Makes the sprite invisible every once in a while. When invisible, he cannot be hurt.
;JSR ClearInv ; Use this to "clear" the invisiblity effect. It's needed if you want to cancel out the effect at some HP.
;JSR RandMove ; Makes the sprite change direction every once in a while.
;JSR Poison
; For X seconds (Whatever poison time you wrote):
; Reduces Mario's jumping height. stops running, changes his colors to green.
;==================================================================
;SPRITE MAIN CODES!
;==================================================================
;Symbolic Addresses
if !SA1
!InvTimer = $418800
else
!InvTimer = $7F9A7B ; Used for many sprite misc. stuff. Uses Wiggler's RAM by default, but changing is not advised at all.
endif
!ChaseTemp = !InvTimer+($2A*1)
!ASRFlags = !InvTimer+($2A*2)
!JumpFlag = !InvTimer+($2A*3)
!JumpTemp = !InvTimer+($2A*4)
!AnimaIndex = !InvTimer+($2A*5)
!ChaseAcc = !InvTimer+($2A*6)
!TurnCount = !InvTimer+($2A*7)
!FireMultip = !InvTimer+($2A*8)
FlashTable:
db $08,$08,$0C,$0C,$0C,$06,$06,$06 ;palettes the sprite should flash through when hurt, if flashing is enabled.
print "INIT ",pc
LDA #!Health ; Store health.
STA !1528,x
if !FaceMario
%SubHorzPos() ; Make him face Mario.
TYA ; Get the sprite's direction relative to Mario into A.
STA !157C,x ; Store new direction.
endif
NoFace:
LDA #$00 ;gotta init all rams with zero value
STA !InvTimer,x ;STZ doesn't support long addresses.
STA !ASRFlags,x
STA !JumpFlag,x
STA !JumpTemp,x
STA !AnimaIndex,x
STA !ChaseAcc,x
STA !TurnCount,x
if !UseMultiplier
STA !FireMultip,x
endif
RTL
;==================================================================
;Sprite Main
;==================================================================
Offset:
db $00,$10
BounceSpeed:
db $0B,$F2
BounceMarioX:
db $E4,$1B
print "MAIN ",pc
PHB
PHK ; Always change the data bank.
PLB
JSR RunSpr
JSR DecrTimers
PLB
RTL ; End the code after jumping to sprite main.
DecrTimers:
LDA $9D ;load sprites/animation locked flag
BNE .nooo ;if set don't decrement
LDA !C2,x
BEQ +
DEC !C2,x
+
LDA !163E,x
BEQ +
LDA $14 ;previously $13
AND #$3F
BNE +
DEC !163E,x
+
LDA !1594,x
BEQ +
DEC !1594,x
+
LDA !1504,x
BEQ .nooo
JSR DoAttack
LDA $14 ;previously $13
AND #$3F ; Decrease poison timer every second.
BNE .nooo
DEC !1504,x
.nooo
RTS
DoAttack:
LDA $16
ORA $18 ; If pressing the jump button ..
AND #$80
BEQ +
LDA $77
AND #$04 ; .. and on ground..
BEQ +
++
LDA #!JumpHeight
STA $7D ; limit height.
+
JSR LimitXSpd
if !SA1 == 0
if !Col
JSR ChangePals
endif
endif
GoAway:
RTS
;==================================================================
;Sprite Main Routine
;==================================================================
RunSpr:
JSR Graphics
if !ShowTiles
PHX
JSR DrawTilemaps ; Draw the tilemaps.
PLX
LDA !1528,x
PHX
JSR HexDec
STX !Position+!NameSize+2|!Base2
STA !Position+!NameSize+3|!Base2
PLX
endif
LDA !14C8,x
CMP #$08
BNE GoAway ; Return if sprite dead.
LDA $9D
BNE GoAway ;Or locked.
LDA $14 ;load effective frame counter
if !AnimationSpd == 0 ;compile if equal 0
LSR #4 ;divide by 2 four times (a.k.a. divide by 16)
endif
if !AnimationSpd == 1 ;compile if equal 1
LSR #3 ;divide by 2 three times (a.k.a. divide by 8)
endif
if !AnimationSpd >= 2 ;compile if bigger or equal 2
LSR #2 ;divide by 2 twice (a.k.a. divide by 4)
endif
CLC
ADC $15E9|!Base2 ; Flip frames when needed.
AND #$01
ASL #2
STA !1602,x
SkipAn:
LDA !1528,x ;load amount of HP
BNE NormalRoutines ;if non-zero, branch to normal routines.
JMP KillSprite ;:thonk: what does this do? lol
NormalRoutines:
LDA !1588,x ; Add all basic stuff.
AND #$03 ; Such as flipping when hitting a wall.
BEQ NoFlipping
LDA !157C,x
EOR #$01
STA !157C,x
TAY
LDA BounceSpeed,y
STA !B6,x
Apply:
JSL $01802A|!BankB ; Prevents a glitch.
LDA #$10 ; Where the sprite runs into a wall.
STA !C2,x
NoFlipping:
LDA !1594,x
BNE NoHit
LDA !InvTimer,x
CMP #$02
BCS NoHit
JSR FireballHP ;this should come after other conditions lol
BEQ NoHit ; Return if there's no fireball/sprite contact.
if !FireballHealth
if !Invulnerangry
LDA !ASRFlags,x
AND #$04
BEQ NormFireCont
LDA #$01
STA $1DF9|!Base2
RTS
endif
NormFireCont:
if !UseMultiplier
LDA !FireMultip,x ; If fireball hits != 2 ..
CMP #$02
BNE +
LDA #$FF
STA !FireMultip,x ; Reset the flag.
endif
DEC !1528,x
+ LDA #!FTimer
STA !1594,x ; Store flash timer.
if !UseMultiplier
LDA !FireMultip,x
INC A
STA !FireMultip,x
endif
LDA #$03 ; \ play sound
STA $1DF9|!Base2 ; /
RTS
NoHit:
else
LDA #$01
STA $1DF9|!Base2
RTS
NoHit:
endif
if !CapeHealth
if !Invulnerangry
LDA !ASRFlags,x
AND #$04
BNE NoCapeHP
endif
LDA !1594,x
BNE NoCapeHP
LDA !InvTimer,x
CMP #$02
BCS NoCapeHP
JSR SCCR
BEQ NoCapeHP
LDA #!FTimer
STA !1594,x
DEC !1528,x
LDA #$03 ; \ play sound
STA $1DF9|!Base2 ; /
STZ $00 : STZ $01
LDA #$08 : STA $02
LDA #$02
%SpawnSmoke()
NoCapeHP:
endif
if !DisableFlight
STZ $149F|!Base2
endif
+
LDA !ASRFlags,x
AND #$02
BNE OnGround
LDA !1588,x
BNE OnGround
if !Ledges
LDA !157C,x
EOR #$01
STA !157C,x
endif
LDA !ASRFlags,x
ORA #$02
STA !ASRFlags,x
OnGround:
LDA !1588,x
AND #$04
BEQ JumpMain
LDA !ASRFlags,x
AND #$FD
STA !ASRFlags,x
JumpMain:
JSR Move ;BlindEdit: now boss will always move/update speeds by default. Change speeds in Tbl1R to zero if you want it to be stationary.
JMP MainPointer
;==================================================================
;Generator Activation Codes
;==================================================================
GenBullets:
PHK
PER NoGGen-1
PEA $F80E ;\ Push 16-bit RTL address.
JML $02B07C|!BankB ;/ Jump to the bullet generation code.
NoGGen:
RTS
GenFire:
PHK
PER NoGGen2-1
PEA $F80E
JML $02B036|!BankB
NoGGen2:
RTS
GenParaBomb:
LDA $14
AND #$7F ; Frequency. Can be 7F or FF.
BNE NoGGen4
JSL $02A9DE|!BankB
BMI NoGGen4
TYX
LDA #$08
STA !14C8,x
JSL $01ACF9|!BankB
LSR
LDA #$40
STA !9E,x
PHK
PER NoGGen4-1
PEA $F80E
JML $02B34D|!BankB
NoGGen4:
RTS
;==================================================================
;Chase Mario Subroutine
;==================================================================
Chase:
LDA !ChaseTemp,x
CMP #$1F
BEQ Done
INC A
STA !ChaseTemp,x
STZ !AA,x
RTS
Done:
%SubHorzPos() ; Get sprite's direction relative to Mario ..
TYA
STA !157C,x
TAY
LDA !B6,x ; .. X speed.
CMP MaxAcceleration,y ; If going beyond the speed limit, skip.
BEQ +
CLC
ADC AccelerationX,y
STA !B6,x ; Acceleration = ..wait.
+
%SubVertPos()
LDA !AA,x
CMP MaxAccelerationY,y
BEQ +
CLC
ADC AccelerationY,y
STA !AA,x
+
LDA #$01
BRA AccelerateON
NoChase:
LDA #$00
STA !ChaseTemp,x
AccelerateON:
STA !ChaseAcc,x
JSL $01801A|!BankB ;update ypos no gravity
JSL $018022|!BankB ;update xpos no gravity
RTS
;==================================================================
;Ramming Subroutine
;==================================================================
Ramming:
LDA !TurnCount,x
CMP #$03
BCS Rage
LDA !1588,x
AND #$43
BEQ NotAngry
LDA !TurnCount,x
INC A
STA !TurnCount,x
BRA NotAngry
Rage:
LDA !ASRFlags,x
ORA #$04
STA !ASRFlags,x
LDA !1588,x
AND #$43
BEQ NotBumpingWall
LDY #!StunTimerA
JSR StunStunStun
ClearRamming:
LDA #$00
STA !TurnCount,x
NotAngry:
LDA !ASRFlags,x
AND #$FB
STA !ASRFlags,x
NotBumpingWall:
RTS
;==================================================================
;Loopy Light Routine(s)
;==================================================================
LoopyLight:
LDA $14 ; $14 -> A.
LSR #3
AND #$07 ; Get the low bits of the envmxdizc register..
TAY ; Into Y.
LDA Flipper,y
STA $0DAE|!Base2
RTS
Flipper:
db $0F,$0E,$0D,$0C,$0B,$0C,$0D,$0E ;brightness values
;==================================================================
;Push Mario Routine
;==================================================================
Push:
JSL $01A7DC|!BankB ; Check for Mario/Sprite contact ..
BCC NoPush ; Return if not any.
%SubVertPos()
LDA $0E
CMP #$E6
BPL SprPush
NoPush:
RTS
SprPush:
LDA $1497|!Base2
BNE + ; No immediate push if flashing.
LDY $76 ; Direction -> Y.
LDA PushSpd,y ; Accumulate push speeds..
STA $7B ; Into $7B.
LDA #!YPush
STA $7D
JSL $00F5B7|!BankB
+
RTS
PushSpd:
db !PushMario,$FF-!PushMario
;==================================================================
;Cape HP Routine
;==================================================================
if !CapeHealth
SCCR:
LDA $13E8|!Base2
BEQ SCCRNOCONTACT
LDA !15D0,x
ORA !154C,x
ORA !1FE2,x
BNE SCCRNOCONTACT
LDA !1632,x
PHY
LDY $74
BEQ SCCRLABEL1
EOR #$01
SCCRLABEL1: PLY
EOR $13F9|!Base2
BNE SCCRNOCONTACT
JSL $03B69F|!BankB
LDA $13E9|!Base2
SEC
SBC #$02
STA $00
LDA $13EA|!Base2
SBC #$00
STA $08
LDA #$14
STA $02
LDA $13EB|!Base2
STA $01
LDA $13EC|!Base2
STA $09
LDA #$10
STA $03
SCCRFINNISH: JSL $03B72B|!BankB
BCC SCCRNOCONTACT
LDA #$01
RTS
SCCRNOCONTACT:
LDA #$00
RTS
endif
;==================================================================
;Fireball Contact Routine (completely modified, ripped from one of
;Sonikku's Mario Bros. sprites)
;==================================================================
FireballHP:
PHX ; push x and y
PHY
LDY #$09 ; times to loop
- LDA $170B|!Base2,y ; \
CMP #$05 ; |
BEQ + ; | only detect yoshi and mario fireballs
CMP #$11 ; |
BNE .loop ; /
+ LDA $171F|!Base2,y ; \
SEC ; |
SBC #$02 ; |
STA $00 ; | fireball clipping x position
LDA $1733|!Base2,y ; |
SBC #$00 ; |
STA $08 ; /
LDA #$0C ; \ fireball clipping width
STA $02 ; /
LDA $1715|!Base2,y ; \
SEC ; |
SBC #$04 ; |
STA $01 ; | fireball clipping y position
LDA $1729|!Base2,y ; |
SBC #$00 ; |
STA $09 ; /
LDA #$0C ; \ fireball clipping height
STA $03 ; /
JSL $03B69F|!BankB ; get sprite clipping
JSL $03B72B|!BankB ; check for contact
BCS +
.loop DEY
BPL -
PLY
PLX
LDA #$00 ;symbolic value, means no fireball contact has happened
RTS
+
LDA #$01 ; \
STA $170B|!Base2,y ; | turn fireball to smoke
LDA #$10 ; |
STA $176F|!Base2,y ; /
PLY
PLX
LDA #$01
RTS
;==================================================================
;Limit X Speed Subroutine
;==================================================================
LimitXSpd:
LDY $7B
LDA $76
BNE RightD ; Branch to right.
CPY #$FF-!Speed
BMI DoFix2
RTS
DoFix2:
LDA #$FF-!Speed
STA $7B
RTS
RightD:
CPY #!Speed
BPL Fix ; If going beyond limit, fix speed.
RTS
Fix:
LDA #!Speed
STA $7B
RTS
;==================================================================
;Change Mario Subroutine
;==================================================================
if !SA1 == 0
if !Col
ChangePals:
LDA #$86
STA $2121
LDA #!High
STA $2122
LDA #!Low
STA $2122
LDA #$8E
STA $2121
LDA #!High
STA $2122
LDA #!Low
STA $2122
LDA #$89
STA $2121
LDA #!High
STA $2122
LDA #!Low
STA $2122
LDA #$8C
STA $2121
LDA #!High2
STA $2122
LDA #!Low2
STA $2122
RTS
endif
endif
;==================================================================
;Hurt/Poison Mario Subroutine
;==================================================================
Poison:
JSL $01A7DC|!BankB
BCC NoContact2
LDA !1594,x
BNE NoContact2
LDA !InvTimer,x
CMP #$02
BCS NoContact3 ; If invisibility is going on, no contact.
LDA !1504,x
BNE OnlyHurt ; Return if already poisoned.
NoContact3:
%SubVertPos()
LDA $0E
CMP #$E6
BPL DoPos
NoContact2:
RTS
DoPos:
LDA #!PoTimer
STA !1504,x
OnlyHurt:
JSL $00F5B7|!BankB
RTS
;==================================================================
;Stun Ground Subroutine
;==================================================================
Strong:
LDY #!StunTimerA
DoStun:
LDA !ASRFlags,x
AND #$02
BEQ NoStun
LDA !1588,x
AND #$04
BNE CheckFlag
LDA !ASRFlags,x
ORA #$01
STA !ASRFlags,x ; Flagg'd if in air.
RTS
CheckFlag:
LDA !ASRFlags,x
AND #$01
BEQ NoStun
StunStunStun:
LDA $77
AND #$04
BEQ + ; Store Y to $18BD if on the ground as well.
STY $18BD|!Base2
+
STY $1887|!Base2
LDA #$09
STA $1DFC|!Base2
LDA !ASRFlags,x
AND #$FE ;reset bit 0
STA !ASRFlags,x
NoStun:
RTS
Strong2:
LDY #!StunTimerB
BRA DoStun
;==================================================================
;Generate Sprite Routine
;==================================================================
RandSpr:
LDA $14
AND #$7F
BNE Fail
LDA !15A0,x
ORA !186C,x
ORA !15D0,x
BNE Fail
JSL $02A9DE|!BankB
BMI Fail
STZ $00 : STZ $01 : STZ $02 : STZ $03 ;no XY offsets nor XY speeds for spawned sprite.
PHX
LDA #!RandTableSize
JSL RANDOM
TAX
LDA SPRITE_TO_GEN,x
PLX
CLC ;clear carry - spawn normal sprite
%SpawnSprite()
CPY #$FF
BEQ Fail ;if no sprite was spawned, don't bother setting state nor playing SFX
LDA #!INITSTAT ;sprite state for spawned sprite
STA !14C8,y
LDA #!SpawnSound ;SFX for sprite spawned
STA !SpawnPort|!Base2
Fail: RTS
RANDOM:
Random:
PHX : PHP
SEP #$30
PHA
JSL $01ACF9|!BankB
PLX
CPX #$FF
BNE .normal
LDA $148B|!Base2
BRA .end
.normal
INX
LDA $148B|!Base2
if !SA1
STZ $2250 ; Set multiplication mode.
REP #$20 ; Accum (16-bit)
AND #$00FF ; Mask out high byte.
STA $2251 ; Write first multiplicand.
TXA ; X -> A and mask out high byte.
AND #$00FF
STA $2253 ; Write second multiplicand.
NOP ; Wait 2 cycles (SEP takes 3, total of 5).
SEP #$20 ; Accum (8-bit)
LDA $2307 ; Read multiplication product.
else
STA $4202 ; Write first multiplicand.
STX $4203 ; Write second multiplicand.
NOP #4 ; Wait 8 cycles.
LDA $4217 ; Read multiplication product (high byte).
endif
.end
PLP : PLX
RTL
;======
AimSpr:
CPY #$FF
BEQ NoAim ;if no sprite was spawned, return.
LDA !14E0,x ;load sprite X pos, high byte
STA $01 ;store to scratch RAM for later calculation.
LDA !E4,x ;load sprite X pos, low byte
STA $00 ;store to scratch RAM for later calculation.
LDA !14D4,x ;load sprite Y pos, high byte
STA $03 ;store to scratch RAM for later calculation.
LDA !D8,x ;load sprite Y pos, low byte
STA $02 ;store to scratch RAM for later calculation.
REP #$20 ;16-bit A
LDA $02 ;load 16-bit sprite Y pos from scratch RAM
SEC ;set carry
SBC #$0016 ;subtract #$16 so we get proper aiming alignment
STA $02 ;store result back.
LDA $00 ;load 16-bit sprite X pos from scratch RAM
SEC ;set carry
SBC $94 ;subtract player's X pos within the level from it
STA $00 ;store result back.
LDA $02 ;load 16-bit sprite Y pos from scratch RAM
SEC ;set carry
SBC $96 ;subtract player's Y pos within the level from it
STA $02 ;store result back.
SEP #$20 ;8-bit A
LDA #!SprAimSpd ;load aiming speed
%Aiming() ;at long last, call aiming routine.
LDA $00 ;load aimed X speed from scratch RAM
STA !B6,y ;storte to spawned sprite's X speed.
LDA $02 ;load aimed Y speed from scratch RAM
STA !AA,y ;storte to spawned sprite's Y speed.
NoAim:
RTS ;return.
;======
GenNSpr:
LDA $14
AND #$7F
BNE NoSpawn
STZ $00 : STZ $01 ;no XY offset
STZ $02 : STZ $03 ;no XY speed
LDA #!NormalSprite
CLC ;clear carry - spawn normal sprite
SpawnDaSpr:
%SpawnSprite()
CPY #$FF
BEQ NoSpawn ;if no sprite was spawned, don't bother setting state nor playing SFX
LDA #!SpawnSound ;SFX for sprite spawned
STA !SpawnPort|!Base2
NoSpawn:
RTS
;======
GenCSpr:
LDA $14
AND #$7F
BNE NoSpawn
STZ $00 : STZ $01 ;no XY offset
STZ $02 : STZ $03 ;no XY speed
LDA #!CustomSprite
SEC ;set carry - spawn custom sprite
BRA SpawnDaSpr
;==================================================================
;Random Movement Routine
;==================================================================
RandMove:
LDA $13
AND #$7F ; CHANGE THIS IF YOU WANT. RAND MOVEMENT DURATION. ABOVE = MORE, BELOW 7F = LESS.
BNE +
LDA !157C,x
EOR #$01
STA !157C,x
+
RTS
;==================================================================
;EndLevel/Teleport/Whatever Routine
;==================================================================
DoExit:
if !ExitType == 0
STZ $141C|!Base2
LDA #$FF
STA $1493|!Base2
DEC $13C6|!Base2
LDA #!ExitSong
STA $1DFB|!Base2 ; Store sound and exit level.
endif
if !ExitType == 1
LDA #$01
STA $141C|!Base2
LDA #$FF
STA $1493|!Base2
LDA #!ExitSong
STA $1DFB|!Base2 ; Store sound and exit level.
endif
if !ExitType == 2
LDA #$06 ; Really simple ..
STA $71 ; .. and my first ASM code.
STZ $89
STZ $88 ; Teleport.
endif
if !ExitType == 3
if !OWExit != 0
LDA $0DD5|!Base2
BNE NoFade
LDA #!OWExit
STA $13CE|!Base2
STA $0DD5|!Base2
INC $1DE9|!Base2
endif
LDA #$0B
STA $0100|!Base2
NoFade:
endif
RTS
;==================================================================
;Message Subroutines
;==================================================================
Msg:
LDA !151C,x
AND #$01 ; Bit one controls message one.
BNE NoSwitch
LDA $14
AND #$3F
BNE NoSwitch
LDA #!Msg1L
STA $13BF|!Base2
LDA #!Msg1T
STA $1426|!Base2
LDA !151C,x
ORA #$01
STA !151C,x
NoSwitch:
RTS
Msg2:
LDA !151C,x
AND #$02 ; Bit two controls message two.
BNE NoSwitch2
LDA $14
AND #$3F
BNE NoSwitch2
LDA #!Msg2L
STA $13BF|!Base2
LDA #!Msg2T
STA $1426|!Base2
LDA !151C,x
ORA #$02
STA !151C,x
NoSwitch2:
RTS
;==================================================================
;Brightness/Darkness Subroutine
;==================================================================
Dark2:
LDA #!Dark2
BRA StoreB
Dark:
LDA #!Dark
BRA StoreB
Bright:
LDA #$0F ;Restore normal brightness..
StoreB:
STA $0DAE|!Base2
RTS
;==================================================================
;"Sprite" Hurt Subroutine (Shell, Throw Block etc.)
;==================================================================
ThrowHurt:
LDA !1594,x
BNE NoProc ; Don't process if sprite is already flashing.
LDA !InvTimer,x
CMP #$02
BCS NoProc ; .. Or if the invisibility timer of the sprite is on.
JSL $01A7DC|!BankB
BCC NotTouching
LDA $0E
CMP #$E6
BPL HurtHurt
LDA $140D|!Base2
BEQ HurtHurt
if !Spinjumpable
LDA #$02
STA $1DF9|!Base2
JSL $01AA33|!BankB
JSL $01AB99|!BankB
if !PushPlayer
%SubHorzPos()
TYA
EOR #$01
TAY
LDA BounceMarioX,y
STA $7B
endif
LDA #$BC
STA $7D
RTS
endif
HurtHurt:
JSL $00F5B7|!BankB ; Hurt Mario regardless of whatever. It's what ThrowHurt is supposed to do.
RTS
NotTouching:
LDY #!SprSize-1
Loop:
LDA !14C8,y
CMP #$09
BEQ Process
CMP #$0A
BEQ Process
LoopSprSpr:
DEY
BPL Loop
NoProc:
RTS
Process:
PHX
TYX
JSL $03B6E5|!BankB
PLX
JSL $03B69F|!BankB
JSL $03B72B|!BankB
BCC LoopSprSpr
PHX
TYX
STZ !14C8,x
LDA !E4,x
STA $9A
LDA !14E0,x
STA $9B
LDA !D8,x
STA $98
LDA !14D4,x
STA $99
PHB
LDA #$02
PHA
PLB
LDA #$FF
JSL $028663|!BankB
PLB
PLX
if !Invulnerangry
LDA !ASRFlags,x
AND #$04
BEQ NotAnAngeredBeastTh
RTS
NotAnAngeredBeastTh:
endif
DEC !1528,x
LDA #!FTimer
STA !1594,x
LDA #!HurtSFX
STA !HurtPort|!Base2
RTS
;==================================================================
;Jump Hurt Subroutine
;==================================================================
SprWins: ; When the sprite touches Mario.
JSL $00F5B7|!BankB ; Hurt him.
RTS
JumpHurt:
LDA !1594,x
BNE NoContact ; If the sprite is flashing, there's no contact.
JSL $01A7DC|!BankB
BCC NoContact ; No contact if sprite touches Mario.
LDA !InvTimer,x
CMP #$02
BCS NoContactX ; If invisibility is going on, no contact.
Effectiveness1:
%SubVertPos()
LDA $0E
CMP #$E6
BPL SprWins
LDA $7D ;\ If Y speed negative (rising) ..
BMI NoContact ;/ ..skip.
JSL $01AA33|!BankB
JSL $01AB99|!BankB ; "Stomp" graphic.
if !PushPlayer
%SubHorzPos()
TYA
EOR #$01
TAY
LDA BounceMarioX,y
STA $7B
endif
LDA #$BC
STA $7D
if !Invulnerangry
LDA !ASRFlags,x
AND #$04
BEQ NotAnAngeredBeast
LDA $140D|!Base2
BNE AlreadySpinjumping
LDA #$01 ; \ set spin jump flag so mario bounces off flag
STA $140D|!Base2 ; /
STZ $140D|!Base2 ; reset spin jump flag
AlreadySpinjumping:
JSL $01A7DC|!BankB ; check for Mario/sprite contact
LDA #$02
STA $1DF9|!Base2
LDA #$02 ;\ no interaction for two frames
STA !1594,x ;/
RTS
NotAnAngeredBeast:
endif
LDA #!HurtSFX
STA !HurtPort|!Base2
LDA #!FTimer
STA !1594,x ; Store flash timer.
DEC !1528,x
NoContact:
RTS
NoContactX:
%SubVertPos() ;\
LDA $0E ; | Sprite can hurt Mario, Mario can't.
CMP #$E6 ;/
BPL SprWins
;==================================================================
;Jump+Throw Hurt Subroutine (this is done at last)
;==================================================================
AnyHurt:
LDA !1594,x
BNE NoContact ; If the sprite is flashing, there's no contact.
JSL $01A7DC|!BankB
BCC TryThrowThen ; No contact if sprite touches Mario.
LDA !InvTimer,x
CMP #$02
BCS TryThrowThen ; If invisibility is going on, no contact.
JSR Effectiveness1
TryThrowThen:
JSR ThrowHurt
RTS
;==================================================================
;Death Subroutine
;==================================================================
KillSprite:
if !DeathType == 0 ;compile if equal 0
STZ !1594,x ; No flashing.
LDA #$02
STA !14C8,x
STZ !AA,x
STZ !B6,x
JSL $01802A|!BankB
JMP DoExit
endif
if !DeathType == 1 ;compile if equal 1
LDA #$04
STA !14C8,x ; Disappear in a puff of smoke.
JSL $03A6C8|!BankB
JMP DoExit
endif
if !DeathType >= 2 ;compile if equal or bigger than 2
LDA #$0D ;
STA !9E,x ;\ Sprite = Bob-omb.
LDA #$08 ;/
STA !14C8,x ;\ Set status for new sprite.
JSL $07F7D2|!BankB ;/ Reset sprite tables (sprite becomes bob-omb)..
LDA #$01 ;\ .. and flag explosion status.
STA !1534,x ;/
LDA #$40 ;\ Time for explosion.
STA !1540,x
LDA #$09 ;\ explosion
STA $1DFC|!Base2 ;/ Sound effect.
LDA #$1B
STA !167A,x
JMP DoExit
endif
;==================================================================
;On/Off and P-Switch Subroutines (they are triggered every frame if
;called so the ON/OFF/P-switch values will be constant during the
;states these are called)
;==================================================================
OnOff:
LDA #$01
STA $14AF|!Base2 ; Turn the ON/OFF switch to OFF.
RTS
PSwitch:
LDA #!PTimer ; Load P-Switch Timer ..
STA $14AD|!Base2 ; Duration into $14AD.
RTS
;==================================================================
;Jump A/B/C Subroutines
;==================================================================
JumpA:
JSR IncJTimer
CMP #$04
BCC +
LDA #$B4
BRA ApplySpdY
+
RTS
JumpB:
JSR IncJTimer ; Increase The Jump Timer every second.
CMP #$03 ; .. If it's 02..
BCC +
LDA #$B7
BRA ApplySpdY
+
RTS
JumpC:
JSR IncJTimer ; Increase The Jump Timer every second.
CMP #$02 ; .. If it's 01..
BCC +
LDA #$BA
BRA ApplySpdY
+
RTS
ApplySpdY:
STA !AA,x ; Make the sprite jump.
JSL $01802A|!BankB ; Update new Y speed.
LDA #$00
STA !JumpTemp,x
RTS
;==================================================================
; Spit Fireball Subroutine
;==================================================================
SpitFire:
LDA $14
AND #$3F
BNE +
JSR DoSpit
+
RTS
DoSpit:
PHX
LDA !157C,x ;load sprite direction
TAX ;it's X index now
LDA XFire,x ;load fireball X speed from table according to index
STA $02 ;store to scratch RAM.
LDA #$04 ;load table size, -1
JSL RANDOM ;RNG
TAX ;transfer A to X
LDA YFire,x ;load fireball Y speed from table according to index to A
PLX ;we can restore sprite index now
STA $03 ;store A value to scratch RAM.
STZ $00 : STZ $01 ;no XY offset
LDA #$02 ;extended sprite to spawn (venus/reznor fireball)
%SpawnExtended()
BCS + ;if no fireball was spawned then don't bother playing SFX
LDA #$06 ;\ fireball spit SFX
STA $1DFC|!Base2 ;/
+
RTS
YFire: db $FE,$04,$F9,$FC,$05
XFire: db $14,$EC
;==================================================================
;Hammer A/B Subroutines
;==================================================================
HammerA:
LDA $14
CMP #$26
BEQ ThrowHammer
CMP #$5D
BEQ ThrowHammer
CMP #$6D
BEQ ThrowHammer
CMP #$BA
BEQ ThrowHammer
CMP #$E2
BEQ ThrowHammer
RTS
HammerB:
LDA $14
CMP #$16
BEQ ThrowHammer
CMP #$31
BEQ ThrowHammer
CMP #$77
BEQ ThrowHammer
CMP #$AA
BEQ ThrowHammer
CMP #$CC
BEQ ThrowHammer
CMP #$EA
BEQ ThrowHammer
RTS
;==================================================================
;Roar Subroutine
;==================================================================
Roar:
LDA $14
AND #$07
BNE .R
JSR ThrowHammer
.R
LDA #$25 ;\ roar SFX
STA $1DF9|!Base2 ;/
RTS
ThrowHammer:
LDA #$04 ;ExSprite = Hammer.
XBA ;flip low/high bytes of A
JMP ThrowEx
;==================================================================
;Bone A/B Subroutines
;==================================================================
BoneA:
LDA $14
CMP #$35
BEQ ThrowBone
CMP #$68
BEQ ThrowBone
CMP #$AC
BEQ ThrowBone
RTS
BoneB:
LDA $14
CMP #$25
BEQ ThrowBone
CMP #$55
BEQ ThrowBone
CMP #$97
BEQ ThrowBone
CMP #$CF
BEQ ThrowBone
RTS
ThrowBone:
LDA #$06 ;ExSprite = bone.
XBA ;flip low/high bytes of A
ThrowEx:
PHX
LDA !157C,x
TAX
LDA XGenPos,x
STA $00 ;X offset
LDA ExSprSpd,x
STA $02 ;X speed
STZ $01
LDA #$C7 ;Y speed (applies to hammer only)
STA $03
PLX
XBA ;flip low/high bytes of A again - restore extended sprite number to spawn
%SpawnExtended()
BCS + ;if no bone/hammer was spawned then don't bother playing SFX
LDA #!ExSound
STA !ExPort|!Base2
+
RTS
ExSprSpd: db $25,$DA
XGenPos: db $02,$FE
;==================================================================
;Follow Subroutine
;==================================================================
Follow:
JSR Proximity ;\
BNE + ;/ NOTE: This is done to avoid glitchfest.
%SubHorzPos() ; Get sprite's direction relative to Mario's.
TYA
STA !157C,x ; And store it.
+
RTS
Proximity: ; If sprite is too close to Mario, return.
LDA !14E0,x
XBA
LDA !E4,x
REP #$20 ; Get sprite's X position.
SEC
SBC $94 ; Subtract Mario's to get the difference range.
SEP #$20
PHA
%SubHorzPos() ; Determine sprite range.
PLA
EOR InvertAbility,y ; Apply inversion based on direction.
CMP #$09 ; Range.
BCS OutofRange
LDA #$01
RTS
OutofRange:
LDA !E4,x
CMP $94
BNE RangeOut
LDA #$01
RTS
RangeOut:
LDA #$00
AccordingToAllKnownLawsOfAviationTheresNoWayABeeShouldBeAbleToFlyItsWingsAreTooSmallToGetItsFatLittleBodyOffOfTheGroundTheBeeOfCourseFliesAnywayBecauseBeesDontCareWhatHumansThinkIsImpossible:
;BlindEdit: ^^^ I totally had to change this label to something more memorable lol
RTS
InvertAbility:
db $FF,$00
;==================================================================
;Moving/Rising/Dropping Subroutine (Move) (Rise) (Drop)
;==================================================================
Move:
LDA !ChaseAcc,x ; COMPLETELY SKIP IF ACCELERATING.
ORA !163E,x
BNE AccordingToAllKnownLawsOfAviationTheresNoWayABeeShouldBeAbleToFlyItsWingsAreTooSmallToGetItsFatLittleBodyOffOfTheGroundTheBeeOfCourseFliesAnywayBecauseBeesDontCareWhatHumansThinkIsImpossible
PHY
LDA !ASRFlags,x
AND #$04
BEQ SkipAngrySpd
LDA !157C,x ; Get the sprite's direction ..
BEQ RightAng
LDA #!RamSpd
EOR #$FF
INC A
STA !1626,x
LDA !1626,x
BRA SetSpeedC
RightAng:
LDA #!RamSpd
BRA SetSpeedC
SkipAngrySpd:
LDY !1528,x ; Get sprite health into Y.
LDA !157C,x ; Get the sprite's direction ..
BEQ Right
LDA Tbl1R,y ;\
EOR #$FF ; |
INC A ; | Sprite left speed = $1626.
STA !1626,x ; |
LDA !1626,x ;/
BRA SetSpeedC
Right:
LDA Tbl1R,y ; Get the speeds value based on health.
SetSpeedC:
STA !B6,x ; Store the sprite X speed.
LDA !ChaseAcc,x
BNE UpdatePos
LDA !JumpFlag,x
BNE UpdatePos ; The Y speed CANNOT be updated if jumping.
; Jumping will control that instead.
LDA !1510,x
CMP #$02
BEQ DropSpr
CMP #$01
BEQ CheckYPos
LDA #!Gravity
STA !AA,x ;Gravity update if zero.
BRA UpdatePos
CheckYPos:
LDA !14D4,x
XBA
LDA !D8,x
REP #$20 ; Check the sprite Y position within the level.
CMP #!RiseLoc
SEP #$20
BCS .Rise ; .. this should actually be BCC?
STZ !AA,x
BRA UpdatePos
.Rise
LDA #!RiseSpeed
STA !AA,x
STZ !B6,x
STZ !1510,x
UpdatePos:
JSL $01802A|!BankB ; Update positions based on speed.
PullNoUpdate:
PLY
RTS
Rise:
LDA #$01
STA !1510,x
RTS
Drop:
LDA !1588,x
AND #$04
BNE .Stop
LDA #$02
STA !1510,x
RTS
.Stop
PHY
STZ !1510,x
BRA PullNoUpdate
DropSpr:
LDA #!DropSpeed
STA !AA,x
STZ !B6,x
BRA UpdatePos
;==================================================================
;Wavy Motion Subroutine.
;==================================================================
WavyMotion:
PHY ; Push Y in case something messes it up.
LDA $14 ; Get the sprite frame counter ..
LSR #3
AND #$07
TAY ; Into Y.
LDA WavySpd,y ; Load Y speeds ..
STA !AA,x
JSL $01801A|!BankB ; Update, with no gravity.
PLY ; Pull Y.
RTS
WavySpd: db $00,$F8,$F2,$F8,$00,$08,$0E,$08
;==================================================================
;InvTimer Increase Routine
;==================================================================
Inv:
LDA $14
AND #$3F
BNE +
LDA !InvTimer,x
INC A
STA !InvTimer,x
+
LDA !InvTimer,x
CMP #$04
BCC ClearA ; If the timer has reached 5 ..
ClearInv:
LDA #$00
STA !InvTimer,x ; Clear it.
ClearA:
RTS
;==================================================================
;Timer Increase Routine
;==================================================================
IncJTimer:
LDA #$01
STA !JumpFlag,x
LDA $14 ; Every 3F Frames ..
AND #$3F
BNE +
LDA !JumpTemp,x
INC A
STA !JumpTemp,x
+
LDA !JumpTemp,x
RTS ; Load it, to save bytes.
;==================================================================
;Draw Tiles To Status Bar.
;==================================================================
DrawTilemaps:
LDX #!NameSize
DrawLoop:
LDA NameTable,x ; Load the tile data indexed by the size.
STA !Position,x ; .. and store to appriopriate tile.
DEX
BPL DrawLoop ; So far, it draws "AAAA"
LDA #$26
STA !Position+!NameSize+1 ; Now, "AAAAx"
RTS ; We draw the health routine later, after pulling X.
; ORLY
;==================================================================
;Hex/Dec Subroutine.
;==================================================================
HexDec:
LDX #$00
HexLoop:
CMP #$0A ; While (A == $0A) {
BCC NoConvo ; }
SBC #$0A ; Else { DrawLine.(A - 10); Fail C++ ftw.
INX ; (X + 1) }
BRA HexLoop ; Cout << ("C++ Fail ftw");
NoConvo: ; Oh wait where's the cin command?!
RTS
;==================================================================
;Animation Change
;==================================================================
Animate3:
LDA #$02
BRA SetAni
Animate2:
LDA #$01
BRA SetAni
Animate:
LDA #$00
SetAni:
STA !AnimaIndex,x
RTS
;======================================================================
;Graphics Routine
;======================================================================
PROPERTIES:
db $40,$00
TILEMAP:
db !TopLeft,!TopRight,!BottomLeft,!BottomRight,!WalkTopLeft,!WalkTopRight,!WalkBottomLeft,!WalkBottomRight
db !TopLeft,!TopRight,!BottomLeft,!BottomRight,!WalkTopLeft,!WalkTopRight,!WalkBottomLeft,!WalkBottomRight
TILEMAP2:
db !TopLeft2,!TopRight2,!BottomLeft2,!BottomRight2,!WalkTopLeft2,!WalkTopRight2,!WalkBottomLeft2,!WalkBottomRight2
db !TopLeft2,!TopRight2,!BottomLeft2,!BottomRight2,!WalkTopLeft2,!WalkTopRight2,!WalkBottomLeft2,!WalkBottomRight2
TILEMAP3:
db !TopLeft3,!TopRight3,!BottomLeft3,!BottomRight3,!WalkTopLeft3,!WalkTopRight3,!WalkBottomLeft3,!WalkBottomRight3
db !TopLeft3,!TopRight3,!BottomLeft3,!BottomRight3,!WalkTopLeft3,!WalkTopRight3,!WalkBottomLeft3,!WalkBottomRight3
VERT_DISP:
db $F0,$F0,$00,$00,$F0,$F0,$00,$00
db $F0,$F0,$00,$00,$F0,$F0,$00,$00
HORIZ_DISP:
db $F8,$08,$F8,$08,$F8,$08,$F8,$08
db $08,$F8,$08,$F8,$08,$F8,$08,$F8
Graphics:
LDA !InvTimer,x
CMP #$02
BCS SkipGFX ; Completely skip if invisible.
BRA Positive
SkipGFX:
JMP SkipGFX2
Positive:
%GetDrawInfo()
LDA !1602,x
STA $03 ; Animation frames -> $03.
LDA !157C,x
STA $02 ; Direction -> $02.
BNE NoAdd
LDA $03
CLC
ADC #$08 ; Add displacement if going left.
STA $03
NoAdd:
PHX ; Push sprite index.
LDX #$03 ; Get # of times to go through loop.
Loop2:
PHX ; Push it for later..
TXA
ORA $03
FaceLeft:
TAX
LDA $00
CLC
ADC HORIZ_DISP,x ; Apply X displacement ..
STA $0300|!Base2,y
LDA $01
CLC
ADC VERT_DISP,x ; .. and Y displacement.
STA $0301|!Base2,y
PHX
LDX $15E9|!Base2
LDA !AnimaIndex,x ;\
PLX ; |
ASL ; |
PHX ; | Animations involve a pointer.
TAX ; |
JMP (PtrPtr,x) ;/
PtrPtr:
dw AnimationFrameA ; 00 ; Normal animation frames (A)
dw AnimationFrameB ; 01 ; Normal animation frames (B)
dw AnimationFrameC ; 02 ; Normal animation frames (C)
AnimationFrameA:
PLX
LDA TILEMAP,x
BRA DoGfx
AnimationFrameB:
PLX
LDA TILEMAP2,x
BRA DoGfx
AnimationFrameC:
PLX
LDA TILEMAP3,x
DoGfx:
STA $0302|!Base2,y
LDX $02 ; X is already preserved, so no need to push it again.
LDA PROPERTIES,x
LDX $15E9|!Base2
ORA !15F6,x
ORA $64 ; Add level property byte.
STA $0303|!Base2,y
LDA !ASRFlags,x
AND #$04
BEQ SkipAngryPal
LDA $0303|!Base2,y
AND #$F1
ORA #!AngryProp
STA $0303|!Base2,y
SkipAngryPal:
if !DoFlash
LDA !1594,x
BEQ NoFlashing ; Sprite flashes when jumped on.
LDA $14
AND #$07 ; 7 frames ..
TAX ; -> X.
LDA $0303|!Base2,y
AND #$F1
ORA FlashTable,x
STA $0303|!Base2,y
endif
NoFlashing:
PLX ; Pull #$03.
INY
INY
INY
INY
DEX ; Decrease it for every 16x16 tile drawn.
BPL Loop2
PLX
LDY #$02
LDA #$03
JSL $01B7B3|!BankB
SkipGFX2:
RTS