; ======================================================================
; CS617 NUMERIC LIBRARY
; format_u32_dec.inc
;
; Unsigned 32-bit integer -> decimal ASCII formatter.
;
; Entry:
;   UFMT32DEC
;
; Preconditions:
;   IX points to a writable buffer of at least 11 bytes in the current
;   IX memory bank.
;   UDIV3216NZ environment is valid:
;       divisor is supplied nonzero by this routine (10)
;       $SX = 0
;       $SY = 1
;       system stack is valid
;
; Input:
;   $15-$18  unsigned 32-bit value, low word first
;   IX       destination buffer
;
; Output:
;   (IX+0)..(IX+$14-1)  ASCII decimal digits, no leading zeroes
;   (IX+$14)            NUL terminator
;   $14                 digit count, 1..10
;   $15-$18             original input preserved
;   IX                   preserved
;
; Examples:
;   0          -> "0"
;   123        -> "123"
;   FFFFFFFFh  -> "4294967295"
;
; Dependencies:
;   UDIV3216NZ from divmod_u32_u16.inc
;   UDIV32NZ   transitively from divmod_u32_u32.inc
;
; Algorithm:
;   - special-case zero;
;   - repeatedly divmod by 10;
;   - store remainder digits in reverse order;
;   - NUL terminate;
;   - reverse the digit bytes in place;
;   - restore the original u32.
;
; This is new CS617 composition, not a historical donor transplant.
;
; Clobbers:
;   arithmetic scratch inherited from UDIV3216NZ / UDIV32NZ
;   $9-$13, $24-$25
;   $14 is the returned length
; ======================================================================

#LIST

UFMT32DEC:
; Preserve the numeric input. Nested UDIV32NZ stack use is balanced.
        PHSM    $18,4

; Stable zero word used for quotient tests. UDIV32NZ preserves $22-$29.
        SBW     $24,$24

; Zero formats as one digit, not as an empty string.
        SBCW    $15,$24
        JR      NZ,F32_BEGIN
        SBCW    $17,$24
        JR      NZ,F32_BEGIN

        LD      $10,&H30
        ST      $10,(IX+$SX)
        LD      $14,$SY
        LD      $10,$SX
        ST      $10,(IX+$14)
        JR      F32_RESTORE

F32_BEGIN:
        LD      $14,$SX

F32_DIVLOOP:
; quotient -> $15-$18
; remainder -> $10-$13
        LDW     $5,10
        CAL     UDIV3216NZ

; Remainder is 0..9. Store ASCII digit in reverse order.
        AD      $10,&H30
        ST      $10,(IX+$14)
        AD      $14,$SY

; Continue until quotient is zero.
        SBCW    $15,$24
        JR      NZ,F32_DIVLOOP
        SBCW    $17,$24
        JR      NZ,F32_DIVLOOP

; Terminate the reverse-order byte sequence.
        LD      $10,$SX
        ST      $10,(IX+$14)

; Reverse digits in place.
; left  = $12 = 0
; right = $13 = length-1
        LD      $12,$SX
        LD      $13,$14
        SB      $13,$SY

F32_REVLOOP:
        SBC     $12,$13
        JR      NC,F32_RESTORE

        LD      $10,(IX+$12)
        LD      $11,(IX+$13)
        ST      $11,(IX+$12)
        ST      $10,(IX+$13)

        AD      $12,$SY
        SB      $13,$SY
        JR      F32_REVLOOP

F32_RESTORE:
        PPSM    $15,4
        RTN
