;   
;    THIS PROGRAM READS FROM HOST COMPUTER AND  
;     WRITES DISK FILE. 
;   TO RUN ENTER:   
;     TRANSFER   FILE.EXT   
;   
;   I/O PARAMETERS  
;   
MDATA   EQU     51H           ; MODEM DATA PORT 
MSTAT   EQU     50H           ; MODEM STATUS PORT   
MRDA    EQU     40H           ; MODEM INPUT STATUS BIT  
MTBE    EQU     80H           ; MODEM OUTPUT STATUS BIT 
;   
LINES	EQU	24		; NUMBER OF LINES
WIDTH	EQU	80		; NUMBER OF COLUMNS
TOP	EQU	0E000H		; TOP OF TV SCREEN
WORDS	EQU	TOP+LINES*WIDTH	; END OF SCREEN
WORDLO	EQU	WORDS AND 0FFH	; LOW ORDER OF END OF SCREEN
;
CRTL	EQU	TOP+3*WIDTH	;
CRTS    EQU     CRTL+WIDTH  
CRTB    EQU     CRTS+WIDTH  
CR      EQU     0DH           ; CHARRIAGE RETURN
LF      EQU     0AH           ; LINE FEED   
;   CP/M PARAMETERS 
;   
READC   EQU     1             ; READ CHAR FROM CONSOLE  
WRITC   EQU     2             ; WRITE CHAR ON CONSOLE   
IOSTAT  EQU     7             ; CHECK KEY STATUS
READB   EQU     10            ; READ A BUFFER   
OMSG    EQU     9             ; PRINT I/O MESSAGE   
INITD   EQU     13            ; INITIALIZE DISK A (SET DMA=80H) 
SELDSK  EQU     14            ; SELECT DISK 
OPENF   EQU     15            ; OPEN FILE   
CLOSE   EQU     16            ; CLOSE FILE  
SEARCH  EQU     17            ; SEARCH FOR FILE 
SRCHN   EQU     18            ; SEARCH FOR NEXT FILE
DELET   EQU     19            ; DELETE FILE 
RNEXT   EQU     20            ; READ NEXT FILE  
WNEXT   EQU     21            ; WRITE NEXT FILE 
MAKEF   EQU     22            ; MAKE DIRECTORY ENTRY
RENAM   EQU     23            ; RENAME FILE 
SETDMA  EQU     26            ; SET DMA ADDRESS 
;   
;  DISK I/O MASTER PACKAGE  
;   
BDOS    EQU     5             ; ADDRESS OF BDOS 
CPM     EQU     0             ; CP-M RETURN ADDRESS 
;   
; FILE CONTROL BLOCK
FCB     EQU     5CH 
FCBDN   EQU     FCB 
FCBFN   EQU     FCB+1   
FCBFT   EQU     FCB+9         ; FILE TYPE   
FCBRL   EQU     FCB+12        ; CURRENT REEL NUMBER OF FILE 
FCBRC   EQU     FCB+15        ; FILES'S CURRENT RECORD NO   
FCBCR   EQU     FCB+32        ; FILES'S RECORD COUNT 0 TO 128)  
FCBLN   EQU     FCB+33        ; FCB LENGTH  
;   
BUFF    EQU     80H           ; INPUT BUFFER
;   
;       READ THE FILE   
;   
        ORG     100H
XFER:                         ; SET LAST CHARACTER FLAG TO 0
        LXI     H,TOP
CRTBL:  MVI     M,' '   
        INX     H   
        MOV     A,H 
	CPI	WORDS SHR 8	; CHECK FOR END OF SCREEN
	JNZ	CRTBL
	MOV	A,L
	CPI	WORDLO
	JNZ	CRTBL
;   OUTPUT TRANSFER MESSAGE 
        JNZ     CRTBL   
        LXI     B,TOP+2*WIDTH
        LXI     H,YMSG  
        CALL    ZMSG
;   
        LDA     FCBFN         ; WAS FILE NAME ENTERED?  
        CPI     ' ' 
        JZ      ERR0
        CALL    OPEN          ; OPEN FILE AND PROMPT FOR HOST FILE  
        LXI     H,XQT         ; OUTPUT CONTROL STATEMENT TO MODEM   
        CALL    OUTMSG        ; 
        CALL    WAIT          ; WAIT FOR LINE FEED  
;   
XFER1:  LXI     H,UBUF  
        MVI     B,0           ; INITIALIZE PREVIOUS CHAR REGISTER   
