;Vera Sprite Manipulation Assembly Language Routines for C02 ;Requires External Routines GETMEA, GETVRB, GETVRG, SETMET, SETSRD, SETVRB ;and External Variables DSTHI, DSTLO, SRCHI, SRCLO, TEMP0, TEMP0, TEMP2 ;Sprite Control Registers ;$F4000 SPR_CTRL Bit 0 - Enabled ;$F4001 SPR_COLLISION Bits 0-3 Collision Mask ;Sprite attributes ;$F5000 - 128 Entries of the Following Format: ; Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 ;+0 ---------------------Address (12:5)--------------------------- ;+1 Mode -------Address (16:13)------- ;+2 ------------------------X (7:0)------------------------------- ;+3 ---X (9:8)--- ;+4 ------------------------Y (7:0)------------------------------- ;+5 ---Y (9:8)--- ;+6 --------Collision mask-------- ---Z-depth--- V-flip H-flip ;+7 Sprite height Sprite width --------Palette offset-------- MAXSPR EQU 128 ;Maximum Sprite Index ;addspd(index,number) - Add to Sprite Address Register ;Args: A = Sprite Index ; Y,X = Number to Add ;Affects: A,X,Y ADDSPD: JSR SAVREG ;Save Sprite Index, Addend JSR GETSPD ;Read Sprite Address Register JSR ADDTXY ;Add Number to Address BRA SETSTD ;Write Sprite (TEMP0) Address Register ;subspd(index,number) - Decrement Sprite Address Register ;Args: A = Sprite Index ; Y,X = Number to Add ;Affects: A,X,Y SUBSPD: JSR SAVREG ;Save Sprite Index, Addend JSR GETSPD ;Read Sprite Address Register JSR ADDTXY ;Add Number to Address BRA SETSTD ;Write Sprite (TEMP0) Address Register ;clrspr(index) - Set Sprite Attributes ;Args: A = Sprite Index ;Destroys: TEMP0 ;Returns: A,Y = 0 ; X = Current Data Port CLRSPR: JSR SETSP0 ;Set Sprite Attributes Address JMP CLRMEM ;and Read from Vera ;getspc() - Read Sprites Collision Status ;Affects: Y ;Returns: A = Sprite Collision Status ; X = Current Data Port GETSPC: LDX #$02 ;Set Offset to Sprite Control LDY #$40 ;Set Page to Sprite Registers JSR GETVRG ;Read Vera Register AND #$0F ;Return Bits 0-3 RTS ;getspd(index) - Get Sprite Address Register ;Args: A = Index ;Affects: A ;Returns: Y,X = Address Register Contents GETSPD: JSR GETSP0 ;Get Sprite Attribute Address JSR GETVRI ;Read Vera Register Pair TYA AND #$0F TAY RTS ;getspe() - Read Sprites Enabled Flag ;Affects: Y ;Returns: A = $FF - Sprites Enabled ; $00 - Sprites Disabled ; X = Current Data Port GETSPE: LDA #$01 ;Set Mask to %0000001 LDX #$00 ;Set Offset to Sprite Control GETSP4: LDY #$40 ;Set Page to Sprite Registers JMP GETVRB ;Get Register Bit Sratus ;getspt(mask) - Test Sprite Collision Status ;Args: A = Collision Bit Mask ;Affects: Y ;Returns: A = Sprite Collision Bits ; X = Current Data Port GETSPT: LDX #$01 ;Set Offset to Sprite Collisions BNE GETSP4 ;Get Register Bit Status ;getspa(index) - Get Sprite Data Address ;Args: A = Index ;Returns: A = Bank ; Y,X = Address GETSPA: JSR GETSPD ;Get Address Register Contents ;getsca(index) - Get Vera Address from Sprite Address ;Args: Y,X = Sprite Address ;Returns: A = Bank ; Y,X = Address GETSCA: LDA #0 ;Set Bank to 0 JSR SAVREG ;Save Address LDX #5 ;Set Shift Count JMP ASLADR ;and Shift Address Left ;getspb(index) - Get Sprite Bits Per Pixel ;Args: A = Index ;Returns: A = Mode (0=4bpp, 1=8bpp) GETSPB: JSR GETSP1 ;Read Sprite Register #1 ASL ;Move High Bit to Carry LDA #0 ;Clear Accumulator ROL ;Move Carry into Low Bit RTS ;getspv(index) - Get Sprite Vertical Flip ;Args: A = Sprite Index ;Returns: A = Vertical Flip Flag GETSPV: LDY #$02 ;Set Bit Mask to Bit 1 .DC $2C ;Skip Next Instruction (Bit Absolute) ;getspf(index) - Get Sprite Horizontal Flip ;Args: A = Sprite Index ;Returns: A = Horizontal Flip Flag GETSPF: LDY #$01 ;Set Bit Mask to Bit 0 STY TEMP0 ;and Store It JSR GETSPN ;Get Sprite Control Register AND TEMP0 ;Mask Bit(s) BEQ GETSXF ;If Clear, Return FALSE LDA #$FF ;Else Return TRUE GETSXF: RTS ;getspw(index) - Get Sprite Width Specifier ;Args: A = Sprite Index ;Returns: A = Palette Offset GETSPW: JSR GETSPS ;Get Sprite Size Register ASL ;Shift Left 2 Bits ASL BRA GETSP6 ;Then Right 6 Bits ;getsph(index) - Get Sprite Height Specifier ;Args: A = Sprite Index ;Returns: A = Sprite Height Specifier GETSPH: JSR GETSPS ;Get Sprite Size Register GETSP6: LSR ;Shift Right 6 Bits LSR LSR LSR LSR LSR RTS ;getspm(index) - Get Sprite Collision Mask ;Args: A = Sprite Index ;Returns: A = Collision Mask GETSPM: JSR GETSPN ;Get Sprite Control Register LSR ;Shift High Nybble to Low Nybble LSR LSR LSR RTS ;getspp(index) - Get Sprite Palette Offset ;Args: A = Sprite Index ;Returns: A = Palette Offset GETSPP: JSR GETSPS ;Get Sprite Size Register AND #$0F ;Return Low Nybble RTS ;getspq(mode) - Calculate Bits Per Pixel ;Args: A = Mode ;Returns: A = Bits per Pixel ; Y = Divisor Shift Count GETSPQ: AND #$01 ;Strip High Bits TAX ;Copy Mode to X LDA GETSTQ,X ;Read BPP from Table LDY GETSYQ,X ;Read Shift Count from Table RTS GETSTQ: .DC 4,8 ;Table: Bits Per Pixel GETSYQ: .DC 1,0 ;Table: Divisor SHift Count ;getsp1(index) - Get Sprite Register 1 (Mode, Addr MSB) ;Args: A = Sprite Index GETSP1: LDY #1 ;Set Offset to Sprite Address MSB .DC $2C ;Skip to GETSPG (Bit Absolute) ;getsps(index) - Get Sprite Size Register ;Args: A = Sprite Index GETSPS: LDY #7 ;Set Offset to Sprite Size Register .DC $2C ;Skip to GETSPG (Bit Absolute) ;getspn(index) - Get Sprite Control Register ;Args: A = Sprite Index ;Returns: Sprite Control Register Contents GETSPN: LDY #6 ;Set Offset to Sprite Address MSB ;getspg(index) - Get Sprite Register ;Args: A = Sprite Index ; Y = Register Offset ;Returns: A = Mode (0=4bpp, 1=8bpp) GETSPG: JSR GETSPO ;Get Sprite Attribute Address JMP GETVRG ;Read Vera Register ;getspx(index) - Get Sprite X-Coordinate ;Args: A = Index ;Returns: Y,X = X-Coordinate GETSPX: LDY #2 ;Set Offset to X-Coordinate .DC $2C ;Skip to GETSPI (Bit Absolute) ;getspy(index) - Get Sprite Y-Coordinate ;Args: A = Index ;Returns: Y,X = X-Coordinate GETSPY: LDY #4 ;Set Offset to Y-Coordinate GETSPI: JSR GETSPO ;Get Sprite Attribute Address JMP GETVRI ;Read Vera Register Pair ;getspz(index) - Get Sprite Z-Depth ;Args: A = Sprite Index ;Returns: A = Z-Depth (0-3) GETSPZ: JSR GETSPN ;Get Sprite Control Register AND #$0F ;Clear High Nybble LSR ;Shift Right Two Bits LSR RTS ;getspk(&spregs) - Get Sprite Control Registers` ;Args: A = Sprite Index ; Y,X = Address of Destination Array GETSPK: JSR SETDST ;Set Destination Address JSR SETSCR ;Set Vera JMP GETMEA ;and Read from Vera ;setscr() - Set Vera Address to Sprite Control Registers SETSCR: LDY #$40 ;Set Page to Sprite Control Registers LDX #$00 ;Set Offset to 0 JSR REGADR ;Set Vera Address to Register LDA #2 ;Set Size to 2 Bytes RTS ;setspk(&spregs) - Get Sprite Control Registers` ;Args: A = Sprite Index ; Y,X = Address of Destination Array SETSPK: JSR SETSRC ;Set Destination Address JSR SETSCR ;Set Vera JMP SETMET ;and Write to Vera ;getspr(index,&sprite) - Get Sprite Attributes ;Args: A = Sprite Index ; Y,X = Address of Destination Array GETSPR: JSR SETDST ;Set Destination Address JSR SETSP0 ;Set Sprite Attributes Address JMP GETMEA ;and Read from Vera ;getspo(index,offset) - Get Sprite Attribute Address ;Args: A = Sprite Index ; Y = Attribute Offset ;Destroys: TEMP3 ;Returns: A,X = Address LSB ; Y = Address MSB GETSP0: LDY #0 ;Set Attribute Offset to 0 GETSPO: STA TEMP3 ;Set LSB to Index TYA ;Copy Offset to Accumulator AND #$07 ;Modulo 8 PHA ;and Save It LDA #0 ;Set MSB to 0 ASL TEMP3 ;Multiply by 8 ROL ASL TEMP3 ROL ASL TEMP3 ROL ORA #$50 ;Add to Register Page TAY ;Return MSB in Y PLA ;Restore Offset ORA TEMP3 ;Add to LSB TAX ;and Return in X RTS ;setspa(index) - Set Vera Address to Sprite Address ;Args: Y,X = Sprite Address ;Affects: A,X,Y SETSPA: JSR GETSCA ;Convert Sprite Address to Vera Address JMP SETADI ;Set Vera Address with Auto-Increment ;setspb() - Set Sprite Bits Per Pixel ;Args: A = Sprite Index ; Y = Bits Per Pixel ;Affects: A,X,Y SETSPB: STY TEMP0 ;Save Bits Per Pixel JSR GETSP1 ;Read Sprite Register #1 ASL ;Shift Out Bit 7 LSR TEMP0 ;Shift BPP to Carry ROR ;then into Bit 7 JMP SETBYN ;and Write to Register ;setspd(index,addr) - Set Sprite Address Register ;Args: A = Index ; Y,X = Address Register Value SETSPD: STA TEMP0 ;Save Sprite Index SETSTD: TYA ;Copy MSB to Accumulator AND #$0F ;Strip High Nybble TAY ;and Copy Back to Y JSR SAVRXY ;Copy Value to TEMP1,TEMP2 LDA TEMP0 ;Restore Sprite Index JSR GETSP1 ;Read MSB Register AND #$F0 ;Strip Low Nybble ORA TEMP2 ;Combine with MSB STA TEMP2 ;and Save for Write LDA TEMP0 ;Restore Sprite Index JSR GETSP0 ;Get Sprite Attribute Address JMP SETREI ;Write TEMP1,TEMP2 to Attribute ;setspm(index) - Set Sprite Collision Mask ;Args: A = Sprite Index ; Y = Collision Mask SETSPM: PHA ;Save Sprite Depth LDX #$0F ;Set Bit Mask TYA ;Copy Mask to Accumulator ASL ;Shift Left Two Byte ASL JMP SETSP2 ;Then Two More and Write ;setspz(index,depth) - Set Sprite Z-Depth ;Args: A = Sprite Index ; Y = Z-Depth (0-3) SETSPZ: PHA ;Save Sprite Depth LDX #$F3 ;Set Bit Mask TYA ;Copy Z-Depth to Accumulator AND #$03 ;Isolate Bits 0 and 1 SETSP2: ASL ;Move to Bits 2 and 3 ASL STX TEMP1 ;Save Bit Mask BRA SETSP6 ;Set Bits in Control Register ;getspu(index) - Get Sprite Width, Height, and Mode ;Args: A = Sprite Index ;Sets: TEMP0 = Sprite Index ;Returns: A = Width Specifier ; Y = Height Specifier ; X = Mode GETSPU: STA TEMP0 ;Save Sprite Index JSR GETSPW ;Get Sprite Width Specifier PHA ;and Save It LDA TEMP0 ;Retrieve Sprite Indes JSR GETSPH ;Get Sprite Height Specifier PHA ;and Save It LDA TEMP0 ;Retrieve Sprite Index JSR GETSPP ;Get Mode TAX ;Return Mode in X PLY ;Height in Y PLA ;and Width in A RTS ;getspl(index) - Get Sprite Data Size ;Args: A = Sprite Index ;Sets: TEMP0 = Sprite Index ; TEMP1,TEMP2 = Data Size LSB,MSB ;Affects: A ;Returns: Y,X = Data Size in Bytes GETSPL: JSR GETSPU ;Get Width, Height, Mode and Execute GETSCL ;getscl(width,height,mode) - Calculate Sprite Data Size ;Args: A = Width Specifier ; Y = Height Specifier ; X = Mode (Bits Per Pixel) ;Sets: TEMP1,TEMP2 = Data Size LSB,MSB ;Affects: A ;Returns: Y,X = Data Size in Bytes GETSCL: ;.DC $FF ;Debug PHX ;Save Mode PHA ;Save Width TYA ;Copy Height to Accumulator JSR GETSCS ;Calculate Height in Pixles STA TEMP1 ;Save as LSB PLA ;Retrieve Width JSR GETSCS ;Get Width Shift Counter in Y LDA #0 ;Set MSB to 0 GETSLK: ASL TEMP1 ;Multiply LSB ROL ;and MSB by 2 DEY ;Decrement Counter BNE GETSLK ;and Loop if Not Zero PLX ;Retrieve Mode BNE GETSSK ;If 0 (4 Bits Per Pixel) LSR ; Divide MSB ROR TEMP1 ; snd LSB by 2 GETSSK: STA TEMP2 ;Save MSB in TEMP2 JMP RESRXY ;Return LSB snd MSB in X and Y ;getscs(size) - Calculate Sprite Size in Pixels ;Args: A = Height/Width Specifier ;Returns: A = Size in Pixels ; Y = Width Multiplier Shift Count ; X = Height/Width Specifier GETSCS: AND #$03 ;Strip High Bits TAX ;Copy Specifier to X LDA GETSCT,X ;Load Size in Pixels from Table LDY GETSCY,X ;Load Shift Count from Table RTS GETSCT: .DC 8,16,32,64 ;Table: Size in Pixels GETSCY: .DC 3, 4, 5, 6 ;Table: Shift Multiplier ;setspv(index) - Set Sprite Vertical Flip ;Args: A = Sprite Index ; Y = Vertical Flip Flag SETSPV: LDX #$02 ;Set Bit Pattern for Register .DC $2C ;Skip Next Instruction (Bit Absolute) ;setspf(index) - Set Sprite Horizontal Flip ;Args: A = Sprite Index ; Y = Horizontal Flip Flag SETSPF: LDX #$01 ;Set Bit Pattern for Register PHA ;Save Sprite Index TXA ;Copy Bit Pattern to Accumulator EOR #$FF ;Convert to Bit Mask STA TEMP1 ;and Save It TYA ;Copy Flag to Accumulator BEQ SETSP6 ;If Not Zero TXA ;Change to %00000001 SETSP6: STA TEMP0 ;and Store It PLA ;Retrieve Sprite Index JSR GETSPN ;Get Sprite Control Register SETSP8: AND TEMP1 ;Apply Mask ORA TEMP0 ;Set Bit(s) JMP SETBYN ;and Write Back to Register ;setspn(index,value) - Set Sprite Attribute Control Register ;Args: A = Sprite Index ; Y = Value to Write ;Returns: A = Mode (0=4bpp, 1=8bpp) SETSPN: STY TEMP0 ;Save Value to Write LDY #6 ;Set Offset to Control Register BNE SETSTG ;and Write Value to Register ;setspg(index,offset,value) - Set Sprite Attribute Register ;Args: A = Sprite Index ; Y = Register Offset ; X = Value to Write ;Returns: A = Mode (0=4bpp, 1=8bpp) SETSPG: STX TEMP0 ;Save Value to Write SETSTG: JSR GETSPO ;Get Attribute Address for Sprite A Register Y JMP SETREH ;Write TEMP0 to Register ;setspw(index) - Set Sprite Width Specifier ;Args: A = Sprite Index ; Y = Sprite Width Specifier SETSPW: PHA ;Save Sprite Index LDX #$CF ;Set Bit Mask TYA ;Copy Specifier to Accumulator AND #$03 ;Isolate Bits 0 and 1 BRA SETSP4 ;Shift Left Four Bits and Write Masked ;setsph(index) - Set Sprite Height Specifier ;Args: A = Sprite Index ; Y = Sprite Height Specifier SETSPH: PHA ;Save Sprite Index LDX #$3F ;Set Bit Mask TYA ;Copy Specifier to Accumulator ASL ;Shift Left Six Bits ASL SETSP4: ASL ASL ASL ASL BRA SETSP7 ;Write Masked to Size Register ;setspp(index) - Set Sprite Palette Offset ;Args: A = Sprite Index ; Y = Palette Offset SETSPP: PHA ;Save Sprite Index LDX #$F0 ;Set Bit Mask TYA ;Copy Offset to Accumulator AND #$0F ;Isolate Low Nybble SETSP7: STA TEMP0 ;Save Value STX TEMP1 ;Save Bit Mask PLA ;Retrieve Sprite Index JSR GETSPS ;Get Sprite Size Register BRA SETSP8 ;Apply Mask, Set Bits, and Write ;setsps(index,value) - Set Sprite Attribute Size Register ;Args: A = Sprite Index ; Y = Value to Write ;Returns: A = Mode (0=4bpp, 1=8bpp) SETSPS: STY TEMP0 ;Save Value to Write LDY #7 ;Set Offset to Size Register BNE SETSTG ;and Write Value to Register ;setspe() - Enable/Disable Sprites ;Args: A = Sprites Enabled Flag ; 0 for Disabled, Any Other Value for Enabled ;Affects: A,X,Y SETSPE: ORA #0 ;If Accumulator BEQ SETSKE ;is Not Zero LDA ##01 ;Set to %00000001 SETSKE: LDY #$FE ;Set Mask to %11111110 STY TEMP0 LDX #$00 ;Set Offset to Sprite Control LDY #$40 ;Set Page to Sprite Registers JMP SETVRB ;Get Register Bit ;setspo(index,offset) - Set Sprite Attributes Address ;Args: A = Sprite Index ; Y = Attribute Offset SETSP0: LDY #0 ;Set Offset to 0 SETSPO: JSR GETSPO ;Get Sprite Attributes Address JSR REGADR ;Set as Vera Register Address LDA #8 ;Set Size to 8 Bytes RTS ;setspr(index,&sprite) - Set Sprite Attributes ;Args: A = Sprite Index ; Y,X = Address of Source Structure ;Destroys: TEMP0 ;Returns: A,Y = Number of Bytes Written ; X = Current Data Port SETSPR: JSR SETSRC ;Set Destination Address JSR SETSP0 ;Set Sprite Attributes Address JMP SETMET ;and Write from Vera ;setspy(index,coord) - Set Sprite Y-Coordinate ;Args: A = Sprite Index ; Y,X = Y-Coordinate SETSPY: JSR SAVRXY ;Store Value in TEMP1,TEMP2 LDY #4 ;Set Register Offset to Y-Coordinate BNE SETSPI ;Write TEMP1,TEMP2 to Registers ;setspx(index,coord) - Set Sprite X-Coordinate ;Args: A = Sprite Index ; Y,X = X-Coordinate SETSPX: JSR SAVRXY ;Store Value in TEMP1,TEMP2 LDY #2 ;Set Register Offset to X-Coordinate ;setspi(index) - Write to Sprite Attribute Register Pair ;Args: A = Sprite Index ; Y = Attribute Offset ;Uses: TEMP1.TEMP2 = Integer to Write SETSPI: JSR GETSPO ;Get Sprite Attribute Address JMP SETREI ;Write TEMP1,TEMP2 to Attribute