From d5d02ece730fe55ef36256d82a6d0eb7422b0537 Mon Sep 17 00:00:00 2001 From: "matthias@arch" Date: Fri, 8 Dec 2023 00:13:43 +0100 Subject: [PATCH] start strf (sprintf) --- util/string.s65 | 163 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 util/string.s65 diff --git a/util/string.s65 b/util/string.s65 new file mode 100644 index 0000000..9b6cb28 --- /dev/null +++ b/util/string.s65 @@ -0,0 +1,163 @@ +;******************************************************************************** +; @module string +; @type utility +; @details +; String utility +;******************************************************************************** +.ifndef INCLUDE_STRING +INCLUDE_STRING = 1 + +.scope str + +.code +.macro _StrfStoreArg arg +.if (.not .blank(arg)) + .if .match(arg, x) + stx ARG4 + @N_ARGS + .elseif .match(arg, y) + sty ARG4 + @N_ARGS + .else + lda arg + sta ARG4 + @N_ARGS + .endif + @N_ARGS .set (@N_ARGS + 1) +.endif +.endmacro + +;******************************************************************************** +; @function Macro for passing arguments to strf +; @param fmt: Format string address +; @param out: Output string address +; @param x0-x9: Additional parameters +; @warning Addresses as additional paramteres must be passed like this `#addr` +; @modifies: A, X, Y +; @see strf +;******************************************************************************** +.macro Strf fmt,out,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9 + @N_ARGS .set 0 ; @ so that it doesnt break cheap labels + lda #fmt + sta ARG1 + lda #out + sta ARG3 + _StrfStoreArg x0 + _StrfStoreArg x1 + _StrfStoreArg x2 + _StrfStoreArg x3 + _StrfStoreArg x4 + _StrfStoreArg x5 + _StrfStoreArg x6 + _StrfStoreArg x7 + jsr strf + .out .sprintf("info: Strf: called with %d arguments", @N_ARGS) +.endmacro + +; TODO allocate zp memory +fmt_idx = $30 +out_idx = $31 +;******************************************************************************** +; @function Format a string +; @details +; If there is no value to be read, the Pz will be set +; Formats: +; - x: unsigned hex integer (1 byte) -> 2 chars +; - X: unsigned hex integer (2 byte) -> 4 chars TODO +; - u: unsigned decimal integer (1 byte) TODO +; - U: unsigned decimal integer (2 bytes) TODO +; @param ARG0-1: Format string address +; @param ARG2-3: Output string address +; @param ARG4+: Additional parameters +; @returns +; @modifies: A, X, Y +;******************************************************************************** +.proc strf + stz out_idx + stz fmt_idx + ldy #0 ; position in string + ldx #0 ; index of format args +@loop: + ldy fmt_idx + lda (ARG0),y + beq @null + cmp #'%' + beq @percent +@normal_char: ; store A in output string + ldy out_idx + sta (ARG2),y + inc fmt_idx + inc out_idx + beq @out_overflow + bra @loop +@percent: ; check for format in next position + iny + sty fmt_idx + lda (ARG0),y + beq @null + ; formats + cmp #'x' + beq @format_hex1 + bra @normal_char +@format_hex1: ; 1 byte hex -> 2 chars + lda ARG4,x + phx + jsr int8_to_hex_str + ldy out_idx + sta (ARG2),y ; most sig digit + iny + beq @out_overflow + txa + sta (ARG2),y ; least sig digit + iny + beq @out_overflow + sty out_idx + plx + inx ; 1 byte of args handeled + ; bra @format_return +@format_return: ; increment fmt_idx to swallow the formating char + inc fmt_idx + bra @loop +@out_overflow: ; store 0 in last position + ldy #$ff + sty out_idx +@store_null: + lda #0 +@null: ; store and return + ldy out_idx + sta (ARG2),y +@rts: + rts +.endproc + + +;******************************************************************************** +; @function Convert a 1 byte number into two hex characters +; @param A: Number to convert +; @returns A: Most significant digit +; @returns X: Least significant digit +; @modifies A,X,Y +;******************************************************************************** +.proc int8_to_hex_str + pha + and #%00001111 + tay + ldx HEX_CHARS_UPPER,y + pla + div A,16 + and #%00001111 + tay + lda HEX_CHARS_UPPER,y + rts +.endproc + + +.rodata +HEX_CHARS_UPPER: .byte "0123456789ABCDEF" +HEX_CHARS_LOWER: .byte "0123456789abcdef" + +.export strf + +.endscope +.endif ; guard