;
; int printf(char *format, ...) -- just like C
;
; Only supports %d, %x, and %s
;
; internally:
; HL = pointer to format string
; IX = pointer to output buffer
; IY = pointer to next arg to be processed
;
_printf
PUSH IY
LD IY, 0
ADD IY, SP
PUSH AF
PUSH IX
; IY points at IY on stack
INC IY
INC IY ; points at return address
INC IY
INC IY ; points at first argument
LD L, (IY + 0) ; format string into HL
LD H, (IY + 1)
INC IY
INC IY
LD IX, PRINTF_BUF
PRINTF_LOOP
LD A, (HL)
CP '%'
JP NZ, PRINTF_NOT_PERCENT
INC HL
LD A, (HL)
CP 'd'
JP NZ, PRINTF_NOT_DECIMAL
CALL PRINTF_CONVERT_DECIMAL
INC HL
JP PRINTF_LOOP
PRINTF_NOT_DECIMAL
CP 'x'
JP NZ, PRINTF_NOT_HEX
CALL PRINTF_CONVERT_HEX
INC HL
JP PRINTF_LOOP
PRINTF_NOT_HEX
CP 's'
JP NZ, PRINTF_NOT_PERCENT
CALL PRINTF_CONVERT_STRING
INC HL
JP PRINTF_LOOP
PRINTF_NOT_PERCENT
LD (IX), A
INC IX
INC HL
CP 0
JP NZ, PRINTF_LOOP
LD HL, PRINTF_BUF
CALL LCDPRINT
LD HL, 0
POP IX
POP AF
POP IY
RET
PRINTF_BUF DS 48 ; 24 bytes on the display, pad to be sure
;
; PRINTF_CONVERT_DECIMAL
;
; Input:
; IY = pointer to int
; IX = buffer to convert into
; Output:
; IY = incremented past int
; IX = incremented past decimal version of int
; Internally:
; HL = int
;
PRINTF_CONVERT_DECIMAL
PUSH HL
PUSH AF
PUSH BC
LD L, (IY + 0)
LD H, (IY + 1)
INC IY
INC IY
XOR A ; reset carry and set A to 0
LD B, A ; BC = 0
LD C, A
ADC HL, BC ; HL = HL (set zero flag)
JP NZ, PCD_NOT_ZERO
LD A, '0'
LD (IX), A
INC IX
JP PCD_END
PCD_NOT_ZERO
PUSH IY
PUSH DE
LD A, 0 ; D = 0 (printed flag)
LD D, A
LD IY, PCD_TABLE
PCD_LOOP
LD A, (IY)
INC IY ; does not affect condition bits
CP '$' ; end of table
JP Z, PCD_LOOP_END
LD C, (IY) ; get word to compare to
INC IY
LD B, (IY)
INC IY
CP '0' ; special case
JP NZ, PCD_NOT_ZERO_DIGIT
LD A, D ; printed flag
CP 0
JP Z, PCD_LOOP ; before first digit, do not print zero
; the number in BC represents the smallest number which HL
; has to be to not print a zero right now
AND A ; clear carry
PUSH HL ; do not clobber it
SBC HL, BC ; HL -= BC
POP HL
JP NC, PCD_LOOP ; HL >= BC
LD A, '0' ; print zero
LD (IX), A
INC IX
JP PCD_LOOP
PCD_NOT_ZERO_DIGIT
AND A ; clear carry
PUSH HL ; do not clobber HL
SBC HL, BC ; HL -= BC
POP HL
JP C, PCD_LOOP ; HL < BC
LD (IX), A ; print digit
INC IX
AND A ; clear carry
SBC HL, BC ; HL -= BC
LD A, 1 ; printed flag = 1
LD D, A
JP PCD_LOOP
PCD_LOOP_END
POP DE
POP IY
PCD_END
POP BC
POP AF
POP HL
RET
PCD_TABLE
DB '6'
DW 60000
DB '5'
DW 50000
DB '4'
DW 40000
DB '3'
DW 30000
DB '2'
DW 20000
DB '1'
DW 10000
DB '0'
DW 1000
DB '9'
DW 9000
DB '8'
DW 8000
DB '7'
DW 7000
DB '6'
DW 6000
DB '5'
DW 5000
DB '4'
DW 4000
DB '3'
DW 3000
DB '2'
DW 2000
DB '1'
DW 1000
DB '0'
DW 100
DB '9'
DW 900
DB '8'
DW 800
DB '7'
DW 700
DB '6'
DW 600
DB '5'
DW 500
DB '4'
DW 400
DB '3'
DW 300
DB '2'
DW 200
DB '1'
DW 100
DB '0'
DW 10
DB '9'
DW 90
DB '8'
DW 80
DB '7'
DW 70
DB '6'
DW 60
DB '5'
DW 50
DB '4'
DW 40
DB '3'
DW 30
DB '2'
DW 20
DB '1'
DW 10
DB '0'
DW 1
DB '9'
DW 9
DB '8'
DW 8
DB '7'
DW 7
DB '6'
DW 6
DB '5'
DW 5
DB '4'
DW 4
DB '3'
DW 3
DB '2'
DW 2
DB '1'
DW 1
DB '$'
;
; PRINTF_CONVERT_HEX
;
; Input:
; IY = pointer to int
; IX = buffer to convert into
; Output:
; IY = incremented past int
; IX = incremented past hex version of int
; Internally:
; HL = int
;
PRINTF_CONVERT_HEX
PUSH HL
LD L, (IY + 0)
LD H, (IY + 1)
INC IY
INC IY
CALL PHEXWORD
POP HL
RET
;
; PRINTF_CONVERT_STRING
;
; Input:
; IY = pointer to string pointer
; IX = buffer to convert into
; Output:
; IY = incremented past pointer
; IX = incremented past string
;
PRINTF_CONVERT_STRING
PUSH HL
LD L, (IY + 0)
LD H, (IY + 1)
INC IY
INC IY
CALL STRCPY ; increments IX for us
POP HL
RET