*************************************************************************
*                                                                       *
*       fprintf - routine to call EXEC RawDoFmt to print to specified   *
*                 output                                                *
*                                                                       *
*       Parameters:                                                     *
*               D0 = output vector                                      *
*                                                                       *
*               A0 = ptr to format string                               *
*               A1 = ptr to first parameter                             *
*                                                                       *
*       Return:                                                         *
*               NONE                                                    *
*                                                                       *
*************************************************************************

fprintf::
        movem.l a2/a3/a6,-(sp)
        bra.s   pf1

*************************************************************************
*                                                                       *
*       printf - routine to call EXEC RawDoFmt to print to output       *
*                                                                       *
*       Parameters:                                                     *
*               A0 = ptr to format string                               *
*               A1 = ptr to first parameter                             *
*                                                                       *
*       Return:                                                         *
*               Write return code (modified by buffering scheme)        *
*                       -1 = ERROR .. Disk Full, Device not Avail, etc  *
*                            call IoErr() to find specific error        *
*                        0 = not defined                                *
*                        n = number of characters written               *
*                                                                       *
*       Notes:                                                          *
*               RawDoFmt requires 4 parameters:                         *
*                       A0 = ptr to format string                       *
*                       A1 = ptr to first parameter, stored in longword *
*                            format, with numbers actually stored, and  *
*                            pointers to strings stored instead of the  *
*                            strings themselves                         *
*                       A2 = ptr to routine to process characters as    *
*                            they are generated by RawDoFmt             *
*                       A3 = ptr to character buffer - convenient way   *
*                            to pass a parameter to the routine whose   *
*                            pointer is in A2                           *
*                                                                       *
*************************************************************************

printf::
        movem.l a2/a3/a6,-(sp)
        movem.l a0/a1,-(sp)             ; save parameters
        move.l  DOSBase,a6              ; get base of dos.library
        Call    Output                  ; find current output vector
        movem.l (sp)+,a0/a1             ; restore parameters
pf1:
        move.l  d0,outvect              ; save output vector
        move.l  _AbsExecBase,a6         ; get base of exec.library
        lea     store(pc),a2            ; put address of 'store' routine in A2
        lea     obuf,a3                 ; put address of buffer in A3
        clr.b   -1(a3)                  ; and clear character count
        Call    RawDoFmt                ; call "The Routine"
        move.l  oerr,d0                 ; check the error code
        bmi.s   1$                      ; real error?
        move.l  totlen,d0               ; Nope.  Get # characters written
1$:
        movem.l (sp)+,a2/a3/a6
        rts

*************************************************************************
*       store - the heart of the printf calls                           *
*                                                                       *
*       DESCRIPTION:                                                    *
*               This routine is called by the RawDoFmt routine to       *
*               process each character as it is generated.              *
*                                                                       *
*               Whereas I could have printed each character as it was   *
*               generated, the Amiga is VERY slow on single character   *
*               I/O, where it will print an entire line in about the    *
*               same time as it takes to print one character.           *
*                                                                       *
*       Parameters:                                                     *
*               RawDoFmt sends the character to process in D0.B, and    *
*               buffer pointer you sent it in A3 is passed through to   *
*               here unchanged, still in A3.                            *
*                                                                       *
*               When the RawDoFmt routine is through, it will send a    *
*               NULL ($00).                                             *
*                                                                       *
*       Return:                                                         *
*               NONE                                                    *
*                                                                       *
*       Notes:                                                          *
*               You cannot change ANY register, except A3!!!            *
*                                                                       *
*************************************************************************

store:
        movem.l d0-d7/a0-a6,-(sp)
        moveq   #0,d1                   ; clear high portion of count
        move.b  -1(a3),d1               ; move actual char count to low byte
        tst.b   d0                      ; NULL from RawDoFmt?
        beq.s   1$                      ; Yep, flush buffer & go home
        move.b  d0,0(a3,d1.W)           ; store character in buffer
        addq    #1,d1                   ; ...and add one to count
        cmpi.b  #80,d1                  ; buffer full?
        bne.s   3$                      ; no, go on
1$:
        tst.l   oerr                    ; have we hit an error before?
        bmi.s   2$                      ; yep, skip this attempt
        move.l  DOSBase,a6              ; get base of dos.library
        move.l  d1,d3                   ; put length in d3
        move.l  outvect,d1              ; put output handle in d1
        move.l  a3,d2                   ; and buffer address in d2
        Call    Write                   ; and write it out!
        move.l  d0,oerr                 ; store the return code
        bmi.s   2$                      ; was it a real error?
        add.l   d0,totlen               ; no, add to total chars written
2$:
        moveq   #0,d1                   ; null count
3$:
        move.b  d1,-1(a3)               ; store current count
        movem.l (sp)+,d0-d7/a0-a6
        rts


        BSS
DOSBase ds.l    1       ; storage for base address of 'dos.library'
outvect ds.l    1       ; storage for output vector for 'store' routine
totlen  ds.l    1       ; total number of characters written
oerr    ds.l    1       ; storage for return code from most recent 'Write'
olen    ds.b    1       ; current length of characters in output buffer
obuf    ds.b    80      ; output buffer

