home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG015.ARK
/
PRINT3.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
16KB
|
777 lines
;**************************************************;
;
; FILE PRINT UTILITY
;
; VERSION 1.3
;
; WRITTEN BY J. KRAVITZ
;
; COPYRIGHT (C) 1977
; BY INTELLECT ENTERPRISES
;
;--------------------------------------------------;
;
; CHANGE HISTORY
;
; 10/15/77 A.R.G COND. ASSM. FOR NON-
; FORM FEED HARDWARE
; 10/15/77 A.R.G COND. ASSM FOR OUTPUT TO
; CONSOLE OR PRINTER
; 11/10/77 J.K.K DIABLO HY-TYPE I DRIVER
; WITH HI SPEED MOVEMENT
; 11/17/77 J.K.K HANDLE IMBEDDED FORM FEED
; CHARACTERS IN FILE
; 11/17/77 J.K.K HANDLE 'N' AND 'C'
; PARAMETERS
; 11/17/77 J.K.K HANDLE '0' AND '2'
; PARAMETERS
; 11/17/77 J.K.K HANDLE PRINTING OF BACKSPACE
; IMBEDDED IN TEXT
;
;**************************************************;
;**************************************************;
;
; MISCELLANEOUS EQUATES
;
;**************************************************;
PAGSZ EQU 66 ;LINES/PAGE
MAXLN EQU 58 ;USABLE LINES/PAGE
NULLS EQU 12 ;NULLS AFTER A FORM FEED
BOOT EQU 0000H ;REBOOT ENTRY POINT
CPM EQU 0005H ;CPM ENTRY POINT
TBUF EQU 0080H ;TRANSIENT PROGRAM BUFFER
TFCB EQU 005CH ;TRANSIENT PROGRAM FCB
OPEN EQU 15 ;OPEN FUNCTION CODE
READ EQU 20 ;READ FUNCTION CODE
LF EQU 0AH ;<LF>
BS EQU 08H ;<BS>
FF EQU 0CH ;<FF>
CR EQU 0DH ;<CR>
TAB EQU 09H ;<TAB>
SPACE EQU 20H ;<SPACE>
RUBOUT EQU 7FH ;USED AS FF NULL. MAY CAUSE PROBLEM
;TO SOME PRINTERS
DIABLO EQU 0FFFFH ;SET TO 0FFFFH FOR DIABLO, 0 OTHERWISE
ODEV EQU 5 ;CON:=2 LST:=5
FORM EQU 0H ;SET 0FFFFH FOR 0CH <FF>
;SET 0 FOR <LF>'S TO PAGE TOP
;TO DEVICE THAT NEEDS LINE-FEEDS
;**************************************************;
;
; INITIALIZATION
;
;**************************************************;
ORG 100H
JMP PRINT
DB '/ PRINT UTILITY VERS. 1.3 /'
IF FORM AND (NOT DIABLO)
DB ' HARDWARE FF /'
ENDIF
IF NOT FORM AND (NOT DIABLO)
DB ' LF TO PAGE TOP /'
ENDIF
IF NOT ODEV-5 AND (NOT DIABLO)
DB ' OUT TO LST: /'
ENDIF
IF NOT ODEV-2 AND (NOT DIABLO)
DB ' OUT TO CON: /'
ENDIF
IF DIABLO
DB ' OUT TO DIABLO: '
ENDIF
;**************************************************;
;
; GET PARAMETERS FROM COMMAND LINE
;
;**************************************************;
PRINT: LXI SP,STACK
LXI H,TBUF ;POINT TO BUFFER
MOV B,M ;GET COUNT OF CHARACTERS IN CMD
MOV A,B ;GET COUNT AGAIN
ORA A ;TEST FOR ZERO
JZ PERR ;YES, NO ARGUMENTS
INX H ;SKIP COUNT
SKP1: MOV A,M ;GET BYTE
CPI ' ' ;SPACE?
JNZ SKP2 ;NO
INX H ;BUMP
DCR B ;DECRMENT COUNT
JNZ SKP1 ;SKIP TO FIRST NON-SPACE
JMP PERR ;NO, NON SPACE AFTER FILE ID
SKP2: MOV A,M ;GET CHAR
CPI ' ' ;SPACE?
JZ SKP3 ;YES
INX H ;BUMP POINTER
DCR B ;DECREMENT COUNT
JNZ SKP2 ;SKIP TO SPACE
JMP PEND ;NO SPACE AFTER FILE ID
SKP3: MOV A,M ;GET CHAR
CPI ' ' ;TEST FOR NON,SPACE
JNZ SKP4 ;FOUND ARGUMENTS
INX H ;BUMP POINTER
DCR B ;DECREMENT COUNT
JNZ SKP3
JMP PEND
SKP4: LXI D,PARMS
SKP4A: MOV A,M
STAX D
INX H
INX D
DCR B
JNZ SKP4A
MVI A,' '
STAX D ;INDICATE END OF PARMS
;**************************************************;
;
; PROCESS PARAMETERS
;
;**************************************************;
PPARM: LXI D,PARMS ;POINT TO PARMS AREA
PLP0: LXI H,PTAB ;POINT TO PARM TABLE
MVI B,PTABS ;SIIZE OF PARM TABLE
PLP1: LDAX D ;GET PARM BYTE
CPI ' ' ;END OF PARMS?
JZ PEND ;YES, DONE
CPI 00 ;END OF PARMS?
JZ PEND ;YES, DONE
CMP M ;COMPARE TO TABLE ENTRY
JZ PFND ;FOUND IT
INX H ;BUMP PARM TABLE PTR
INX H
INX H
DCR B ;DECREMENT COUNT
JNZ PLP1 ;KEEP LOOKING
PERR: LXI D,PERMSG ;POINT TO PARM ERROR MSG
MVI C,09 ;WRITE MSG
CALL CPM
JMP BOOT ;EXIT
PFND: INX H ;POINT TO ROUTINE ADDR
PUSH D ;SAVE PARM POINTER
MOV E,M
INX H
MOV D,M ;GET ROUTINE ADDR
LXI H,PRET ;RETURN ADDRESS
PUSH H ;SIMULATE CALL
XCHG ;GET ROUTINE ADDR
PCHL ;EXIT TO PARM PROC. ROUTINE
PRET: POP D ;GET PARM POINTER AGAIN
INX D ;POINT TO NEXT ONE
JMP PLP0 ;CONTINUE
;**************************************************;
;
; PARAMETER PROCESSING ROUTINES
;
;**************************************************;
NPARM: MVI A,0FFH ;SET 'NO HEADING' SWITCH
STA NSWT
RET
CPARM: MVI A,0FFH ;SET 'NO PAGINATION' SWITCH
STA CSWT
RET
TENP: LXI H,0006 ;SET TEN PITCH
SHLD CHRINC
RET
TWELVEP:
LXI H,0005 ;SET 12 PITCH
SHLD CHRINC
RET
;**************************************************;
;
; OPEN FILE FOR INPUT
;
;**************************************************;
PEND: LXI D,TFCB ;POINT TO FCB
CALL FOPEN ;OPEN FILE
JC ERR ;IF ERROR, EXIT
IF DIABLO
CALL RSTR ;RESTORE THE PRINTER
ENDIF
IF FORM AND (NOT DIABLO)
CALL TPAGE ;POSITION AT TOP OF PAGE
CALL HEAD ;PRINT HEADING
ENDIF
IF (NOT FORM) OR DIABLO
;IF NO HARDWARE FF, ASSUME
;PAPER IS IN POSITION
CALL HEAD ;PRINT HEADING
ENDIF
;**************************************************;
;
; MAIN PROCESSING LOOP
;
;**************************************************;
LOOP: CALL GETBT ;GET A BYTE
JC ERR ;ERROR
CPI 1AH ;EOF?
JZ DONE ;YES
CPI CR ;CR?
JZ CRET ;YES
CPI LF ;LF?
JZ LFEED ;YES
CPI TAB ;TAB?
JZ TABMOV ;YES
CPI FF ;FORM FEED?
JZ FFEED ;YES
CPI BS ;BACKSPACE
JZ BSPACE ;YES
CPI SPACE ;ODD CONTROL CHR?
JC LOOP ;YES, IGNORE IT
CALL PBYT ;OTHERWISE PRINT IT
JMP LOOP ;CONTINUE
;*************************************************;
;
; FINAL PROCESSING
;
;*************************************************;
DONE: CALL TPAGE ;MOVE TO TOP OF PAGE
JMP BOOT ;EXIT TO CPM
;**************************************************;
;
; PROCESS TABS
;
;**************************************************;
TABMOV: LXI H,COL ;POINT TO COLUMN
TBLP: MVI A,SPACE ;PRINT ONE SPACE
CALL PBYT
MOV A,M ;GET COLUMN
ANI 07H ;MODULO 8
JNZ TBLP ;IF NOT AT TAB STOP, KEEP TYPEIN
JMP LOOP
CALL PBYT ;PRINT BYTE
JMP LOOP
;**************************************************;
;
; PROCESS <CR>
;
;**************************************************;
CRET: XRA A
STA COL
MVI A,CR
CALL PBYT ;PRINT <CR>
JMP LOOP ;CONTINUE IN MAIN LOOP
;**************************************************;
;
; PROCESS <LF>
;
;**************************************************;
LFEED: LDA CSWT ;GET PAGINATION SWITCH
ORA A ;SEE IF 'NO PAGINATION'
JNZ LFEED2 ;TRUE, SKIP PAGINATION TEST
LDA LINE ;GET LINE COUNT
CPI MAXLN ;PAGE OVERFLOW?
JZ FFEED ;YES
LFEED2: LDA LINE ;GET LINE COUNT
INR A ;BUMP LINE COUNT
STA LINE
MVI A,LF
CALL PBYT
JMP LOOP
;**************************************************;
;
; PROCESS <BS>
;
;**************************************************;
BSPACE: MVI A,BS
CALL PBYT
LDA COL ;GET COLUMN COUNTER
ORA A ;IF ZERO, DONT DECREMENT IT
JZ LOOP
DCR A
STA COL ;DECREMENT COLUMN COUNT
JMP LOOP
;**************************************************;
;
; PROCESS FORM FEED
;
;**************************************************;
FFEED: MVI A,CR
CALL PBYT ;PRINT CR
CALL TPAGE ;POSITION AT TOP OF PAGE
CALL HEAD ;PRINT HEADING
JMP LOOP ;CONTINUE IN MAIN LOOP
;**************************************************;
;
; HEADING PRINT ROUTINE
;
;**************************************************;
HEAD: LDA NSWT ;NO HEADING SWITCH
ORA A ;IF SET, NO HEADING
JNZ HEADA
LXI H,FMSG ;POINT TO MESSAGE
CALL PSTRNG ;PRINT STRING
LXI H,TFCB+1;POINT TO NAME
MVI B,8 ;SIZE OF NAME
CALL PCNT ;PRINT COUNT
MVI A,SPACE ;PRINT A SPACE
CALL PBYT
LXI H,TFCB+9;POINT TO TYPE
MVI B,03 ;SIZE OF TYPE
CALL PCNT ;PRINT COUNT
LXI H,PMSG ;POINT TO MESSAGE
CALL PSTRNG ;PRINT STRING
LDA PAGE ;GET PAGE NUMBER
INR A ;BUMP IT
STA PAGE ;SAVE IT
CALL DEC ;CONVERT TO DECIMAL
LXI H,DECWRK;POINT TO DEC STRING
MVI B,3
CALL PCNT ;PRINT PAGE NUMBER
MVI A,CR ;PRINT CR
CALL PBYT
MVI A,LF
CALL PBYT ;PRINT LF
MVI A,LF
CALL PBYT ;AND SECOND
MVI A,LF
CALL PBYT ;AND A THIRD
MVI A,3 ;SET NUMBER OF LINES PRINTED
JMP HEADB
HEADA: XRA A
HEADB: STA LINE ;RESET LINE COUNT
XRA A ;RESET COLUMN
STA COL ;RESET COLUMN
RET
;**************************************************;
;
; CHARACTER PRINT ROUTINE
;
;**************************************************;
PBYT: PUSH H
PUSH B
PUSH PSW
IF NOT DIABLO
MOV E,A
MVI C,ODEV
CALL CPM ;PRINT
ENDIF
IF DIABLO
CALL DDVR
ENDIF
POP PSW
CPI SPACE ;NON-PRINTING?
JC PBY2 ;YES, DONT BUMP COL
LXI H,COL ;INCREMENT COLUMN
INR M
PBY2: MVI C,11 ;GET CONSOLE STATUS
CALL CPM
CPI 00 ;BREAK?
JNZ BOOT ;YES, DONE
POP B
POP H
RET
;**************************************************;
;
; STRING PRINT ROUTINE
;
;**************************************************;
PSTRNG: MOV A,M ;GET BYTE
CPI '$' ;STRING END?
RZ ;YES, DONE
CALL PBYT ;PRINT BYTE
INX H ;BUMP POINTER
JMP PSTRNG ;LOOP
;**************************************************;
;
; STRING PRINT ROUTINE (COUNT IN B)
;
;**************************************************;
PCNT: MOV A,M ;GET BYTE
CALL PBYT ;PRINT IT
INX H ;BUMP POINTER
DCR B ;DECREMENT COUNT
JNZ PCNT
RET
;**************************************************;
;
; DECIMAL OUTPUT ROUTINE
;
;**************************************************;
DEC: LXI H,DECWRK
MVI C,100
CALL DIGIT
MVI C,10
CALL DIGIT
MVI C,1
CALL DIGIT
RET
DIGIT: MVI M,'0'
DI0: SUB C
JM DI1
INR M
JMP DI0
DI1: ADD C
INX H
RET
;**************************************************;
;
; TOP OF PAGE ROUTINE
;
;**************************************************;
IF FORM AND (NOT DIABLO)
TPAGE: MVI A,FF ;ISSUE FORM FEED
CALL PBYT
MVI B,NULLS ;NUMBER OF NULLS
TPAGE2: MVI A,RUBOUT
CALL PBYT
DCR B ;PRINT N RUBOUTS
JNZ TPAGE2
RET
ENDIF
IF (NOT FORM) OR DIABLO
TPAGE: LXI H,LINE ;POINT TO CURRENT LINE
MVI A,PAGSZ
SUB M ;LINES LEFT TO PRINT
MOV B,A
TLP2: MVI A,LF ;<LF>
CALL PBYT
DCR B ;DCREMENT COUNT
JNZ TLP2 ;PRINT 'N' LINES TO PAGE TOP
CALL PBYT ;ONE MORE TO TOP OF PAGE
RET
ENDIF
;**************************************************;
;
; I/O ERROR MESSAGE ROUTINE
;
;**************************************************;
ERR: LXI D,ERMSG
MVI C,09H ;WRITE MSG
CALL CPM
JMP BOOT
;**************************************************;
;
; F O P E N
; ROUTINE TO OPEN A DISK FILE
;
; INPUT: DE=A(FCB)
; OUTPUT: CARRY=ERROR
;
;**************************************************;
FOPEN: MVI C,OPEN ;OPEN CODE
CALL CPM ;ISSUE OPEN
CPI 0FFH ;ERROR?
JZ FOERR ;YES
XRA A ;CLEAR CARRY
RET
FOERR: STC
RET
;**************************************************;
;
; G E T B T
; ROUTINE TO READ A BYTE
;
; OUTPUTS: A=BYTE
; CARRY=ERROR
;
;**************************************************;
GETBT: LXI H,TBUF+128
XCHG ;BUFFER END ADDR. IN DE
LHLD INPTR ;CURRENT POINTER IN HL
CALL CPHL ;TEST FOR END OF BUFFER
JZ GETB2 ;YES, READ
GETB1: MOV A,M ;GET BYTE
INX H ;BUMP POINTER
SHLD INPTR ;SAVE POINTER
ORA A ;RESET CARRY
RET
GETB2: MVI C,READ ;READ CODE
LXI D,TFCB ;FCB ADDRESS
CALL CPM ;ISSUE READ
CPI 00 ;ERROR?
JNZ IERR ;YES
LXI H,TBUF ;RESET BUFFER POINTER
SHLD INPTR
JMP GETB1 ;CONTINUE
IERR: STC
RET
;**************************************************;
;
; MISCELLANEOUS SUBROUTINES
;
;**************************************************;
;**************************************************;
;
; C P H L
; COMPARE HL VS DE
;
;**************************************************;
CPHL: MOV A,H
CMP D
RNZ
MOV A,L
CMP E
RET
;**************************************************;
;
; DIABLO DRIVER FOR N.Y. INTERFACE BOARD
; WITH HI SPEED TABBING FUNCTION
;
;**************************************************;
IF DIABLO
DDVR: PUSH PSW ;SAVE PSW
PUSH B ;SAVE BC
PUSH D ;SAVE DE
PUSH H ;SAVE HL
CPI 0DH ;CR?
JZ PCR ;YES
CPI 0AH ;LINE FEED?
JZ PLF ;YES
CPI 08H ;BACKSPACE?
JZ PBS ;YES
CPI 20H ;OTHER CONTROL?
JC DXIT ;YES, IGNORE
JZ PSP ;SPACE
CPI 7FH
JC PCH ;CONTINUE IF ASCII
DXIT: POP H
POP D
POP B
POP PSW ;EXIT TO CALLER
RET
PCH: PUSH PSW ;SAVE CHAR
CALL CKMOV ;TEST FOR SAVED MOVE
POP PSW ;RESTORE CHAR
STA DLOW ;SAVE CHAR
MVI A,0
STA DHIGH ;CLEAR DATA HIGH
MVI B,CHRDY ;TEST FOR CHAR READY
CALL CKSTT ;CALL STATUS CHECK
CALL OUT16 ;OUTPUT 16 BITS TO DIABLO
OUT CHSTB ;OUTPUT CHARACTER STROBE
OUT CHSTB ;AND AGAIN FOR Z-80
JMP PSP
PCR: LHLD CLOC ;GET CURRENT LOCATION
MOV A,H
ORI 04H ;SET REVERSE DIRECTION BIT
MOV H,A ;SET DIRECTION
CALL CMOVE ;RETURN CARRIAGE
LXI H,0000 ;ZERO CLOC
SHLD CLOC
SHLD SPCNT ;ZERO SPACE COUNT
JMP DXIT ;EXIT TO CALLER
PLF: CALL CKMOV ;CHECK FOR PREVIOUS MOVE
LHLD LININC ;GET LINE INCREMENTS
CALL PMOVE
JMP DXIT ;RETURN TO CALLER
PSP: LHLD SPCNT ;GET SPACE COUNT
XCHG ;INTO DE
LHLD CHRINC ;GET CHARACTER INCREMENT
DAD D ;ADD TO CURRENT SPACE COUNT
SHLD SPCNT ;SAVE IT
JMP DXIT ;DONE
PBS: CALL CKMOV ;CHECK FOR PREVIOUS MOVE
LHLD CLOC ;CURRENT LOCATION
XCHG
LHLD CHRINC ;GET SINGLE CHARACTER SIZE
XCHG
CALL CPHL
JC DXIT ;IF CLOC<CHRINC IGNORE BACKSPACE
PBS2: LHLD CHRINC
MOV A,H
ORI 04H ;SET REVERSE DIRECTION
MOV H,A
CALL CMOVE ;MOVE CARRIAGE
LHLD CHRINC ;CHARACTER INCREMENT
XCHG
LHLD CLOC ;CURRENT LOCATION
MOV A,L
SUB E ;SUBTRACT CHRINC FROM CLOC
MOV L,A
MOV A,H
SBB D
MOV H,A
SHLD CLOC
JMP DXIT
CKMOV: LHLD SPCNT ;TEST FOR NON ZERO SPACE COUNT
MOV A,H
ORA L
RZ ;ZERO, IGNORE
CALL CMOVE ;NON ZERO, MOVE CARRIAGE
LHLD SPCNT
XCHG
LHLD CLOC
DAD D
SHLD CLOC ;UPDATE CARRIAGE LOCATION
LXI H,0000
SHLD SPCNT ;ZERO THE SPACE COUNT
RET
CKSTT: IN DSTAT ;GET DIABLO STATUS
CMA
ANA B ;TEST STATUS
JZ CKSTT ;LOOP TILL READY
RET
CMOVE: SHLD DLOW ;SAVE DATA
MVI B,CMRDY
CALL CKSTT
CALL OUT16 ;SEND 16 BITS TO DIABLO
OUT CMSTB ;CARRIAGE MOVEMENT STROBE
RET
PMOVE: SHLD DLOW
MVI B,PMRDY ;TEST PAPER MOVEMENT STATUS
CALL CKSTT
CALL OUT16 ;OUTPUT 16 BITS TO DIABLO
OUT PMSTB ;PAPER MOVEMENT STROBE
RET
OUT16: LDA DLOW ;GET LOW ORDER DATA BYTE
RAL ;ROTATE TO POSITION BITS
OUT DALOW ;OUTPUT TO DATA LOW PORT
OUT DALOW ;AND AGAIN
LDA DHIGH ;GET HIGH ORDER BYTE
RAL ;ROTATE
OUT DAHIGH
OUT DAHIGH ;AND AGAIN
RET
RSTR: OUT RSSTB ;OUTPUT TO RESTORE STROBE
LXI H,0000
SHLD CLOC ;ZERO CURRENT CARRIAGE LOC
SHLD SPCNT ;ZERO SPACE COUNTER
RET
DLOW: DB 0
DHIGH: DB 0
CLOC: DW 0000
SPCNT: DW 0000
CHRINC: DW 0006 ;TEN PITCH
LININC: DW 0008 ;6 LINES PER INCH
DSTAT: EQU 20H
DALOW: EQU 20H
DAHIGH: EQU 21H
CHSTB EQU 22H
CMSTB EQU 23H
PMSTB EQU 24H
RSSTB: EQU 25H
CHRDY EQU 01H
CMRDY EQU 02H
PMRDY EQU 04H
ENDIF
;**************************************************;
;
; D A T A
;
;**************************************************;
NSWT: DB 00 ;NO HEADING SWITCH
CSWT: DB 00 ;NO PAGINATION SWITCH
INPTR: DW TBUF+128 ;INPUT POINTER
DECWRK: DB '000' ;DECIMAL WORK AREA
COL: DB 0 ;COLUMN COUNTER
LINE: DB 0 ;LINE COUNTER
PAGE: DB 0 ;PAGE COUNTER
FMSG: DB CR,'FILE: $'
PMSG: DB ' PAGE $'
PERMSG: DB 'PARAMETER ERROR',0DH,0AH,'$'
ERMSG: DB 'ERROR',0DH,0AH,'$'
PARMS: DS 16 ;PARAMETER STORAGE AREA
;**************************************************;
;
; PARAMETER PROCESSING TABLE
;
; ENTRIES ARE 3 BYTES WIDE
;
; BYTE 1 = PARAMETER BYTE
;
; BYTES 2,3 = ROUTINE ADDRESS
;
;**************************************************;
PTAB: DB 'N'
DW NPARM
DB 'C'
DW CPARM
DB '0'
DW TENP
DB '2'
DW TWELVEP
PTABS EQU ($-PTAB)/3
DS 32
STACK EQU $
END PRINT