Added decimal output lib and used it in new multdivlib demo.

This commit is contained in:
Mattias Hansson 2026-05-17 15:02:20 +02:00
parent 930e81573a
commit 182c81b26a
5 changed files with 380 additions and 20 deletions

3
examples/multdiv_demo/cm.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
PROGNAME="multdiv_demo"
c65gm ${PROGNAME}.c65

View file

@ -0,0 +1,172 @@
//-----------------------------------------------------------
// Mult/Div Library Demo
// Demonstrates multiply and divide routines with
// human-readable decimal output via decoutlib
//-----------------------------------------------------------
#INCLUDE <c64start.c65>
#INCLUDE <c64defs.c65>
#INCLUDE <multdivlib.c65>
#INCLUDE <cbmiolib.c65>
#INCLUDE <decoutlib.c65>
#PRAGMA _P_USE_CBM_STRINGS 1
GOTO start
//-----------------------------------------------------------
// Wait for key press
//-----------------------------------------------------------
FUNC wait_key
BYTE key
WHILE 1
key = PEEK $c5
IF key = 64
BREAK
ENDIF
WEND
WHILE 1
key = PEEK $c5
IF key != 64
BREAK
ENDIF
WEND
POKE $c6 WITH 0
FEND
//-----------------------------------------------------------
// Main demo
//-----------------------------------------------------------
FUNC main
lib_cbmio_cls()
lib_cbmio_printlf("multdivlib demo")
lib_cbmio_printlf("===============")
lib_cbmio_lf()
//---------------------------------------------------------
// Demo 1: Multiplication
// 123 * 45 = 5535 (fits in 16 bits)
//---------------------------------------------------------
lib_cbmio_printlf("demo 1: multiply")
lib_cbmio_printlf("----------------")
lib_multdiv_acc = 123
lib_multdiv_aux = 45
lib_multdiv_mult(lib_multdiv_acc, lib_multdiv_aux)
lib_cbmio_print("123 * 45 = ")
lib_decout_decoutw(lib_multdiv_acc)
lib_cbmio_lf()
lib_cbmio_lf()
lib_cbmio_print("press any key...")
wait_key()
lib_cbmio_lf()
lib_cbmio_lf()
//---------------------------------------------------------
// Demo 2: Large multiplication (32-bit result)
// 1000 * 2000 = 2000000
// Note: mult stores high word in lib_multdiv_ext
//---------------------------------------------------------
lib_cbmio_printlf("demo 2: large multiply (32-bit)")
lib_cbmio_printlf("-------------------------------")
lib_multdiv_acc = 1000
lib_multdiv_aux = 2000
lib_multdiv_mult32(lib_multdiv_acc, lib_multdiv_aux, lib_multdiv_ext)
lib_cbmio_print("1000 * 2000 = $")
lib_cbmio_hexoutw(lib_multdiv_ext)
lib_cbmio_hexoutw(lib_multdiv_acc)
lib_cbmio_lf()
lib_cbmio_lf()
lib_cbmio_print("press any key...")
wait_key()
lib_cbmio_lf()
lib_cbmio_lf()
//---------------------------------------------------------
// Demo 3: Division
// 10000 / 33 = 303 remainder 1
//---------------------------------------------------------
lib_cbmio_printlf("demo 3: division")
lib_cbmio_printlf("----------------")
lib_multdiv_acc = 10000
lib_multdiv_aux = 33
lib_multdiv_divmod(lib_multdiv_acc, lib_multdiv_aux, lib_multdiv_ext)
lib_cbmio_print("10000 / 33 = ")
lib_decout_decoutw(lib_multdiv_acc)
lib_cbmio_print(" remainder ")
lib_decout_decoutw(lib_multdiv_ext)
lib_cbmio_lf()
lib_cbmio_lf()
lib_cbmio_print("press any key...")
wait_key()
lib_cbmio_lf()
lib_cbmio_lf()
//---------------------------------------------------------
// Demo 4: Division with exact result
// 65535 / 255 = 257 remainder 0
//---------------------------------------------------------
lib_cbmio_printlf("demo 4: exact division")
lib_cbmio_printlf("---------------------")
lib_multdiv_acc = 65535
lib_multdiv_aux = 255
lib_multdiv_divmod(lib_multdiv_acc, lib_multdiv_aux, lib_multdiv_ext)
lib_cbmio_print("65535 / 255 = ")
lib_decout_decoutw(lib_multdiv_acc)
lib_cbmio_print(" remainder ")
lib_decout_decoutw(lib_multdiv_ext)
lib_cbmio_lf()
lib_cbmio_lf()
lib_cbmio_print("press any key...")
wait_key()
lib_cbmio_lf()
lib_cbmio_lf()
//---------------------------------------------------------
// Demo 5: Chain operations (multiply then divide)
// (25 * 17) / 5 = 85 remainder 0
//---------------------------------------------------------
lib_cbmio_printlf("demo 5: chain: multiply then divide")
lib_cbmio_printlf("-----------------------------------")
lib_multdiv_acc = 25
lib_multdiv_aux = 17
lib_multdiv_mult(lib_multdiv_acc, lib_multdiv_aux)
WORD tmp
tmp = lib_multdiv_acc
lib_multdiv_acc = tmp
lib_multdiv_aux = 5
lib_multdiv_divmod(lib_multdiv_acc, lib_multdiv_aux, lib_multdiv_ext)
lib_cbmio_print("(25 * 17) / 5 = ")
lib_decout_decoutw(lib_multdiv_acc)
lib_cbmio_print(" remainder ")
lib_decout_decoutw(lib_multdiv_ext)
lib_cbmio_lf()
lib_cbmio_lf()
lib_cbmio_printlf("demo complete!")
FEND
LABEL start
main()
SUBEND

