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.