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
/
BEEHIVE
/
COMMS
/
MODEM9.ARC
/
FILES.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-02-02
|
11KB
|
677 lines
;
; FILES.ASM
;
;Disk file routines for MODEM9.xx.
;
;
;Multi-file access subroutine. Allows processing of multiple files
;(i.e., *.ASM) from disk. This routine builds the proper name in the
;FCB each time it is called. This command would be used in such pro-
;grams such as modem transfer, tape save, etc. in which you want to
;process single or multiple files.
;
;The FCB will be set up with the next name, ready to do normal proces-
;sing (OPEN, READ, etc.) when routine is called.
;
;Carry is set if no more names can be found
;
MFNAME: PUSH B ;INIT DMA ADDR, FCB
PUSH D
PUSH H
MVI C,STDMA
LXI D,80H
CALL BDOS
POP H
POP D
POP B
XRA A
STA FCBEXT
LDA MFFLG1
ORA A
JNZ MFN01 ;IF FIRST TIME
MVI A,1 ;TURN OFF 1ST TIME SW
STA MFFLG1
LXI H,FCB ;SAVE THE REQUESTED NAME
LXI D,MFREQ
LXI B,12
CALL MOVER
LDA FCB
STA MFCUR ;SAVE DISK IN CURRENT FCB
LXI H,MFREQ ;SRCHF REQ NAME
LXI D,FCB
LXI B,12
CALL MOVER
PUSH B
PUSH D
PUSH H
MVI C,SRCHF
LXI D,FCB
CALL BDOS
POP H
POP D
POP B
JMP MFN02
;
MFN01: LXI H,MFCUR ;SRCHF CURR NAME
LXI D,FCB
LXI B,12
CALL MOVER
PUSH B
PUSH D
PUSH H
MVI C,SRCHF
LXI D,FCB
CALL BDOS
POP H
POP D
POP B
LXI H,MFREQ ;SRCHN REQ NAME
LXI D,FCB
LXI B,12
CALL MOVER
PUSH B
PUSH D
PUSH H
MVI C,SRCHN
LXI D,FCB
CALL BDOS
POP H
POP D
POP B
MFN02: INR A ;RETURN CARRY IF NOT FOUND
STC
JNZ MFFIX1
STA MFFLG1
RET
;
MFFIX1: DCR A ;MOVE NAME FOUND TO CURR
ANI 3
ADD A
ADD A
ADD A
ADD A
ADD A
ADI 81H
MOV L,A
MVI H,0
PUSH H ;SAVE NAME POINTER
LXI D,MFCUR+1
LXI B,11
CALL MOVER
POP H ;MOVE NAME FOUND TO FCB
LXI D,FCB+1
LXI B,11
CALL MOVER
XRA A ;SETUP FCB
STA FCBEXT
STA FCBRNO
RET
;
; Move subroutine
;
MOVER: MOV A,M
STAX D
INX H
INX D
DCX B
MOV A,B
ORA C
JNZ MOVER
RET
;
;Lists directory and gives free space remaining on the requested drive.
;
DIRLST:
LXI D,CMDBUF ;PUT COMMAND LINE IN FCB
LXI H,5CH
CALL CPMLINE
LXI H,SRCHFCB
CALL INITFCBS
LDA 6CH ;GET DRIVE #
STA SRCHFCB
LDA 6DH
CPI 20H ;IF BLANK GET ALL NAMES
PUSH PSW
CZ QSTMARK
POP PSW
CNZ MOVENAME ;ELSE MOVE NAME INTO FCB
LXI D,80H
MVI C,STDMA
CALL BDOS
XRA A
STA NAMEGD
LDA NOOFCOL ;GET NUMBER OF COLUMNS
STA NAMECT ;STORE TO CALCULATE CRLF POSITION
LXI D,SRCHFCB
MVI C,SRCHF ;DO FIRST SEARCH
CALL BDOS
CPI 0FFH
JZ NOFILE
PUSH PSW
DIRLP: POP PSW
CALL GETADD
LXI D,15 ;OFFSET FOR RECORD COUNT
DAD D
MOV A,M
ORA A
JZ NEXTSR ;NO LIST IF FILE IS ZERO LENGTH
LXI D,-5
DAD D ;POINT TO $SYS ATTRIB BYTE
MOV A,M
ANI 80H
JNZ NEXTSR ;NO LIST IF $SYS FILE
LXI D,-10
DAD D ;POINT TO BEGINNING OF NAME
INX H ;POINT TO FIRST LETTER
LXI D,PRNTNAME
MVI B,8
CALL MOVE
INX D
MVI B,3
CALL MOVE
CALL ILPRT
PRNTNAME:
DB ' ','.',' ',' ', 0 ;8 SPACES, PERIOD, 3 SPACES, 1 SPACE
MVI A,0FFH
STA NAMEGD
NEXTSR: LXI D,SRCHFCB
MVI C,SRCHN ;DO NEXT SEARCH
CALL BDOS
CPI 0FFH
JZ DIRDONE
PUSH PSW
LDA NAMEGD
ORA A
JZ DIRLP
LDA NAMECT
DCR A
STA NAMECT
ORA A
CZ NEWCT
CNZ FENCE
XRA A
STA NAMEGD
JMP DIRLP
;
NOFILE: CALL ILPRT
DB 'NO FILE',0
;
; Determines free space remaining
;
DIRDONE:
LDA SRCHFCB
ORA A
JZ DEFLT
DCR A
MOV E,A
MVI C,SELDSK
CALL BDOS
DEFLT: MVI C,GETPARM ;CURRENT DISK PARAMETER BLOACK
CALL BDOS
INX H
INX H
MOV A,M ;GET BLOCK SHIFT FACTOR
STA BSHIFTF
INX H ;BUMP TO BLOCK MASK
MOV A,M ;GET IT
STA BMASK
INX H
INX H
MOV E,M ;GET MAX BLOCK NUMBER
INX H
MOV D,M
XCHG
SHLD BMAX ;PUT IT AWAY
MVI C,GETALC ;ADDRESS OF CP/M ALLOCATION VECTOR
CALL BDOS
XCHG ;GET ITS LENGTH
LHLD BMAX
INX H
LXI B,0 ;INITIALIZE BLOCK COUNT TO ZERO
GSPBYT: PUSH D ;SAVE ALLOCATION ADDRESS
LDAX D
MVI E,8 ;SET TO PROCESS 8 BLOCKS
GSPLUP: RAL ;TEST BIT
JC NOTFRE
INX B
NOTFRE: MOV D,A ;SAVE BITS
DCX H
MOV A,L
ORA H
JZ ENDALC ;QUIT IF OUT OF BLOCKS
MOV A,D ;RESTORE BITS
DCR E ;COUNT DOWN 8 BITS
JNZ GSPLUP ;DO ANOTHER BIT
POP D ;BUMP TO NEXT COUNT OF ALLOCATION VECTOR
INX D
JMP GSPBYT ;PROCESS IT
;
ENDALC: POP D ;CLEAR ALLOCATION VECTOR FROM STACK
MOV L,C ;COPY BLOCK TO 'HL'
MOV H,B
LDA BSHIFTF ;GET BLOCK SHIFT FACTOR
SUI 3 ;CONVERT FROM RECORDS TO THOUSANDS
JZ PRTFREE ;SKIP SHIFTS IF 1K BLOCKS
FREKLP: DAD H ;MULTIPLY BLOCKS BY 'K PER BLOCK'
DCR A
JNZ FREKLP
PRTFREE:
PUSH H
CALL ILPRT
DB CR,LF,'Drive ',0
LDA SRCHFCB ;IF NO DRIVE, GET
ORA A ;LOGGED IN DRIVE
JNZ PRNTHD
MVI C,CURDSK
CALL BDOS
INR A
PRNTHD: ADI 'A'-1
STA DRNAME
CALL ILPRT
DRNAME: DB ' has ',0
POP H ;GET NUMBER OF BYTES AVAILABLE
CALL DECOUT
CALL ILPRT
DB 'K bytes free',CR,LF,0
RET
;
; Subroutines
;
FENCE: CALL ILPRT
DB '| ',0
RET
;
NEWCT: CALL CRLF
LDA NOOFCOL
STA NAMECT
RET
;
QSTMARK:
MVI A,'?' ;IF BLANK IN FCB, PUT IN 11 ?'s
MVI B,11
LXI H,SRCHFCB+1
QSTLP: MOV M,A
INX H
DCR B
JNZ QSTLP
RET
;
MOVENAME
LXI H,6DH
LXI D,SRCHFCB+1
MVI B,11
CALL MOVE ;MOVE IN MAIN PROGRAM
RET
;
GETADD: ANI 03H ;GET MOD4 FOR CP/M 1.4
ADD A ;ADD 32
ADD A
ADD A
ADD A
ADD A
MOV E,A
MVI D,0
LXI H,80H ;ADD DMA OFFSET
DAD D
RET
;
;IN CP/M V.2, IF FILE IS R/O OR SYS, IT IS CHANGED TO 'BAK'.
;
CKCPM2:
MVI C,12
CALL BDOS
ORA A ;RETURN 0 MEANS CP/M 1
RZ
MVI C,STDMA
LXI D,80H
CALL BDOS
MVI C,SRCHF ;SEARCH FOR FILE
LXI D,FCB
CALL BDOS
CPI 0FFH
RZ
ADD A
ADD A ;MULT A-REG BY..
ADD A
ADD A ;..32 TO FIND..
ADD A ;..NAME IN DMA.
LXI H,80H
ADD L
MOV L,A ;HL POINTS TO DIR NAME
LXI D,9
DAD D ;POINT TO R/O ATTRIB BYTE
MOV A,M
ANI 80H ;TEST MSB
JNZ MKCHG ;IF SET, MAKE CHANGE
INX H ;CHECK SYSTEM ATTRIB BYTE
MOV A,M
ANI 80H
RZ ;NOT $SYS OR $R/O
DCX H
MKCHG: LXI D,-8
DAD D ;POINT HL TO FILENAME + 1
LXI D,FCB+1 ;MOVE DIR NAME TO FCB..
MVI B,11 ;..WITHOUT CHANGING DRIVE.
CALL MOVE
LXI H,FCB+9 ;R/O ATTRIB
MOV A,M
ANI 7FH ;STRIP R/O ATTRIB
MOV M,A
INX H ;SYS ATTRIB
MOV A,M
ANI 7FH
MOV M,A
LXI D,FCB
MVI C,30 ;SET NEW ATTRIBS IN DIR
CALL BDOS
;
;MAY BE CALLED BY CKBAKUP BELOW. ITS RETURN DONE HERE
;
PLANCHG:
LXI H,FCB ;CHANGE NAME TO TYPE "BAK"
LXI D,6CH
MVI B,9 ;MOVE DRIVE AND NAME (NOT TYPE)
CALL MOVE
LXI H,75H ;START OF TYPE IN FCB2
MVI M,'B'
INX H
MVI M,'A'
INX H
MVI M,'K'
LXI D,6CH
MVI C,ERASE ;ERASE ANY PREV BACKUPS
CALL BDOS
LXI H,6CH ;FCB2 DR FIELD SHOULD..
MVI M,0 ;..0 FOR RENAME.
LXI D,FCB
MVI C,23 ;RENAME
CALL BDOS
RET
;
CKBAKUP:
LDA BAKUPBYTE
ORA A
RZ
MVI C,SRCHF
LXI D,FCB
CALL BDOS
INR A
RZ ;FILE NOT FOUND
JMP PLANCHG ;IN "CKCPM2" - RET DONE THERE
;
ERASFIL:
LXI H,FCB ;CHECK FOR WILD CARDS
MVI B,11
ERASFIL1:
INX H
MOV A,M
CPI '?' ;IS IT A WILD CARD?
JZ WILDERR ;GO IF SO
DCR B
JNZ ERASFIL1
LDA BATCHFLG ;DON'T ASK FOR ERASE..
ORA A ;..IN MULTI-FILE MODE,..
JZ NOASK ;..JUST DO IT.
LXI D,FCB
MVI C,SRCHF
CALL BDOS
INR A
RZ
CALL ILPRT
DB 'File exists -- Type ''Y'' to erase: ',BELL,0
CALL KEYIN
PUSH PSW
CALL TYPE
POP PSW
CALL UCASE
CPI 'Y'
JNZ MENU
CALL CRLF
NOASK: LXI D,FCB
MVI C,ERASE
JMP BDOS ;USE JUMP SO CAN RET TO VARIOUS CALLING ROUTINES
;
WILDERR:
POP H ;RESTORE STACK
CALL ILPRT
DB '++ No ambiguous file names allowed ++',CR,LF,BELL,0
JMP MENU
;
BLKFILE:
CALL ILPRT ;ROUTINE IF NO FILE IS NAMED FOR "SEND" OR "RECEIVE"
DB CR,LF,'No file specified',CR,LF,BELL,0
JMP MENU
MAKEFIL:
LXI D,FCB
MVI C,MAKE
CALL BDOS
INR A
RNZ
CALL ERXIT
DB 'Error - Can''t make file',CR,LF
DB 'Directory is likely full',CR,LF,'$'
;
IF CPM2X
;
CNREC: MVI C,FILSIZ ;COMPUTE FILE SIZE FUNCTION IN CP/M 2.x
LXI D,FCB ;POINT TO FILE CONTROL BLOCK
CALL BDOS
LHLD FCB+33 ;GET RECORD COUNT
SHLD RCNT ;STORE IT
LXI H,0 ;ZERO HL
SHLD FCB+33 ;RESET RANDOM RECORD IN FCB
RET
;
ENDIF ;CPM2X
;
IF NOT CPM2X
;
CNREC: MVI A,'?' ;MATCH ALL EXTENTS
STA FCBEXT
MVI A,0FFH
STA MAXEXT ;INIT MAX EXT NO.
MVI C,SRCHF ;GET 'SEARCH FIRST' FNC
LXI D,FCB
CALL BDOS ;READ FIRST
INR A ;WERE THERE ANY?
JNZ SOME ;GOT SOME
CALL ERXIT
DB '++ File not found ++$'
;
;READ MORE DIRECTORY ENTRIES
;
MOREDIR:
MVI C,SRCHN ;SEARCH NEXT
LXI D,FCB
CALL BDOS ;READ DIR ENTRY
INR A ;CHECK FOR END (0FFH)
JNZ SOME ;NOT END OF DIR...PROCESS EXTENT
LDA MAXEXT ;HIT END...GET HIGHEST EXTENT NO. SEEN
MOV L,A ;WHICH GIVES EXTENT COUNT -1
MVI H,0
MOV D,H
LDA RCNT ;GET RECORD COUNT OF MAX EXTENT SEEN
MOV E,A ;SAVE IT IN DE
DAD H
DAD H ;MULTIPLY # OF EXTENTS -1
DAD H ; TIMES 128
DAD H
DAD H
DAD H
DAD H
DAD D ;ADD IN SIZE OF LAST EXTENT
SHLD RCNT ;SAVE TOTAL RECORD COUNT
RET ;AND EXIT
;
;POINT TO DIRECTORY ENTRY
;
SOME: DCR A ;UNDO PREV 'INR A'
ANI 3 ;MAKE MODULUS 4
ADD A ;MULTIPLY...
ADD A ;..BY 32 BECAUSE
ADD A ;..EACH DIRECTORY
ADD A ;..ENTRY IS 32
ADD A ;..BYTES LONG
LXI H,80H POINT TO BUFFER
ADD L ;POINT TO ENTRY
ADI 15 ;OFFSET TO RECORD COUNT
MOV L,A ;HL NOW POINTS TO REC COUNT
MOV B,M ;GET RECORD COUNT
DCX H
DCX H ;BACK DOWN TO EXTENT NUMBER
DCX H
LDA MAXEXT ;COMPARE WITH CURRENT MAX.
ORA A ;IF NO MAX YET
JM BIGGER ;THEN SAVE RECORD COUNT ANYWAY
CMP M
JNC MOREDIR
BIGGER: MOV A,B ;SAVE NEW RECORD COUNT
STA RCNT
MOV A,M ;SAVE NEW MAX. EXTENT NO.
STA MAXEXT
JMP MOREDIR ;GO FIND MORE EXTENTS
;
ENDIF ;NOT CPM2X
;
OPENFIL:
XRA A
STA FCBEXT
LXI D,FCB
MVI C,OPEN
CALL BDOS
INR A
JNZ OPENOK
CALL ERXIT
DB 'Can''t open file$'
OPENOK:
LDA QFLG
ORA A
RZ
CALL SENDTIM ;A LIB MACRO SHOWS TIME TO SEND
RET
;
CLOSFIL:
LXI D,FCB
MVI C,CLOSE
CALL BDOS
INR A
RNZ
CALL ERXIT
DB 'Can''t close file$'
RDSECT:
LDA SECINBF
DCR A
STA SECINBF
JM RDBLOCK
LHLD SECPTR
LXI D,80H
CALL MOVE128
SHLD SECPTR
RET
;
RDBLOCK:
LDA EOFLG
CPI 1
STC
RZ
MVI C,0
LXI D,DBUF
RDSECLP:
PUSH B
PUSH D
MVI C,STDMA
CALL BDOS
LXI D,FCB
MVI C,READ
CALL BDOS
POP D
POP B
ORA A
JZ RDSECOK
DCR A
JZ REOF
CALL ERXIT
DB '++ File read error ++$'
RDSECOK:
LXI H,80H
DAD D
XCHG
INR C
MOV A,C
CPI DBUFSIZ*8 ;BUFFER SIZE IN 128 BYTE SECTORS
JZ RDBFULL
JMP RDSECLP
;
REOF: MVI A,1
STA EOFLG
MOV A,C
RDBFULL:
STA SECINBF
LXI H,DBUF
SHLD SECPTR
LXI D,80H
MVI C,STDMA
CALL BDOS
JMP RDSECT
;
WRSECT:
LHLD SECPTR
XCHG
LXI H,80H
CALL MOVE128
XCHG
SHLD SECPTR
LDA SECINBF
INR A
STA SECINBF
CPI DBUFSIZ*8 ;BUFFER SIZE IN 128 BYTE SECTORS
RNZ
WRBLOCK:
LDA SECINBF
ORA A
RZ
MOV C,A
LXI D,DBUF
DKWRLP:
PUSH H
PUSH D
PUSH B
MVI C,STDMA
CALL BDOS
LXI D,FCB
MVI C,WRITE
CALL BDOS
POP B
POP D
POP H
ORA A
JNZ WRERR
LXI H,80H
DAD D
XCHG
DCR C
JNZ DKWRLP
XRA A
STA SECINBF
LXI H,DBUF
SHLD SECPTR
RET
;
WRERR: MVI C,CAN
CALL SEND
CALL ERXIT
DB CR,LF,'Error writing file',CR,LF,'$'
;
LINK FINISH
;
MVI C,STDMA
CALL BDOS
LXI D,FCB
MVI C,READ
CALL BDOS
POP D
POP B
ORA A