View file

@ -0,0 +1 @@
x64 -autostartprgmode 1 multdiv_demo.prg

188
lib/decoutlib.c65 Normal file
View file

@ -0,0 +1,188 @@
//------------------------------------------------------------------------
// Decimal Output Library
//
// Purpose: Display BYTE and WORD values as decimal numbers
//
// Functions:
// lib_decout_decoutb({BYTE value}) - Print BYTE (0-255) as decimal
// lib_decout_decoutw({WORD value}) - Print WORD (0-65535) as decimal
//
// Dependencies: cbmiolib.c65 (for lib_cbmio_print)
// No ZP usage required
//
// Algorithm: Repeated subtraction per decimal place
// - decoutb: max 7 iterations (2+5+0 for 255)
// - decoutw: max 19 iterations (6+5+5+3+0 for 65535)
// No division needed, self-contained, ~5-6x faster than general div
//------------------------------------------------------------------------
#IFNDEF __LIB_DECOUT
#DEFINE __LIB_DECOUT = 1
GOTO lib_decout_skip
//-----------------------------------------------------------
// Output string buffer (5 digits + null terminator = 6 bytes)
//-----------------------------------------------------------
ASM
lib_decout_buf
!8 0,0,0,0,0,0
ENDASM
//-----------------------------------------------------------
// Pointer for building the output string
// Non-ZP: compiler uses self-modifying code for POKE
//-----------------------------------------------------------
WORD lib_decout_ptr
//-----------------------------------------------------------
// decoutb - Display BYTE (0-255) as decimal with leading zero
// suppression
//-----------------------------------------------------------
FUNC lib_decout_decoutb ( {BYTE value} )
BYTE digit
BYTE leading
BYTE ch
POINTER lib_decout_ptr TO lib_decout_buf
leading = 0
// Hundreds place
digit = 0
WHILE value >= 100
value = value - 100
digit++
WEND
IF digit != 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
leading = 1
ENDIF
// Tens place
digit = 0
WHILE value >= 10
value = value - 10
digit++
WEND
IF digit != 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
leading = 1
ENDIF
IF leading != 0
IF digit == 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
ENDIF
ENDIF
// Ones place
ch = value + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
POKE lib_decout_ptr , 0
CALL lib_cbmio_print ( @lib_decout_buf )
FEND
//-----------------------------------------------------------
// decoutw - Display WORD (0-65535) as decimal with leading
// zero suppression
//-----------------------------------------------------------
FUNC lib_decout_decoutw ( {WORD value} )
BYTE digit
BYTE leading
BYTE ch
POINTER lib_decout_ptr TO lib_decout_buf
leading = 0
// Ten-thousands place
digit = 0
WHILE value >= 10000
value = value - 10000
digit++
WEND
IF digit != 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
leading = 1
ENDIF
// Thousands place
digit = 0
WHILE value >= 1000
value = value - 1000
digit++
WEND
IF digit != 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
leading = 1
ENDIF
IF leading != 0
IF digit == 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
ENDIF
ENDIF
// Hundreds place
digit = 0
WHILE value >= 100
value = value - 100
digit++
WEND
IF digit != 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
leading = 1
ENDIF
IF leading != 0
IF digit == 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
ENDIF
ENDIF
// Tens place
digit = 0
WHILE value >= 10
value = value - 10
digit++
WEND
IF digit != 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
leading = 1
ENDIF
IF leading != 0
IF digit == 0
ch = digit + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
ENDIF
ENDIF
// Ones place
ch = value + $30
POKE lib_decout_ptr , ch
INC lib_decout_ptr
POKE lib_decout_ptr , 0
CALL lib_cbmio_print ( @lib_decout_buf )
FEND
LABEL lib_decout_skip
#IFEND

