; Vera Memory Access Assembly Language Routines for C02
; Requires External Routines RESRXY, SETDST, and SETSRC
; and External Variables TEMP0 and TEMP1

;Vera External Registers    
;$9F20  Address LSB         
;$9F21  Address MSB         
;$9F22  Auto-Increment and Address Bank    
;$9F23  Data Port 0         
;$9F24  Data Port 1
;$9F25  Control Register
;$9F26  Interrupt Enable
;$9F27  Interrupt Status

;asladr() - Shift Vera Address Left`
;Args: X = Number of Bits to Shift
;Updates: TEMP0 = Bank
;         TEMP1 = Address LSB
;         TEMP3 = Address MSB
;Returns: A = Bank
;         Y,X = Address
ASLADR: ASL TEMP1   ;Shift LSB Left
        ROL TEMP2   ;Rotate Carry Left into MSB
        ROL TEMP0   ;Rotate Carry Left into LSB
        DEX         ;Decrement Shift Count 
        BNE ASLADR  ;and Loop if Not Zero
        BRA RESREG  ;Return Bank, MSB, LSB

;chkadr(opts,addr) - Check Vera Address
;Args: A = Bank + Auto-Increment
;      Y,X = Address
;Returns: A = $00 - Address is Invalid
;             $FF - Address is Valid 
CHKADR: AND #$0F    ;Isolate Bank
        CMP #$0F    ;If Registers
        BEQ GETVRT  ;  Return True
        CMP #$02    ;Else If <2
        BCS GETVRT  ;  Return True
        LDA #$0     ;Else Return False
        RTS

;clrmem(count) - Write Array to Vera Memory
;Args: A = Number of Bytes to Clear
;Returns: A,Y = 0
;         X = Current Data Port
CLRMEM: TAY             ;Copy Number of Bytes to Y
        LDA #0          ;Set Write Value to Zero 

;filmem(byte, count) - Fill Vera Memory with Byte
;Args: A = Byte to Fill Memory With
;      Y = Number of Bytes to Fill
;Returns: Y = 0
;         X = Current Data Port
FILMEM  LDX $9F25       ;Get Current Data Port
FILMEL: STA $9F23,X     ;Write Byte to Data Port
        DEY             ;Decrement Counter
        BNE FILMEL      ;If Not Zero Loop
        RTS

;getadr() - Get Vera Address
;Args: A = Bank + Auto-Increment
;      Y,X = Address
GETADR: LDX $9F20   ;Read Address LSB
        LDY $9F21   ;Read Address MSB
        LDA $9F22   ;Read Bank & Auto-Increment
        RTS

;getvrb(&addr) - Get Vera Register Bit Status
;Args: A = Bit Mask
;      Y,X = Address
;Returns: A = Mode
;         X = Current Data Port
GETVRB: STA TEMP0   ;Save Bit Mask
        JSR GETVRG  ;Read Register
        AND TEMP0   ;Mask Register Bit
        BEQ GETVRX  ;If Set 
GETVRT: LDA #$FF    ;  Return TRUE
GETVRX: RTS         ;Else Return FALSE        

;getvrg(&addr) - Read Vera Internal Register
;Args: Y,X = Address
;Returns: A = Mode
;         X = Current Data Port
GETVRG: LDA #$0F    ;Set Bank to Registers
                    ;and Execute GETBYT
;getbyt(&addr);
;Args: A = Bank
;      Y,X = Address
;Affects: Y
;Returns: A = Contents of Memory
;         X = Current Data Port
GETBYT: JSR SETADR  ;Set Vera Address
        LDX $9F25   ;Get Current Data Port
        LDA $9F23,X ;Read LSB from Data Port
        RTS

;getmem(count, &addr) - Read Array From Vera Memory
;Args: A = Number of Bytes to Read
;      Y,X = Address of Array to Read Into
;Requires: setadr() 
;Sets: DSTLO,DSTHI = Address of Array
;      TEMP0 = Number of Bytes to Read
;Affects: A
;Returns: Y = Number of Bytes Read
;         X = Current Data Port
GETMEM: JSR SETDST      ;Save Destination Address
GETMEA: STA TEMP0       ;Save Number of Bytes
        LDY #0          ;Initialize Counter
        LDX $9F25       ;Get Current Data Port
GETMEL: LDA $9F23,X     ;Read Byte from Data Port
        STA (DSTLO),Y   ;Store in Memory
        INY             ;Increment Counter
        CPY TEMP0       ;If Limit Not Reached
        BNE GETMEL      ;  Loop
        TYA             ;Return Count
        RTS

;getvri(addr); Read Vera Register Pair
;Args: Y,X = Address
;Returns: A,X = Integer LSB
;         Y = Integer LSB
GETVRI: LDA #$0F    ;Set Bank to Registers

;getint(addr); Read Integer from Vera Memory
;Args: A = Bank
;      Y,X = Address
;Returns: A,X = Integer LSB
;         Y = Integer LSB
GETINT: AND #$0F    ;Set Auto-Increment to 1
        ORA #$10    
        JSR SETADR  ;Set Vera Address
        LDX $9F25   ;Get Current Data Port
        LDA $9F23,X ;Read LSB from Data Port
        LDY $9F23,X ;Read MSB Data Port
        TAX         ;Copy LSB to X
        RTS

;regadr(addr) - Set Vera Address to Internal Register
;Args: Y,X = Register Address
;Returns: A = Bank | Auto-Increment
REGADR: LDA #$0F    ;Set Bank and Auto-Increment

;setadi(bank,addr) - Set Vera Address with Auto-Increment
;Args: A = Bank
;      Y,X = Address
SETADI: ORA #$10    ;Set Auto-Increment to 1

;setadr(opts,addr) - Set Vera Address
;Args: A = Bank + Auto-Increment
;      Y,X = Address
SETADR: STX $9F20   ;Store Address LSB
        STY $9F21   ;Store Address MSB
        STA $9F22   ;Store Bank & Auto-Increment
        RTS

;setvrb(bits, &addr) - Set Vera Register Bits
;Args: A = Bit Pattern
;      Y,X = Address
;Uses: TEMP0 = Bit Mask
;Sets: TEMP1 = Bit Pattern
;Affects: A,Y,X
SETVRB: STA TEMP1   ;Save Bit Pattern
        JSR GETVRG  ;Read Register
        AND TEMP0   ;Mask Result
        ORA TEMP1   ;Set Bits
        BRA SETBYN  ;Write Back to Register 

;setreg(addr) - Set Register 
;Args: A = Value to Write
;      Y,X = Address
;Sets: TEMP0 = Value to Write
;Returns: A = Value Written
;         X = Current Data Port
SETREG: STA TEMP0   ;Save Value to Write
SETREH: LDA #$0F    ;Set Bank, Auto-Increment

;setbyt(addr) - Write Byte to Vera Memory
;Args: A = Bank
;      Y,X = Address
;Uses: TEMP0 = Value to Write
;Returns: A = Value Written
;         X = Current Data Port
SETBYT: JSR SETADR  ;Set Vera Address
        LDA TEMP0   ;Retrieve Value to Write
SETBYN: LDX $9F25   ;Get Current Data Port
        STA $9F23,X ;Write Value to Data Port
        RTS

;setrei(addr) - Set Vera Register to Integer
;Args: Y,X = Address
;Uses: TEMP1,TEMP2 = Integer Value
;Affects: A,Y
;Returns: X = Current Data Port
SETREI: LDA #$0F    ;Set Bank to Registers

;setina(addr) - Write Integer to Vera Address
;Args: A = Bank
;      Y,X = Address
;Uses: TEMP1,TEMP2 = Integer Value
;Affects: A,Y
;Returns: X = Current Data Port
SETINA: ORA #$10    ;Set Auto-Increment to 1
        JSR SETADR  ;Set Vera Address
        JSR RESRXY  ;Restore Integer into Y,X

;setint(addr) - Write Integer to Vera Memory
;Args: Y,X = Integer to Write
;Requires: setadr();
;Affects: A,Y
;Returns: X = Current Data Port
SETINT: TXA         ;Copy LSB to Accumlator
        LDX $9F25   ;Get Current Data Port
        STA $9F23,X ;Write to Data Port
        TYA         ;Copy MSB to Accumlator
        STA $9F23,X ;Write to Data Port
        RTS

;setmem(count, &addr) - Write Array to Vera Memory
;Args: A = Number of Bytes to Write
;      Y,X = Address of Array to Write From
;Requires: setadr() 
;Sets: SRCLO,SRCHI = Address of Array
;      TEMP0 = Number of Bytes to Write
;Returns: A,Y = Number of Bytes Written
;         X = Current Data Port
SETMEM: JSR SETSRC      ;Save Source Address
SETMET: STA TEMP0       ;Save Number of Bytes
SETMEA: LDX $9F25       ;Get Current Data Port
        LDY #0          ;Initialize Counter
SETMEL: LDA (SRCLO),Y   ;Read Byte from Array
        STA $9F23,X     ;Write Byte to Data Port
        INY             ;Increment Counter
        CPY TEMP0       ;If Limit Not Reached
        BNE SETMEL      ;  Loop
        TYA             ;Return Count
        RTS