;   
MLOOP:  CALL    MIN           ; INPUT A CHARACTER FROM THE MODEM
        MOV     C,A           ; SAVE THE CHARACTER  
        CPI     7FH           ; DEL CHARACTER?  
        JZ      MLOOP         ; IF SO, IGNORE IT.   
        CPI     ' ' 
        JNC     MLOP1         ; JUMP IF NOT A CTL CHAR  
        CPI     LF            ; IS IT A LINE FEED?  
        JZ      MLOP1   
        CPI     CR            ; IS IT A CHARRIAGE RETURN?   
        JNZ     MLOOP         ; IGNORE OTHER CTL CHARACTERS 
;   
MLOP1:  MOV     A,B           ; LOOK AT LAST CHARACTER  
        CPI     LF            ; IS IT A LINE FEED?  
        JNZ     MLOP2         ; JUMP, IF NOT
        CALL    DECDR   
        DW      CRTL
        DW      0       ; LINE COUNT
        DB      'RECORD COUNT       ',0 
;   
        MOV     A,C           ; GET THE CHARACTER   
        CPI     '/'           ; END OF FILE?
        JZ      FINISH        ; IF SO, THAT IS IT   
        CPI     5CH           ; BACKSLASH INDICATES THAT BUFFER IS FILLE
        JZ      FILLED  
MLOP2:  MOV     M,C           ; SAVE CHARACTER  
        MOV     B,C 
        INX     H   
        JMP     MLOOP         ; LOOP UNTIL FINISHED 
;   
;    HOST INPUT BUFFER IS FILLED. ... NOW TRANSFER IT TO DISK   
;   
;   
FILLED: CALL    WAIT          ; WAIT FOR LINE FEED  
;   
        CALL    DECDR   ; INCREMENT BLOCK COUNT AND DISPLAY 
        DW      CRTB
        DW      0   
        DB      '1108 BLOCK NUMBER: ',0 
;   
        CALL    WBUF          ; NOW, WRITE BUFFER TO DISK   
        MVI     C,CR          ; OUTPUT A CR TO MODEM
        CALL    MOUT
        CALL    WAIT          ; WAIT FOR LINE FEED  
        JMP     XFER1   
;   
;  SUBROUTINE TO WAIT FOR A CARRIAGE RETURN 
;   
WAIT:   CALL    MIN           ; INPUT A CHARACTER   
        CPI     LF            ; IS IT A LINE FEED?  
        RZ                    ; IF SO, RETURN   
        JMP     WAIT          ; WAIT ON...  
;   
;     MODEM I/O ROUTINES
;   
MIN:    IN      MSTAT         ; ANY DATA?   
        ANI     MRDA
        JZ      MIN           ; LOOP UNTIL INPUT IS AVAILABLE   
        IN      MDATA   
        ANI     7FH 
        RET 
;   
MOUT:   IN      MSTAT         ; TBE?
        ANI     MTBE
        JZ      MOUT
        MOV     A,C 
        ANI     7FH           ; CLEAR HIGH ORDER BIT
        JPE     MOUT1         ; IS IT EVEN PARITY   
        ORI     80H           ; SET PARITY TO MAKE IT EVEN  
MOUT1:  OUT     MDATA         ; OUTPUT THE CHARACTER
        RET 
;   
;   OUTPUT MESSAGE ROUTINE  
;   
OUTMSG: MOV     A,M 
        ORA     A   
        RZ                    ; RETURN IS LAST CHARACTER
        MOV     C,A 
        CALL    MOUT          ; OUTPUT CHARACTER
        INX     H   
        JMP     OUTMSG        ; LOOP UNTIL ENTIRE MESSAGE IS OUTPUT 
;   
;   
;       OPEN THE CP/M FILE  
;   
OPEN:   CALL    GNAME         ; GET FILE NAME   
        LXI     H,BUFF-1      ; POINT TO DMA BUFFER (FOR DISK I/O)  
        SHLD    DBUF          ; AND SAVE FILE TO WRITE  
;   
        JZ      OPEN1         ; =255, IF NOT THERE  
        MVI     C,OMSG        ; FILE IS THERE...
        LXI     D,DESMSG      ; DESTROY FILE?   
        CALL    BDOS
        MVI     C,READC       ; READ A CHARACTER
        CALL    BDOS
        CPI     'Y' 
        JNZ     ENDIO         ; QUIT, UNLESS USER ANS ='YES'
        MVI     C,DELET       ; DELETE THE FILE 
        CALL    FILE
        CALL    CRLF
