;********************************************************
;*                                                      *
;*          FILE SCREEN PAGING UTILITY                  *
;*                                                      *
;********************************************************
;
;       Copyright (C) 1980
;
;       By:     Bill Bolton
;               Software Tools,
;               P.O. Box 80,
;               Newport Beach,
;               NSW, 2106,
;               AUSTRALIA
;
;       Date:   July 1, 1980
;
;       Version: 1.0
;
TITLE   ;YOU CAN'T ASSEMBLE THIS WITH MAC, USE ASM.COM
;
REVERSE EQU     0               ;NON ZERO FOR ADM-31 REVERSE VIDEO
PAGE    EQU     23              ;LINES/PAGE
WIDTH   EQU     79              ;CHARACTERS/LINE
WBOOT   EQU     0000H           ;REBOOT ENTRY POINT
BDOS    EQU     0005H           ;CPM ENTRY POINT
BUFFER  EQU     0080H           ;TRANSIENT PROGRAM BUFFER
TFCB    EQU     005CH           ;TRANSIENT PROGRAM FCB
DIRECT  EQU     6               ;DIRECT CONSOLE FUNCTION
STRING  EQU     9               ;STRING PRINT FUNCTION
STATUS  EQU     11              ;CONSOLE STATUS FUNCTION
VERSION EQU     12              ;VERSION NUMBER FUNCTION
OPEN    EQU     15              ;OPEN FUNCTION CODE
READ    EQU     20              ;READ FUNCTION CODE
CREAD   EQU     0FFH            ;DIRECT CONSOLE INPUT
TAB     EQU     009H            ;ASCII TAB
ALF     EQU     00AH            ;ASCII LINE FEED
ACR     EQU     00DH            ;ASCII CARRIAGE RETURN
ESC     EQU     01BH            ;ASCII ESCAPE
SPACE   EQU     020H            ;ASCII SPACE
DEVICE  EQU     2               ;CP/M CONSOLE
;
;
       ORG     100H
;
START:
       LXI     SP,STAKTOP      ;SET UP THE STACK
       MVI     C,VERSION       ;CP/M VERSION FUNCTION
       CALL    BDOS
       MOV     A,L             ;GET VERSION NUMBER
       CPI     20H             ;>=VERSION 2.0?
       JC      ERROR3          ;NO, EXIT
       LXI     D,TFCB          ;POINT TO FCB
       CALL    FOPEN           ;OPEN FILE
       JC      ERROR1          ;IF ERROR, EXIT
       CALL    RESET
LOOP:
       CALL    FETCH$BYTE      ;GET NEXT BYTE FROM FILE
       JC      ERROR2          ;EXIT IF ERROR
       CPI     1AH             ;EOF?
       JZ      EXIT            ;YES, EXIT
       CPI     ACR             ;CR?
       JZ      CRET            ;YES, UPDATE COLUMN COUNT
       CPI     ALF             ;LF?
       JZ      LFEED           ;YES, UPDATE LINE COUNT
       CPI     TAB             ;TAB?
       JZ      TABMOV          ;YES, DO IT
       CPI     SPACE           ;ANOTHER CONTROL CHARACTER?
       JNC     DISPLAY         ;NO, PRINT CHACTER
       JMP     LOOP            ;YES, IGNORE IT
;
TABMOV:
       LXI     H,COL           ;POINT TO COLUMN
TABLOOP:
       MVI     A,SPACE         ;GET A SPACE
       CALL    DBYTE           ;DISPLAY IT
       MOV     A,M             ;GET CURRENT COLUMN
       ANI     07H             ;MOD 8, AT TAB STOP?
       JNZ     TABLOOP         ;NO, ANOTHER SPACE
       JMP     LOOP
;
DISPLAY:
       CALL    DBYTE           ;DISPLAY THE CHARACTER
       JMP     LOOP
;
CRET:
       XRA     A
       STA     COL             ;RESET COLUMN COUNT
       MVI     A,ACR           ;GET A CARRIAGE RETURN
       JMP     DISPLAY
;
LFEED:
       LDA     LINE            ;GET LINE COUNT
       CPI     PAGE            ;SCREEN FULL?
       JZ      NEXTPAGE        ;YES, WAIT FOR KEYPRESS
       INR     A               ;NO, BUMP LINE COUNT
       STA     LINE            ;SAVE NEW LINE COUNT
       MVI     A,ALF           ;GET A LINE FEED
       JMP     DISPLAY
;
NEXTPAGE:
       CALL    KEYLOOP         ;WAIT FOR KEYPRESS
       MVI     A,ALF           ;GET A LINE FEED
       JMP     DISPLAY
;
KEYLOOP:
       CALL    KEY             ;CHECK CONSOLE
       CPI     0               ;KEY PRESSED ?
       JZ      KEYLOOP         ;NO, WAIT FOR KEYPRESS
       CALL    RESET           ;RESET COUNTERS
       RET
;
KEY:
       PUSH    H               ;SAVE
       PUSH    D               ;  THE
       PUSH    B               ;    ENVIRONMENT
       MVI     C,DIRECT        ;DIRECT CONSOLE FUNCTION6
       MVI     E,CREAD         ;CONSOLE INPUT
       CALL    BDOS
       POP     B               ;RESTORE
       POP     D               ;  THE
       POP     H               ;    ENVIRONMENT
       RET
;
RESET:
       XRA     A
       STA     LINE            ;RESET LINE COUNT
       STA     COL             ;RESET COLUMN COUNT
       RET
