# C64 OS PROGRAMMER'S GUIDE

## Math and Floating Point

#### Zero Page Memory Locations

The C64 OS Math module uses the same zero page memory that is used by the BASIC ROM as temporary workspace. To use these routines the operands must first be copied into these workspace memory locations.

Variable Description Zero Page Address(es)
DIVISOR 16-bit Integer Divisor \$61, \$62
DIVIDND 16-bit Integer Dividend \$63, \$64
REMANDR 16-bit Integer Remainder \$65, \$66
DIVRSLT 16-bit Integer Division Result (Quotient) \$63, \$64 (See: DIVIDND)
DIVROND Division Rounding Flag \$67
MULTPLR 16-bit Integer Multiplier \$61, \$62
MULTCND 16-bit Integer Multiplicand \$63, \$64
PRODUCT 32-bit Integer Multiplication Result (Product) \$65, \$66, \$67, \$68
TXTPTR Pointer to a string containing a number \$7a, \$7b
INT32 Signed 32-bit integer output \$62, \$63, \$64, \$65

#### Math Module KERNAL Calls

The 6502 itself supports 8-bit integer subtraction and addition, which can be extended wider than 8-bits by using the processor's Carry flag. Neither the 6502 nor the C64 KERNAL or BASIC ROM provide integer multiplication or division. C64 OS provides these instead. The BASIC ROM provides 32-bit floating math routines and how to use them will be covered below.

##### mul16

MULTPLR → 16-bit Int Multiplier
MULTCND → 16-bit Int Multiplicand
PRODUCT ← 32-bit Int Product

The MULTPLR and MULTCND must first be prepopulated with 16-bit integers. The result of the multiplication is then found in PRODUCT.

##### div16

DIVISOR → 16-bit Int Divisor
DIVIDND → 16-bit Int Dividend
DIVRSLT ← 16-bit Int Quotient
REMANDR ← 16-bit Int Remainder

The DIVISOR and DIVIDND must first be prepopulated with 16-bit integers. The result of the division is then found in DIVRSLT and any remainder in REMANDR.

##### tostr

DIVISOR → Number Base (Maximum 10)
DIVIDND → 16-bit Integer
RegPtr ← Pointer to temporary string representation of the number.

Converts the integer provided into a string representation in the base specified, up to a maximum of Base10. The pointer returned is to a temporary string. The string should be copied to a more permanent memory location.

##### toint

MULTCND → Number Base (Maximum 10)
RegPtr → Pointer to a String
A → String Length (Optional)
MULTPLR ← 16-bit Integer

Converts a string containing an integer (between 0 and 65535) to a 16-bit integer found in MULTPLR.

##### tohex

A → 8-bit Integer
X ← Lower Nybble ("0" to "F")
Y ← Upper Nybble ("0" to "F")

Converts a single 8-bit integer to PETSCII. The upper and lower nybbles are returned in the X and Y registers. Processing source integers larger than 8-bits requires repeated calls to this routine.

##### seebas

From the system default state of KERNAL and I/O patched in, seebas enables the BASIC ROM. It takes no input parameters and returns no parameters, but preserves the A, X and Y registers.

## Floating Point

The C64 BASIC ROM implements floating point arithmetic, some trignometric and transcendental functions, and also defines numerous useful floating point constants. Below are defined the constants and functions for which C64 OS provides programming headers. For more details on how floating point numbers are implemented and how to use these routines, see the weblog post, Floating Point Math from BASIC.

Note that the BASIC ROM must be patched in to call these routines, and the mapping must be manually reconfigured to KERNAL and I/O only (C64 OS provides, seeioker) before returning to system code. See above, C64 OS provides the routine seebas to patch in the BASIC ROM.

Floating point routines operate on data that is stored in two floating point workspace memory ranges: FAC and ARG. Functions are provided for moving data from main memory into and out of workspace memory. The inputs and outputs of all routines are listed as combinations of FAC and ARG.

#### Memory Move Functions

##### facmem

FAC → Floating Point Number
RegPtr → Pointer to Memory

Copy FAC to memory pointed to by RegPtr.

##### memfac

RegPtr → Pointer to Memory
FAC ← Floating Point Number

Copy memory pointed to by RegPtr to FAC.

##### memarg

RegPtr → Pointer to Memory
ARG ← Floating Point Number

Copy memory pointed to by RegPtr to ARG.

##### facarg

FAC → Floating Point Number
ARG ← Floating Point Number

Copy FAC to ARG.

##### argfac

ARG → Floating Point Number
FAC ← Floating Point Number

Copy ARG to FAC.

#### Arithmetic Operations

##### memplus

FAC → Floating Point Number
A/Y → Pointer to Floating Point Number
FAC ← FAC + Memory

Adds two floating point numbers, one which is already in FAC to one pointed to in memory. The result is found in FAC.