OPEN1:  
        MVI     C,MAKEF       ; CREATE NEW DIRECTORY ENTRY  
        CALL    FILE
        XRA     A   
        STA     FCBRC         ; ZERO OUT RECORD COUNT   
        STA     FCBCR         ; ZERO OUT FIRST RECORD   
        STA     FCBRL         ; ZERO OUT CURRENT RECORD 
        RET 
;   
;   WRITE OUT THE INPUT BUFFER  
;   
;      UPON ENTRY, HL POINTS TO LAST CHARACTER IN HOST INPUT BUFFER 
WBUF:   XCHG                  ; TO DE REG   
        LXI     H,UBUF        ; HL POINT TO TOP OF HOST INPUT BUFFER
;   
WBUF1:  MOV     C,M           ; PICK UP THE CHARACTER   
        PUSH    H   
        PUSH    D   
        CALL    WCHAR   
        POP     D   
        POP     H   
        INX     H             ; POINT TO NEXT CHARACTER 
        MOV     A,H           ; CHECK LIMITS
        CMP     D   
        JC      WBUF1         ; LOOP UNTIL FINISHED 
        MOV     A,L           ; CHECK LOW ORDER BYTE
        CMP     E   
        JC      WBUF1   
        RET                   ; OTHERWISE, FINISHED 
;   
;   WRITE A CHARACTER TO DISK   
;   
WCHAR:  PUSH    B             ; SAVE THE CHARACTER (IN C-REG)   
        LHLD    DBUF          ; GET POINTER 
        INX     H   
        MOV     A,H 
        CPI     1             ; BUFFER FULL?
        JC      WCH1          ; IF NOT, GO SAVE CHARACTER   
        MVI     C,WNEXT       ; WRITE THE RECORD
        CALL    FILE
        ORA     A   
        JNZ     ERRIO         ; I/O ERROR   
;   
        CALL    DECDR         ; INCREMENT SECTOR COUNT AND DISPLAY  
        DW      CRTS
        DW      0           ; SECTOR COUNT  
        DB        'SECTOR COUNT:      ',0   
        LXI     H,BUFF        ; POINT TO BEGINNING OF I/O BUFFER
WCH1:   POP     B   
        MOV     M,C           ; SAVE CHARACTER IN I/O BUFFER
        SHLD    DBUF          ; AND SAVE POINTER
        RET 
;   
;   
;       ERROR ROUTINES  
;   
ERRIO:  LXI     D,ERRMSG      ; SET ERROR MESSAGE   
        JMP     EXIT
;   
ERR0:   LXI     D,NFMSG       ; FILE SPECIFICATION IS MISSING   
        JMP     EXIT
;   
ERR1:   LXI     D,FNERR       ; FILE NOT IN DIRECTORY   
        JMP     EXIT
;   
ERR2:   LXI     D,CEMSG       ; CLOSE ERROR 
EXIT:   PUSH    D   
        CALL    CRLF
        POP     D   
        MVI     C,OMSG  
        CALL    BDOS
ERR:    CALL    CRLF
        JMP     CPM 
;   
;   
;     FINISH UP AND RETURN TO SUBSYSTEM 
;   
FINISH: MVI     M,1AH         ; CP/M EOF INDICATOR  
        INX     H   
        CALL    WBUF          ; FLUSH BUFFERS   
        MVI     C,WNEXT       ; AND WRITE IT TO DISK
        CALL    FILE
;   
        MVI     C,CLOSE 
        CALL    FILE          ; GO CLOSE FILE   
        JZ      ERR2
ENDIO:  LXI     D,IOMSG 
        JMP     EXIT          ; PRINT COMPLETION MESSAGE AND EXIT   
;   
; OUTPUT CARRIAGE RET, LINE FEED
;   
CRLF:   MVI     E,0DH         ; CR  
        CALL    PCHAR   
        MVI     E,0AH         ; LF  
;   
;   
PCHAR:  MVI     C,WRITC       ; SET TO WRITE
        JMP     BDOS
;   
; READ FILE NAME
;   
GNAME:  CALL    CRLF
        MVI     C,INITD       ;  RESET SYSTEM   
        CALL    BDOS
        LXI     D,PROMPT      ; PROMPT USER 
        MVI     C,OMSG  
        CALL    BDOS          ; PRINT PROMPT
        LXI     D,USPEC 
        MVI     C,10          ; READ A THE 1108 FILE NAME   
        CALL    BDOS
        CALL    CRLF
;   
        LXI     D,FCB   
VAL2:   MVI     C,OPENF       ; SEE IF FILE IS THERE
        XRA     A   
        STA     FCB 
        STA     FCBRL         ; EXTENSION NUMBER
        CALL    FILE
        RET 
