From 182c81b26a30645d1fd652ac4491307ca97c6462 Mon Sep 17 00:00:00 2001 From: Mattias Hansson Date: Sun, 17 May 2026 15:02:20 +0200 Subject: [PATCH] Added decimal output lib and used it in new multdivlib demo. --- examples/multdiv_demo/cm.sh | 3 + examples/multdiv_demo/multdiv_demo.c65 | 172 ++++++++++++++++++++++ examples/multdiv_demo/start_in_vice.sh | 1 + lib/decoutlib.c65 | 188 +++++++++++++++++++++++++ lib/libsc.c65 | 36 +++-- 5 files changed, 380 insertions(+), 20 deletions(-) create mode 100755 examples/multdiv_demo/cm.sh create mode 100644 examples/multdiv_demo/multdiv_demo.c65 create mode 100755 examples/multdiv_demo/start_in_vice.sh create mode 100644 lib/decoutlib.c65 diff --git a/examples/multdiv_demo/cm.sh b/examples/multdiv_demo/cm.sh new file mode 100755 index 0000000..894533b --- /dev/null +++ b/examples/multdiv_demo/cm.sh @@ -0,0 +1,3 @@ +#!/bin/sh +PROGNAME="multdiv_demo" +c65gm ${PROGNAME}.c65 diff --git a/examples/multdiv_demo/multdiv_demo.c65 b/examples/multdiv_demo/multdiv_demo.c65 new file mode 100644 index 0000000..5410ee9 --- /dev/null +++ b/examples/multdiv_demo/multdiv_demo.c65 @@ -0,0 +1,172 @@ +//----------------------------------------------------------- +// Mult/Div Library Demo +// Demonstrates multiply and divide routines with +// human-readable decimal output via decoutlib +//----------------------------------------------------------- + +#INCLUDE +#INCLUDE +#INCLUDE +#INCLUDE +#INCLUDE + +#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 diff --git a/examples/multdiv_demo/start_in_vice.sh b/examples/multdiv_demo/start_in_vice.sh new file mode 100755 index 0000000..6f49085 --- /dev/null +++ b/examples/multdiv_demo/start_in_vice.sh @@ -0,0 +1 @@ +x64 -autostartprgmode 1 multdiv_demo.prg diff --git a/lib/decoutlib.c65 b/lib/decoutlib.c65 new file mode 100644 index 0000000..1ecdf25 --- /dev/null +++ b/lib/decoutlib.c65 @@ -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 diff --git a/lib/libsc.c65 b/lib/libsc.c65 index f24a92d..a136c49 100644 --- a/lib/libsc.c65 +++ b/lib/libsc.c65 @@ -14,33 +14,29 @@ #DEFINE __LIB_SC = 1 #IFDEF __LIB_FAT16 - #DEFINE mount = lib_fat16_mount_partition - #DEFINE fopen = lib_fat16_fopen - #DEFINE fclose = lib_fat16_fclose - #DEFINE fcloses = lib_fat16_fcloses - #DEFINE fblockread = lib_fat16_fblockread - #DEFINE fblockwrite = lib_fat16_fblockwrite - #DEFINE chdir = lib_fat16_chdir - #DEFINE dirstart = lib_fat16_dirstart - #DEFINE dirnext = lib_fat16_dirnext + #DEFINE mount = lib_fat16_mount_partition + #DEFINE fopen = lib_fat16_fopen + #DEFINE fcloses = lib_fat16_fcloses + #DEFINE fclose = lib_fat16_fclose + #DEFINE fblockwrite = lib_fat16_fblockwrite + #DEFINE fblockread = lib_fat16_fblockread + #DEFINE chdir = lib_fat16_chdir + #DEFINE dirstart = lib_fat16_dirstart + #DEFINE dirnext = lib_fat16_dirnext #IFEND - #IFDEF __LIB_CBMIO - #DEFINE print = lib_cbmio_print - #DEFINE printlf = lib_cbmio_printlf - #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 + #IFDEF __LIB_DECOUT + #DEFINE decoutb = lib_decout_decoutb + #DEFINE decoutw = lib_decout_decoutw #IFEND #IFDEF __LIB_STRING + #DEFINE strncpy = lib_string_strncpy + #DEFINE strncat = lib_string_strncat + #DEFINE stpcpy = lib_string_stpcpy #DEFINE strlen = lib_string_strlen #DEFINE strchr = lib_string_strchr #DEFINE strcpy = lib_string_strcpy - #DEFINE stpcpy = lib_string_stpcpy - #DEFINE strncpy = lib_string_strncpy #DEFINE strcmp = lib_string_strcmp #DEFINE memset = lib_string_memset #DEFINE strcat = lib_string_strcat @@ -51,9 +47,9 @@ #IFEND #IFDEF __LIB_STRLIST + #DEFINE sl.strget = lib_strlist_strget #DEFINE sl.count = lib_strlist_count #DEFINE sl.get = lib_strlist_get - #DEFINE sl.strget = lib_strlist_strget #DEFINE sl.add = lib_strlist_add #DEFINE sl.free = lib_strlist_free #IFEND