; C02 library stdlib.h02 assembly language subroutines ; Requires ; external zero page locations SRCLO and SRCHI ; and external locations RANDOM, RDSEED, TEMP0, TEMP1, and TEMP2. ;abs(n) - Get ABSolute Value ;Args: A = Number to get Absolute Value Of ;Affects: C, N, Z ;Returns: A = Absolute Value of Argument ABS: CMP #$80 ;If Negative (High Bit Set) BCC ABSX ; Carry will Already be Set EOR #$FF ; One's Complement ADC #$00 ; and Increment (Carry set by CMP) ABSX: RTS ;max(m,n) - Get MAXimum of Two Numbers ;Args: A,Y = Numbers to Compare ;Sets: TEMP0 = Second Argument ;Affects: N,Z,C ;Returns: A = Larger of the Two Arguments MAX: STY TEMP0 ;Save Second Parameter CMP TEMP0 ;If First Parameter BCC MAXX ; Greater than Second Parameter TYA ;Copy Second Parameter into Accumulator MAXX: RTS ;min(m,n) - Get MINimum Get MAXimum of Two Numbers ;Args: A,Y = Numbers to Compare ;Sets: TEMP0 = Second Argument ;Affects: N,Z,C ;Returns: A = Smaller of the Two Arguments MIN: STY TEMP0 ;Save Second Parameter CMP TEMP0 ;If First Parameter BCS MINX ; Less than Second Parameter TYA ;Copy Second Parameter into Accumulator MINX: RTS ;mult(m,n) - MULTiply Two Numbers ;Args: A = Multiplicand ; Y = Nultiplier ;Sets: TEMP0 = Multiplicand ; TEMP1 = 0 ; TEMP2 = Product MSB ;Affects: N,Z,C ;Returns: A = Product LSB ; Y = Product MSB MULT: STA TEMP0 ;Store Multiplicand STY TEMP1 ;Store Multiplier ;Multiply TEMP0 times TEMP1 MULTT: LDA #$00 ;Initialize Accumulator BEQ MULTE ;Enter Loop MULTA: CLC ADC TEMP0 ;Add Multiplicand MULTL: ASL TEMP0 ;Shift Multiplicand Left MULTE: LSR TEMP1 ;Shift Multiplier Right BCS MULTA ;If Bit Shifted Out, Add Multiplicand BNE MULTL ;Loop if Any 1 Bits Left LDY TEMP2 ;Load Y with MSB TAX ;and Copy LSB to X RTS ;div(m,n) - MULTiply Two Numbers ;Args: A = Dividend ; Y = Divisor ;Sets: TEMP0 = 0 ; TEMP1 = Divisor ;Affects: N,Z,C ;Returns: A = Quotient ; Y = Remainder DIV: STA TEMP0 ;Store Dividend STY TEMP1 ;Store Divisor ;Divide TEMP0 by TEMP1 DIVT: LDA #$00 ;Clear Accumulator LDX #$07 ;Load Loop Counter CLC DIVL: ROL TEMP0 ;Shift Bit Out of Dividend ROL ; into Accumulator CMP TEMP1 ;If Accumulator BCC DIVS ; >= Divisor SBC TEMP1 ;Subtract Divisor DIVS: DEX ;Decrement Counter BPL DIVL ; and Loop ROL TEMP0 ;Shift Result into Dividend TAY ;Copy Remainder to Y Register LDA TEMP0 ;Load Result into Accumulator RTS ;Generate Pseudo-Random Number between 1 and 255 ;Uses RANDOM (must be non-zero on entry) ;Affects A,N,Z,C RAND: LDA RANDOM ;Load Last Result ASL ;Shift the Seed BCC RANDX ;If a one was shifted out EOR #$1D ; Twiddle the bite RANDX: STA RANDOM ;Save the Seed RTS ;Seed Pseudo-Random Number Generator ;Uses RDSEED (if A is zero) ;Affects A,N,Z,C ;Sets RANDOM RANDS: ORA #$00 ;If Passed Value not 0 BNE RANDX ; Store in Seed and Return LDA RDSEED ;Load System Generated Seed BNE RANDX ;If Not 0, Store and Return ADC #$01 ;Else Add 1 or 2 BNE RANDX ; then Store and Return ;Return A Shifted Y Bytes to the Left ;Affects A,Y,N,Z,C ;Affects A,Y,N,Z,C SHIFTL: ASL ;Shift Byte to Left DEY ;Decrement Counter BNE SHIFTL ; and Loop if Not 0 RTS ;Return A Shifted Y Bytes to the Right ;Affects A,Y,N,Z,C SHIFTR: LSR ;Shift Byte to Right DEY ;Decrement Counter BNE SHIFTR ; and Loop if Not 0 RTS ;atoc(&s) - ASCII string TO Character ;Args: Y,X = Address of String to Convert ;Uses: TEMP0, TEMP1 ;Sets: SRCLO, SRCHI = Address of String ;Returns: A = Converted Number ; C,N,Z based on Accumulator ; Y = Number of Digits ATOC: JSR SETSRC ;Initialize Source String STY TEMP0 ;Initialize Result ATOCL: LDA (SRCLO),Y ;Get Next Character CMP #$30 ;If Less Than '0' BCC ATOCX ; Exit CMP #$3A ;If Greater Than '9' BCS ATOCX ; Exit AND #$0F ;Convert to Binary Nybble STA TEMP1 ; and Save It LDA TEMP0 ;Load Result ASL ;Multiply by 5 by ASL ; Multiplying by 4 ADC TEMP0 ; And Adding Itself ASL ;Multiply that by 2 ADC TEMP1 ;Add Saved Nybble STA TEMP0 ; and Store Result INY ;Increment Index BPL ATOCL ; and Loop ATOCX: LDA TEMP0 ;Load Result RTS ;And Return ;ctoa(n) - Character TO ASCII string ;Args: Y,X = Address of String to Populate ;Sets: DSTLO, DSTHI = Address of String ; TEMP0 = Ones Digit ; TEMP1 = Tens Digit ; TEMP2 = Hundreds Digit ;Affects: C,N.Z ;Returns: A,Y = Length of String CTOA: JSR SETDST ;Initialize Source String LDY #0 ;Initialize Index into String JSR CUBCD ;Convert Accumulator to Unpacked BCD LDA TEMP2 ;Get MSB BEQ CTOA1 ;If Not Zero JSR CTOAN ; Convert Low Nybble CTOA1: LDA TEMP1 ;Get Low Byte BNE CTOA2 ;If Not Zero CMP TEMP2 ; and Hundreds BEQ CTOA3 ; not Zero CTOA2: JSR CTOAN ; Convert It CTOA3: LDA TEMP0 ;Get Low Byte JSR CTOAN ;and Convert Low Nybble LDA #$00 BEQ CTOAX ;Terminate String CTOAN: ORA #$30 ;Convert to ASCII digit CTOAX: STA (DSTLO),Y ;Store in String INY ;and Increment Offset TYA ;Copy String Length to Accumulator RTS ;cubcd(n) - Convert and Unpack BCD number ;Args: A - Number to Convert ;upbcd() - UnPack 3-digit BCD number ;Uses: TEMP1 = Low Byte ; TEMP2 = High Nybble ;Sets: TEMP0 = Ones Digit ; TEMP1 = Tens Digit ; TEMP2 = Hundreds Digit ;Affects: A,N,Z ;Returns: X = 0 CUBCD: JSR CVBCD ;Convert Accumulator to BCD UPBCD: LDA TEMP1 ;Get Low Byte AND #$0F ;Strip High Nybbleet STA TEMP0 ;Save in Ones LDA TEMP1 ;Get Low Byte LSR ;Shift High Nybble LSR ; into Low Nybble LSR LSR STA TEMP1 ;Save in Tens RTS ;ConVert number to packed Binary Coded Decimal ;Args: A - Number to Convert ;Destroys: TEMP0 ;Sets: TEMP1 = Tens and Ones Digit ; TEMP2 = Hundreds Digit ;Returns: A = Hundreds Digit ; X = 0 CVBCD: STA TEMP0 ;Save Binary Value CVBCDT: LDA #0 ;Clear BCD Bytes STA TEMP1 STA TEMP2 LDX #8 ;Process 8 bits of Binary PHP ;Save Status Register SEI ;Disable Interupts SED ;Set Decimal Mode CVBCDL: ASL TEMP0 ;Shift High Bit into Carry LDA TEMP1 ;Add BCD Low Byte to Itself ADC TEMP1 ; Plus Bit Shifted out of Binary STA TEMP1 ; Effectively Multiplying It by 2 LDA TEMP2 ;Add BCD MSB to Itself ADC TEMP2 ; Plus Bit Shifted out of Low Byte STA TEMP2 ; Effectively Multiplying It by 2 DEX ;Decrement Counter and BNE CVBCDL ; Process Next Bit PLP ;Restore Status Register RTS