1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;
  3. ;; Fire-Spitting Piranha Plant, by imamelia
  4. ;;
  5. ;; This is a Piranha Plant that spits fireballs when it emerges from its pipe.
  6. ;;
  7. ;; Uses first extra bit: YES
  8. ;;
  9. ;; If the first extra bit is clear, the plant will spit only one pair of fireballs.
  10. ;; If the first extra bit is set, the plant will spit three pairs of fireballs.
  11. ;;
  12. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  13. ;incsrc subroutinedefsx.asm
  14. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  15. ;;
  16. ;; defines and tables
  17. ;;
  18. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  19. ; $151C,x = holder for the sprite's initial Y position low byte
  20. ; $1528,x = holder for the sprite's initial X position low byte
  21. Speed: ; the Piranha Plant's speed for each sprite state (inverted for down and right plants)
  22. db $00,$F0,$00,$10 ; in the pipe, moving forward, resting at the apex, moving backward
  23. TimeInState: ; the time the sprite will spend in each sprite state, indexed by bits 2, 4, and 5 of the behavior table
  24. db $30,$20,$30,$20 ; long Piranha Plants
  25. db $30,$18,$30,$18 ; short Piranha Plants
  26. !StemYOffset = $10 ;
  27. HeadTilemap:
  28. db $AE,$AC
  29. !StemTile = $CE
  30. ; These two are indexed by ------lc, where c = color and l = length.
  31. ; Add 1 to each of these values if you want the tile to use the second graphics page.
  32. StemPalette: ; the palette of the stem tiles
  33. db $0A,$08,$0A,$08
  34. HeadPalette: ; the palette of the head tiles
  35. db $08,$08,$0A,$08
  36. ; This tile will be invisible because it has sprite priority setting 0,
  37. ; but it will go in front of the plant tiles to cover it up when it is in a pipe.
  38. ; That way, the plant tiles don't need to have hardcoded priority.
  39. ; This tile should be as close to square as possible.
  40. ; Note: The default value WILL NOT completely hide the tiles unless you have changed its graphics!
  41. ; But the only completely square tile in a vanilla GFX00/01 is the message box tile, which is set to be overwritten by default.
  42. !CoverUpTile = $40 ; the invisible tile used to cover up the sprite when it is in a pipe
  43. !InitOffsetYLo = $FF
  44. !InitOffsetYHi = $FF
  45. !InitOffsetXLo = $08
  46. !InitOffsetXHi = $00
  47. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  48. ;;
  49. ;; init routine wrapper
  50. ;;
  51. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  52. print "INIT ",pc
  53. PHB
  54. PHK
  55. PLB
  56. JSR PiranhaInit
  57. PLB
  58. RTL
  59. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  60. ;;
  61. ;; init routine
  62. ;;
  63. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  64. PiranhaInit:
  65. LDA !7FAB28,x ;
  66. AND #$04 ;
  67. LSR #2 ;
  68. STA !1510,x ;
  69. LDA !D8,x ;
  70. CLC ;
  71. ADC #!InitOffsetYLo ; Y position low byte
  72. STA !D8,x ;
  73. LDA !14D4,x ;
  74. ADC #!InitOffsetYHi ; Y position high byte
  75. STA !14D4,x ;
  76. LDA !E4,x ;
  77. CLC ;
  78. ADC #!InitOffsetXLo ; X position low byte
  79. STA !E4,x ;
  80. LDA !14E0,x ;
  81. ADC #!InitOffsetXHi ; X position high byte
  82. STA !14E0,x ;
  83. LDA !1510,x ; get the bits for the sprite state timer index
  84. AND #$01 ;
  85. ASL #2 ;
  86. STA !1504,x ;
  87. LDA !D8,x ;
  88. STA !151C,x ; back up the sprite's initial XY position (low bytes)
  89. LDA !E4,x ;
  90. STA !1528,x ;
  91. RTS
  92. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  93. ;;
  94. ;; main routine wrapper
  95. ;;
  96. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  97. print "MAIN ",pc
  98. PHB
  99. PHK
  100. PLB
  101. JSR PiranhaPlantsMain
  102. PLB
  103. RTL
  104. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  105. ;;
  106. ;; main routine
  107. ;;
  108. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  109. EndMain:
  110. RTS
  111. PiranhaPlantsMain:
  112. ;LDA $1594,x ; if the sprite is in a pipe and the player is near...
  113. ;BNE NoGFX ; don't draw the sprite
  114. LDA !C2,x ;
  115. BEQ NoGFX ;
  116. JSR PiranhaPlantGFX ; draw the sprite
  117. NoGFX: ;
  118. LDA $9D ; if sprites are locked...
  119. BNE EndMain ; terminate the main routine right here
  120. %SubOffScreen() ;
  121. PiranhaAnimation: ;
  122. JSR SetAnimationFrame ; determine which frame the plant should show
  123. LDA !1594,x ; if the plant is in a pipe...
  124. BNE NoInteraction ; don't let it interact with the player
  125. JSL $01803A|!BankB ; interact with the player and other sprites
  126. NoInteraction: ;
  127. LDA !C2,x ; if the extra bit is set...
  128. CMP #$02 ; then make sure it's in the correct sprite state (resting at the apex)
  129. BNE NoFireCheck ;
  130. LDA !7FAB10,x ;
  131. AND #$04 ; if the extra bit isn't set...
  132. BEQ NoFireCheck ; don't check certain timer values to see if it should spit a fireball
  133. LDA !1540,x ;
  134. CMP #$20 ; if the fire timer
  135. BEQ Fire ; is at certain numbers...
  136. CMP #$10 ; spit a fireball
  137. BEQ Fire ;
  138. NoFireCheck:
  139. LDA !C2,x ; use the sprite state
  140. AND #$03 ; to determine what the sprite's speed should be
  141. TAY ;
  142. LDA !1540,x ; if the timer for changing states has run out...
  143. BEQ ChangePiranhaState ;
  144. LDA Speed,y ; load the base speed
  145. STA !AA,x ; store the speed value to the sprite Y speed table
  146. JSL $01801A|!BankB ; update sprite Y position without gravity
  147. RTS ;
  148. ChangePiranhaState: ;
  149. LDA !C2,x ; sprite state
  150. AND #$03 ; 4 possible states, so we need only 2 bits
  151. STA $00 ; store to scratch RAM for subsequent use
  152. LDA !1510,x ;
  153. AND #$02 ; if the plant is a red one...
  154. ORA $00 ; or the sprite isn't in the pipe...
  155. BNE NoProximityCheck ; don't check to see if the player is near
  156. %SubHorzPos() ; get the horizontal distance between the player and the sprite
  157. LDA #$01 ;
  158. STA !1594,x ; set the invisibility flag if necessary
  159. LDA $0E ;
  160. CLC ;
  161. ADC #$1B ; if the sprite is within a certain distance...
  162. CMP #$37 ;
  163. BCC EndStateChange ; don't change the sprite state
  164. NoProximityCheck: ;
  165. STZ !1594,x ; if the sprite is out of range, clear the invisibility flag
  166. LDA !C2,x ;
  167. INC ; increment the sprite state
  168. AND #$03 ;
  169. STA !C2,x ;
  170. STA $00 ;
  171. LDA !1510,x ;
  172. AND #$01 ; use the stem length bit
  173. ASL #2 ;
  174. ORA $00
  175. TAY ; to set the timer for changing sprite state
  176. LDA TimeInState,y ;
  177. STA !1540,x ; set the time to change state
  178. CPY #$02 ; if the sprite state isn't 02...
  179. BNE EndStateChange ; don't spit fire
  180. JSR SpitFireballs ;
  181. EndStateChange: ;
  182. RTS
  183. SetAnimationFrame: ;
  184. INC !1570,x ; $1570,x - individual sprite frame counter, in this context
  185. LDA !1570,x ;
  186. LSR #3 ; change image every 8 frames
  187. AND #$01 ;
  188. STA !1602,x ; set the resulting image
  189. RTS
  190. Fire: ;
  191. JMP SpitFireballs ;
  192. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  193. ;;
  194. ;; graphics routine
  195. ;;
  196. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  197. PiranhaPlantGFX: ; I made my own graphics routine, since the Piranha Plant uses a shared routine.
  198. %GetDrawInfo() ; set some variables up for writing to OAM
  199. LDA !1510,x ;
  200. AND #$04 ; stem length
  201. LSR ;
  202. STA $04 ;
  203. LDA !1510,x ;
  204. AND #$08 ;
  205. LSR #3 ; plus color
  206. TSB $04 ;
  207. LDA !1602,x ;
  208. STA $03 ; frame = bit 0 of the index
  209. LDA !1510,x ;
  210. AND #$01 ; if the plant has a short stem...
  211. BNE AlwaysCovered ; then the stem is always partially obscured by the cover-up tile
  212. LDA !C2,x ;
  213. CMP #$02 ; if the sprite is all the way out of the pipe...
  214. BEQ StemOnly ; then draw just the stem
  215. AlwaysCovered: ;
  216. LDA !D8,x ;
  217. SEC ;
  218. SBC !151C,x ;
  219. STA $06 ;
  220. LDA !E4,x ;
  221. SEC ;
  222. SBC !1528,x ;
  223. CLC ;
  224. ADC $06 ;
  225. CLC ;
  226. ADC #$10 ;
  227. CMP #$20 ;
  228. BCC CoverUpTileOnly ;
  229. StemAndCoverUpTile: ;
  230. JSR DrawCoverUpTile ;
  231. INY #4 ;
  232. JSR DrawStem ;
  233. LDA #$02 ;
  234. EndGFX: ;
  235. PHA ;
  236. INY #4 ;
  237. LDX $03 ;
  238. JSR DrawHead ; the head tile is always drawn
  239. PLA ;
  240. LDY #$02 ;
  241. LDX $15E9|!Base2 ;
  242. JSL $01B7B3|!BankB ;
  243. RTS ;
  244. StemOnly: ;
  245. JSR DrawStem ;
  246. LDA #$01 ;
  247. BRA EndGFX ;
  248. CoverUpTileOnly: ;
  249. JSR DrawCoverUpTile ;
  250. LDA #$01 ;
  251. BRA EndGFX ;
  252. DrawHead:
  253. LDA $00 ;
  254. STA $0300|!Base2,y ;
  255. LDA $01 ;
  256. STA $0301|!Base2,y ;
  257. LDA HeadTilemap,x ; set the tile for the head
  258. STA $0302|!Base2,y
  259. LDX $04 ; load the palette index
  260. LDA HeadPalette,x ; add in the palette/GFX page bits
  261. ORA $64 ; and the level's sprite priority
  262. STA $0303|!Base2,y ;
  263. RTS
  264. DrawStem:
  265. LDX $03
  266. LDA $00 ;
  267. STA $0300|!Base2,y ;
  268. LDA $01 ;
  269. CLC ;
  270. ADC #$10 ;
  271. STA $0301|!Base2,y ;
  272. LDA #!StemTile ; set the tile for the stem
  273. STA $0302|!Base2,y
  274. LDX $04 ; load the palette index
  275. LDA StemPalette,x ; add in the palette/GFX page bits
  276. ORA $64 ; and the level's sprite priority
  277. STA $0303|!Base2,y ;
  278. RTS ;
  279. DrawCoverUpTile: ;
  280. LDX $15E9|!Base2 ;
  281. LDA !1528,x ;
  282. STA $09 ;
  283. LDA !151C,x ; make backups of the XY init positions
  284. STA $0A ;
  285. LDA $09 ;
  286. SEC ;
  287. SBC $1A ;
  288. STA $0300|!Base2,y ;
  289. LDA $0A ;
  290. SEC ;
  291. SBC $1C ;
  292. STA $0301|!Base2,y ;
  293. LDA #!CoverUpTile ;
  294. STA $0302|!Base2,y ;
  295. LDA #$00 ;
  296. STA $0303|!Base2,y ;
  297. RTS ;
  298. LDX $15E9|!Base2 ; sprite index back into X
  299. LDY #$02 ; the tiles were 16x16
  300. LDA $05 ; we drew 2 or 3 tiles
  301. JSL $01B7B3|!BankB ;
  302. RTS ;
  303. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  304. ;;
  305. ;; fireball-spit routine
  306. ;;
  307. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  308. !FireXOffset = $04
  309. !FireYSpeed = $D0
  310. FireXSpeeds:
  311. db $10,$F0
  312. SpitFireballs:
  313. LDA !E4,x
  314. STA $01
  315. LDA !14E0,x
  316. STA $02
  317. LDA !D8,x
  318. STA $03
  319. LDA !14D4,x
  320. STA $04
  321. LDX #$01
  322. SpitFireballLoop:
  323. LDY #$07
  324. ExSpriteLoop:
  325. LDA $170B|!Base2,y
  326. BEQ FoundExSlot
  327. DEY
  328. BPL ExSpriteLoop
  329. RTS
  330. FoundExSlot:
  331. STY $00
  332. LDA #$0B
  333. STA $170B|!Base2,y
  334. LDA $01
  335. CLC
  336. ADC #!FireXOffset
  337. STA $171F|!Base2,y
  338. LDA $02
  339. ADC #$00
  340. STA $1733|!Base2,y
  341. LDA $03
  342. STA $1715|!Base2,y
  343. LDA $04
  344. STA $1729|!Base2,y
  345. LDA FireXSpeeds,x
  346. STA $1747|!Base2,y
  347. LDA #!FireYSpeed
  348. STA $173D|!Base2,y
  349. LDA #$FF
  350. STA $176F|!Base2,y
  351. DEX
  352. BPL SpitFireballLoop
  353. LDX $15E9|!Base2
  354. RTS