;=================================================================
; [strings.mac] - original code by Neviksti
;                 some mods by kr Software, 17th-18th Feb-2003
;
;  Comment: Thanx a bunch to Neviksti for these routines!!
;=================================================================


.DEFINE STR_CURSOR $10
.DEFINE STR_TXTBUF $7F0000      ; -> 7F03FF


;=================================================================


; calculates new offset by given values (y,x)

.MACRO GOTOXY
    ldx   #$20*\1+\2
    stx   STR_CURSOR
.ENDM


;================================


; print string

.MACRO PRINTS
   ldx   #STRPSS\@
   jsl   PPRINTF
   bra   STRPSE\@
STRPSS\@:
   .db \1,0
STRPSE\@:
.ENDM


;================================


; print number (bytesized)
; e.g: PRINTNUM $2103 -> prints value of reg $2103
;      PRINTNUM #69   -> prints 69 *sigh*

.MACRO PRINTNUM
    lda   \1
    jsl   STR_DO_PRNINT8_NL
.ENDM


; and this one prints values in hex

.MACRO PRINTHNUM
    lda   \1
    jsl   STR_DO_PRNHEX8_NL
.ENDM


;================================


.BANK 0 SLOT 0
.SECTION "printhandler"

; PPRINT -> prints an ascii-chr to the bg#3-buffer which needs to be copied
;           into vram in the nmi-handler.  oh yeah! an 8x8 ascii tileset must
;           have been loaded and the vram pointer set ahead of the operation.
; IN: (A)scii-code
; OUT: none
; MODIFIES: P
PPRINT:
    phx
    ldx   STR_CURSOR
    sta   STR_TXTBUF, X         ; output character
    inx
    stx   STR_CURSOR
    plx
    rtl

; PPPRINTF -> printf a formatted, null-terminated string to stdout
; IN: X = points to format string
;     Y = points to parambuffer
; OUT: none
; MODIFIES: none
;<--->
; supported format characters:
;    %b = 8bit integer (reads 8bit data from Y data)
;    %d = 16bit integer (reads 16bit data from Y data)
;    %s = substring (reads 16bit-pointer from Y data)
;    %x = 8bit hex-integer (reads 8bit data from Y data)
;    \b = page break
;    \n = new line
;    \t = tab
;    \\ = \
;   Note! String pointer all refers to current data bank (db).
;   Assumes 8bit mem, 16bit index.
PPRINTF:
    php
    pha
    phx
    phy
    rep   #$10                  ; A/mem=8bit, X/Y=16bit
    sep   #$20
PPPRINTFLOOP:
    lda   $0000, X              ; read next format string chr
    beq   PPPRINTFEND           ; branch if null-terminated
    inx                         ; increment input pointer
    cmp   #'%'
    beq   PPPRINTFFORMAT        ; handle format character
    cmp   #'\'
    beq   PPPRINTFCTRL          ; handle control character
PPPRINTFNORM:                   ; print the character normally
    jsl   PPRINT
    bra   PPPRINTFLOOP
PPPRINTFEND:
    ply
    plx
    pla
    plp
    rtl
PPPRINTFCTRL:
    lda   $0000, X              ; read control character
    beq   PPPRINTFEND           ; branch if null-terminated
    inx                         ; increment input pointer
    cmp   #'n'
PPPcn:
    bne   PPPct
    rep   #$30                  ; 16bit mem, 16bit X
    lda   STR_CURSOR            ; get current position
    clc
    adc   #$0020                ; goto next line
    and   #$FFE0
    sta   STR_CURSOR            ; save new position
    sep   #$20                  ; 8bit mem, 16bit X
    bra   PPPRINTFLOOP
PPPct:
    cmp   #'t'
    bne   PPPcb
    rep   #$30                  ; 16bit mem, 16bit X
    lda   STR_CURSOR            ; get current position
    clc
    adc   #$0008                ; goto next tab
    and   #$FFF8
    sta   STR_CURSOR            ; save new position
    sep   #$20                  ; 8bit mem, 16bit X
    bra   PPPRINTFLOOP
PPPcb:
    cmp   #'b'
    bne   PPPPRNTF_DEF_C
    stz   STR_CURSOR            ; page break
    stz   STR_CURSOR+1
