diff --git a/spicode.s65 b/spicode.s65 index 0a9da16..138407b 100644 --- a/spicode.s65 +++ b/spicode.s65 @@ -136,18 +136,6 @@ fmt_digit = $32 rts .endproc -; todo error handling -.proc hex_char_to_int - cmp #'A' - bge @char - sbc #'0' - rts -@char: - sbc #('A' - $A) - rts -.endproc - - ;******************************************************************************** ; @function Convert any int into hex ; @param ARG2-3: Address of output string @@ -160,9 +148,9 @@ fmt_digit = $32 ; @modifies X,Y,A ;******************************************************************************** .proc int_to_hex_str - cmp #0 -@loop: + bit beq @rts ; check done +@loop: ; load next byte pha lda ARG4,x @@ -188,11 +176,106 @@ fmt_digit = $32 plx pla dec + bne @loop @rts: rts .endproc + +;******************************************************************************** +; @function Convert a hex char into a binary number +; @details +; The char must be one of [0-9,a-f,A-F]. +; All results are only valid if N == 0. +; @param A: Char to convert +; @returns N: 0 == success, 1 == invalid char +; @returns A: The converted number +;******************************************************************************** +.proc hex_char_to_int + sec + sbc #'0' + bmi @invalid ; char was in [0, '0') + cmp #10 + bcc @rts ; A in [0, 10) + ; char higher than '9' + sbc #('A' - '0') + bmi @invalid ; char was in ('0', 'A') + cmp #7 + bcc @hex_char ; A in [0, 6] + ; char higher than 'F' + sbc #('a' - 'A') + bmi @invalid ; char was in ('F', 'a') + cmp #17 + bcc @hex_char ; A in [0, 6] + ; char was in ('f', $ff] +@invalid: + lda #$ff ; sets N flag + rts +@hex_char: + ; carry is not set + adc #10 +@rts: + rts +.endproc + + +;******************************************************************************** +; @function Convert a number encoded as hexadecimal string to a binary number +; @details +; The string must only consist of [0-9,a-f,A-F]. +; All results are only valid if N == 0. +; @param ARG0-1: Address of string +; @param A: Number of chars to convert +; @param Y: Offset onto string so that first char = (ARG0) + Y +; @returns N: 0 => success, 1 => invalid string +; @returns A: 0 +; @returns X: Size of the number in bytes +; @returns Y: Offset onto string, past the end of the number +; @modifies X,Y,A +;******************************************************************************** +.proc hex_to_int + bit #%11111111 ; check if accumulator is zero + beq @rts + ldx #0 + bit #%00000001 ; check if accumulator is even + beq @loop ; even + ; not even + stz ARG2 + pha + bra @less_sig_char +@loop: + pha + ; more significant char + lda (ARG0),y ; load next char + iny + jsr hex_char_to_int + bmi @invalid + rol + rol + rol + rol + sta ARG2,x +@less_sig_char: + ; less significant char + lda (ARG0),y ; load next char + iny + jsr hex_char_to_int + bmi @invalid + ora ARG2,x + sta ARG2,x + inx + pla + dec + bne @loop +@invalid: +@rts: + rts + +.endproc + + + TEST_FMT: .asciiz "%x -> %x -> %x:)" TEST_OUT: .asciiz "TESTOUT" HEX_CHARS_UPPER: .byte "0123456789ABCDEF"