;   
;  THIS ROUTINE IS REFERENCED TO REFERENCE BDOS FOR FILE I/O
;   
FILE:   LXI     D,FCB         ; FILE REFERENCE ROUTINE  
        CALL    BDOS
        CPI     255           ; CHECK STATUS
        RET 
;   
;-----------------------------------------------------------
;     DECIMAL DISPLAY PACKAGE   
;   
;-----------------------------------------------------------
;       DECDR CONVERTS A NUMBER TO DECIMAL AND  
;       SAVES IT ON THE CRT 
;   
;       USAGE:  
;               CALL DECDR      ; CALL THE PROCESSER DRIVER 
;               DW      CRTLOC  ;  = ADDRESS OF CRT LOCATION
;               DW      NUMBER  ;  ACTUAL NUMBER TO BE INCREMENTED  
;                                  CONVERTED TO DECIMAL AND 
;                                  DISPLAYED ON CRT.
;               DB      'MESSAGE...' ,0, ; MESSAGE  
;   
;       REGISTER USAGE: ONLY CONTENTS OF A-REG DESTROYED
;   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;   
DECDR:  
        XTHL    ; SWAP HL AND RET ADDRESS   
        PUSH    B   

        PUSH    D   
        MOV     C,M     ; PICK UP CRT LOCATION  
        INX     H   
        MOV     B,M 
        INX     H   
        INR     M       ; INCREMENT NUMBER (LOW ORDER PART) 
        MOV     E,M     ; LOCATION OF NUMBER TO BE CONVERTED
        INX     H   
        JNZ     DECD1   
        INR     M       ; IF CARRY, INCREMENT HIGH ORDER PORTION OF NUMB
ER  
DECD1:  MOV     D,M 
        INX     H       ; NOW HL POINTS TO MESSAGE  
        CALL    ZMSG    ; PRINT THE MESSAGE 
        MOV     A,C 
        STA     DECP2   
        MOV     A,B 
        STA     DECP2+1 
        SHLD    DECRET+1 ; RETURN ADDRESS SAVE  
        CALL    DECPRT  
        POP     D   
        POP     B   
        POP     H   
DECRET: JMP     0   
;   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
;   
DECPRT: 
        XCHG
;   
;  OK MESSAGE IS STORED.... NOW DO DECIMAL CONVERSION   
;   
DECP0:  
        PUSH    B   
        PUSH    D   
        PUSH    H   
        LXI     B,-10           ; B=-10 
        LXI     D,-1
;   
DECP1:  DAD     B   
        INX     D               ; USE SUCCESSIVE ADDS   
        JC      DECP1   
;   
        LXI     B,10
        DAD     B   
        XCHG
        MOV     A,H 
        ORA     L               ; IS H=L=0, YET?
        CNZ     DECP0           ; CALL ADDER, IF NOT
        MOV     A,E             ; PICK UP CHARACTER TO OUTPUT   
        ADI     '0' 
        LHLD    DECP2   
        MOV     M,A 
        INX     H   
        MVI     M,' '   
        SHLD    DECP2   
        POP     H   
        POP     D   
        POP     B   
        RET 
;   
ZMSG:   MOV     A,M 
        INX     H   
        ORA     A       ;SET FLAGS  
        RZ              ; RETURN IF A=0 
        STAX    B   
        INX     B   
        JMP     ZMSG
;   
YMSG:  DB '1108 PF ELEMENT TO DISK TRANSFER PROGRAM. ',0
DECP2:  DB      0   
;   
;-----------------------------------------------------------
;   
CEMSG:  DB      'CANNOT CLOSE$' 
PROMPT: DB      'ENTER EXEC-8 ELEMENT NAME (FILE.ELEMENT): $'   
DKFULL: DB      'DIRECTORY IS FULL$'
ERRMSG: DB      'DISK I/O ERROR $'  
IOMSG:  DB      'I/O COMPLETE $'
DESMSG: DB      'DESTROY FILE: $'   
FNERR:  DB      'FILE IS NOT IN THE DIRECTORY $'
NFMSG:  DB      'FILE SPECIFICATION IS MISSING.$'   
XQT:    DB      '@SHIG*WORK.DISKDUMP '
USPEC:  DB      '                                          '
        DB      CR,0
DBUF:   DW      0   
;   
;   THIS IS THE BUFFER THAT RECEIVES DATA FROM THE HOST COMPUTER
        ORG     2000H   
STACK   EQU     $   
UBUF:   DS      1000H         ; INPUT BUFFER
        END