PPPPRNTF_DEF_C:
    lda   #'\'                  ; `\\' -> a normal `\'
    bra   PPPRINTFNORM
PPPRINTFFORMAT:
    lda   $0000, X              ; read format chr
    beq   PPPRINTFEND           ; null-terminated?
    inx                         ; increment input pointer
PPPsf:
    cmp   #'s'
    bne   PPPdf
    phx                         ; preserve current format string pointer
    ldx   0,Y                   ; load sub-string pointer
    iny
    iny
    jsl   PPRINTF
    plx
    bra   PPPRINTFLOOP
PPPdf:
    cmp   #'d'
    bne   PPPbf
    jsl   PPRINTINT16           ; print 16bit integer
    bra   PPPRINTFLOOP
PPPbf:
    cmp   #'b'
    bne   PPPxf
    jsl   PPRINTINT8            ; print 8bit integer
    bra   PPPRINTFLOOP
PPPxf:
    cmp   #'x'
    bne   PPPPRNTF_DEF_F
    jsl   PPRINTHEX8            ; print 8bit integer (in hex)
    jml   PPPRINTFLOOP
PPPPRNTF_DEF_F:
    lda   #'%'
    bra   PPPRINTFNORM


;================================


; PPRINTINT16 -> reads a 16bit value pointed to by reg_Y and prints it to stdout.
;               uses _PRINT to output ascii to stdout.
; IN: Y (points to integer in current databank)
; OUT: Y+=2
; MODIFIES: P
PPRINTINT16:                    ; assumes 8bit mem, 16bit index
    lda   #$00
    pha                         ; push $00 (push A)
    lda   $0000, Y
    sta   $4204
    lda   $0001, Y
    sta   $4205
    iny
    iny
PPPRNTI16_DIVL:                 ; div loop .. now wasn't that quite self-explanatory or what?! ;)
    lda   #$0A
    sta   $4206                 ; division startl here, but we'd better wait about 16-17 cycles..
    nop                         ; 2 cycles
    nop                         ; 2 cycles
    nop                         ; 2 cycles
    pha                         ; 3 cycles
    pla                         ; 4 cycles
    lda   #'0'                  ; 2 cycles
    clc                         ; 2 cycles
    adc   $4216                 ; .. back to work!!!
    pha
    lda   $4214
    sta   $4204
    beq   PPPlow0
    lda   $4215
    sta   $4205
    bra   PPPRNTI16_DIVL        ; is it necessary to repeat?
PPPlow0:
    lda   $4215
    sta   $4205
    beq   PPPintprntl           ; if equal then branch to integer_print_loop
    bra   PPPRNTI16_DIVL
PPPintprntl:                    ; .. until we get to the end of the string ..
    pla
    beq   PPPendoint
    jsl   PPRINT
    bra   PPPintprntl
PPPendoint:
    rtl


;================================


; same as PPRINTINT16, but OUT: Y++

PPRINTINT8:                     ; assumes 8bit mem, 16bit index
    lda   $0000, Y
    iny
STR_DO_PRNINT8_NL:
    sta   $4204
    lda   #$00
    sta   $4205
    pha
    bra   PPPRNTI16_DIVL
STR_DO_PRNINT16_NL:
    lda   #$00
    pha                         ; push $00
    stx   $4204
    jsl   PPPRNTI16_DIVL


;================================


; same as PPRINTINT8

PPRINTHEX8:                     ; assumes 8bit mem, 16bit index
    lda   $0000, Y
    iny
STR_DO_PRNHEX8_NL:
    pha
    lsr   A
    lsr   A
    lsr   A
    lsr   A
    jsl   PPPRNTH8_NIBBLE
    pla
    and   #$0F
    jsl   PPPRNTH8_NIBBLE
    rtl
PPPRNTH8_NIBBLE:                ; assumes 8bit mem, 16bit index
    cmp   #$0A
    bcs   PPPRNTH8_NLETTER
    clc
    adc   #'0'
    jsl   PPRINT
    rtl
PPPRNTH8_NLETTER:
    clc
    adc   #'A'-10
    jsl   PPRINT
    rtl

.ENDS
