;
;  PROGRAM:  SYSTEST
;  AUTHOR:  Richard Conn
;  PURPOSE:  This program dumps the disk file specified by the user
;               in hexadecimal and ASCII
;  NOTE:  This test demonstrates the use of the SYSLIB Byte-Oriented
;               File Input routines
;

;  External CP/M Buffers
fcb     equ     5ch     ; address of FCB filled in by CP/M's CCP (or ZCPR2)

;  External References for SYSLIB routines used
       ext     fi1$open        ; Open File for Byte-Oriented Input
       ext     fi1$close       ; Close File
       ext     f1$get          ; Get Byte from File
       ext     cout            ; Character Output
       ext     pa2hc           ; Print A as 2 Hex Chars
       ext     phldc           ; Print HL as up to 5 decimal digits
       ext     print           ; String Print
       ext     crlf            ; New Line

;
;  Start of Routine -- Print Banner
;
       call    print
       db      'SYSTEST - Sample DUMP Program to Illustrate SYSLIB '
       db      'Byte-Oriented File Input'
       db      0
       call    crlf    ; new line

;
;  Set Offset Counter
;
       lxi     h,0     ; Init to zero
       shld    counter

;
;  Open File for Input
;
       lxi     d,fcb   ; pt to FCB filled in by Operating System
       call    fi1$open        ; try to open it
       jz      loop    ; continue if OK
       call    print   ; not ok, so file must not have been found
       db      'File Not Found',0
       ret             ; return to Operating System

;
;  Main Loop
;
loop:
       lhld    counter ; get counter value
       call    phldc   ; print as decimal number
       lxi     d,16    ; add 16 to counter for next print
       dad     d
       shld    counter ; save count away
       call    print
       db      ': ',0
       mvi     b,0     ; set byte count to zero
       lxi     h,buffer        ; point to first byte of buffer
readlp:
       call    f1$get  ; get next byte
       jnz     readdn  ; done if past EOF
       mov     m,a     ; store byte into buffer
       inx     h       ; point to next byte in buffer
       inr     b       ; increment byte count
       mov     a,b     ; check for done
       cpi     16      ; read in 16 bytes?
       jnz     readlp
       call    bufprint        ; print contents of buffer
       call    crlf    ; new line
       jmp     loop    ; continue until End of File

;
;  Done with Read -- Print current Buffer and Exit
;  B = Number of bytes to print
;
readdn:
       call    bufprint        ; print buffer
       call    crlf            ; new line
       call    fi1$close       ; close file
       ret

;
;  Buffer print routine; print the contents of the buffer for B bytes
;
bufprint:
       lxi     h,buffer        ; point to first byte of buffer
       push    b       ; save character count
bufploop:
       mov     a,b     ; check count first (in case it is zero)
       ora     a       ; done?
       jz      ascprint        ; print as ASCII chars if done
       dcr     b       ; count down
       mov     a,m     ; get byte from buffer
       inx     h       ; point to next byte in buffer
       call    pa2hc   ; print byte as 2 Hex chars
       mvi     a,' '   ; print a space
       call    cout
       jmp     bufploop
;  Now print buffer as ASCII characters
ascprint:
       lxi     h,buffer        ; point to first character
       pop     b       ; get character count
       call    print   ; print a separator
       db      '! ',0
ascploop:
       mov     a,b     ; check for empty buffer
       ora     a       ; done if zero
       rz              ; return to caller if so
       dcr     b       ; count down
       mov     a,m     ; get byte to output
       ani     7fh     ; mask out most significant bit
       mov     c,a     ; save character in C
       cpi     ' '     ; test for printable character
       jnc     ascp    ; print character if printable
       mvi     c,'.'   ; print dot if not printable character
ascp:
       mov     a,c     ; get char to print
       call    cout    ; print it
       inx     h       ; point to next character
       jmp     ascploop        ; continue until count is exhausted

counter:
       ds      2       ; Offset Counter
buffer:
       ds      16      ; 16-byte buffer for input bytes

       end