home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
catlog
/
label.asm
< prev
next >
Wrap
Assembly Source File
|
1994-07-13
|
14KB
|
621 lines
;**************** BYPASS CUSTOMIZING SECTION ************************
ORG 100H
JMP START
;********************************************************************
;
; TITLE: DLABEL.ASM Author: R.Bascom
;
P$LOGON DB 'DLABEL 1.0 24/11/85',0Dh,0Ah,0Ah,'$'
;
; PURPOSE: To print an alphabetically sorted disk directory on a
; label in small (condensed) font.
;
; FEATURE: (1) The condensed font is used for the main directory.
; (2) The program can be repeated, using the same drive
; and optional filenames. Allowing for labeling
; numerous disks at one time.
;
; USAGE: DLABELER [D][FILENAME.TYP]
;
; D = disk (i.e. A:, B:, ect)
; filename.typ = filename using conventional wildcards
;
TRUE EQU 0FFh
FALSE EQU 00h
;
;*********************** PROGRAM EQUATES ****************************
;
MAXFILS EQU 255 ;maximum number of directory entries
BDOS EQU 5
FCB EQU 5Ch ;first file control block
;
CR EQU 0Dh ;carriage return
LF EQU 0Ah ;line feed
ESC EQU 1Bh ;escape
BELL EQU 7 ;bell
CTL$C EQU 3 ;end of text
;
;
;*********************** BDOS EQUATES *******************************
;
B$CONIN EQU 1 ;read CON byte
B$CONOUT EQU 2 ;write CON byte
B$LISTOUT EQU 5 ;write PRN byte
B$DIRCONIO EQU 6 ;direct CON input and output
B$PRINTS EQU 9 ;write a $ terminated string to CON
B$CONST EQU 11 ;read CON status
B$RESETDSK EQU 13 ;reset disk system
B$SEARCHF EQU 17 ;search for first name match
B$SEARCHN EQU 18 ;search for next name match
;
;******************** CUSTOMIZING SECTION ***************************
;
V$COLUMNS DB 60 ;number of label columns (maximum of
;250 columns) based on char per inch
;of condensed fontè;
V$ROWS DB 8 ;number of label rows based on the
;line spacing
;
V$SPACES DB 1 ;lines btwn labels (based on line spacing)
;
;This string is the divider fence that is printed between filenames and can
;be changed as desired. The divider is not printed before the first or after
;the last filename on a line. String can have a maximum of of 5 chars and
;must end with $. NOTE the first byte is the char count.
;
V$FENCE DB 3 ;char count (# of divider chars)
DB ' | ' ;the divider chars
DB '$' ;end of string
DB 0,0 ;spares
;
;******************** PRINTER CONTROL STRINGS ***********************
;
;This string is used to set line spacing (usually to 9 LPI) and small print
;font (usually condensed). It may include any printer characteristics you
;desire. String can have a maximum of 15 chars and must end with $.
;
V$CONDENST:
DB ESC,'B',3 ;set pitch to condensed (17 CPI)
DB ESC,'A',8 ;set line spacing to 8/72
DB '$' ;end of string
DB 0,0,0,0,0,0,0,0,0,0,0 ;spares
;
;This string is used to return printer to its normal line spacing (usually
;6 LPI) and normal print font (usually 10 CPI). It may also include any
;printer characteristics you desire. String can have a maximum of 15 chars
;and must end with $.
;
V$RESETST:
DB ESC,'@' ;reset the printer
DB '$' ;end of string
DB 0,0,0,0,0,0,0,0,0,0,0,0 ;spares
;
;****************** END OF CUSTOMIZING SECTION *************************
;***********************************************************************
;***********************************************************************
; M A I N P R O G R A M
;***********************************************************************
;
START:
LXI SP,STACK ;get new stack
;
;save disk for restarting later
;
LXI H,FCB
MOV A,M
STA SAVEFCB
;
;type logonè;
LXI D,P$LOGON
MVI C,B$PRINTS
CALL BDOS
;----------------
;
;calculate label width (in number of filenames/fences across the label)
;
LDA V$FENCE ;number of fence chars
MVI H,12 ;plus number chars for filename
ADD H
MOV B,A ;B = number of chars per filename/fence
;
XRA A ;clear flags
LDA V$COLUMNS ;number of columns
CPI 251 ;maximum number of columns is 250 (FAh)
JNC COLERR ;err if max num of colums is exceeded
MOV H,A
LDA V$FENCE ;plus length of one fence
ADD H ;A = line length and one fence length
;
MVI C,0 ;C is the dividend
ANA A ;prepare for divide - clear carry
;
;mod divide A by B
;
LWID:
SUB B ;repeated subtraction
JC LWID1
INR C ;count the number of subtractions
JMP LWID
LWID1:
MOV A,C ;
CPI 0 ;check for zero filename width
JZ LWIDERR ; then error
STA LBLWID ; else save the width
;----------------
;
;check number of rows
;
CKROWS:
LDA V$ROWS
CPI 0
JZ ROWERR ;err if zero rows calculated
;----------------
;
;set maximum number of files
;
SETMFIL:
LDA V$ROWS ;get the number of filenames wide
MOV B,A
LDA LBLWID ;get the number of rows
MOV C,A
XRA A ;zero A and clear carry
SETMFIL1:è ADD C
JC MFILERR ;error if count exceeds 255 (FFh)
DCR B
JNZ SETMFIL1
STA MAXFIL ;maximum possible filenames on a label
;----------------
;
;got something - set up the printer
;
LXI H,V$CONDENST ;set condensed print
CALL WRPRNT ;send initialization string to printer
;----------------
;
;able to restart the program here using the same command tail
;
REINIT:
MVI A,0
STA COUNT ;clear counters
STA SCOUNT
STA WCOUNT
STA LCOUNT
STA SWITCH
;----------------
;
;does the command tail exist?
;
LDA SAVEFCB ;restore disk
STA FCB
LXI H,FCB+1 ;set pointer first char of FCB
MOV A,M
CPI ' '
JNZ GOTFCB ;yes, comand tail exists
;
;command tail does not exist
;
MVI B,11 ;initial filename and filetype count
QLOOP:
MVI M,'?' ;store '?' in FCB
INX H
DCR B
JNZ QLOOP
;
;look up the FCB in the directory
;
GOTFCB:
LDA V$ROWS ;initialize # of lines remaining on
STA LCOUNT ; label to full count
MVI C,B$SEARCHF ;search for first name match
LXI D,FCB
CALL BDOS ;read first
INR A ;were there any?
STA TEMP ;save extent
JZ FNFERR ;didn't get any
LDA TEMP ;reload extent
;----------------è;
;point to directory entry
;
SOME:
DCR A ;undo previous 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,81H ;point to buffer (skip to FN/FT)
ADD L ;point to entry
MOV L,A ;save (can't carry to H)
LDA MAXFIL ;is there room in table for entry ?
MOV B,A
LDA COUNT
CMP B
JZ TMFERR ;err - too many files for the label
;
;move entry to table
;
XCHG ;entry to DE
LHLD NEXTT ;next table entry to HL
MVI B,31 ;entry length
TMOVE:
LDAX D ;get entry char
MOV M,A ;store in table
INX D
INX H
DCR B ;more?
JNZ TMOVE
SHLD NEXTT ;save updated table adx
LDA COUNT ;get previous count
INR A
STA COUNT
;
;read more directory entries
;
MVI C,B$SEARCHN ;search for next name match
LXI D,FCB
CALL BDOS ;read dir entry
INR A ;check for end (0FFh)
JNZ SOME ;more
;----------------
;
;sort filenames
;
LDA COUNT ;init the order table
STA SCOUNT ;save as # to sort
LXI H,ORDER
LXI D,TABLE
LXI B,31 ;entry length
BLDORD:
MOV M,E ;save LO order adxè INX H
MOV M,D ;save HI order adx
INX H
XCHG ;table adx to HL
DAD B ;point to next entry
XCHG
DCR A ;more?
JNZ BLDORD ; yes
SORT XRA A ;get a zero
STA SWITCH ;show none switched
LDA SCOUNT ;get count
DCR A ;use 1 less
STA TEMP ;save # to compare
STA SCOUNT ;save highest entry
JZ DONE ;exit if no more
LXI H,ORDER ;point to order table
SORTLP CALL COMPR ;compare 2 entries
CM SWAP ;swap if not in order
INX H ;bump order
INX H ; table pointer
LDA TEMP ;get count
DCR A
STA TEMP
JNZ SORTLP ;continue
;
;one pass of sort done
;
LDA SWITCH ;any swaps done?
ORA A
JNZ SORT
;
;sort is all done - print entries
;
DONE LXI D,ORDER ;DE point to 1st entry in ORDER
PUSH D ;Save DE
LDA LBLWID ;get initial count of filenames per line
STA WCOUNT ; and save it for a counter
;----------------
;
;print the label
;
PRINT:
MVI C,B$CONST ;check status of keyboard
CALL BDOS ;are any keys pressed?
DCR A
JZ 0 ;yes, abort
POP D ;restore DE
LDAX D ;no - get memory byte addressed by DE
MOV L,A ; and put in L
INX D ;move to next location in ORDER
LDAX D ;get memory byte addressed by DE
MOV H,A ; and put in L
INX D ;move to next location in ORDER
PUSH D ; and save DE
MVI B,8 ;file name lengthè CALL TYPEIT ;type filename
MVI E,'.'
CALL TYPE
MVI B,3 ;get the filetype
CALL TYPEIT
;
;check for last directory entry
;
LDA COUNT ;decrement count of file names to print
DCR A
STA COUNT
JZ TOP ;exit if count is zero
;
;check for maximum directory entries on current row
;
WFENCE LDA WCOUNT ;decrement # of entries left on this
DCR A ; line for filenames
STA WCOUNT
JZ NXTLIN ;no more room on line so skip divider fence
;
;divider fence goes to the printer
;
LXI H,V$FENCE+1 ;since there is room for another filename
CALL WRPRNT ; put divider fence btwn filenames
JMP PRINT
;
;end of current line
;
NXTLIN:
CALL CRLF ;output CR/LF
JMP PRINT ;go to print next line and file name
;----------------
;
;completed printing the directory entries, now set up for next label
;
TOP:
LDA LCOUNT ;number of remaining lines in the label
CPI 0 ;done?
JZ TOP2 ;yes, then space out btwn labels
CALL CRLF ;no, send out CR/LF
JMP TOP ;try again
;
TOP2:
LDA V$SPACES ;get number of lines btween labels
TOP3:
CPI 0 ;done
JZ AGAIN ;yes, then ask if another label desired
PUSH A ;no, spaceing line count
CALL CRLF ;send out CR/LF
POP A ;restore spacing line count
DCR A ;decrement count
JMP TOP3 ;try again
;----------------
;
;do another label or exit?è;
AGAIN:
LDA SAVEFCB
CPI 0
JNZ AGAIN1 ;zero means use current disk
LDA 4 ;get curent disk and user
ANI 0Fh ;bits 0-3 are the current disk
INR A
AGAIN1:
ADI '@' ;change to alfa 1->A, 2->B,...ect.
STA CDR1 ;set drive in prompt
CALL ILPRT
DB 'Mount another DISK TO BE LABELED in Drive '
CDR1:
DB 'A:' ;hot-patched to show correct drive
DB ' Ready? (Y/N): ',0
AGAIN2:
MVI C,B$DIRCONIO ;direct input from keyboard
MVI E,TRUE ; true = read keyboard char
CALL BDOS
CPI 'N' ;N exits
JZ EXIT
CPI 'n' ;and little n too
JZ EXIT
CPI ' ' ;accept space as yes
JZ AGAIN3
CPI CR ;accept CR as yes
JZ AGAIN3
CPI 'Y' ;accept Y
JZ AGAIN3
CPI 'y' ;and little y
JNZ AGAIN2 ;anything else is not accepted
;
AGAIN3:
CALL ILPRT
DB CR,' '
DB ' ',CR,0
MVI C,B$RESETDSK ;reset the disks
CALL BDOS
JMP REINIT
;----------------
;
;reset the printer and return to CP/M
;
EXIT:
MVI A,CR ;CR
CALL CRTOUT
MVI A,LF ;LF
CALL CRTOUT
LXI H,V$RESETST ;reset printer to Normal mode
CALL WRPRNT
JMP 0
;--------------------------------------------------------------------
;
; S U B R O U T I N E Sè;
; Inline print subroutine
;
ILPRT: XTHL ;get starting address of string to 'HL'
;
ILPLP: MOV A,M
PUSH H
CALL CRTOUT ;show the character on the CRT
POP H
INX H
MOV A,M
ORA A
JNZ ILPLP
INX H
XTHL ;return address to top of stack
RET
;----------------
;
; Displays one character on the CRT
;
CRTOUT: PUSH PSW ;save the character
MVI C,B$CONOUT
MOV E,A ;get the character into 'E' reg.
CALL BDOS ;show the character on the crt
POP PSW ;get the character back
RET
;----------------
;
;char in E goes to the printer
;
TYPE PUSH B
PUSH D
PUSH H
MVI C,B$LISTOUT
CALL BDOS
POP H
POP D
POP B
RET
;----------------
;
;string specified by HL goes to the printer
;
WRPRNT MVI A,'$'
CMP M
RZ
MOV E,M
CALL TYPE
INX H
JMP WRPRNT
;----------------
;
;string specified by HL and length in B goes to the printer
;with any tag bits stripped off
;èTYPEIT:
MOV A,M ;get rid of any tag bits in name
ANI 07Fh ; for print out
MOV E,A
CALL TYPE
INX H
DCR B
JNZ TYPEIT
RET
;----------------
;
;CR/LF go to the printer and
;reset label width counter and decrement line counter
;
CRLF:
MVI E,CR ;get CR character in E
CALL TYPE ; and output it
MVI E,LF ;get LF character in E
CALL TYPE ; and output it
;
LDA LBLWID ;reset number of filenames across label
STA WCOUNT
;
LDA LCOUNT ;decrement line count
DCR A
STA LCOUNT
;
RET
;----------------
;
;compare routine for sort
;
COMPR:
PUSH H ;save table adx
MOV E,M ;load LO
INX H
MOV D,M ;load HI
INX H
MOV C,M
INX H
MOV B,M
;
;BC and DE now point to entries to be compared
;
XCHG
CMPLP:
MOV A,M ;get rid of any tag bit in name
ANI 07FH ; before comparing names for sort
MOV M,A
LDAX B
ANI 07FH
CMP M
INX H
INX B
JZ CMPLPè POP H
RET ;cond code tells all
;----------------
;
;swap entries in the order table
;
SWAP:
MVI A,1
STA SWITCH ;show a swap was made
MOV C,M
INX H
PUSH H ;save table adx+1
MOV B,M
INX H
MOV E,M
MOV M,C
INX H
MOV D,M
MOV M,B
POP H
MOV M,D
DCX H ;back pointer to correct location
MOV M,E
RET
;----------------
;
; E R R O R R O U T I N E S
;
COLERR:
CALL ILPRT
DB CR,LF,'++ YOUR SETTINGS ALLOW MORE THAN 250 COLUMNS ++'
DB BELL,0
JMP 0
;
LWIDERR:
CALL ILPRT
DB CR,LF,'++ YOUR SETTINGS DO NOT ALLOW AT LEAST 12 COLUMNS ++'
DB BELL,0
JMP 0
;
ROWERR:
CALL ILPRT
DB CR,LF,'++ YOUR SETTINGS DO NOT ALLOW ANY ROWS ON A LABEL ++'
DB BELL,0
JMP 0
;
MFILERR:
CALL ILPRT
DB CR,LF,'++ YOUR SETTINGS ALLOW MORE THAN 255 FILENAMES ++'
DB BELL,0
JMP 0
;
FNFERR:
CALL ILPRT
DB CR,LF,'++ FILE(S) NOT FOUND ++',CR,LF,0è JMP AGAIN ;try another disk or exit
;
TMFERR:
CALL ILPRT
DB CR,LF,'++ TOO MANY FILENAMES ++',CR,LF,0
JMP AGAIN ;try another disk or exit
;
;
;
;
;
NEXTT DW TABLE ;next table entry
LBLWID DB 0 ;label width = (V$COLUMNS+V$FENCE)/(12+V$FENCE)
MAXFIL DB 0 ;max number of disk filenames on one label
COUNT DB 0 ;entry count
SCOUNT DB 0 ;# to sort
WCOUNT DB 0 ;# of filename sapces left across line
LCOUNT DB 0 ;# of lines remaining on this Label
SWITCH DB 0 ;swap switch for sort
SAVEFCB DB 0 ;save disk FCB
TEMP DS 1
ORDER DS 2*MAXFILS ;order table
DS 50 ;stack area
STACK
TABLE DB 0 ;read entries from here to top of BDOS
END 100H