2018-08-14 18:14:32 +00:00
|
|
|
; C02 library stdlib.h02 assembly language subroutines
|
2018-01-28 18:30:49 +00:00
|
|
|
; Requires
|
2019-03-23 01:18:49 +00:00
|
|
|
; external zero page locations SRCLO and SRCHI
|
2018-01-28 18:30:49 +00:00
|
|
|
; and external locations RANDOM, RDSEED, TEMP0, TEMP1, and TEMP2.
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;abs(n) - Get ABSolute Value
|
|
|
|
;Args: A = Number to get Absolute Value Of
|
|
|
|
;Affects: C, N, Z
|
|
|
|
;Returns: A = Absolute Value of Argument
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;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
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;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
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;mult(m,n) - MULTiply Two Numbers
|
|
|
|
;Args: A = Multiplicand
|
|
|
|
; Y = Nultiplier
|
|
|
|
;Sets: TEMP0 = Multiplicand
|
|
|
|
; TEMP1 = 0
|
2018-07-30 23:30:20 +00:00
|
|
|
; TEMP2 = Product MSB
|
2018-07-25 23:00:46 +00:00
|
|
|
;Affects: N,Z,C
|
|
|
|
;Returns: A = Product LSB
|
|
|
|
; Y = Product MSB
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
2018-07-30 23:30:20 +00:00
|
|
|
LDY TEMP2 ;Load Y with MSB
|
|
|
|
TAX ;and Copy LSB to X
|
2018-01-28 18:30:49 +00:00
|
|
|
RTS
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;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
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
2018-07-30 23:30:20 +00:00
|
|
|
TAY ;Copy Remainder to Y Register
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
2018-07-25 23:00:46 +00:00
|
|
|
;Affects A,Y,N,Z,C
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
2018-07-25 23:00:46 +00:00
|
|
|
BNE SHIFTR ; and Loop if Not 0
|
2018-01-28 18:30:49 +00:00
|
|
|
RTS
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;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
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;ctoa(n) - Character TO ASCII string
|
|
|
|
;Args: Y,X = Address of String to Populate
|
2019-05-27 21:12:10 +00:00
|
|
|
;Sets: DSTLO, DSTHI = Address of String
|
2018-07-25 23:00:46 +00:00
|
|
|
; TEMP0 = Ones Digit
|
|
|
|
; TEMP1 = Tens Digit
|
|
|
|
; TEMP2 = Hundreds Digit
|
|
|
|
;Affects: C,N.Z
|
|
|
|
;Returns: A,Y = Length of String
|
2019-05-27 21:12:10 +00:00
|
|
|
CTOA: JSR SETDST ;Initialize Source String
|
|
|
|
LDY #0 ;Initialize Index into String
|
2018-02-02 23:02:06 +00:00
|
|
|
JSR CUBCD ;Convert Accumulator to Unpacked BCD
|
2018-07-30 23:30:20 +00:00
|
|
|
LDA TEMP2 ;Get MSB
|
2018-02-02 23:02:06 +00:00
|
|
|
BEQ CTOA1 ;If Not Zero
|
2018-01-28 18:30:49 +00:00
|
|
|
JSR CTOAN ; Convert Low Nybble
|
2018-02-02 23:02:06 +00:00
|
|
|
CTOA1: LDA TEMP1 ;Get Low Byte
|
2018-01-28 18:30:49 +00:00
|
|
|
BNE CTOA2 ;If Not Zero
|
2018-02-02 23:02:06 +00:00
|
|
|
CMP TEMP2 ; and Hundreds
|
2018-01-28 18:30:49 +00:00
|
|
|
BEQ CTOA3 ; not Zero
|
|
|
|
CTOA2: JSR CTOAN ; Convert It
|
2018-02-02 23:02:06 +00:00
|
|
|
CTOA3: LDA TEMP0 ;Get Low Byte
|
2018-01-28 18:30:49 +00:00
|
|
|
JSR CTOAN ;and Convert Low Nybble
|
|
|
|
LDA #$00
|
|
|
|
BEQ CTOAX ;Terminate String
|
2018-02-02 23:02:06 +00:00
|
|
|
CTOAN: ORA #$30 ;Convert to ASCII digit
|
2019-05-27 21:12:10 +00:00
|
|
|
CTOAX: STA (DSTLO),Y ;Store in String
|
2018-01-28 18:30:49 +00:00
|
|
|
INY ;and Increment Offset
|
2018-07-25 23:00:46 +00:00
|
|
|
TYA ;Copy String Length to Accumulator
|
2018-02-02 23:02:06 +00:00
|
|
|
RTS
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;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
|
2018-02-02 23:02:06 +00:00
|
|
|
;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
|
2018-01-28 18:30:49 +00:00
|
|
|
RTS
|
|
|
|
|
2018-07-25 23:00:46 +00:00
|
|
|
;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
|
2018-01-28 18:30:49 +00:00
|
|
|
CVBCD: STA TEMP0 ;Save Binary Value
|
2018-02-02 23:02:06 +00:00
|
|
|
CVBCDT: LDA #0 ;Clear BCD Bytes
|
2018-01-28 18:30:49 +00:00
|
|
|
STA TEMP1
|
|
|
|
STA TEMP2
|
|
|
|
LDX #8 ;Process 8 bits of Binary
|
2018-07-25 23:00:46 +00:00
|
|
|
PHP ;Save Status Register
|
2018-01-28 18:30:49 +00:00
|
|
|
SEI ;Disable Interupts
|
|
|
|
SED ;Set Decimal Mode
|
2019-05-27 21:12:10 +00:00
|
|
|
CVBCDL: ASL TEMP0 ;Shift High Bit into Carry
|
2018-01-28 18:30:49 +00:00
|
|
|
LDA TEMP1 ;Add BCD Low Byte to Itself
|
|
|
|
ADC TEMP1 ; Plus Bit Shifted out of Binary
|
|
|
|
STA TEMP1 ; Effectively Multiplying It by 2
|
2018-07-30 23:30:20 +00:00
|
|
|
LDA TEMP2 ;Add BCD MSB to Itself
|
2018-01-28 18:30:49 +00:00
|
|
|
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
|
2018-07-25 23:00:46 +00:00
|
|
|
PLP ;Restore Status Register
|
2018-01-28 18:30:49 +00:00
|
|
|
RTS
|
2018-07-30 23:30:20 +00:00
|
|
|
|