;====================================================================================== ;Defines ;====================================================================================== !R0 = $3000 ;default source/destination register !R1 = $3002 ;PLOT X position !R2 = $3004 ;PLOT Y position !R3 = $3006 !R4 = $3008 !R5 = $300A ; !R6 = $300C ;multiplier for FMULT and LMULT !R7 = $300E ;used in MERGE !R8 = $3010 ;used in MERGE !R9 = $3012 ; !R10 = $3014 ; !R11 = $3016 ;Return adress set by LINK !R12 = $3018 ;loop counter !R13 = $301A ;loop adress !R14 = $301C ;ROM buffer !R15 = $301E ;Program counter !SFR = $3030 ;SuperFx status flag !PBR = $3034 ;Program bank !ROMBR = $3036 ; !RAMBR = $303C ; !CBR = $303E ; !SCBR = $3038 ; !SCMR = $303A ; !BRAMR = $3033 ; !VCR = $303B ; !CFGR = $3037 ; !CLSR = $3039 ; ;====================================================================================== print "INIT ",pc RTL print "MAIN ",pc PHB PHK ; Always change the data bank. PLB JSR SprRoutine PLB RTL SprRoutine: JSR Graphics STX !R6 REP #$20 LDY.b #(SpriteCustom>>16)&$3F ;\ Load the sprite code LDA.w #SpriteCustom ;/ JSR $1E80 JSL $01802A ; Apply speed. RTS arch superfx SpriteCustom: IBT R0,#(SpriteCustom>>16)&$3F ;\ Set ROM Bank ROMB ;/ IBT R0,#$19 ;\ This code loads the table below LDB (R0) ; | Based on player powerup (1-bit) AND #1 ; | If Player is Small, it walks only MULT #2 ;/ Otherwise, it jumps. LEA R10,SpriteTable ; Load the table FROM R10 ;\ Load table value... TO R14 ; | ADD R0 ; | Add with the values we set with R0 GETB ; | INC R14 ; | TO R10 ; | GETBH ; | JMP R10 ;/ Jump according to the result CACHE ; Jump and load code to be on CACHE RAM ;The whole routine above, sets the ROM bank and loads the Sprite table below ;After that, it gets the RAM value set in R0 and then does everything SNES does ;Multiplies the value by 2 and add to the current table value which THEN is buffered ;Transferred to R10 and properly jumps at the address location SpriteTable: dw Walk dw Jump NOP Walk: IBT R0,#$08 LEA R1,$B6 WITH R1 ADD R6 STB (R1) STOP NOP NOP Jump: SUB R0 LEA R1,$B6 WITH R1 ADD R6 STB (R1) IBT R0,#$F8 LEA R1,$AA WITH R1 ADD R6 STB (R1) STOP NOP arch 65816 Graphics: REP #$20 LDY.b #(GDI>>16)&$3F ;\ Load the sprite code LDA.w #GDI ;/ JSR $1E80 LDA $75C4,x ;\ This is a RAM related to off-screen... BNE ++ ;/ If this isn't zero, pull A and return to new routine? LDY !R1 ;RAM_SprOAMIndex ; Y = Index into sprite OAM BRA + ++ PLA ;\ I don't understand much, from what I know... PLA ; | This pulls A two times and returns to original routine. ;/ Without OAM Index. This saves a BIT of time, the original didn't had this. ; after: Y = index to sprite OAM ($300) ; $00 = sprite x position relative to screen boarder ; $01 = sprite y position relative to screen boarder + LDA $00 ; set x position of the tile STA $6300,y LDA $01 ; set y position of the tile STA $6301,y LDA #$24 STA $6302,y LDA $75F6,x ; get sprite palette info ORA $64 ; add in the priority bits from the level settings STA $6303,y ; set properties LDY #$02 ; #$02 means the tiles are 16x16 LDA #$00 ; This means we drew one tile JSL $01B7B3 RTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GET_DRAW_INFO - Optimized version ; This is a helper for the graphics routine. It sets off screen flags, and sets up ; variables. It will return with the following: ; ; Y = index to sprite OAM ($300) ; $00 = sprite x position relative to screen boarder ; $01 = sprite y position relative to screen boarder ; ; It is adapted from the subroutine at $03B760 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GetDrawInfo - Optimized version ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; arch superfx GDI: LEA R1,$14E1 ; LDA $14E0,x : XBA : LDA $E4,x WITH R1 ; $14E0 is using an odd number because ADD R6 ; In Super FX, odd addresses are loaded like this TO R7 ; High byte = Address-1 LDW (R1) ; Thus, it'll effectively load $14E0, only at high byte though LEA R1,$E4 ; WITH R1 ; ADD R6 ; TO R8 ; LDW (R1) ; The MERGE operation grabs high byte (R7) and low byte (R8) MERGE ; and obviously MERGEs it LMS R1,($1A) ; REP #$20 : SEC : SBC $1A : STA $00 SUB R1 ; CLC : ADC #$0040 : CMP #$0180 : SEP #$20 SMS ($00),R0 ; MOVE R12,R0 ; This is used in order to avoid another buffering IBT R1,#$40 ; IWT R2,#$0180 ; ADD R1 ; CMP R2 ; FROM R12 ; LDA $01 : BEQ + HIB ; Bearing in mind, the earlier operation stored R0 on $00 BEQ + ; Thus, another loading is not necessary NOP IBT R0,#$01 ; LDA #$01 : STA $15A0,x + LEA R2,$15A0 ; or WITH R2 ; [...] : LDA #$01 : + STA $15A0,x ADD R6 ; STB (R2) ; XOR R0 ; TDC (Technically Zero) ROL ; ROL A : STA $15C4 : BNE LEA R2,$15C4 ; WITH R2 ; ADD R6 ; ALT1 ; This ALT and STW is a smart way of saving cycles BNE .Invalid ; AND being efficient STW (R2) ; LEA R1,$14D5 ; LDA $14D4,x WITH R1 ; Same case as above, unlike above routine ADD R6 ; It will be used several times, so it is "ready for usage" TO R7 ; High byte = Address-1 LDW (R1) ; IBT R1,#$20 ; LDA $1662,x : AND #$20 : BEQ LEA R2,$1662 ; WITH R2 ; ADD R6 ; LDW (R2) ; AND R1 ; BEQ .CheckOnce ; NOP .CheckTwice LEA R1,$D8 ; $14D4 is already at high byte... WITH R1 ; LDA $D8,x : REP #$21 : ADC #$001C ADD R6 ; SEC : SBC $1C : SEP $20 TO R8 ; LDW (R1) ; MERGE ; IBT R1,#$1C ; ADD R1 ; FROM R1 ; LDW (R1) ; SUB R1 ; BEQ .CheckOnce NOP IBT R0,#$02 .CheckOnce LEA R1,$186C ;LDA #$02 : STA $186C,x WITH R1 ;or ADD R6 ;[...] : LDA #$02 : + STA $186C,x STB (R1) LEA R1,$D8 ; $14D4 is already at high byte... WITH R1 ; LDA $D8,x : REP #$21 : ADC #$000C ADD R6 ; SEC : SBC $1C : SEP $21 : SBC #$0C TO R8 ; STA $01 : XBA : BEQ : INC $186C,x LDW (R1) ; LDY $15EA,x MERGE ; ADD #$C ; LMS R1,($1C) ; SUB R1 MOVE R12,R0 SUB #$0C IBT R1,#$01 STB (R1) FROM R12 HIB BEQ .OnScreenY NOP LEA R1,$186C WITH R1 ADD R6 LDB (R1) INC R0 STB (R1) .OnScreenY LEA R1,$15EA WITH R1 ADD R6 LDW (R1) STOP .Invalid STOP PLA PLA RTS arch 65816