##### plus

FAC → Floating Point Number
ARG → Floating Point Number
FAC ← FAC + ARG

Adds two floating point numbers, one in FAC to one in ARG. The result is found in FAC.

##### memminus

FAC → Floating Point Number
A/Y → Pointer to Floating Point Number
FAC ← FAC - Memory

Subtracts a floating point number pointed to in memory from a floating point number in FAC. The result is found in FAC.

##### minus

FAC → Floating Point Number
ARG → Floating Point Number
FAC ← FAC - ARG

Subtracts a floating point number in ARG from a floating point number in FAC. The result is found in FAC.

##### memmult

FAC → Floating Point Number
A/Y → Pointer to Floating Point Number
FAC ← FAC * Memory

Multiplies two floating point numbers, one which is already in FAC with one pointed to in memory. The result is found in FAC.

##### mult

FAC → Floating Point Number
ARG → Floating Point Number
FAC ← FAC * ARG

Adds two floating point numbers, one in FAC with one in ARG. The result is found in FAC.

##### memdivi

FAC → Floating Point Number
A/Y → Pointer to Floating Point Number
FAC ← Memory / FAC

Divides a floating point number pointed to in memory by a floating point number in FAC. The result is found in FAC. NOTE: Notice that FAC is the divisor, not the dividend.

##### divi

FAC → Floating Point Number
ARG → Floating Point Number
FAC ← ARG / FAC

Divides a floating point number in ARG by a floating point number in FAC. The result is found in FAC. NOTE: Notice that FAC is the divisor, not the dividend.

##### mempow

FAC → Floating Point Number
A/Y → Pointer to Floating Point Number
FAC ← Memory ^ FAC

Raises a floating point number pointed to in memory to the power of a floating point number in FAC. The result is found in FAC.

##### power

FAC → Floating Point Number
ARG → Floating Point Number
FAC ← ARG ^ FAC

Raises a floating point number in ARG to the power of a floating point number in FAC. The result is found in FAC.

##### mult10

FAC → Floating Point Number
FAC ← FAC * 10

Multiples a floating point number in FAC by 10. The result is found in FAC.

##### divi10

FAC → Floating Point Number
FAC ← FAC / 10

Divides a floating point number in FAC by 10. The result is found in FAC.

#### Floating Point Functions

All of the following operate on a value in FAC, and return their result in FAC.

Function Description
fp_rnd Generates a pseudo-random number between 0 and 1
fp_abs Converts a number to its absolute value
fp_sgn Reduces a number to a flag representing its sign
fp_exp Raises E to the power of the argument
fp_int Strips the fractional component resulting in a whole number
fp_log Produces the natural logarithm (Base E) of the argument.
To convert to Base X, divide the result by LOG(X).
fp_sqr Produce the square root of the argument
fp_sin Produce the SINE value of the argument in radians
fp_cos Produce the COSINE value of the argument in radians
fp_tan Produce the TANGENT value of the argument in radians
fp_atn Produce the angle in radians from a TANGENT value

#### Text ↔ Floating Point Conversion Routines

##### strfac

TXTPTR → Pointer to String
FAC ← Floating Point Number

Parses a number out of the pointed-to string, and converts to a floating point number. Result is found in FAC.

##### facstr

FAC → Floating Point Number
A/Y ← Pointer to temporary string representation of the number.

Converts the floating point number in FAC into a string representation in Base 10. The pointer returned is to a temporary string. The string should be copied to a more permanent memory location.

##### int8fac

A → 8-bit Signed Int
FAC ← Floating Point Number

Converts the 8-bit signed integer found in A to a floating point number. Result is found in FAC.

##### uint8fac

A → 8-bit Unsigned Int
FAC ← Floating Point Number

Converts the unsigned 8-bit integer found in A to a floating point number. Result is found in FAC.

##### int16fac

A/Y → 16-bit Signed Int
FAC ← Floating Point Number

Converts the signed 16-bit integer found in A/Y to a floating point number. Result is found in FAC.

##### facint32

FAC → Floating Point Number
INT32 ← 13-bit Signed Int

Converts the floating point number in FAC to a 32-bit signed int. Result is found in INT32. (See workspace variables, above.)

## Floating Point Constants

PI Pi \$aea8
PI2_1 Pi * 2 \$e2e5
PI1_2 Pi / 2 \$e2e0
NEG1_2 -1/2 \$b9e0
POS1_4 1/4 \$e2ea
POS1 1 \$b9bc
POS10 10 \$baf9
INT16MIN Smallest 16-bit integer (-32768) \$b1a6
POS1_SQR2 1/√2 \$b9d6
POSSQR2 2 \$b9db
POS1_LOG2 1/LOG(2) \$bfbf
POSLOG2 LOG(2) \$b9e5