;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; To edit the displayed graphics, simply edit the tables below, you can add as many tiles as you want. ; They're all 16x16 tiles, also make extra sure all the tables have the same amount of entries. ; ; The entries already there are just examples, feel free to delete/edit them. ; They should look like a diagonal line of glitchy tiles by default (just so you can see if it works). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Don't edit these defines: !8 = $20 !9 = $22 !A = $24 !B = $26 !C = $28 !D = $2A !E = $2C !F = $2E !Xflip = $40 !Yflip = $80 !Second = $01 !OAM = $0200 ;oam table !Size = !OAM&$1FF/4+$420 ;size table ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Do edit these tables: ;This table determines which graphics to display. ;To get the right values, open your 8x8 editor, scroll down to your sprite page and hover over the tile's top left corner. ;It'll show the value in the bottom left of the 8x8 editor window, only use the last 2 digits. Tiles: ;db $20,$22,$24,$26,$28,$2A,$2C,$2E,$40,$42,$44,$46,$48,$4A,$4C,$4E,$62,$64,$66,$68,$6A,$6C,$0A,$0C,$0E,$80,$82,$84,$86,$88,$8A,$8C,$8E,$A0,$A2,$A4,$A6,$A8,$AA,$AC,$AE,$C0,$C2,$C4,$A4,$C6,$C8,$CA,$CC,$CE,$E0,$E2,$E4,$E6,$E8,$EA,$EC,$EE,$20,$22 db $20,$22,$24,$26,$28,$2A,$2C,$2E,$40,$42,$44,$46,$48,$4A,$4C,$4E,$60,$62,$64,$66,$68,$6A,$6C ;Which palette each tile uses. ;Since the YXPPCCCT format might be a bit confusing and gets annoying quickly if you have a lot of tiles, use the defines instead. ;If you want to flip a tile horizontally or vertically, add |!Xflip or |!Yflip after it, like "db !8|!Xflip,!9,!A etc" ;If the tile is on the second graphics page (SP3 and SP4), add |!Second after it. Palettes: ;db !8,!9,!9,!9,!9,!9,!9,!9,!9,!9,!9,!9,!9,!9,!A,!B,!A,!A,!9,!C,!C,!C,!C,!C,!C,!D,!D,!D,!D,!D,!D,!D,!D,!D,!F,!F,!F,!F,!F,!F,!F,!F,!F,!D,!F,!D,!D,!D,!D,!D,!D,!D,!D,!D,!D,!D,!D,!D,!D|!Second,!D|!Second db !D,!D,!D,!D,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C,!C ;This table determines the X (horizontal) position of the tile on the screen. ;The higher the number, the further to the right the tile is. $00 is the left edge. ;Because this is just for a title screen that won't scroll, the tiles also don't scroll, so simply put in Lunar Magic coordinates. XPositions: ;db $60,$70,$60,$70,$80,$90,$A0,$A0,$90,$80,$70,$60,$50,$50,$60,$70,$80,$90,$90,$80,$70,$60,$60,$70,$80,$70,$80,$90,$A0,$B0,$C0,$60,$50,$40,$40,$50,$60,$70,$80,$90,$A0,$B0,$C0,$40,$50,$60,$70,$80,$90,$A0,$B0,$C0,$B0,$A0,$90,$80,$70,$60,$50,$40 db $70,$80,$70,$80,$50,$50,$50,$30,$30,$30,$70,$80,$70,$80,$90,$90,$90,$A0,$A0,$A0,$C0,$C0,$C0 ;This table determines the Y (vertical) position of the tile on the screen. ;The higher the number, the further down the tile is. $00 is the top edge. ;Because this is just for a title screen that won't scroll, the tiles also don't scroll, so simply put in Lunar Magic coordinates. YPositions: ;db $AF,$AF,$9F,$9F,$9F,$9F,$9F,$8F,$8F,$8F,$8F,$8F,$8F,$7F,$7F,$7F,$7F,$7F,$6F,$6F,$6F,$6F,$5F,$5F,$5F,$4F,$4F,$4F,$4F,$4F,$4F,$4F,$4F,$4F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F,$2F,$2F,$2F,$2F,$2F,$2F,$2F,$2F,$2F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F db $8F,$8F,$7F,$7F,$AF,$9F,$8F,$AF,$9F,$8F,$3F,$3F,$2F,$2F,$9F,$8F,$AF,$AF,$9F,$8F,$8F,$9F,$AF ; = Macros = ; ;finds free oam slots, starting from where y is currently at ;16bit x/y macro getOAM() ?slotLoop: CPY #$0200 BEQ ?foundSlot LDA !OAM+$1,y CMP #$F0 BEQ ?foundSlot INY : INY : INY : INY BRA ?slotLoop ?foundSlot: endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; sprite INIT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; print "INIT ",pc RTL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; sprite MAIN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; print "MAIN ",pc PHB ; \ PHK ; | The same old PLB ; / JSR SubGFX ; Jump to sprite code PLB ; Yep RTL ; Return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GFX Routine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SubGFX: JSR SubOffScreen_X3 PHX LDA #$00 XBA LDA.b #Palettes-Tiles-$1 REP #$30 STA $0F TAX LDY #$0000 ;load index of 0 at the start SEP #$20 .TileLoop %getOAM() ;put free oam slot index into y LDA XPositions,x STA $0200,y ;store to oam x pos LDA YPositions,x STA $0201,y ;store to oam y pos LDA Tiles,x STA $0202,y ;store to oam tile LDA Palettes,x STA $0203,y ;store to oam props REP #$20 TYA LSR A LSR A PHY TAY SEP #$20 LDA #$02 ;16x16 STA !Size,y ;store to size table PLY DEX BPL .TileLoop SEP #$10 PLX RTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SUB_OFF_SCREEN ; This subroutine deals with sprites that have moved off screen ; It is adapted from the subroutine at $01AC0D ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SPR_T12: db $40,$C0 SPR_T13: db $01,$FE SPR_T14: db $30,$C0,$A0,$C0,$A0,$F0,$60,$90 ;bank 1 sizes db $30,$C0,$A0,$80,$A0,$40,$60,$B0 ;bank 3 sizes SPR_T15: db $01,$FF,$01,$FF,$01,$FF,$01,$FF ;bank 1 sizes db $01,$FF,$01,$FF,$01,$00,$01,$FF ;bank 3 sizes SubOffScreen_X1: LDA #$02 ; \ entry point of routine determines value of $03 BRA STORE_03 ; | (table entry to use on horizontal levels) SubOffScreen_X2: LDA #$04 ; | BRA STORE_03 ; | SubOffScreen_X3: LDA #$06 ; | BRA STORE_03 ; | SubOffScreen_X4: LDA #$08 ; | BRA STORE_03 ; | SubOffScreen_X5: LDA #$0A ; | BRA STORE_03 ; | SubOffScreen_X6: LDA #$0C ; | BRA STORE_03 ; | SubOffScreen_X7: LDA #$0E ; | STORE_03: STA $03 ; | BRA START_SUB ; | SubOffScreen_X0: STZ $03 ; / START_SUB: JSR SUB_IS_OFF_SCREEN ; \ if sprite is not off screen, return BEQ RETURN_35 ; / 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_35 ; / LDA $13 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0756 VC:176 00 FL:205 AND #$01 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0780 VC:176 00 FL:205 ORA $03 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0796 VC:176 00 FL:205 STA $01 ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0820 VC:176 00 FL:205 TAY ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0844 VC:176 00 FL:205 LDA $1A ;A:8A01 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizcHC:0858 VC:176 00 FL:205 CLC ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0882 VC:176 00 FL:205 ADC SPR_T14,y ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZcHC:0896 VC:176 00 FL:205 ROL $00 ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizcHC:0928 VC:176 00 FL:205 CMP $E4,x ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:0966 VC:176 00 FL:205 PHP ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:0996 VC:176 00 FL:205 LDA $1B ;A:8AC0 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizCHC:1018 VC:176 00 FL:205 LSR $00 ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdiZCHC:1042 VC:176 00 FL:205 ADC SPR_T15,y ;A:8A00 X:0009 Y:0001 D:0000 DB:01 S:01F0 P:envMXdizcHC:1080 VC:176 00 FL:205 PLP ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F0 P:eNvMXdizcHC:1112 VC:176 00 FL:205 SBC $14E0,x ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1140 VC:176 00 FL:205 STA $00 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1172 VC:176 00 FL:205 LSR $01 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:eNvMXdizCHC:1196 VC:176 00 FL:205 BCC SPR_L31 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1234 VC:176 00 FL:205 EOR #$80 ;A:8AFF X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdiZCHC:1250 VC:176 00 FL:205 STA $00 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1266 VC:176 00 FL:205 SPR_L31: LDA $00 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1290 VC:176 00 FL:205 BPL RETURN_35 ;A:8A7F X:0009 Y:0001 D:0000 DB:01 S:01F1 P:envMXdizCHC:1314 VC:176 00 FL:205 ERASE_SPRITE: LDA $14C8,x ; \ if sprite status < 8, permanently erase sprite CMP #$08 ; | BCC KILL_SPRITE ; / LDY $161A,x ;A:FF08 X:0007 Y:0001 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1108 VC:059 00 FL:2878 CPY #$FF ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZCHC:1140 VC:059 00 FL:2878 BEQ KILL_SPRITE ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1156 VC:059 00 FL:2878 LDA #$00 ;A:FF08 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdizcHC:1172 VC:059 00 FL:2878 STA $1938,y ;A:FF00 X:0007 Y:0000 D:0000 DB:01 S:01F3 P:envMXdiZcHC:1188 VC:059 00 FL:2878 KILL_SPRITE: STZ $14C8,x ; erase sprite RETURN_35: RTS ; return VERTICAL_LEVEL: LDA $167A,x ; \ if "process offscreen" flag is set, return AND #$04 ; | BNE RETURN_35 ; / LDA $13 ; \ LSR A ; | LSR A BCS RETURN_35 ; / LDA $E4,x ; \ CMP #$00 ; | if the sprite has gone off the side of the level... LDA $14E0,x ; | SBC #$00 ; | CMP #$02 ; | BCS ERASE_SPRITE ; / ...erase the sprite LDA $13 ;A:0000 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:1218 VC:250 00 FL:5379 LSR A ;A:0016 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1242 VC:250 00 FL:5379 AND #$01 ;A:000B X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1256 VC:250 00 FL:5379 STA $01 ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1272 VC:250 00 FL:5379 TAY ;A:0001 X:0009 Y:00E4 D:0000 DB:01 S:01F3 P:envMXdizcHC:1296 VC:250 00 FL:5379 LDA $1C ;A:001A X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0052 VC:251 00 FL:5379 CLC ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0076 VC:251 00 FL:5379 ADC SPR_T12,y ;A:00BD X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0090 VC:251 00 FL:5379 ROL $00 ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:enVMXdizCHC:0122 VC:251 00 FL:5379 CMP $D8,x ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0160 VC:251 00 FL:5379 PHP ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0190 VC:251 00 FL:5379 LDA.w $001D ;A:006D X:0009 Y:0001 D:0000 DB:01 S:01F2 P:eNVMXdizcHC:0212 VC:251 00 FL:5379 LSR $00 ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdiZcHC:0244 VC:251 00 FL:5379 ADC SPR_T13,y ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:enVMXdizCHC:0282 VC:251 00 FL:5379 PLP ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F2 P:envMXdiZCHC:0314 VC:251 00 FL:5379 SBC $14D4,x ;A:0000 X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNVMXdizcHC:0342 VC:251 00 FL:5379 STA $00 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0374 VC:251 00 FL:5379 LDY $01 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0398 VC:251 00 FL:5379 BEQ SPR_L38 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0422 VC:251 00 FL:5379 EOR #$80 ;A:00FF X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0438 VC:251 00 FL:5379 STA $00 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0454 VC:251 00 FL:5379 SPR_L38: LDA $00 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0478 VC:251 00 FL:5379 BPL RETURN_35 ;A:007F X:0009 Y:0001 D:0000 DB:01 S:01F3 P:envMXdizcHC:0502 VC:251 00 FL:5379 BMI ERASE_SPRITE ;A:8AFF X:0002 Y:0000 D:0000 DB:01 S:01F3 P:eNvMXdizcHC:0704 VC:184 00 FL:5490 SUB_IS_OFF_SCREEN: LDA $15A0,x ; \ if sprite is on screen, accumulator = 0 ORA $186C,x ; | RTS ; / return