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
/
CPM
/
UTILS
/
DIRUTL
/
MAP104.LBR
/
MAP104.AQM
/
MAP104.ASM
Wrap
Assembly Source File
|
2000-06-30
|
17KB
|
686 lines
; MAP.ASM
; version 1.04
;
; 04/06/85
; v1.03 had a bug in it. When someone tried to MAP a specific
; drive, the program would report drive A: instead of the selected
; drive. MAP command syntax now makes a little more sense.
;
; 04/02/85
; Another major change. This version will now let the user select
; which drive to map. In addition, the descriptive mode routines
; are now conditional (see EQUate DESCRIP), this is for sysops who
; don't want to use extra disk space to handle section
; descriptions. In the library, I've changed README.TXT to
; MAPxxx.MOD.
;
; 03/01/85
; This sucker's getting pretty slick. I've added a routine to
; print a description of the section along with its name
; (description is inside -*.* file, see README.TXT in MAP102.LBR
; for more information). I've also added an abort and XOFF
; handling routine, in the process switching over to all BDOS
; direct console I/O.
;
; * * *
;
; This program was designed for RCP/M systems that, for one reason
; or another, cannot use SECTION (i.e. a system whose download
; areas change daily). It goes through the directory of each
; online user area and drive looking for catalog label files
; (-*.*). Upon finding such a file it displays bytes 2-8 of the
; filename and the drive/user area where the file is located. For
; example, a file in A6: called -UTILITY.05A would be displayed as
; "A6: = UTILITY". Of course, this means that filename bytes 2-8
; have to be somehow descriptive of that particular section.
;
; If you have any bug reports/fixes, please contact me either by
; calling B-RCP/M (214) 840-9552 and leaving a message via the
; CP/M NOTE command or write to:
;
; Bob Horn
; c/o Horn Engineering Associates
; 1714 Patricia Lane
; Garland, Texas 75042
;
; PS: The RCP/M hours are pretty sporadic, but if you call about
; 7PM central time or early morning (midnight to 8AM) you
; stand a pretty good chance of getting online. Note that at
; some hours an aux. 5" based system is up with just a
; bulletin board online
;
TRUE EQU 0FFH
FALSE EQU NOT TRUE
;
; CP/M Equates
;
BOOT EQU 0 ;org zero CP/M
BDOS EQU BOOT+5 ;bdos entry
DEFDMA EQU 80H ;normal default DMA address
TPA EQU BOOT+100H ;ORG address
DFCB EQU 5CH ;CP/M default FCB
CONIN EQU 1 ;BDOS console input function
CONOUT EQU 2 ;console output function
DIRCON EQU 6 ;direct console I/O
PBUF EQU 9 ;print buffer function
RDCON EQU 10 ;read console buffer function
CONSTAT EQU 11 ;console status function
SELDISK EQU 14 ;select default disk function
OPENF EQU 15 ;open file function
CLOSEF EQU 16 ;close file function
SRCHF EQU 17 ;search for first dir file function
SRCHN EQU 18 ;search for next file function
DELF EQU 19 ;delete file function
READF EQU 20 ;read file function
WRITEF EQU 21 ;write file function
MAKEF EQU 22 ;make file function
GETDISK EQU 25 ;get default disk function
SETDMA EQU 26 ;set DMA address function
SETATTR EQU 30 ;set file attributes
USRSTAT EQU 32 ;get/set user number
ACHAR EQU 'C'-'@' ;characters for abort and pause,
XOFF EQU 'S'-'@' ;respectively. MUST be ctrl chars.
;
; Misc Equates
;
BELL EQU 07H ;bell character
BS EQU 08H ;backspace character
LF EQU 0AH ;line feed
CR EQU 0DH ;carriage return
BLANK EQU 20H ;space character
;
; Program Equates
;
VERS EQU 1 ;version
REV EQU 04 ;revision #
MONTH EQU 04 ;date of last revision
DAY EQU 06
YEAR EQU 85
;
; If you make any changes, please change the above accordingly
;
;
FENCE EQU '|' ;separator between section names
NUMCOL EQU 4 ;# of sections to be displayed on
;each line, 4 for 80 column display
;
DESCRIP EQU TRUE ;true, produce description code
ZCPR EQU TRUE ;true if using ZCPR for MXDRV/USR
; ;if false, see IF NOT ZCPR area below
IF ZCPR
MXDRV EQU 3DH ;set to location of ZCPR MAXDRV
MXUSR EQU 3FH ; " MAXUSER
ENDIF
;
ORG TPA ;program runs here
;
; Main program
;
START: JMP START1 ;jump over fixed data
;
IF NOT ZCPR
MXDRV: DB 1 ;max drive to search (A:=0, B:=1, etc.)
MXUSR: DB 8 ;max user to search +1
ENDIF
;
DIRFNAME:
DB '-??????????' ;wild card directory name
START1: LXI H,0 ;find CP/M stack pointer
DAD SP
SHLD OLDSP ;save old stack pointer
LXI SP,STACK ;set up our local stack
;
LDA DFCB+1 ;get first character of command line
CPI '?' ;request for help?
JZ HELP ;then help 'im
;
IF DESCRIP
CPI 'D' ;? if descriptive mode
JNZ START2 ;it's not, go ahead
MVI A,0FFH ;it is, set the flag
STA DESFLG
ENDIF ;descrip
;
START2: LXI H,SIGNON ;point to signon message
CALL IPBUF ;and show it
;
; Get the default drive & user, save them, and log onto A0:
;
MVI C,GETDISK ;get the default drive
CALL BDOS
STA DEFDRV ;save it
;
MVI C,USRSTAT ;get the default user
MVI E,0FFH
CALL BDOS
STA DEFUSR ;save it
;
MVI E,0 ;set default to A:
MVI C,SELDISK ;
CALL BDOS
;
MVI E,0 ;user 0
MVI C,USRSTAT
CALL BDOS
;
LDA DFCB ;see if specific drive
ORA A ;set flags
CNZ SPCDRV ;one specific drive, set it
;
; Here we set up the DMA and initialize some values
;
LXI D,DEFDMA ;set the CP/M DMA address
MVI C,SETDMA
CALL BDOS
;
; Now start the directory search.
;
LFORFL: CALL ZFCB ;zero the FCB
LXI B,11 ;11 char in file name
LXI H,DIRFNAME ;the wild card file name
LXI D,FCB+1 ;point to FCB file name space
CALL MOVE ;move the file name in
;
LXI D,FCB ;find first match
MVI C,SRCHF
CALL BDOS
INR A ;returns 0ffh if not found
JZ MORETGO ;None there
DCR A ;set A back to normal
LXI H,DEFDMA ;point to DMA buffer
CALL FINDFN ;find the file name in the DMA space
;
IF DESCRIP
LDA DESFLG ;see if descriptive mode
ORA A ;set flags
JNZ DESCAL ;call descriptive routine if so
ENDIF ;descrip
;
CALL PRINTFN ;Print the filename with pertinent data
;
MORETGO:
LDA CURUSR ;get the current user
MOV B,A
LDA MXUSR ;and the max user
INR B ;bump the current user
CMP B ;same as (MXUSR)?
JZ NDRIVE ;if so, go to the next drive
MOV A,B ;and if not, store new current user
STA CURUSR
MVI C,USRSTAT ;and move up one
MOV E,B
CALL BDOS
JMP LFORFL ;look for another file
;
NDRIVE: LDA DFCB ;see if specific drive
ORA A ;set flags
JNZ EXIT ;yeah, quit now
;
LDA CURDRV ;get current drive
MOV B,A
LDA MXDRV ;get max drive
CMP B ;same?
JZ EXIT ;if so, we're done
MOV A,B ;if not, get CURDRV back in A
INR A ;...bump current drive counter
STA CURDRV ;...save it
MOV E,A ;...and log onto the next drive
MVI C,SELDISK
CALL BDOS
XRA A ;zero user area count
STA CURUSR
MOV E,A ;...and log onto user 0
MVI C,USRSTAT
CALL BDOS
CALL CRLF ;new line
LDA CURCOL ;get current column count
ORA A ;set flags
JZ LFORFL ;it's been reset by ZCOL already
;so look for next file
XRA A ;else reset
STA CURCOL
CALL CRLF ;new line
JMP LFORFL ;look for file
;
IF DESCRIP
DESCAL: CALL DESFN ;call the descriptive filename routine
JMP MORETGO ;and go back
ENDIF ;descrip
;
EXIT: LXI H,QMSG ;tell how to get help
CALL IPBUF
;
EXIT1: LDA DEFUSR ;get default user area back
MOV E,A
MVI C,USRSTAT
CALL BDOS ;set it
;
LDA DEFDRV ;get default drive back
MOV E,A
MVI C,SELDISK
CALL BDOS ;set it
;
CALL CRLF
;
LHLD OLDSP ;recover CP/M SP
SPHL ;set it
RET ;and exit quietly to CP/M
;
ABORT: MVI C,PBUF ;print abort message
LXI D,AMSG
CALL BDOS
JMP EXIT1
;
;************************
;*** CONSOLE MESSAGES ***
;************************
;
SIGNON: DB CR,LF,'MAP v',VERS+'0','.',(REV/10)+'0',(REV MOD 10)+'0',', '
DB (MONTH/10)+'0',(MONTH MOD 10)+'0','-'
DB (DAY/10)+'0',(DAY MOD 10)+'0','-'
DB '19',(YEAR/10)+'0',(YEAR MOD 10)+'0'
DB CR,LF,'from Horn Engineering Associates',CR,LF,LF
DB 'Ctrl-',ACHAR+'@'
DB ' to abort, Ctrl-',XOFF+'@'
DB ' to pause...',CR,LF,LF,'$'
;
AMSG: DB CR,LF,LF,'++ Aborted ++',CR,LF,LF,'$'
;
SAMSG: DB 'Illegal drive...',CR,LF,'$'
;
DRMSG: DB 'MAP of drive $'
;
QMSG: DB CR,LF,LF,'Type ''MAP ?'' for assistance with using this'
DB ' program.',CR,LF,'$'
;
IF DESCRIP
;
NULMSG: DB 29,'Description not available...$'
; ^ ^
; # of bytes in message MUST END WITH $
;
ENDIF
;
;**************************************
;*** THE PRIVATE FILE CONTROL BLOCK ***
;**************************************
;
FCB:
FCB$DISK: DB 0 ;preset default drive
FCB$NAME: DB '-???????' ;preset default file name
FCB$TYP DB '???' ;file type
FCB$EXTENT: DB 0 ;preset extent
FCB$RESV: DB 0,0 ;reserved by CP/M
FCB$RECUSED: DB 0 ;records used
FCB$ABUSED: DB 0,0,0,0,0,0,0,0 ;assigned blocks
DB 0,0,0,0,0,0,0,0
FCB$SEQREC: DB 0 ;sequential record number
FCB$RANREC: DW 0 ;random record number
FCB$RANRECO: DB 0 ;record overflow
;
;*******************
;*** SUBROUTINES ***
;*******************
;
; PRINTFN - Presents all pertinent section data
;
PRINTFN:
INX H ;Point past "-"
INX H
PUSH H ;save it for later
;
; Ok, now, where is the section?
;
LDA CURDRV ;get current drive
;
ADI 'A' ;make drive ASCII
CALL PCHAR ;print it
LDA CURUSR ;get current user
CALL PASC ;make # ASCII
;
MVI A,' '
CALL PCHAR
MVI A,'='
CALL PCHAR
MVI A,' '
CALL PCHAR ;print " = "
;
; Now, print the section name
;
POP H
MVI C,7
CALL PSTRING
;
; Check the column counter and act accordingly. Don't want a messy
; screen
;
LDA CURCOL ;get the current column
CPI NUMCOL-1 ;printed all on this line yet?
JZ ZCOL ;yep, zero counter
INR A ;nope, bump counter
STA CURCOL ;and save it
;
MVI A,' ' ;print " | " between section names
CALL PCHAR
MVI A,FENCE
CALL PCHAR
MVI A,' '
CALL PCHAR
RET ;back we go
;
ZCOL: XRA A ;zero A
STA CURCOL ;store it as the current column
CALL CRLF ;end of line
RET
;
IF DESCRIP
;
; DESFN - Print filename and description
;
DESFN: INX H ;Point past "-"
INX H
PUSH H ;save it for later
;
; Ok, now, where is the section?
;
LDA CURDRV ;get current drive
;
ADI 'A' ;make drive ASCII
CALL PCHAR ;print it
LDA CURUSR ;get current user
CALL PASC ;make # ASCII
;
MVI A,' '
CALL PCHAR
MVI A,'='
CALL PCHAR
MVI A,' '
CALL PCHAR ;print " = "
;
; Now, print the section name
;
POP H
PUSH H
MVI C,7
CALL PSTRING
MVI A,' ' ;make sure at least 2 spaces between
CALL PCHAR ;filename and description
MVI A,' '
CALL PCHAR
;
; Now we're ready to move the filename into the FCB, open it,
; and read the description (if any).
;
CALL ZFCB ;first clean things up
POP H ;recover filename
DCX H ;get the "-" back
LXI B,11 ;# of characters to move
LXI D,FCB+1 ;where to move them
CALL MOVE ;do it
;
; Now open the file and read 1 record
;
MVI C,OPENF ;BDOS open file
LXI D,FCB
CALL BDOS
;
MVI C,READF ;BDOS read sequential
LXI D,FCB
CALL BDOS
ORA A ;set flags
CNZ NULFLE ;must be empty file
;
; Close the file (even though we don't really have to)
;
MVI C,CLOSEF ;BDOS close file
LXI D,FCB
CALL BDOS
;
; Now display information
;
LXI H,DEFDMA
CALL IPBUF
;
CALL CRLF ;new line
;
RET ;go home
;
NULFLE: LDA NULMSG ;get # of bytes in message
MOV C,A ;put it in BC
MOV B,0
LXI H,NULMSG+1 ;point to message
LXI D,DEFDMA ;put it in the DMA
CALL MOVE ;move it
RET ;go home to Kansas
;
ENDIF ;descrip
;
; ZFCB - Zero the 36 bytes in the designated FCB
;
ZFCB: MVI C,36
LXI H,FCB ;point to FCB
ZLOOP: MVI M,0 ;enter a zero
INX H ;bump pointer
DCR C ;bump down counter
JNZ ZLOOP ;loop for more
RET
;
; FINDFN - Locates directory file name in DMA after directory
; search. Returns pointer in HL. Entry with directory code in A.
;
FINDFN: ADD A ;*2
ADD A ;*4
ADD A ;*8
ADD A ;*16
ADD A ;*32
MOV E,A ;offset to DE
MVI D,0
DAD D ;add to HL
RET
;
; MOVE - Moves the number of characters in BC from (HL) to (DE)
;
MOVE: MOV A,M ;get char from (HL)
STAX D ;put in (DE)
INX H
INX D
DCX B
MOV A,C ;get LS count byte
ORA B ;both B & C zero?
JNZ MOVE ;loop til done
RET
;
; PSTRING - Prints string pointed to by HL.
; Number of characters to print in C
;
PSTRING:
PUSH H ;save string pointer
PUSH B ;save count
MOV A,M ;get a character
CALL PCHAR ;print it
POP B ;restore count
POP H ;restore pointer
INX H ;bump it
DCR C ;done?
JNZ PSTRING ;if not
RET
;
; IPBUF - Same is BDOS PBUF, 'cept it checks for abort character
; and expects the print string to be pointed to by HL
;
IPBUF: PUSH H ;save string pointer
MOV A,M ;get a character
CPI '$' ;is that all?
JZ PDONE ;if so, quit
CALL PCHAR ;if not, print a character
POP H ;else restore counter
INX H ;bump up
JMP IPBUF ;go again
PDONE: POP H ;save stack
RET
;
;
; CRLF - Puts a CR and LF out to console
;
CRLF: MVI A,CR
CALL PCHAR
MVI A,LF
CALL PCHAR
RET
;
; PCHAR - Prints the character in A
;
PCHAR: PUSH PSW
;
CALL GETCON ;see if a key pressed
CPI ACHAR ;if so, was it an abort request?
JZ ABORT ;then abort
CPI XOFF ;XOFF?
CZ PAUSE ;then pause until key pressed
;
POP PSW
MOV E,A
MVI C,DIRCON
CALL BDOS
RET
;
; PASC - Unpacks two ascii decimal digits from value in A
; displays them on the console with no leading 0's.
;
PASC: MVI C,0 ;initialize quotient
PASC1: SUI 10 ;repeatedly subtract 10
JC PASC2 ;if underflow
INR C ;else increment the quotient
JMP PASC1 ;and subtract again
;
PASC2: ADI 10 ;Correct the underflow
PUSH PSW ;save the remainder
MOV A,C ;get the quotient
ORA A ;set flags
JZ ONENUM ;only one number to display
ADI 030H ;adjust to ascii
CALL PCHAR ;print it
POP PSW ;get remainder
ADI 030H ;make ascii
CALL PCHAR ;print it
;
MVI A,':' ;print a ":" after the drive/user
CALL PCHAR
;
RET
;
ONENUM: POP PSW ;get the #
ADI 030H ;make ASCII
CALL PCHAR ;print it
MVI A,':' ;and a colon
CALL PCHAR
MVI A,' ' ;and a space to make up for the leading
CALL PCHAR ;0
;
RET ;go home
;
GETCON: MVI C,DIRCON ;BDOS direct console I/O
MVI E,0FFH ;for input
CALL BDOS ;do it
RET
;
PAUSE: PUSH PSW ;save EVERYTHING
PUSH B
PUSH D
PUSH H
;
PLOOP: MVI C,DIRCON ;direct console I/O
MVI E,0FFH ;input
CALL BDOS
ORA A
JZ PLOOP ;wait until key pressed
;
POP H ;get everything back
POP D
POP B
POP PSW
;
RET
;
; SPCDRV - if a specific drive chosen for map, this routine checks
; MXDRV to see if possible, and if so sets up that drive
; as default.
;
SPCDRV: LDA MXDRV ;get max drive
MOV B,A ;move to B
LDA DFCB ;get drive chosen
DCR A ;bump down
INR B ;and fix B for compare
CMP B ;compare the two
JNC SPCABT ;not ok, exit
MOV E,A
MVI C,SELDISK ;select disk
CALL BDOS ;do it
;
LXI H,DRMSG ;Say MAP of drive x:
CALL IPBUF
LDA DFCB ;Get MAP drive back
DCR A ;bump down
STA CURDRV ;store it for display
ADI 'A' ;Make ASCII
CALL PCHAR ;print it
MVI A,':' ;...and a colon
CALL PCHAR
;
CALL CRLF
CALL CRLF
;
RET
;
SPCABT: LXI H,SAMSG ;print "drive out of range"
CALL IPBUF
JMP EXIT ;and exit to CP/M.
;
HELP: LXI H,HMSG ;print help message
CALL IPBUF
JMP EXIT1 ;and exit to CP/M
;
HMSG: DB CR,LF,LF
DB 'Examples of use:',CR,LF,LF
DB ' MAP presents a map of all drives/'
DB 'user-areas, no'
DB CR,LF,' descriptions.'
IF DESCRIP
DB CR,LF,LF
DB ' MAP D presents a map of all drives/'
DB 'user-areas with'
DB CR,LF,' descriptions.'
ENDIF
DB CR,LF,LF
DB ' MAP B: presents a map of drive B:,'
DB ' no descriptions.'
IF DESCRIP
DB CR,LF,LF
DB ' MAP B:D presents a map of drive B:,'
DB ' with descriptions.'
ENDIF
DB CR,LF,'$'
;
;
;************************
;*** UNITIALIZED AREA ***
;************************
;
DEFUSR: DB 0 ;storage for default user area
DEFDRV: DB 0 ;default drive
CURUSR: DB 0 ;current user area
CURDRV: DB 0 ;current drive
;
CURCOL: DB 0 ;current column
;
IF DESCRIP
DESFLG: DB 0 ;marks descriptive mode
ENDIF ;descrip
;
OLDSP: DW 0
DS 64 ;our private stack area
STACK: EQU $
;
END
f