;
DBYTE:
       PUSH    H               ;SAVE THE
       PUSH    B               ;  ENVIRONMENT
       PUSH    PSW             ;SAVE THE CHARACTER
       MOV     E,A             ;COPY THE CHARACTER
       MVI     C,DEVICE        ;GET FUNCTION
       CALL    BDOS
       POP     PSW             ;RESTORE THE CHARACTER
       CPI     SPACE           ;IS A CR OR LF?
       JC      CONT            ;YES, DONT BUMP COLUMN COUNT
       LXI     H,COL           ;GET COLUMN COUNT
       INR     M               ;BUMP IT
       MOV     A,M             ;GET NEW COLUMN COUNT
       CPI     WIDTH           ;AT THE END OF A LINE?
       JNZ     CONT            ;NO
       MVI     A,ACR           ;GET A CARRIAGE RETURN
       CALL    DBYTE           ;SEND IT
       LDA     LINE            ;GET LINE NUMBER
       CPI     PAGE            ;AT END OF PAGE
       JNZ     CONT2           ;NO, DO LINE FEED
       CALL    KEYLOOP         ;WAIT FOR KEYPRESS
CONT2:
       MVI     A,ALF           ;GET A LINE FEED
       CALL    DBYTE
       LDA     LINE            ;GET THE LINE COUNT
       INR     A               ;BUMP IT
       STA     LINE            ;SAVE THE LINE COUNT
CONT:
       MVI     C,STATUS        ;CONSOLE STATUS FUNCTION
       CALL    BDOS
       CPI     0               ;KEY PRESSED?
       JNZ     DONE            ;YES, EXIT
       POP     B               ;RESTORE THE
       POP     H               ;  ENVIRONMENT
       RET
;
DONE:
       JMP     WBOOT           ;QUIT
;
EXIT:
       LXI     D,MESSG4        ;POINT TO EOF MESSAGE
       JMP     MESSAGE
;
ERROR3:
       LXI     D,MESSG3        ;POINT TO VERSION MESSAGE
       JMP     MESSAGE
;
ERROR2:
       LXI     D,MESSG2        ;POINT TO READ MESSAGE
       JMP     MESSAGE
;
ERROR1:
       LXI     D,MESSG1        ;POINT TO OPEN MESSAGE
MESSAGE:
       MVI     C,STRING        ;DISPLAY THE MESSAGE
       CALL    BDOS
       JMP     WBOOT
;
       DB      'FILE PAGE UTILITY, VERSION 1.0 '
       DB      '(C) Bill Bolton, Software Tools, June 1980'
;
;****************************************************************
;*                                                              *
;*              ROUTINE TO OPEN A DISK FILE                     *
;*                                                              *
;****************************************************************
;
FOPEN:                          ;DE POINTS TO A FCB
       MVI     C,OPEN          ;FILE OPEN FUNCTION
       CALL    BDOS
       CPI     0FFH            ;OPEN FILE  ERROR?
       JZ      OPENERR         ;YES, EXIT
       XRA     A               ;CLEAR CARRY
       RET
OPENERR:
       STC                     ;SET CARRY
       RET
;
;
;****************************************************************
;*                                                              *
;*               ROUTINE TO READ A BYTE                         *
;*                                                              *
;****************************************************************
;
FETCH$BYTE:
       LXI     H,BUFFER+128
       XCHG                    ;BUFFER END ADDRESS IN DE
       LHLD    POINTER         ;CURRENT POINTER IN HL
       MOV     A,H             ;END OF BUFFER?
       CMP     D
       JNZ     NEXT$CHAR       ;NO, GET ANOTHER CHARACTER
       MOV     A,L
       CMP     E
       JZ      NEXT$BLOCK      ;YES, READ ANOTHER BLOCK
NEXT$CHAR:
       MOV     A,M             ;GET CHARACTER
       INX     H               ;BUMP POINTER
       SHLD    POINTER         ;SAVE POINTER
       ORA     A               ;RESET CARRY
       RET
;
NEXT$BLOCK:
       MVI     C,READ          ;READ FUNCTION
       LXI     D,TFCB          ;FCB ADDRESS
       CALL    BDOS
       CPI     0               ;ERROR?
       JNZ     INERROR         ;YES, EXIT
       LXI     H,BUFFER        ;RESET BUFFER POINTER
       SHLD    POINTER
       JMP     NEXT$CHAR       ;CONTINUE
;
INERROR:
       STC                     ;SET CARRY
       RET
;
;
COL:
       DB      0               ;COLUMN COUNTER
LINE:
       DB      0               ;LINE COUNTER
POINTER:
DW      BUFFER+128      ;INPUT POINTER
;
MESSG1:
       DB      '**** '
       if      REVERSE
       DB      ESC,'G4'
       endif
       DB      'File Open Error'
       if      REVERSE
       DB      ESC,'G0'
       endif
       DB      ' ****'
       DB      ACR,ALF,'$'
;
MESSG2:
       DB      '**** '
       if      REVERSE
       DB      ESC,'G4'
       endif
       DB      'File Read Error'
       if      REVERSE
       DB      ESC,'G0'
       endif
       DB      ' ****'
       DB      ACR,ALF,'$'
;
MESSG3:
       DB      TAB,'Sorry, you need CP/M Version'
       DB      ' 2.0 or later to run PAGE !'
       DB      '$'
;
MESSG4:
       if      REVERSE
       DB      ESC,'G4'
       endif
       DB      ' End of Input File Reached '
       if      REVERSE
       DB      ESC,'G0'
       endif
       DB      '$'
;
STACK:
       DS      40
STAKTOP EQU     $
;
       END     START