View file

@ -16,31 +16,27 @@
#IFDEF __LIB_FAT16 #IFDEF __LIB_FAT16
#DEFINE mount = lib_fat16_mount_partition #DEFINE mount = lib_fat16_mount_partition
#DEFINE fopen = lib_fat16_fopen #DEFINE fopen = lib_fat16_fopen
#DEFINE fclose = lib_fat16_fclose
#DEFINE fcloses = lib_fat16_fcloses #DEFINE fcloses = lib_fat16_fcloses
#DEFINE fblockread = lib_fat16_fblockread #DEFINE fclose = lib_fat16_fclose
#DEFINE fblockwrite = lib_fat16_fblockwrite #DEFINE fblockwrite = lib_fat16_fblockwrite
#DEFINE fblockread = lib_fat16_fblockread
#DEFINE chdir = lib_fat16_chdir #DEFINE chdir = lib_fat16_chdir
#DEFINE dirstart = lib_fat16_dirstart #DEFINE dirstart = lib_fat16_dirstart
#DEFINE dirnext = lib_fat16_dirnext #DEFINE dirnext = lib_fat16_dirnext
#IFEND #IFEND
#IFDEF __LIB_CBMIO #IFDEF __LIB_DECOUT
#DEFINE print = lib_cbmio_print #DEFINE decoutb = lib_decout_decoutb
#DEFINE printlf = lib_cbmio_printlf #DEFINE decoutw = lib_decout_decoutw
#DEFINE hexoutb = lib_cbmio_hexoutb
#DEFINE hexoutw = lib_cbmio_hexoutw
#DEFINE lf = lib_cbmio_lf
#DEFINE home = lib_cbmio_home
#DEFINE input = lib_cbmio_input
#IFEND #IFEND
#IFDEF __LIB_STRING #IFDEF __LIB_STRING
#DEFINE strncpy = lib_string_strncpy
#DEFINE strncat = lib_string_strncat
#DEFINE stpcpy = lib_string_stpcpy
#DEFINE strlen = lib_string_strlen #DEFINE strlen = lib_string_strlen
#DEFINE strchr = lib_string_strchr #DEFINE strchr = lib_string_strchr
#DEFINE strcpy = lib_string_strcpy #DEFINE strcpy = lib_string_strcpy
#DEFINE stpcpy = lib_string_stpcpy
#DEFINE strncpy = lib_string_strncpy
#DEFINE strcmp = lib_string_strcmp #DEFINE strcmp = lib_string_strcmp
#DEFINE memset = lib_string_memset #DEFINE memset = lib_string_memset
#DEFINE strcat = lib_string_strcat #DEFINE strcat = lib_string_strcat
@ -51,9 +47,9 @@
#IFEND #IFEND
#IFDEF __LIB_STRLIST #IFDEF __LIB_STRLIST
#DEFINE sl.strget = lib_strlist_strget
#DEFINE sl.count = lib_strlist_count #DEFINE sl.count = lib_strlist_count
#DEFINE sl.get = lib_strlist_get #DEFINE sl.get = lib_strlist_get
#DEFINE sl.strget = lib_strlist_strget
#DEFINE sl.add = lib_strlist_add #DEFINE sl.add = lib_strlist_add
#DEFINE sl.free = lib_strlist_free #DEFINE sl.free = lib_strlist_free
#IFEND #IFEND