Guest User

NPC Sprite

a guest
Jun 28th, 2020
20
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;; NPC sprite v3.1, by Dispari Scuro and Alcaro
  3. ;;
  4. ;; This sprite displays a message when Mario touches it and presses UP.
  5. ;; It cannot hurt Mario and cannot be killed.
  6. ;; Read below to figure out how to use and fully customize this sprite!
  7. ;;
  8. ;; When placing the sprite in a level, the sprite uses three different variables
  9. ;; to determine which message it displays. Although this system is a little
  10. ;; complicated, this is to ensure that users use as few config files as possible.
  11. ;; With this system, you can have as many as 32 NPCs per level which all display
  12. ;; different messages, all with one config file!
  13. ;;
  14. ;; Firstly, the "Extra Info" is used to determine which message the sprite
  15. ;; displays from its level. With the new system, there's no need to specifically
  16. ;; display the "you found Yoshi" message, because it can be done directly.
  17. ;; Alternatively, if you set the second extra property byte 02, you can make the NPC
  18. ;; display no message at all!
  19. ;; Extra Info is set when you create a sprite in Lunar Magic. Normally when you insert
  20. ;; a custom sprite, you put Extra Info as 02. This sprite has different behavior if you
  21. ;; set it as 03 instead.
  22. ;;
  23. ;; Extra Info:
  24. ;; 02 = Message 1
  25. ;; 03 = Message 2
  26. ;;
  27. ;; After you determine which message the sprite will read from, you need to place it
  28. ;; in a good X position on the screen. When placing the sprite, the X position will
  29. ;; determine part one of which level the sprite actually reads from. There are 16
  30. ;; unique X positions possible per screen, which allows up to 16 unique messages.
  31. ;; The number starts over on the next screen. So if your sprite is in the first
  32. ;; position but on page 4, it's still considered 0 (position 1). Think of it like
  33. ;; the original messagebox, which changed its message based on its X position.
  34. ;; Only instead of only displaying one of two messages, you display one of 16.
  35. ;; In commbination with the Extra Info, that's one of 32.
  36. ;;
  37. ;; The reason for the X position is to determine which color on the palette to read
  38. ;; from to use. If you set the X position for a sprite to 0, it will use the first
  39. ;; color on the palette as a reference. Therefore, you can set color 0 to color 24
  40. ;; to make the sprite read messages from level 24. This DOES mean that you can use
  41. ;; ExAnimation to palette animate this color and generate "random" messages! Please
  42. ;; note the special handling for levels over 24. For any level number over 24,
  43. ;; subtract DC from the level number. For example, level 105 would be 29. Note
  44. ;; that to properly use the palette, you have to set the color so that its SNES
  45. ;; RGB value is the level you want it to be, times 100. So if you want to read
  46. ;; from level 20, the SNES RGB value needs to be 2000. The easiest way to do this
  47. ;; is to set an ExAnimation palette animation of 2000 and then check the actual
  48. ;; palette to see what to paste. 2000 for instance is 0 red, 0 green, 64 blue.
  49. ;;
  50. ;; Here are some examples of how these three varibles come together. For the
  51. ;; sake of this example, we will assume the sprite is still reading from palette E.
  52. ;;
  53. ;; Example 1:
  54. ;; Extra Info is 2. X position is 6 (on screen 1). Palette E6 is 1200. This means the
  55. ;; sprite will display message 1 from level 12. X position is 6 so it reads from E6.
  56. ;; F6 says to read from level 12.
  57. ;;
  58. ;; Example 2:
  59. ;; Extra Info is 3. X position is 42 (on screen 3). Palette EB is 3200. This means the
  60. ;; sprite will display message 2 from level 10E. X position is 11 (11th spot on screen
  61. ;; 3). EB (B = 11) says to read from level 10E (32 + DC = 10E).
  62. ;;
  63. ;; If you're still confused about how to set the messages, check the included demo file
  64. ;; to see just how all the NPCs are set.
  65. ;;
  66. ;; For additional configuration for sprites which you may want to vary on an individual
  67. ;; basis and not just an overall behavior (unlike the sound the sprites make when spoken
  68. ;; to, which should remain the same across all sprites), use the following variables
  69. ;; found in the config file. With this, you can have a couple different NPCs with
  70. ;; varying behavior without having to change the ASM file.
  71. ;;
  72. ;; Extra Byte Property 1:
  73. ;; 00 = Sprite is stationary (if stationary, sprite always faces Mario).
  74. ;; Anything else = Sprite moves back and forth, and this is how long before it turns
  75. ;; around and starts in the other direction. Note that the NPC's turn timer will be
  76. ;; reset if he touches an object or a cliff (if set to stay on ledges). This is to
  77. ;; prevent the NPCs from "hugging" the wall.
  78. ;;
  79. ;; Extra Byte Property 2:
  80. ;; 00 = Sprite displays one message when spoken to.
  81. ;; 01 = Sprite displays two messages when spoken to, one after the other.
  82. ;; Note that if sprite is set to display level message two, using this feature will cause
  83. ;; it to display level message two and then the "you found Yoshi" message.
  84. ;; 02 = Sprite doesn't display any message at all.
  85. ;;
  86. ;; For all other configurables, see below!
  87. ;;
  88. ;; Thank yous to:
  89. ;; andyk250
  90. ;; Heisanevilgenius
  91. ;; S.N.N.
  92. ;; mikeyk
  93. ;;
  94. ;; Based on the following sprite(s):
  95. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  96. ;; Shy Guy, by mikeyk
  97. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  98. ;; SMB2 Birdo, by mikeyk
  99. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  100. ;; Palenemy Lakitu, by Glyph Phoenix and Davros.
  101. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  102.  
  103. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  104. ; Configurables for the sprite
  105. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  106.  
  107. !MessagePalette = $E0 ; Which palette to read from for messages. E by default.
  108. ; Change to suit your needs. Please use the palette you
  109. ; want to use, followed by a zero. If you want to use
  110. ; palette D, change this to $D0
  111.  
  112. !SoundEffect = $22 ; Which sound to play. Use in conjunction with SoundBank.
  113. ; Check online to find a list of sound effects.
  114. ; Default is the same sounds message boxes use.
  115.  
  116. !SoundBank = $1DFC|!Base2 ; Which sound bank to read from.
  117. ; Acceptible values: $1DF9, $1DFA, $1DFB, $1DFC
  118.  
  119. !SpriteStop = $91 ; How long a sprite stops before it turns around.
  120. ; Set this to 00 if you don't want NPCs to stop
  121. ; before turning around.
  122.  
  123. !DirAtStart = $FF ; How does the sprite start off? The classic NPC would
  124. ; always start off walking to the right no matter what.
  125. ; The new version is configurable. By default (FF) it will
  126. ; walk toward Mario at the start. If you don't like this
  127. ; behavior, you can set 00 so it always walks right and
  128. ; 01 so it always walks left. The default walking toward
  129. ; Mario is so the sprite doesn't walk off screen and
  130. ; disappear.
  131.  
  132. !StayOnLedges = 1 ; Does the NPC stay on ledges? 1 for yes, 0 for no.
  133.  
  134. !ButtonToPush = $08 ; This controls what you must push to open a messagebox.
  135. ; Edit this to suit your button-pushing needs:
  136. ; 01 = Right
  137. ; 02 = Left
  138. ; 04 = Down
  139. ; 08 = Up
  140. ; 10 = Start
  141. ; 20 = Select
  142. ; 00 = R and L
  143. ; 40 = Y and X
  144. ; 80 = B and A
  145.  
  146. !DisplayMessage = 1 ; Do the NPC display a message? 1 for yes, 0 for no.
  147.  
  148. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  149. ; Basic mikey stuff
  150. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  151.  
  152. !UpdateSpritePos = $01802A|!BankB
  153. !MarioSprInteract = $01A7DC|!BankB
  154. !GetSpriteClippingA = $03B69F|!BankB
  155. !FinishOAMWrite = $01B7B3|!BankB
  156.  
  157. !ExtraProperty1 = !7FAB28
  158. !ExtraProperty2 = !7FAB34
  159. !RAM_SpriteDir = !157C
  160. !RAM_SprTurnTimer = !15AC
  161.  
  162. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  163. ;; Dispari's stuff
  164. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  165.  
  166. !ExtraInfo = !7FAB10
  167. !X_Position = !1504
  168. !Message2_Timer = !163E
  169. !RAM_SprStopTimer = !1564
  170.  
  171. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  172. ; sprite init JSL
  173. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  174.  
  175. print "INIT ",pc
  176.  
  177. LDA #!DirAtStart
  178. CMP #$FF
  179. BNE SetDir
  180.  
  181. %SubHorzPos()
  182. TYA
  183. STA !157C,x
  184. BRA DoneWithDir
  185.  
  186. SetDir:
  187. LDA #!DirAtStart
  188. STA !157C,x
  189.  
  190. DoneWithDir:
  191. LDA !167A,x
  192. STA !1528,x
  193.  
  194. LDA #$01
  195. STA !151C,x
  196.  
  197. LDA !E4,x ; \ Grab X position
  198. LSR A ; |
  199. LSR A ; |
  200. LSR A ; |
  201. LSR A ; |
  202. STA !X_Position,x ; / Save for later
  203.  
  204. LDA !ExtraProperty1,x ; \ Load walking duration into RAM address as a timer
  205. STA !RAM_SprTurnTimer,x ; /
  206.  
  207. RTL
  208.  
  209. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  210. ; sprite code JSL
  211. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  212.  
  213. print "MAIN",pc
  214. PHB
  215. PHK
  216. PLB
  217. JSR SpriteMainSub
  218. PLB
  219. RTL
  220.  
  221. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  222. ; sprite main code
  223. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  224.  
  225. SpeedX:
  226. db $08,$F8
  227.  
  228. Return:
  229. RTS
  230. SpriteMainSub:
  231. LDA !ExtraProperty1,x ; \
  232. BNE NormalCode ; | If NPC is stationary...
  233. %SubHorzPos() ; | ...always face Mario.
  234. TYA ; |
  235. STA !157C,x ; /
  236.  
  237. NormalCode:
  238. JSR SubGfx
  239.  
  240. LDA $9D ; \ if sprites locked, return
  241. BNE Return ; /
  242.  
  243. LDA #$01
  244. %SubOffScreen() ; Handle off screen situation
  245. INC !1570,x
  246.  
  247. StartSpeed:
  248. LDA !ExtraProperty1,x ; \ If NPC is stationary...
  249. BNE HandleTurnaround ; |
  250. STZ !B6,x ; / ...set speed as 0.
  251. BRA DoneWithSpeed
  252.  
  253. HandleTurnaround:
  254. LDA !RAM_SprStopTimer,x ; \ If sprite has stopped long enough...
  255. CMP #$01 ; |
  256. BEQ RestartSpriteMove ; / ...restart its movement
  257.  
  258. LDA !RAM_SprTurnTimer,x ; \ If turn timer is zero...
  259. BNE SetSpeed ; |
  260. LDA #!SpriteStop ; | ...and sprite doesn't stop...
  261. BEQ RestartSpriteMove ; / ...just turn around.
  262.  
  263. LDA !RAM_SprStopTimer,x ; \ If sprite isn't already stopped...
  264. BNE SetSpeed ; |
  265. LDA #!SpriteStop ; | ...start the stop timer.
  266. STA !RAM_SprStopTimer,x ; /
  267. BRA SetSpeed
  268.  
  269. RestartSpriteMove:
  270. STZ !RAM_SprStopTimer,x
  271. JSR SpriteTurning ; \ Turn the NPC around...
  272. LDA !ExtraProperty1,x ; |
  273. STA !RAM_SprTurnTimer,x ; / ...and reset turn timer.
  274.  
  275. SetSpeed:
  276. LDY !157C,x ; Set x speed based on direction
  277. LDA SpeedX,y
  278. STA !B6,x
  279.  
  280. LDA !RAM_SprStopTimer,x ; \
  281. CMP #$02 ; | Reset speed to zero...
  282. BCC DoneWithSpeed ; | ...if Stop Timer is going.
  283. STZ !B6,x ; /
  284.  
  285. DoneWithSpeed:
  286. JSL !UpdateSpritePos ; Update position based on speed values
  287.  
  288. LDA !1588,x ; If sprite is in contact with an object...
  289. AND #$03
  290. BEQ NoObjContact
  291. JSR SpriteTurning ; ...change direction
  292. LDA !ExtraProperty1,x ; \ Load walking duration into RAM address as a timer
  293. STA !RAM_SprTurnTimer,x ; /
  294.  
  295. NoObjContact:
  296. if !StayOnLedges
  297. JSR MaybeStayOnLedges
  298. endif
  299.  
  300. LDA !1588,x ; if on the ground, reset the turn counter
  301. AND #$04
  302. BEQ NotOnGround
  303. STZ !AA,x
  304. STZ !151C,x ; Reset turning flag (used if sprite stays on ledges)
  305.  
  306. NotOnGround:
  307. LDA !1528,x
  308. STA !167A,x
  309.  
  310. LDA !ExtraProperty2,x
  311. AND #$02
  312. BNE ReturnZ
  313.  
  314. JSL !MarioSprInteract ; \ Check for sprite contact
  315. BCC ReturnZ ; /
  316.  
  317. LDA !Message2_Timer,x ; \ Handle second message if needed
  318. BNE Message2 ; /
  319.  
  320. LDA $15 ; \ Check if Mario is pressing UP...
  321. AND #!ButtonToPush ; | or whatever button you defined
  322. BEQ ReturnZ ; /
  323. LDA #!SoundEffect ; \ Play a sound.
  324. STA !SoundBank ; /
  325.  
  326. LDA #!MessagePalette ; \
  327. CLC ; | Figure out which palette to use for level
  328. ADC !X_Position,x ; /
  329. PHX
  330. REP #$30
  331. AND.w #$00FF
  332. ASL A
  333. TAX
  334. LDA $0704|!Base2,x
  335. SEP #$30
  336. PLX
  337. ; STA $2121 ;
  338. ; LDA $213B ; \ palette to read data
  339. ; LDA $213B ; /
  340. STA $08 ; Store so we know which level to read from
  341.  
  342. LDA !ExtraInfo,x ; \ Get Extra Info
  343. AND #$04 ; /
  344. BNE Scratch_1 ; \
  345. LDA #$01 ; | Extra Info is kinda wacky
  346. BRA Scratch_2 ; /
  347.  
  348. Scratch_1:
  349. LDA #$02
  350.  
  351. Scratch_2:
  352.  
  353. STA $09 ; Scratch RAM is a go
  354.  
  355. LDA $08 ; \ This allows you to read from any level
  356. STA $13BF|!Base2 ; | you want by tricking the game into thinking
  357. ; | the level's number is something other than
  358. ; / what it actually is.
  359.  
  360. LDA $09
  361. STA $1426|!Base2 ; Display message specified
  362. LDA #$0F ; \ Set double message
  363. STA !Message2_Timer,x ; /
  364.  
  365. ReturnZ:
  366. RTS
  367.  
  368. Message2: ; NOTE: Repeat code is fail, but the alternative
  369. ; is spaghetti code.
  370.  
  371. LDA !ExtraProperty2,x ; \ If not set to display two messages...
  372. AND #$01 ; |
  373. BEQ ReturnX ; / ...return.
  374.  
  375. LDA #!MessagePalette ; \
  376. CLC ; | Figure out which palette to use for level
  377. ADC !X_Position,x ; /
  378. PHX
  379. REP #$30
  380. AND.w #$00FF
  381. ASL A
  382. TAX
  383. LDA $0704|!Base2,x
  384. SEP #$30
  385. PLX
  386. ; STA $2121 ;
  387. ; LDA $213B ; \ palette to read data
  388. ; LDA $213B ; /
  389. STA $08 ; Store so we know which level to read from
  390.  
  391. LDA !ExtraInfo,x ; \ Get Extra Info
  392. AND #$04 ; /
  393. BNE Scratch_3 ; \
  394. LDA #$01 ; | Extra Info is kinda wacky
  395. BRA Scratch_4 ; /
  396.  
  397. Scratch_3:
  398. LDA #$02
  399.  
  400. Scratch_4:
  401. CLC
  402. ADC #$01
  403. STA $09 ; Scratch RAM is a go
  404.  
  405. LDA $08 ; \ This allows you to read from any level
  406. STA $13BF|!Base2 ; | you want by tricking the game into thinking
  407. ; | the level's number is something other than
  408. ; / what it actually is.
  409.  
  410. LDA $09
  411. STA $1426|!Base2 ; Display second message
  412. STZ !Message2_Timer,x
  413.  
  414. ReturnX:
  415. RTS
  416.  
  417. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  418. ;; Some mikey routines
  419. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  420.  
  421. SpriteTurning:
  422. LDA !157C,x ; \ If sprite is going right...
  423. BNE GoLeft ; / ...go left.
  424. LDA #$01 ; \ Otherwise go right.
  425. STA !157C,x ; /
  426. RTS
  427.  
  428. GoLeft:
  429. LDA #$00
  430. STA !157C,x
  431. RTS
  432.  
  433. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  434. ;; Ledges
  435. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  436.  
  437. MaybeStayOnLedges:
  438. LDA !1588,x ; If the sprite is in the air
  439. ORA !151C,x ; and not already turning
  440. BNE NoFlipDirection
  441. JSR SpriteTurning ; flip direction
  442. LDA #$01 ; set turning flag
  443. STA !151C,x
  444. LDA !ExtraProperty1,x ; \ Load walking duration into RAM address as a timer
  445. STA !RAM_SprTurnTimer,x ; /
  446. NoFlipDirection:
  447. RTS
  448.  
  449. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  450. ; sprite graphics routine
  451. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  452.  
  453. TILEMAP: db $67,$69 ; Walking 1 (upper, lower)
  454. db $6B,$6D ; Walking 2 (upper, lower)
  455. VERT_DISP: db $F0,$00
  456. db $F0,$00
  457. PROPERTIES: db $40,$00 ;xyppccct format
  458.  
  459. SubGfx:
  460. %GetDrawInfo() ; after: Y = index to sprite tile map ($300)
  461. ; $00 = sprite x position relative to screen boarder
  462. ; $01 = sprite y position relative to screen boarder
  463. LDA !1602,x ; \
  464. ASL A ; | $03 = index to frame start (frame to show * 2 tile per frame)
  465. STA $03 ; /
  466.  
  467. LDA !ExtraProperty1,x ; \ If NPC is stationary, don't animate
  468. BEQ SpriteDir ; /
  469. LDA !RAM_SprStopTimer,x ; \ If NPC is stopped, don't animate
  470. BNE SpriteDir ; /
  471. LDA $14 ; Frame Counter
  472. LSR A ; Change every 4 frames
  473. LSR A
  474. AND #$02 ; 2 walking frames, sprite is made up of 2 tiles
  475. STA $03
  476.  
  477. SpriteDir:
  478. LDA !157C,x ; \ $02 = sprite direction
  479. STA $02 ; /
  480. PHX ; push sprite index
  481. LDX #$01 ; loop counter = (number of tiles per frame) - 1
  482.  
  483. LOOP_START:
  484. PHX ; push current tile number
  485. TXA ; \ X = index to horizontal displacement
  486. ORA $03 ; / get index of tile (index to first tile of frame + current tile number)
  487.  
  488. FACING_LEFT:
  489. TAX ; \
  490. LDA $00 ; | tile x position = sprite x location ($00)
  491. STA $0300|!Base2,y ; /
  492.  
  493. LDA $01 ; \ tile y position = sprite y location ($01) + tile displacement
  494. CLC ; |
  495. ADC VERT_DISP,x ; |
  496. STA $0301|!Base2,y ; /
  497.  
  498. LDA TILEMAP,x ; \ store tile
  499. STA $0302|!Base2,y ; /
  500.  
  501. LDX $02 ; \
  502. LDA PROPERTIES,x ; | get tile properties using sprite direction
  503. LDX $15E9|!Base2 ; |
  504. ORA !15F6,x ; | get palette info
  505. ORA $64 ; | put in level properties
  506. STA $0303|!Base2,y ; / store tile properties
  507.  
  508.  
  509. PLX ; \ pull, X = current tile of the frame we're drawing
  510. INY ; | increase index to sprite tile map ($300)...
  511. INY ; | ...we wrote 1 16x16 tile...
  512. INY ; | ...sprite OAM is 8x8...
  513. INY ; | ...so increment 4 times
  514. DEX ; | go to next tile of frame and loop
  515. BPL LOOP_START ; /
  516.  
  517. PLX ; pull, X = sprite index
  518. LDY #$02 ; \ 02, because we didn't write to 460 yet
  519. LDA #$01 ; | A = number of tiles drawn - 1
  520. JSL $01B7B3|!BankB ; / don't draw if offscreen
  521. RTS ; return
RAW Paste Data