# C64 OS PROGRAMMER'S GUIDE

Last modified: Feb 02, 2022

## 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

Constant | Description | Address |
---|---|---|

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 |

## Next Section: Timers

### Table of Contents

## This document is continually updated.

Refer to the *last modified* date at the top of
this document for the most recent changes.