.include "zeropage.inc"
- .export __printf
+ .export __printf
- .import popax, pushax, pusheax, decsp6, push1, axlong, axulong
- .import _ltoa, _ultoa
- .import _strlower, _strlen
+ .import popax, pushax, pusheax, decsp6, push1, axlong, axulong
+ .import _ltoa, _ultoa
+ .import _strlower, _strlen
- .macpack generic
+ .macpack generic
; ----------------------------------------------------------------------------
; We will store variables into the register bank in the zeropage. Define
; equates for these variables.
-ArgList = regbank+0 ; Argument list pointer
-Format = regbank+2 ; Format string
-OutData = regbank+4 ; Function parameters
+ArgList = regbank+0 ; Argument list pointer
+Format = regbank+2 ; Format string
+OutData = regbank+4 ; Function parameters
; ----------------------------------------------------------------------------
; Other zero page cells
-Base = ptr1
-FSave = ptr1
-FCount = ptr2
+Base = ptr1
+FSave = ptr1
+FCount = ptr2
.code
; return zero in Y.
GetFormatChar:
- ldy #0
- lda (Format),y
+ ldy #0
+ lda (Format),y
IncFormatPtr:
- inc Format
- bne @L1
- inc Format+1
-@L1: rts
+ inc Format
+ bne @L1
+ inc Format+1
+@L1: rts
; ----------------------------------------------------------------------------
; Output a pad character: outfunc (d, &padchar, 1)
OutputPadChar:
- lda PadChar
+ lda PadChar
; ----------------------------------------------------------------------------
; Call the output function with one character in A
Output1:
- sta CharArg
- jsr PushOutData
- lda #<CharArg
- ldx #>CharArg
- jsr pushax
- jsr push1
- jmp CallOutFunc ; fout (OutData, &CharArg, 1)
+ sta CharArg
+ jsr PushOutData
+ lda #<CharArg
+ ldx #>CharArg
+ jsr pushax
+ jsr push1
+ jmp CallOutFunc ; fout (OutData, &CharArg, 1)
; ----------------------------------------------------------------------------
; Decrement the argument list pointer by 2
DecArgList2:
- lda ArgList
- sub #2
- sta ArgList
- bcs @L1
- dec ArgList+1
-@L1: rts
+ lda ArgList
+ sub #2
+ sta ArgList
+ bcs @L1
+ dec ArgList+1
+@L1: rts
; ----------------------------------------------------------------------------
; Get an unsigned int or long argument depending on the IsLong flag.
GetUnsignedArg:
- lda IsLong ; Check flag
- bne GetLongArg ; Long sets all
- jsr GetIntArg ; Get an integer argument
- jmp axulong ; Convert to unsigned long
+ lda IsLong ; Check flag
+ bne GetLongArg ; Long sets all
+ jsr GetIntArg ; Get an integer argument
+ jmp axulong ; Convert to unsigned long
; ----------------------------------------------------------------------------
; Get an signed int or long argument depending on the IsLong flag.
GetSignedArg:
- lda IsLong ; Check flag
- bne GetLongArg ; Long sets all
- jsr GetIntArg ; Get an integer argument
- jmp axlong ; Convert to long
+ lda IsLong ; Check flag
+ bne GetLongArg ; Long sets all
+ jsr GetIntArg ; Get an integer argument
+ jmp axlong ; Convert to long
; ----------------------------------------------------------------------------
; Get a long argument from the argument list. Returns 0 in Y.
GetLongArg:
- jsr GetIntArg ; Get high word
- sta sreg
- stx sreg+1
+ jsr GetIntArg ; Get high word
+ sta sreg
+ stx sreg+1
; Run into GetIntArg fetching the low word
; Get an integer argument from the argument list. Returns 0 in Y.
GetIntArg:
- jsr DecArgList2
- ldy #1
- lda (ArgList),y
- tax
- dey
- lda (ArgList),y
- rts
+ jsr DecArgList2
+ ldy #1
+ lda (ArgList),y
+ tax
+ dey
+ lda (ArgList),y
+ rts
; ----------------------------------------------------------------------------
; Read an integer from the format string. Will return zero in Y.
ReadInt:
- ldy #0
- sty ptr1
- sty ptr1+1 ; Start with zero
-@Loop: lda (Format),y ; Get format string character
- sub #'0' ; Make number from ascii digit
- bcc @L9 ; Jump if done
- cmp #9+1
- bcs @L9 ; Jump if done
+ ldy #0
+ sty ptr1
+ sty ptr1+1 ; Start with zero
+@Loop: lda (Format),y ; Get format string character
+ sub #'0' ; Make number from ascii digit
+ bcc @L9 ; Jump if done
+ cmp #9+1
+ bcs @L9 ; Jump if done
; Skip the digit character
- jsr IncFormatPtr
+ jsr IncFormatPtr
; Add the digit to the value we have in ptr1
- pha ; Save digit value
- lda ptr1
- ldx ptr1+1
- asl ptr1
- rol ptr1+1 ; * 2
- asl ptr1
- rol ptr1+1 ; * 4, assume carry clear
- adc ptr1
- sta ptr1
- txa
- adc ptr1+1
- sta ptr1+1 ; * 5
- asl ptr1
- rol ptr1+1 ; * 10, assume carry clear
- pla
- adc ptr1 ; Add digit value
- sta ptr1
- bcc @Loop
- inc ptr1+1
- bcs @Loop ; Branch always
+ pha ; Save digit value
+ lda ptr1
+ ldx ptr1+1
+ asl ptr1
+ rol ptr1+1 ; * 2
+ asl ptr1
+ rol ptr1+1 ; * 4, assume carry clear
+ adc ptr1
+ sta ptr1
+ txa
+ adc ptr1+1
+ sta ptr1+1 ; * 5
+ asl ptr1
+ rol ptr1+1 ; * 10, assume carry clear
+ pla
+ adc ptr1 ; Add digit value
+ sta ptr1
+ bcc @Loop
+ inc ptr1+1
+ bcs @Loop ; Branch always
; We're done converting
-@L9: lda ptr1
- ldx ptr1+1 ; Load result
- rts
+@L9: lda ptr1
+ ldx ptr1+1 ; Load result
+ rts
; ----------------------------------------------------------------------------
; Put a character into the argument buffer and increment the buffer index
-PutBuf: ldy BufIdx
- inc BufIdx
- sta Buf,y
- rts
+PutBuf: ldy BufIdx
+ inc BufIdx
+ sta Buf,y
+ rts
; ----------------------------------------------------------------------------
; Get a pointer to the current buffer end and push it onto the stack
PushBufPtr:
- lda #<Buf
- ldx #>Buf
- add BufIdx
- bcc @L1
- inx
-@L1: jmp pushax
+ lda #<Buf
+ ldx #>Buf
+ add BufIdx
+ bcc @L1
+ inx
+@L1: jmp pushax
; ----------------------------------------------------------------------------
; Push OutData onto the software stack
PushOutData:
- lda OutData
- ldx OutData+1
- jmp pushax
+ lda OutData
+ ldx OutData+1
+ jmp pushax
; ----------------------------------------------------------------------------
; Output Width pad characters
;
PadLoop:
- jsr OutputPadChar
+ jsr OutputPadChar
OutputPadding:
- inc Width
- bne PadLoop
- inc Width+1
- bne PadLoop
- rts
+ inc Width
+ bne PadLoop
+ inc Width+1
+ bne PadLoop
+ rts
; ----------------------------------------------------------------------------
; Output the argument itself: outfunc (d, str, arglen);
;
OutputArg:
- jsr PushOutData
- lda Str
- ldx Str+1
- jsr pushax
- lda ArgLen
- ldx ArgLen+1
- jsr pushax
- jmp CallOutFunc
+ jsr PushOutData
+ lda Str
+ ldx Str+1
+ jsr pushax
+ lda ArgLen
+ ldx ArgLen+1
+ jsr pushax
+ jmp CallOutFunc
; ----------------------------------------------------------------------------
; ltoa: Wrapper for _ltoa that pushes all arguments
-ltoa: sty Base ; Save base
- jsr pusheax ; Push value
- jsr PushBufPtr ; Push the buffer pointer...
- lda Base ; Restore base
- jmp _ltoa ; ultoa (l, s, base);
+ltoa: sty Base ; Save base
+ jsr pusheax ; Push value
+ jsr PushBufPtr ; Push the buffer pointer...
+ lda Base ; Restore base
+ jmp _ltoa ; ultoa (l, s, base);
; ----------------------------------------------------------------------------
; ultoa: Wrapper for _ultoa that pushes all arguments
-ultoa: sty Base ; Save base
- jsr pusheax ; Push value
- jsr PushBufPtr ; Push the buffer pointer...
- lda Base ; Restore base
- jmp _ultoa ; ultoa (l, s, base);
+ultoa: sty Base ; Save base
+ jsr pusheax ; Push value
+ jsr PushBufPtr ; Push the buffer pointer...
+ lda Base ; Restore base
+ jmp _ultoa ; ultoa (l, s, base);
; ----------------------------------------------------------------------------
; Save the register bank variables into the save area
- pha ; Save low byte of ap
- ldy #5
-Save: lda regbank,y
- sta RegSave,y
- dey
- bpl Save
+ pha ; Save low byte of ap
+ ldy #5
+Save: lda regbank,y
+ sta RegSave,y
+ dey
+ bpl Save
; Get the parameters from the stack
- pla ; Restore low byte of ap
- sta ArgList ; Argument list pointer
- stx ArgList+1
+ pla ; Restore low byte of ap
+ sta ArgList ; Argument list pointer
+ stx ArgList+1
- jsr popax ; Format string
- sta Format
- stx Format+1
+ jsr popax ; Format string
+ sta Format
+ stx Format+1
- jsr popax ; Output descriptor
- sta OutData
- stx OutData+1
+ jsr popax ; Output descriptor
+ sta OutData
+ stx OutData+1
; Initialize the output counter in the output descriptor to zero
- lda #0
- tay
- sta (OutData),y
- iny
- sta (OutData),y
+ lda #0
+ tay
+ sta (OutData),y
+ iny
+ sta (OutData),y
; Get the output function from the output descriptor and remember it
- iny
- lda (OutData),y
- sta CallOutFunc+1
- iny
- lda (OutData),y
- sta CallOutFunc+2
+ iny
+ lda (OutData),y
+ sta CallOutFunc+1
+ iny
+ lda (OutData),y
+ sta CallOutFunc+2
; Start parsing the format string
MainLoop:
- lda Format ; Remember current format pointer
- sta FSave
- lda Format+1
- sta FSave+1
-
- ldy #0 ; Index
-@L1: lda (Format),y ; Get next char
- beq @L2 ; Jump on end of string
- cmp #'%' ; Format spec?
- beq @L2
- iny ; Bump pointer
- bne @L1
- inc Format+1 ; Bump high byte of pointer
- bne @L1 ; Branch always
+ lda Format ; Remember current format pointer
+ sta FSave
+ lda Format+1
+ sta FSave+1
+
+ ldy #0 ; Index
+@L1: lda (Format),y ; Get next char
+ beq @L2 ; Jump on end of string
+ cmp #'%' ; Format spec?
+ beq @L2
+ iny ; Bump pointer
+ bne @L1
+ inc Format+1 ; Bump high byte of pointer
+ bne @L1 ; Branch always
; Found a '%' character or end of string. Update the Format pointer so it is
; current (points to this character).
-@L2: tya ; Low byte of offset
- add Format
- sta Format
- bcc @L3
- inc Format+1
+@L2: tya ; Low byte of offset
+ add Format
+ sta Format
+ bcc @L3
+ inc Format+1
; Calculate, how many characters must be output. Beware: This number may
; be zero. A still contains the low byte of the pointer.
-@L3: sub FSave
- sta FCount
- lda Format+1
- sbc FSave+1
- sta FCount+1
- ora FCount ; Is the result zero?
- beq @L4 ; Jump if yes
+@L3: sub FSave
+ sta FCount
+ lda Format+1
+ sbc FSave+1
+ sta FCount+1
+ ora FCount ; Is the result zero?
+ beq @L4 ; Jump if yes
; Output the characters that we have until now. To make the call to out
; faster, build the stack frame by hand (don't use pushax)
- jsr decsp6 ; 3 args
- ldy #5
- lda OutData+1
- sta (sp),y
- dey
- lda OutData
- sta (sp),y
- dey
- lda FSave+1
- sta (sp),y
- dey
- lda FSave
- sta (sp),y
- dey
- lda FCount+1
- sta (sp),y
- dey
- lda FCount
- sta (sp),y
- jsr CallOutFunc ; Call the output function
+ jsr decsp6 ; 3 args
+ ldy #5
+ lda OutData+1
+ sta (sp),y
+ dey
+ lda OutData
+ sta (sp),y
+ dey
+ lda FSave+1
+ sta (sp),y
+ dey
+ lda FSave
+ sta (sp),y
+ dey
+ lda FCount+1
+ sta (sp),y
+ dey
+ lda FCount
+ sta (sp),y
+ jsr CallOutFunc ; Call the output function
; We're back from out(), or we didn't call it. Check for end of string.
-@L4: jsr GetFormatChar ; Get one char, zero in Y
- tax ; End of format string reached?
- bne NotDone ; End not reached
+@L4: jsr GetFormatChar ; Get one char, zero in Y
+ tax ; End of format string reached?
+ bne NotDone ; End not reached
; End of format string reached. Restore the zeropage registers and return.
- ldx #5
-Rest: lda RegSave,x
- sta regbank,x
- dex
- bpl Rest
- rts
+ ldx #5
+Rest: lda RegSave,x
+ sta regbank,x
+ dex
+ bpl Rest
+ rts
; Still a valid format character. Check for '%' and a '%%' sequence. Output
; anything that is not a format specifier. On intro, Y is zero.
NotDone:
- cmp #'%'
- bne @L1
- lda (Format),y ; Check for "%%"
- cmp #'%'
- bne FormatSpec ; Jump if really a format specifier
- jsr IncFormatPtr ; Skip the second '%'
-@L1: jsr Output1 ; Output the character...
- jmp MainLoop ; ...and continue
+ cmp #'%'
+ bne @L1
+ lda (Format),y ; Check for "%%"
+ cmp #'%'
+ bne FormatSpec ; Jump if really a format specifier
+ jsr IncFormatPtr ; Skip the second '%'
+@L1: jsr Output1 ; Output the character...
+ jmp MainLoop ; ...and continue
; We have a real format specifier
; Format is: %[flags][width][.precision][mod]type
; Initialize the flags
- lda #0
- ldx #FormatVarSize-1
-@L1: sta FormatVars,x
- dex
- bpl @L1
+ lda #0
+ ldx #FormatVarSize-1
+@L1: sta FormatVars,x
+ dex
+ bpl @L1
; Start with reading the flags if there are any. X is $FF which is used
; for "true"
ReadFlags:
- lda (Format),y ; Get next char...
- cmp #'-'
- bne @L1
- stx LeftJust
- beq @L4
+ lda (Format),y ; Get next char...
+ cmp #'-'
+ bne @L1
+ stx LeftJust
+ beq @L4
-@L1: cmp #'+'
- bne @L2
- stx AddSign
- beq @L4
+@L1: cmp #'+'
+ bne @L2
+ stx AddSign
+ beq @L4
-@L2: cmp #' '
- bne @L3
- stx AddBlank
- beq @L4
+@L2: cmp #' '
+ bne @L3
+ stx AddBlank
+ beq @L4
-@L3: cmp #'#'
- bne ReadPadding
- stx AltForm
+@L3: cmp #'#'
+ bne ReadPadding
+ stx AltForm
-@L4: jsr IncFormatPtr
- jmp ReadFlags ; ...and start over
+@L4: jsr IncFormatPtr
+ jmp ReadFlags ; ...and start over
; Done with flags, read the pad char. Y is still zero if we come here.
ReadPadding:
- ldx #' ' ; PadChar
- cmp #'0'
- bne @L1
- tax ; PadChar is '0'
- jsr IncFormatPtr
- lda (Format),y ; Read current for later
-@L1: stx PadChar
+ ldx #' ' ; PadChar
+ cmp #'0'
+ bne @L1
+ tax ; PadChar is '0'
+ jsr IncFormatPtr
+ lda (Format),y ; Read current for later
+@L1: stx PadChar
; Read the width. Even here, Y is still zero. A contains the current character
; from the format string
ReadWidth:
- cmp #'*'
- bne @L1
- jsr IncFormatPtr
- jsr GetIntArg ; Width is an additional argument
- jmp @L2
+ cmp #'*'
+ bne @L1
+ jsr IncFormatPtr
+ jsr GetIntArg ; Width is an additional argument
+ jmp @L2
-@L1: jsr ReadInt ; Read integer from format string...
-@L2: sta Width
- stx Width+1 ; ...and remember in Width
+@L1: jsr ReadInt ; Read integer from format string...
+@L2: sta Width
+ stx Width+1 ; ...and remember in Width
; Read the precision. Even here, Y is still zero.
- sty Prec ; Assume Precision is zero
- sty Prec+1
- lda (Format),y ; Load next format string char
- cmp #'.' ; Precision given?
- bne ReadMod ; Branch if no precision given
+ sty Prec ; Assume Precision is zero
+ sty Prec+1
+ lda (Format),y ; Load next format string char
+ cmp #'.' ; Precision given?
+ bne ReadMod ; Branch if no precision given
ReadPrec:
- jsr IncFormatPtr ; Skip the '.'
- lda (Format),y
- cmp #'*' ; Variable precision?
- bne @L1
- jsr IncFormatPtr ; Skip the '*'
- jsr GetIntArg ; Get integer argument
- jmp @L2
-
-@L1: jsr ReadInt ; Read integer from format string
-@L2: sta Prec
- stx Prec+1
+ jsr IncFormatPtr ; Skip the '.'
+ lda (Format),y
+ cmp #'*' ; Variable precision?
+ bne @L1
+ jsr IncFormatPtr ; Skip the '*'
+ jsr GetIntArg ; Get integer argument
+ jmp @L2
+
+@L1: jsr ReadInt ; Read integer from format string
+@L2: sta Prec
+ stx Prec+1
; Read the modifiers. Y is still zero.
ReadMod:
- lda (Format),y
- cmp #'z' ; size_t - same as unsigned
- beq @L2
- cmp #'h' ; short - same as int
- beq @L2
+ lda (Format),y
+ cmp #'z' ; size_t - same as unsigned
+ beq @L2
+ cmp #'h' ; short - same as int
+ beq @L2
cmp #'t' ; ptrdiff_t - same as int
beq @L2
cmp #'j' ; intmax_t/uintmax_t - same as long
beq @L1
- cmp #'L' ; long double
- beq @L1
- cmp #'l' ; long int
- bne DoFormat
-@L1: lda #$FF
- sta IsLong
-@L2: jsr IncFormatPtr
- jmp ReadMod
+ cmp #'L' ; long double
+ beq @L1
+ cmp #'l' ; long int
+ bne DoFormat
+@L1: lda #$FF
+ sta IsLong
+@L2: jsr IncFormatPtr
+ jmp ReadMod
; Initialize the argument buffer pointers. We use a static buffer (ArgBuf) to
; assemble strings. A zero page index (BufIdx) is used to keep the current
; Y is zero when we come here.
DoFormat:
- sty BufIdx ; Clear BufIdx
- ldx #<Buf
- stx Str
- ldx #>Buf
- stx Str+1
+ sty BufIdx ; Clear BufIdx
+ ldx #<Buf
+ stx Str
+ ldx #>Buf
+ stx Str+1
; Skip the current format character, then check it (current char in A)
- jsr IncFormatPtr
+ jsr IncFormatPtr
; Is it a character?
- cmp #'c'
- bne CheckInt
+ cmp #'c'
+ bne CheckInt
; It is a character
- jsr GetIntArg ; Get the argument (promoted to int)
- sta Buf ; Place it as zero terminated string...
- lda #0
- sta Buf+1 ; ...into the buffer
- jmp HaveArg ; Done
+ jsr GetIntArg ; Get the argument (promoted to int)
+ sta Buf ; Place it as zero terminated string...
+ lda #0
+ sta Buf+1 ; ...into the buffer
+ jmp HaveArg ; Done
; Is it an integer?
CheckInt:
- cmp #'d'
- beq @L1
- cmp #'i'
- bne CheckCount
+ cmp #'d'
+ beq @L1
+ cmp #'i'
+ bne CheckCount
; It is an integer
-@L1: ldx #0
- lda AddBlank ; Add a blank for positives?
- beq @L2 ; Jump if no
- ldx #' '
-@L2: lda AddSign ; Add a plus for positives (precedence)?
- beq @L3
- ldx #'+'
-@L3: stx Leader
+@L1: ldx #0
+ lda AddBlank ; Add a blank for positives?
+ beq @L2 ; Jump if no
+ ldx #' '
+@L2: lda AddSign ; Add a plus for positives (precedence)?
+ beq @L3
+ ldx #'+'
+@L3: stx Leader
; Integer argument
- jsr GetSignedArg ; Get argument as a long
- ldy sreg+1 ; Check sign
- bmi @Int1
- ldy Leader
- beq @Int1
- sty Buf
- inc BufIdx
+ jsr GetSignedArg ; Get argument as a long
+ ldy sreg+1 ; Check sign
+ bmi @Int1
+ ldy Leader
+ beq @Int1
+ sty Buf
+ inc BufIdx
-@Int1: ldy #10 ; Base
- jsr ltoa ; Push arguments, call _ltoa
- jmp HaveArg
+@Int1: ldy #10 ; Base
+ jsr ltoa ; Push arguments, call _ltoa
+ jmp HaveArg
; Is it a count pseudo format?
CheckCount:
- cmp #'n'
- bne CheckOctal
+ cmp #'n'
+ bne CheckOctal
; It is a count pseudo argument
- jsr GetIntArg
- sta ptr1
- stx ptr1+1 ; Get user supplied pointer
- ldy #0
- lda (OutData),y ; Low byte of OutData->ccount
- sta (ptr1),y
- iny
- lda (OutData),y ; High byte of OutData->ccount
- sta (ptr1),y
- jmp MainLoop ; Done
+ jsr GetIntArg
+ sta ptr1
+ stx ptr1+1 ; Get user supplied pointer
+ ldy #0
+ lda (OutData),y ; Low byte of OutData->ccount
+ sta (ptr1),y
+ iny
+ lda (OutData),y ; High byte of OutData->ccount
+ sta (ptr1),y
+ jmp MainLoop ; Done
; Check for an octal digit
CheckOctal:
- cmp #'o'
- bne CheckPointer
+ cmp #'o'
+ bne CheckPointer
; Integer in octal representation
- jsr GetSignedArg ; Get argument as a long
- ldy AltForm ; Alternative form?
- beq @Oct1 ; Jump if no
- pha ; Save low byte of value
- stx tmp1
- ora tmp1
- ora sreg
- ora sreg+1
- ora Prec
- ora Prec+1 ; Check if value or Prec != 0
- beq @Oct1
- lda #'0'
- jsr PutBuf
- pla ; Restore low byte
-
-@Oct1: ldy #8 ; Load base
- jsr ltoa ; Push arguments, call _ltoa
- jmp HaveArg
+ jsr GetSignedArg ; Get argument as a long
+ ldy AltForm ; Alternative form?
+ beq @Oct1 ; Jump if no
+ pha ; Save low byte of value
+ stx tmp1
+ ora tmp1
+ ora sreg
+ ora sreg+1
+ ora Prec
+ ora Prec+1 ; Check if value or Prec != 0
+ beq @Oct1
+ lda #'0'
+ jsr PutBuf
+ pla ; Restore low byte
+
+@Oct1: ldy #8 ; Load base
+ jsr ltoa ; Push arguments, call _ltoa
+ jmp HaveArg
; Check for a pointer specifier (%p)
CheckPointer:
- cmp #'p'
- bne CheckString
+ cmp #'p'
+ bne CheckString
; It's a pointer. Use %#x conversion
- ldx #0
- stx IsLong ; IsLong = 0;
- inx
- stx AltForm ; AltForm = 1;
- lda #'x'
- bne IsHex ; Branch always
+ ldx #0
+ stx IsLong ; IsLong = 0;
+ inx
+ stx AltForm ; AltForm = 1;
+ lda #'x'
+ bne IsHex ; Branch always
; Check for a string specifier (%s)
CheckString:
- cmp #'s'
- bne CheckUnsigned
+ cmp #'s'
+ bne CheckUnsigned
; It's a string
- jsr GetIntArg ; Get 16bit argument
- sta Str
- stx Str+1
- jmp HaveArg
+ jsr GetIntArg ; Get 16bit argument
+ sta Str
+ stx Str+1
+ jmp HaveArg
; Check for an unsigned integer (%u)
CheckUnsigned:
- cmp #'u'
- bne CheckHex
+ cmp #'u'
+ bne CheckHex
; It's an unsigned integer
- jsr GetUnsignedArg ; Get argument as unsigned long
- ldy #10 ; Load base
- jsr ultoa ; Push arguments, call _ultoa
- jmp HaveArg
+ jsr GetUnsignedArg ; Get argument as unsigned long
+ ldy #10 ; Load base
+ jsr ultoa ; Push arguments, call _ultoa
+ jmp HaveArg
; Check for a hexadecimal integer (%x)
CheckHex:
- cmp #'x'
- beq IsHex
- cmp #'X'
- bne UnknownFormat
+ cmp #'x'
+ beq IsHex
+ cmp #'X'
+ bne UnknownFormat
; Hexadecimal integer
-IsHex: pha ; Save the format spec
- lda AltForm
- beq @L1
- lda #'0'
- jsr PutBuf
- lda #'X'
- jsr PutBuf
-
-@L1: jsr GetUnsignedArg ; Get argument as an unsigned long
- ldy #16 ; Load base
- jsr ultoa ; Push arguments, call _ultoa
-
- pla ; Get the format spec
- cmp #'x' ; Lower case?
- bne @L2
- lda Str
- ldx Str+1
- jsr _strlower ; Make characters lower case
-@L2: jmp HaveArg
+IsHex: pha ; Save the format spec
+ lda AltForm
+ beq @L1
+ lda #'0'
+ jsr PutBuf
+ lda #'X'
+ jsr PutBuf
+
+@L1: jsr GetUnsignedArg ; Get argument as an unsigned long
+ ldy #16 ; Load base
+ jsr ultoa ; Push arguments, call _ultoa
+
+ pla ; Get the format spec
+ cmp #'x' ; Lower case?
+ bne @L2
+ lda Str
+ ldx Str+1
+ jsr _strlower ; Make characters lower case
+@L2: jmp HaveArg
; Unknown format character, skip it
UnknownFormat:
- jmp MainLoop
+ jmp MainLoop
; We have the argument, do argument string formatting
; ArgLen = strlen (Str);
- lda Str
- ldx Str+1
- jsr _strlen ; Get length of argument
- sta ArgLen
- stx ArgLen+1
+ lda Str
+ ldx Str+1
+ jsr _strlen ; Get length of argument
+ sta ArgLen
+ stx ArgLen+1
; if (Prec && Prec < ArgLen) ArgLen = Prec;
- lda Prec
- ora Prec+1
- beq @L1
- ldx Prec
- cpx ArgLen
- lda Prec+1
- tay
- sbc ArgLen+1
- bcs @L1
- stx ArgLen
- sty ArgLen+1
+ lda Prec
+ ora Prec+1
+ beq @L1
+ ldx Prec
+ cpx ArgLen
+ lda Prec+1
+ tay
+ sbc ArgLen+1
+ bcs @L1
+ stx ArgLen
+ sty ArgLen+1
; if (Width > ArgLen) {
-; Width -= ArgLen; /* padcount */
+; Width -= ArgLen; /* padcount */
; } else {
; Width = 0;
; }
; Since width is used as a counter below, calculate -(width+1)
-@L1: sec
- lda Width
- sbc ArgLen
- tax
- lda Width+1
- sbc ArgLen+1
- bcs @L2
- lda #0
- tax
-@L2: eor #$FF
- sta Width+1
- txa
- eor #$FF
- sta Width
+@L1: sec
+ lda Width
+ sbc ArgLen
+ tax
+ lda Width+1
+ sbc ArgLen+1
+ bcs @L2
+ lda #0
+ tax
+@L2: eor #$FF
+ sta Width+1
+ txa
+ eor #$FF
+ sta Width
; /* Do padding on the left side if needed */
; if (!leftjust) {
; /* argument right justified */
; while (width) {
-; fout (d, &padchar, 1);
-; --width;
+; fout (d, &padchar, 1);
+; --width;
; }
; }
- lda LeftJust
- bne @L3
- jsr OutputPadding
+ lda LeftJust
+ bne @L3
+ jsr OutputPadding
; Output the argument itself
-@L3: jsr OutputArg
+@L3: jsr OutputArg
; /* Output right padding bytes if needed */
; if (leftjust) {
; /* argument left justified */
; while (width) {
-; fout (d, &padchar, 1);
-; --width;
+; fout (d, &padchar, 1);
+; --width;
; }
; }
- lda LeftJust
- beq @L4
- jsr OutputPadding
+ lda LeftJust
+ beq @L4
+ jsr OutputPadding
; Done, parse next chars from format string
-@L4: jmp MainLoop
+@L4: jmp MainLoop
; ----------------------------------------------------------------------------
.bss
; Save area for the zero page registers
-RegSave: .res regbanksize
+RegSave: .res regbanksize
; One character argument for OutFunc
-CharArg: .byte 0
+CharArg: .byte 0
; Format variables
FormatVars:
-LeftJust: .byte 0
-AddSign: .byte 0
-AddBlank: .byte 0
-AltForm: .byte 0
-PadChar: .byte 0
-Width: .word 0
-Prec: .word 0
-IsLong: .byte 0
-Leader: .byte 0
-BufIdx: .byte 0 ; Argument string pointer
-FormatVarSize = * - FormatVars
+LeftJust: .byte 0
+AddSign: .byte 0
+AddBlank: .byte 0
+AltForm: .byte 0
+PadChar: .byte 0
+Width: .word 0
+Prec: .word 0
+IsLong: .byte 0
+Leader: .byte 0
+BufIdx: .byte 0 ; Argument string pointer
+FormatVarSize = * - FormatVars
; Argument buffer and pointer
-Buf: .res 20
-Str: .word 0
-ArgLen: .res 2
+Buf: .res 20
+Str: .word 0
+ArgLen: .res 2
.data
; Stuff from OutData. Is used as a vector and must be aligned
-CallOutFunc: jmp $0000
+CallOutFunc: jmp $0000