;********************************************************
;* *
;* FILE SCREEN PAGING UTILITY *
;* *
;********************************************************
;
; By: Bill Bolton
; Software Tools,
; P.O. Box 80,
; Newport Beach,
; NSW, 2106,
; AUSTRALIA
;
; Date: July 1, 1980 Version 1.0
;
; August 17, 1980 Version 1.1, modified to require a
; different key to abort from that
; pressed to advance to next page,
; for those poor folks with bouncy
; keyboards. Released concurrently
; with version 1.0
;
; Version: 1.1
;
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
STA LAST$KEY ;SAVE FOR LATER
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:
CALL KEY
CPI 0 ;KEY PRESSED?
CNZ CHECK$EXIT ;YES, CHECK IF EXIT NEEDED
POP B ;RESTORE THE
POP H ; ENVIRONMENT
RET
;
CHECK$EXIT:
LXI H,LAST$KEY ;POINT TO LAST KEY PRESSED
CMP M ;SAME?
RZ ;YES, DONT QUIT
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.1 '
DB '(C) Bill Bolton, Software Tools, August 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
LAST$KEY:
DB 0 ;LAST KEY HIT
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