.Z80 ; Zilog mnemonics CSEG ; for M80 assembler ; versno equ '0' revno equ '5' ; ; MCAT Version 5, DISK CATALOG PROGRAM - (CP/M 3.0 COMPATIBLE) ; ; by Harold F. Bower ; ; Derived from MCAT45.ASM, 1984 by Irv Hoff ; ; Many of the routines to access DateStamper (tm) provided ; by Bridger Mitchell of Plu*Perfect Systems ; ; NOTE: DateStamper is trademarked by Plu*Perfect Systems. ; CP/M is trademarked by Digital Research, Inc. ;----------------------------------------------------------------------- ; ; This catalog program updates a 'MAST.CAT' file previously created with ; an editor, or from MCAT with a built-in command. A companion program, ; XCAT, can then be used to produce human-readable cross-reference list- ; ings on the Console device, Printer, or to a user-definable disk file. ; ; Each disk to be processed must have a unique disk "ID". This ID must ; be a disk file beginning with a leading dash ("-"), and should have a ; type field different from any other disk ID. As a suggestion, the ID ; could reflect a unique "serial number" assigned to each disk. While ; characters are accepted in the name portion (after the leading dash) ; if the ID file, it is recommended that it be blank to insure that this ; file is sorted in its proper position in before all others. If an ; attempt is made to catalog a disk that does not contain a valid ID, ; MCAT will allow you to add one and re-try the catalog operation. When ; added in this way, the name field is always blank except for the lead- ; ing blank. The disk ID can also be added from CP/M 1.x or 2.x by ; saving a null-length file as: ; ; A>SAVE 0 -.123 ; ;* NOTE: For CP/M 3.0, the SAVE command is not used in the same way. ;* Since you can not save a file with 0 bytes. A special program cal- ;* led NULL.ASM was written by Guy Gamble that will allow easy naming ;* of CP/M 3.0 disks. ; ; A typical 'MAST.CAT' file might have a few names in the "IGNORE" list ; (those files which are plentiful enough you do not need to know their ; quantity or location). These files must be contained in parentheses ; at the beginning of the catalog. Version 5 of MCAT has added a spec- ; ial field at the beginning of the IGNORE list to insure that optional ; formatting parameters from MAST.CAT match those in the MCAT program. ; The format of these parameters is described below. Ambiguous names ; are also accepted to allow tailored catalogs by IGNOREing whole cata- ; gories of files. An example of an IGNORE list is: ; ; ({;|85} (note opening left parenthesis) ; !!!TIME&.DAT (excluded when used with DateStamper) ; LOAD.COM ; *.MAC (exclude all .MAC files) ; STAT.COM) (note closing right parenthesis, ; which must be followed with a RET) ; ; If all files are to be cataloged, the IGNORE list would be: ; ; ({;|85}) followed with a RET ; ; HOW TO USE: ; ---------- ; ; MCAT Catalogs the default drive to a MAST.CAT at default disk ; and user location from the Menu Mode. Repetative opera- ; tions may be performed, catalogs initialized, and para- ; meters varied. ; MCAT .... ; Calls MCAT for cataloging a single operation with the ; parameters passed in the option list. After the single ; pass, operation returns to CP/M. ; ; TECHNICAL DESCRIPTION: ; ---------------------- ; ; Version 5 of MCAT incorporates interfaces to Plu*Perfect's ; DateStamper system which adds Time and Date-stamping provisions to ; standard CP/M 2.2. An additional six characters containing day, ; month and year are optionally added to each entry of the MAST.CAT file ; to provide a way to recover the date information after cataloging. A ; corresponding change has been added to XCAT Version 5 to accomodate ; the added length of entries, and print date information if requested. ; ; One more feature has been added to pass Format data along to the ; companion XCAT Cross-reference program (Ver 5). MAST.CAT files ; initiated from within MCAT (Using the ^I command) contain a special ; field and optional file names in the IGNORE list. This field contains ; flags to indicate whether MAST.CAT contains USER and DATE information ; with the basic File name, type and disk data. If DATE information is ; included, the Current Year is also included for future use in reducing ; the size of MAST.CAT. Variations of the IGNORE list field are: ; ; ({;|85}) Both USER and DATES included, CURYR = 85 ; ({;}) Only USER information included ; ({|85}) Only DATES included, CURYR = 85 ; ({}) Neither USER nor DATES included. ; ; THIS SPECIAL FIELD IS REQUIRED ON ALL CATALOGS TO INSURE THE CORRECT ; FORMAT IS BEING USED. It should be added to any existing catalogs ; before any update is performed. ; ; Additional changes to MCAT include a proposed standard 'header' at ; the beginning of the code which defines various cursor addressing ; commands. If these entries are blank (null), then the default opera- ; tion with carriage return/line feed sequences scrolls the screen thru ; the cataloging sequence. If present, the screen is dynamically alloca- ; ted into a series of 'windows' which depict the status of various parts ; of MCAT. ; ; Default settings active when MCAT is called can be changed by control ; characters from within the program. The basic functions (except for ; screen re-draw) are listed in abbreviated form on the second line of ; the top window (if screen addressing is available) or second printed ; line (if in line-oriented mode). These commands are: ; ; (Control-D) Change the disk drive to catalog. A single character ; representing a disk drive is expected. ; (Control-L) Log the disk/user area for MAST.CAT. A character, char- ; acter and number, or number only are all acceptable. ; (Control-I) Create a MAST.CAT with optional IGNORE list. A MAST.CAT ; is created on the selected drive/user area. If one ; already exists, it is renamed to MAST.BAK. The user is ; then prompted for names to be added to the IGNORE list. ; A single carriage return terminates the command. ; (Control-F) Specify catalog with or without USER and DATE entries. ; The user is asked whether each parameter is to be used ; in the catalog. Yes/No answers are accepted. ; (Control-R) Remove all entries for a specified disk. The user is ; prompted for a 3-character disk ID. This is the type ; field of the ID file on a disk. If characters exist in ; the name portion of the ID file, they are ignored. ; (Control-Z) Redraw the Screen. ; ; Bypassing the menus can be done by passing parameters to MCAT on the ; command line as: ; ; MCAT b10 $DU - Catalog the a: drive with MAST.CAT in user ; area 10 on drive B:. Include user areas and ; date information. ; MCAT >c: $U - Catalog the default drive to Drive C in the ; default area with only names and user areas. ; MCAT $UD - Catalog the default drive to MAST.CAT in the ; default drive/user area. Include both date ; and user area information.> ; ; NOTE: The colon after the drive designator is optional. The drive ; designator before the ID of the MAST.CAT disk/user is optional. ; The dollar sign ($) denotes the options for MAST.CAT fields. ; The "<" symbol preceeds the drive designator to catalog, and ; the ">" symbol shows the disk and user area where a MAST.CAT ; catalog is located. ; ; Earlier limitations in MCAT which required re-assembly to increase ; the number of directory names has been eliminated by using the DIRMAX ; field of the Disk Parameter Block from CP/M 2.2. Reassembly is now ; only necessary to change the maximum number of names in the IGNORE list. ; ; Harold F. Bower 'Hal' WA5JAY ; Box 946 ; APO NY 09128 ; ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; 08/10/85 Added checking for duplicate disk IDs and ambiguous names ; v5.05 to IGNORE list. Moved TDBUFF/pointer storage above NABUF ; and made IGNORE buffer fixed-length records. Changed date ; fields in In/Out records to 3-char BCD, deleted MODAT buff. ; Modified Names buffer, In/Out routines, compressed all to ; handle 2048 directory entries with 53K or greater CP/M. ; - H. F. Bower ; ; 07/25/85 Fixed date ptr update for erased entries. Fixed buffer ; v5.04 allocation for DIRMAX <> power of 2. Removed advance ; test of MAST.CAT existence when disk-swapping in a single ; drive. - B. Mitchell ; ; 07/21/85 Replaced sort routine with shellsort of pointers. ; v5.03 Shortened time-date buffer to 3 chars/entry. ; Pointers and dates share same TDBUFF buffer. ; Default fast disk-reset and option. - B. Mitchell ; ; 07/19/85 Fixed allocation of buffer size at SHFT0 to handle up ; v5.02 to 1024-entry directories. Initialize extent byte ; in tdfcb. - Bower/Mitchell ; ; 06/30/85 Bug-fixing and added screen-redraw, and entry of IGNORE ; v5.01 names when Initializing a MAST.CAT. Redefined screen ; window layout. - H. F. Bower ; ; 06/15/85 Basic release. - H. F. Bower ; v5.00 ; ;-------------------------- History ---------------------------------- ; 08/29/84 Fixed NEXTS: so large disks with more than 256 names will ; v4.5 be able to use the program consistently. Restored program ; to my original format. - Irv Hoff ; ; 07/04/84 Added code to ignore CP/M 3.0 time and date stamping. ; v4.4 - Guy Gamble ; ; 03/29/84 Restored to work with all computers, not just the Osborne ; v4.3 Executive. Other changes. - Irv Hoff ; ; 03/19/84 Added Cp/M 3.0 free disk space routine from MDM7. ; v4.2 - Guy Gamble ; ; 01/21/84 Added suggestion by Bill Boulton for large directories. ; v4.1 - Irv Hoff ; ; 11/20/83 Released to the public domain. ; v4.0 - Irv Hoff ; ; ??/??/?? CAT, QCAT, ... original versions by ; v 1.0 - Ward Christensen ; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; NO EQU 0 YES EQU NOT NO ; TRUE EQU YES FALSE EQU NO ; ; ASCII Character Equates ; BELL EQU 07H ; Bell character BS EQU 08H ; Backspace character LF EQU 0AH ; Line Feed character CR EQU 0DH ; Carriage Return character EOF EQU 1AH ; End-of-File marker ESC EQU 1BH ; Escape Character DEL EQU 7FH ; Delete Character ; ;..... TPA EQU 100H ; Starting address of Transient Program ; Area M80 EQU TRUE ; Set flag TRUE if using Microsoft's M80. ; if NOT M80 ; No ORG if using Macro-80 assembler ORG TPA ;normal program start endif ; ; JP START ;program start ; ;======================================================================= ; DateStamper TERMCAP ; These locations MUST remain in the order and sizes indicated, and must ; immediately follow the initial JUMP instruction in the program in ; order for the SETTERM utility to properly configure MCAT to various ; terminal definitions. If manual configuration is done, be sure you do ; NOT change the length or ordering of the definitions. ;----------------------------------------------------------------------- ; ROWNO: defb 0 ; Terminal number in data base & rowno TNAME: defb 'Heath 19' defb 0,0,0,0, 0,0,0 ; 15 bytes ; THEIGHT: defb 24 ; Rows TWIDTH: defb 80 ; Columns USELAST: defb 0 ; Use last w/0 scrolling ROWFIRST: defb 0FFH ; True if ROW sent first BINARY: defb 0FFH ; Send binary (not ASCII) coordinates ROWBIAS: defb 20H COLBIAS: defb 20H COMPFLG: defb 0 ; Complement binary value ; LEADIN: defb ESC,'Y',0,0, 0,0,0 FASTFLG: defb 0 ; Last byte NZ ==> Use fast routine MIDSTR: defb 0,0,0,0, 0,0,0,0 TAILSTR: defb 0,0,0,0, 0,0,0,0 ; CLRSCRSTR: defb ESC,'E',0,0, 0,0,0,0 ; Clear screen & home CLREOSSTR: defb ESC,'J',0,0, 0,0,0,0 ; Clear to End of Screen CLREOLSTR: defb ESC,'K',0,0, 0,0,0,0 ; Clear to End of Line ; INSLINSTR: defb ESC,'L',0,0, 0,0,0,0 ; Insert Line DELLINSTR: defb ESC,'M',0,0, 0,0,0,0 ; Delete Line CURUPSTR: defb ESC,'A',0,0, 0,0,0,0 ; Cursor UP HILITSTR: defb ESC,'p',0,0, 0,0,0,0 ; Hilite ON UNHILITSTR: defb ESC,'q',0,0, 0,0,0,0 ; Hilite OFF VCSTR: defb '|',0,0,0, 0,0,0,0 ; Vertical Divider HCSTR: defb '=',0,0,0, 0,0,0,0 ; Horizontal Divider ; ; These are slow on H19 ; ;VCSTR: defb ESC,'F',96,ESC,'G',0,0,0 ; Vertical Divider ;HCSTR: defb ESC,'F',97,ESC,'G',0,0,0 ; Horizontal Divider ; defb 0,0,0,0,0,0,0,0 ; 16-bytes Reserved Space defb 0,0,0,0,0,0,0,0 ; KAYVIDPORT equ 1DH ; Kaypro Video port for version checking. ; ;====================== End TERMCAP Definitions ========================= ; ; USER MODIFIABLE equates and flags. Keep in order, and same length. ; ;----------------------------------------------------------------------- ; CURYR: defb 85H ; Static year - here for DSCONFIG'ing ; change only once/yr ; ; If date stamping information is desired from DateStamper(tm), set the ; following equate to true. Each entry will then require 20 bytes with ; day-month-year information stored as 6 ASCII characters with each ; file entry. CP/M 2.2 is required. ; DATES0: defb YES ; YES = Date stamp file entries ; ; Set USER0 to 'NO' if you want a normal display of each file. ; Set USER0 to 'YES' if you want to include the user area for each file. ; USER0: defb YES ;NO=user areas not shown, YES=shown ; ; This value for the default drive to hold the MAST.CAT catalog. It can ; be over-ridden by command line entry, or from the command menu. Change ; the quoted character to the drive letter desired, or use 0FFH to ; default to current drive. ; DEFMDR: defb 0FFH ; Drive designator (e.g. 'A'-40H) ; ; The following storage location holds the default user area to use for ; the MAST.CAT database. It can be over-ridden by command line entry, or ; from the command menu. Change to reflect the desired user area, or use ; 0FFH for currently logged user area. ; DEFMUS: defb 0FFH ; User area for MAST.CAT (0-31) ; ; The following storage location holds the default drive ; TO BE CATALOGED. Change this byte to reflect the drive ; designator desired, or use 0FFH to default to currently logged drive. ; DEFCDR: defb 0FFH ; Drive designator (e.g. 'B'-40H) ; ; Unless DEFRES is non-zero, drives will be logged off and relogged- ; in using the fast BDOS functions 37. If your BIOS does not redetermine ; the disk type when a new disk is selected, you will need to set ; this option in order to switch types of disks within a single ; MCAT run. ; DEFRES: defb 00h ; Reset all drives if non-zero ; ;----------------- End Defined Configuration Storage ------------------- ; ; Space for the IGNORE buffer (for file names not to be cataloged.) Few ; lists use more than 10-12 names. Each name stores as 14 characters. ; Change the first number below if you need more than 36 file names. ; IGNSIZE EQU 36*11+1 ;buffer size for ignored names ; ;****************************************************************** ;* ..... PROGRAM STARTS HERE ..... * ;****************************************************************** ; START: LD HL,0 ; Save stack in case of Help request. ADD HL,SP LD (STACK),HL LD SP,STACK ; ; Print initial notification of program and terminal type ; call ILPRT defb CR,LF,'MCAT5' defb versno,revno,' ',0 ld hl,TNAME ; Set to installed Term name ld a,(hl) or a jp z,NOTERM ; ..jump if term not installed push hl call ILPRT defb 'for - ',0 pop hl call HLPRT ld bc,0 ; Give max delay STDLY: dec bc ld a,b or c jp nz,STDLY ; Pause a little while ; ld hl,TNAME ; Check for Kaypro models ld a,(hl) ; Get first char of term name call UPPER cp 'K' jp nz,NOTERM inc hl ld a,(hl) call UPPER cp 'A' jp nz,NOTERM ld a,CR call CRTOUT in a,(KAYVIDPORT) ; Read Kaypro-84 video port inc a jp nz,NOTERM ; xor a ; FF => Kaypro-83 ld (HILITSTR),a ; Zap Kaypro-84 attributes ld (UNHILITSTR),a ld a,'|' ; ..and set ordinary chars ld (VCSTR),a ld a,'=' ld (HCSTR),a ; NOTERM: LD A,(TBUF+2) ; Was help requested ? CP '?' jp nz,STARTX ld a,(TBUF) ; Only one question mark ? cp 2 ; ..if one, then... JP Z,HELP ; ..then jump and exit ; ; Get current user and disk, save for EXITing ; STARTX: ld c,CURDSK ; Get current disk call BDOS ld (CURDRV),a ; ..and save call GETUSR ; Get current user from BDOS ld (CUSER),a ; ..and save. ; ; Set default drives and user in positions designated ; ld a,(DEFCDR) ; Get default drive to catalog cp 0FFH ; Default to current drive ? jp nz,DEF0 ; ..Jump if not. ld a,(CURDRV) ; Get current drive. DEF0: ld (CDRIVE),a ; ..and save. ; ld a,(DEFMDR) ; Get default Master drive cp 0FFH ; Default to current drv ? jp nz,DEF1 ; ..jump if not. ld a,(CURDRV) ; Get current drive DEF1: ld (MDRIVE),a ; ..and place it ld a,(DEFMUS) ; Prepare default user area cp 0FFH ; Stay in current user area ? jp nz,DEF2 ; ..jump if not. ld a,(CUSER) ; Get current user DEF2: ld (MUSER),a ; ..for MAST.CAT. ; ld a,(USER0) ; Set default user.. ld (USER),a ld a,(DATES0) ; ..and date flags ld (DATES),a ; call CHKCRLF ; Do CRLF if no cursor addr. ld hl,CLRSCRSTR ; Clear screen if possible call HLPRT ld a,6 ; Set current line ld (SCRLIN),a ld d,a ; ..and cursor (for errors) ld e,0 call SETCUR ; ; Check for clock, and DateStamper ; ld a,TRUE ld (TDFLG),a xor a ; Assume clock is Real ld (RELCLK),a ; call CKCLK ; Get clock address ld a,h or l ; Is DateStamper active? jp nz,P2 ; ..Jump if not. ; call ILPRNL ; Print Warning message defb '!! DateStamper NOT Installed !!',0 call SCROLL xor a jp P3 ; P2: ld a,YES ; Show DateStamper is installed P3: ld (DSFLAG),a or a push af call z,ENTDAT ; If DateStamper not installed... pop af call nz,GTDATE ; ..else read current Date/Time... call ASCONVRT ; ..and convert to ASCII string ; ; Examine commad line arguments, and Parse string if present. ; ld de,TBUF ; Move buffer to local and parse ld hl,CBUFF ld b,32 call MOVER ; ; See if this is for immediate execution, and set flag accordingly ; ld hl,TBUF ; Point to CP/M buffer ld a,(hl) or a jp z,ST3AA ; Show not immediate if no tail ld b,a ST3LL: inc hl ld a,(hl) cp ' ' ; Is this space ? ld a,TRUE jp nz,ST3AA ; ..If not show Immed execution dec b jp nz,ST3LL xor a ; If done, all spaces. ST3AA: ld (IMMED),a ; ; Parse command tail. ; ld hl,CBUFF+1 ; Set buffer address ld (CMDPTR),hl call PARSE ; Parse comd tail if present ; ; Draw screen and set current line for SCROLL routine reference. ; ld a,5 ld (SCRLIN),a call DRAWSCR ; Draw the screen ; call ILPRNL DEFB 'For Help, reboot then type: MCAT ?',0 ; ; Check for proper version(s) of CP/M Operating System ; LD C,CPMVER ;if ALLUSR enabled, see that we are CALL BDOS ; running under CP/M 2.x or later; ; ld a,(DATES) or a jp z,DS002 ld a,l cp 22H ; DateStamper requires CP/M 2.2 jp nz,BADVR1 ; ..Error exit if not 2.2. ; DS002: LD A,H ; If old version, do an error exit OR L JP Z,BADVERS ; ld a,(LEADIN) ; If cursor controls, position.. or a jp nz,TOPRITE ; ..then bypass header call CRLF call ILPRT defb 'Today''s Date is : ',0 jp DONDAT ; ;................................................... ; Main Program LOOP. Executed for each disk. ;................................................... ; ; Rewrite Screen in case something messed it up. ; DRWAGN: ld a,5 ; Position to line 6.. ld (SCRLIN),a call DRAWSCR ; Draw the whole screen call SCROLL ; Go to next line call CLEOSCR ; ..and clear rest of screen ld a,(PRFSIZ) ; Should we print file size ? or a call nz,ALDON0 TOPRITE: ld a,(TWIDTH) ; Get screen width sub 15 ; ..move in from edge ld e,a ld d,0 call SETCUR DONDAT: call DATLIN ; Convert date to string ld a,FALSE ; Let it read clock ld (RELCLK),a call RDTIM ; ..read time ld a,(SCRLIN) ; ..and re-position cursor ld d,a ld e,0 call SETCUR ; AGAIN: LD SP,STACK ;reset stack each time through xor a ; Clear memory locations each pass ld hl,IGNORE ; ..from here.. ld de,MASTSIZE ; ..to here. call FILL16 xor a ld hl,FRSTIM ; From here.. ld de,FREPTR+1 ; ..to here. call FILL16 ; call SETMDRV ; ; Initialize the lengths of Name entries and Master record sizes ; ld c,NAMEREC ; Put base Name length in C.. ld d,MASTREC ; ..and Record length in D ld a,(USER) or a ; If user active.. jp z,US010 ld b,1 ld a,c add a,b ; ..add 2.. ld c,a ; ..and put back in C ld a,d ; Now add to Master size add a,b ld d,a US010: ld a,(DATES) ; If Dateing is to be used.. or a jp z,DS010 ld b,3 ; ..add 3.. ld a,c add a,b ld c,a ; ..and put back C ld a,d add a,b ; Add to Master size ld d,a DS010: ld a,(USER) ; Add one if either USER or DATES ld l,a ld a,(DATES) or l jp z,DS010A inc c inc d DS010A: ld a,c ld (NAMSIZE),a ; Store result ld a,d ld (MASTSIZE),a ; CATMSG: call SCROLL ld a,(IMMED) ; If immediate, show no prompt or a jp z,CATMS0 call ILPRT defb '...Cataloging drive : ',0 ld hl,CDR1 call HLPRT call SCROLL jp CATGO ; CATMS0: CALL ILPRT defb 'Catalog Drive ' CDR1: DEFB 'B:',0 ;hot-patched to show correct drive call ILPRT defb ' (NO = Exit) ',0 CALL CMDIN ;get a keyboard character. cp 'N' jp z,EXITNO ; Exit if NO CP 'Y' ;process disk if yes JP Z,CATMS1 ld a,CR call CRTOUT ; Do CR and reprint prompt JP CATMS0 ;ask again if none of these ; CATMS1: call SHOW$Y ; Spell 'YES' response CALL SCROLL ;acknowledge with a new line ; ; CATGO: ld a,(MDRIVE) ; If using same drive for ld hl,CDRIVE ; ..MAST.CAT and to-be-cataloged disk cp (hl) jp z,CATGOA ; ..skip check for existing MAST.CAT ; call SETCAT ; set catalog du and ld de,FCBM_IN ; ...check for existing MAST.CAT ld c,SRCHF call BDOS inc a jp nz,CATGOA ; NEWCAT: xor a ; No MAST.CAT ld (IMMED),a ; ensure Menu mode call ILPRNL DEFB BELL,'++ No MAST.CAT File ++',0 call ILPRNL defb ' Do you want to Create a MAST.CAT ? : ',0 call CRTIN cp 'N' ; Back to main menu if not push af call z,SHOW$N pop af jp z,DRWAGN call SHOW$Y jp CMDINIT ; ..else go to Command Initialization ; ; The following is necessary with double density systems to allow the ; system to log in a diskette with (possibly) changed disk character- ; istics (density, sector size, etc) ; ; Select the disk to be cataloged as either the originally logged drive ; or the drive specified at runtime. Do only if not Erase operation. ; CATGOA: ld hl,NABUF ld (TDBUFF),hl ; Preset NABUF address. ; ld a,(ERADSK) ; Bypass reset & read if Erasing.. or a ; ..references to specified disk ID. jp nz,SHFDO1 ; LD A,(CDRIVE) ;Reset & relog the catalog drive CALL FRESET ; ld e,0 ; ..and Set for User 0 call SETUSR ; ; This gets DISKSTATS first, then allocates large enough date buffer ; and sets date read limit ; No T & D read needed if delete-volume pass ; Fix calc of dirmax * namsize for non power-of-2 ; ;************************************************** ; ; Now that the drive to be cataloged has been selected, get the address ; of the disk parameter block for that drive, the extent mask, and the ; number of directory entries on the disk. ; CATGO0: LD C,DPB CALL BDOS LD (DPBADDR),HL ex de,hl ; Save in DE LD hl,4 ; Offset for Extent mask ADD HL,DE LD A,(HL) LD (EXMASK),A ld hl,7 ; Offset for DIRMAX-1 add hl,de ld e,(hl) ; Get # Directory entries in DE inc hl ld d,(hl) inc de ; Make DIRMAX ex de,hl ld (NAMES),hl ; ..and save ; ; Allocate space for maximum number of disk names. ; ex de,hl ; (NAMES) to DE registers. ld hl,0 ld a,(NAMSIZE) ; Calc HL = NAMSIZE * DIRMAX MULTNA: add hl,de dec a jp nz,MULTNA ld bc,NABUF ; TDBUFF = size + NABUF add hl,bc inc hl ; ..add one for EOF byte. ld (TDBUFF),hl ; TD start addr set, (NAMES) still in DE ; ; Check to insure enough room exists for 3*(DIRMAX + 9) bytes ; above TDBUFF to handle !!!TIME&.DAT entries without exceeding ; BDOS in rare case of DIRMAX mod 8 .ne. 0 ; ld hl,9 ; (NAMES) still in DE. add hl,de ld b,h ld c,l add hl,hl ; 2x add hl,bc ; 3x ld b,h ld c,l ld hl,(TDBUFF) add hl,bc ; HL has top of Date entries jp c,BUFOVF ; ..carry means overflow xor a sub l ld a,(BDOS+2) ; ..get BDOS page.. sbc a,h jp c,BUFOVF ; Go error if BDOS page exceeded ; ; Now set the TDBUFF size for the minimum needed for NABUF pointers ; used for sorting and accessing names. Allocate DIRMAX+1 words. ; ex de,hl ; Moves NAMES to HL inc hl ; Add one for EOF pointer add hl,hl ex de,hl ; move back to DE ld hl,(TDBUFF) add hl,de ; ; Finds amount of space available for buffers, divides into 2 equal ; parts for the in/out buffers. ; SHFDO1: LD (MSTINADR),HL ; main buffer start address LD (MSTINPTR),HL ;main buffer start pointers EX DE,HL ;buffer address to 'DE' LD A,(BDOS+2) ;get 'BDOS' entry point and 0FEH ;make an even page LD H,A ;save page in 'H' ; ; Calculate the difference to get free space ; XOR A ;nulls the 'A' reg. SUB E LD L,A LD A,H SBC A,D jp c,BUFOVF ; Error if no space. rra ; Divide # pages in two or a ; ..and check for no space jp nz,BUFSZ1 ; BUFOVF: call ILPRNL defb '++ Insufficient Buffer Space ++',BELL,0 jp AGAIN ; Back to main loop. ; BUFSZ1: LD H,A LD L,0 ;make buffers full 256-byte pages ; ; Now store the buffer length at appropriate places ; LD (BUFFERSIZE),HL LD (MSTINLEN),HL LD (MSTOTLEN),HL ; ; Set up the output buffer address ; ADD HL,DE ;add end of program to buffer length LD (MSTOTADR),HL LD (MSTOTPTR),HL ; LD HL,NABUF ;set up file name buffer LD (BUFPTR),HL LD (FREPTR),HL ;initialize 'PHANTOM FILE' pointer LD HL,0 LD (BLKSFRE),HL ;initialize blocks free inc HL ;initialize file counter to 1, to LD (FCT),HL ;save 16-bit value ; LD HL,' ' ;get 2 spaces LD (COUNT),HL ;blank out entry counter LD (COUNT+2),HL ld (DLNUM),hl ; Blank out file counts ld (ADNUM),hl ld hl,' '+256*'0' ;show a zero ld (DLNUM+2),hl ld (ADNUM+2),hl LD A,')' ;fix IGNORE table LD (IGNORE),A XOR A ;get a zero... LD (MIEOFLG),A ;fix end-of-file flags LD (NAEOFLG),A ; ; If this is an ERASE operation, Jump around catalog operations ; ld a,(ERADSK) ; or a ; jp nz,ERAS0 ; ; ; Load !!!TIME&.DAT file contents (if present) into memory ; xor a ; Zero Time&.Dat FCB ld hl,TDFCB+12 ; 7/19 ld b,24 call FILL ; ld hl,(TDBUFF) ; ..Set pointer ld (TDPTR),hl push hl call RDTIMFIL ; Read !!!TIME&.DAT file pop hl ld (TDPTR),hl ; ..again ; ; Make search return every entry ; LD HL,FCB LD (hl),'?' ; ; Create a "phantom file" entry with free disk space as name ; LD HL,NABUF CALL AAAA DEFB ' FRE' ; AAAA: LD B,DKSIZE ; Size of NAME, TYPE POP DE CALL MOVER push hl CALL FRESPC ;get free space on disk to new file pop hl ; ld a,(USER) or a jp z,US002 LD (HL),';' INC HL LD (HL),'-' inc hl ; US002: ld a,(DATES) or a jp z,DS003 ld a,(USER) ; No Date Separator if user has one or a jp nz,US002A ld (hl),'|' inc hl US002A: ld de,BCDBUF+2 ; Address Day digit call MBCDAT ; ..and move date in position ; ; Read the directory entries ; DS003: push hl ; Say that we are starting to process call ILPRT defb '....Processing disk : -',0 pop hl ; LD C,SRCHF JP CALLB ; LOOP: LD C,SRCHN push hl ld hl,(TDPTR) ; Bump TDPTR to next entry inc hl inc hl inc hl ld (TDPTR),hl pop hl ; CALLB: PUSH HL ;save current buffer address LD DE,FCB CALL BDOS POP HL ;get current buffer address back INC A JP Z,NOMORE ; ; Move the name into the buffer ; LOOP1: DEC A ;get back original value AND 3 PUSH HL LD L,A LD H,0 ADD HL,HL ;x32 ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD DE,TBUF ADD HL,DE ; ; 'HL' now points to entry (table entries will be 11/13/15/16 bytes each) ; EX DE,HL LD HL,12 ;if extent byte in directory entry is ADD HL,DE ; larger than the extent mask, the en- LD A,(EXMASK) ; try we are looking at is not the CP (HL) ; 'PRIMARY' directory entry for this POP HL ; file, ignore. JP C,LOOP LD A,(DE) ;if the file has been erased do not move CP 0E5H ; it to the buffer (do not include it JP Z,LOOP ; in the catalog). ; LD C,A ;save the user number for this file ; INC DE ;skip first byte LD A,(DE) ; replace the '-' token used to mark CP '-' ; the disk name file with a null. This JP NZ,TOK ; is for internal use only, and pre- XOR A ; serves the correct sort-order. LD (DE),A ; TOK: LD B,DKSIZE ;number of characters in filename move, CALL MOVNC ;filtering out commas & hi-order bits. ; ld a,(USER) or a jp z,US003 LD (HL),';' INC HL LD A,C ;get user area number add a,'0' ; Fixed code to print drives.. cp '9'+1 ; ..A,B,C...F,G,H,I...W,X,Y,Z jp c,TOK1 add a,7 TOK1: LD (HL),A ;set user number INC HL ; US003: ld a,(DATES) or a jp z,DS004 ld a,(USER) ; No separator if USER present or a jp nz,US003A ld (hl),'|' ; Separator for date inc hl US003A: ld a,(TDFLG) ; See if Time&Dat file here or a ; ..set flags call GTFDAT ; Store modified/created date or NUL ; ; Increment file count (16 bit) ; DS004: PUSH HL LD HL,(FCT) INC HL LD (FCT),HL POP HL JP LOOP ; ;..... ; No more entries ; NOMORE: LD (HL),0FFH ;endflag names buffer push hl ;save this for final ptr ; ;-------------------- ; 7/20 shell-sort ; ORDTBL EQU TDBUFF ; reuse the td buffer for sorting ptrs ; (M80 can't handle forward equates - must preceed 1st reference) ; ld a,(NAMSIZE) ;a = # bytes to compare ld c,a ld b,0 ;bc = length of a names record ld de,NABUF ;de = names buffer ld hl,(FCT) ;hl = count ; call kpsort ;sort the names into table of ptrs ; ld hl,(ORDTBL) ;initialize name pointer ld (NAMPTR),hl ex de,hl ld hl,(FCT) ;find end of ptrs add hl,hl add hl,de pop de ;get addr of EOF byte ld (hl),e ;install ptr to eof record inc hl ;so EOF sentinal will work ld (hl),d jp DONE ; ;---------------------------------- ; ; Shellsort routine adapted from Kernigan & Plaugher's SOFTWARE TOOLS ; by Bridger Mitchell (Plu*Perfect Systems). 7/20/85 ; ; The one external reference is: ; ; ORDTBL: a buffer for at least COUNT (word) pointers ; ; Substitute a different kpCOMP routine for other compare functions. ; ; enter: ; a = # bytes to compare in the entry ; bc = size of an entry field ; de = addr of buffer with fields (names) to be compared ; hl = COUNT (number of names) ; exit: ; ORDTBL contains sorted pointers to buffer fields ; kpSORT: ld (kpchcnt),a ; ; Initialize the order table with ascending ptrs ; to name fields ; push hl ;save file count on stack ld (kpcnt),hl ;save as # to sort ld hl,(ORDTBL) ;point to order table ; kpinit: LD (HL),E ;install pointer in ordtbl INC HL LD (HL),D INC HL EX DE,HL ;table addr to HL ADD HL,BC ;point to next entry EX DE,HL EX (SP),HL ;save tbl addr, fetch loop counter DEC HL ;count down loop LD A,L OR H ;more? EX (SP),HL ;(restore tbl addr, save counter) JP NZ,kpinit ;yes, go do another one POP HL ;clean loop counter off stack LD HL,(kpcnt) ;get count DEC HL ;only 1 entry? LD A,L OR H ret z ;yes, so skip sort ; ; shell-sort the pointers ; inc hl ;number of entries kpl0: OR A ;clear carry LD A,H ;GAP=GAP/2 RRA LD H,A LD A,L RRA LD L,A OR H ;is it zero? ret z ;then none left LD A,L ;make gap odd OR 1 LD L,A LD (kpGAP),HL INC HL ;I=GAP+1 ; kpl1: LD (kpI),HL EX DE,HL LD HL,(kpGAP) LD A,E ;J=I-GAP SUB L LD L,A LD A,D SBC A,H LD H,A ; kpl2: LD (kpJ),HL EX DE,HL LD HL,(kpGAP) ;JG=J+GAP ADD HL,DE LD (kpJG),HL ; call kpCOMP ;compare (J) and (JG) JP P,kpl3 ;if A(J)<=A(JG) LD HL,(kpJ) EX DE,HL LD HL,(kpJG) ; ; Swap entries in the order table - ;exchange A(J) and A(JG) ; kpSWAP: ld a,(ORDTBL) ; Put ORDTBL in BC ld c,a ld a,(ORDTBL+1) ld b,a dec bc ; dec bc ADD HL,HL ;*2 ADD HL,BC ;+ base EX DE,HL ADD HL,HL ;*2 ADD HL,BC ;+ base LD C,(HL) LD A,(DE) EX DE,HL LD (HL),C LD (DE),A INC HL INC DE LD C,(HL) LD A,(DE) EX DE,HL LD (HL),C LD (DE),A ; LD HL,(kpJ) ;J=J-GAP EX DE,HL LD HL,(kpGAP) LD A,E SUB L LD L,A LD A,D SBC A,H LD H,A JP M,kpl3 ;if J>0 GOTO kpl3 OR L ;check for zero jp nz,kpl2 ; kpl3: LD HL,(kpcnt) ;N EX DE,HL LD HL,(kpI) ;I=I+1 INC HL LD A,E ;if I<=N GOTO kpl1 SUB L LD A,D SBC A,H JP P,kpl1 LD HL,(kpGAP) JP kpl0 ; ; Ordered compare of 2 entries for (kpchcnt) bytes ; return: Z if equal, else MINUS if less, else PLUS ; kpCOMP: ld a,(ORDTBL) ; Put ORDTBL in BC ld c,a ld a,(ORDTBL+1) ld b,a dec bc ; dec bc ADD HL,HL ADD HL,BC EX DE,HL ADD HL,HL ADD HL,BC EX DE,HL LD C,(HL) ;bc = 1st field INC HL LD B,(HL) EX DE,HL LD E,(HL) ;de = 2nd field INC HL LD D,(HL) EX DE,HL ld a,(kpchcnt) ;get byte count LD E,A ;to E ; ; compare E bytes at BC, HL ; (Modified to delete MSB masking - HFB, 08/10/85) ; kpCMPLP: LD d,(HL) ;7-bit compare LD A,(BC) CP D INC BC INC HL RET NZ DEC E JP NZ,kpCMPLP RET ; ; local storage for kpsort routine ; kpchcnt:db 0 ; # chars to compare kpcnt: dw 0 kpGAP: dw 0 kpI: dw 0 kpJ: dw 0 kpJG: dw 0 ; ;---------------------------------- ; ; Sort all done - verify "flag" file present ; DONE: ld hl,(TDBUFF) ;get first-sorted file ld e,(hl) inc hl ld d,(hl) ex de,hl push hl ld de,TYPF ; Check type field validity add hl,de ld a,(hl) inc hl or (hl) inc hl or (hl) cp ' ' pop hl ; Get address back jp z,BADTYP ld a,(hl) OR A JP Z,NAMEOK BADTYP: call ILPRNL DEFB '++ Missing/Invalid "-.nnn" File On Disk ++',0 call ILPRNL ; Check for addition defb ' Want to add disk ID (Y/N) ? ',0 call CRTIN cp 'N' jp nz,DONE00 call SHOW$N ld a,(IMMED) or a jp z,DRWAGN jp EXIT ; If immediate, Go exit. ; DONE00: call SHOW$Y BADTP0: call ILPRNL defb ' ==> Enter 3-char unique Disk ID : -.',0 call GTYPFCB ; Input name into default buffer ld hl,FCB+TYPF ; ..check for validity ld a,(hl) inc hl or (hl) inc hl or (hl) cp ' ' ; If spaces, bad entry jp nz,TYPOK call ILPRT defb '...Bad Entry',BELL,0 jp BADTP0 ; TYPNOK: call ILPRNL ; Here if ID.typ duplicated defb '++ ID Type field duplicated. Re-enter...',0 jp BADTP0 ; TYPOK: call ILPRNL defb '..Checking for Duplicate IDs..',0 ld a,TRUE ld (IDCHEK),a call NAME0 ; Open Master_In & read past ignore TYPOK0: call READMI ; Read M_I record ld a,(MIEOFLG) ; Check for EOF or a jp nz,TYPOK2 ; ..EOF means automatic unique ID ld hl,MIDAT+TYPF ; Check for file type = .FRE ld de,FTFRE ld b,3 call COMPR jp nz,TYPOK0 TYPOK1: ld hl,FCB+TYPF ld de,MIDSK+TYPF ld b,3 ; Compare type fields call COMPR jp z,TYPNOK call READMI ; Read another record ld a,(MIEOFLG) ; ..and check for EOF or a jp nz,TYPOK2 ; ..EOF means unique ID ld hl,MIDAT+TYPF ; ..until filetyp .ne. .FRE ld de,FTFRE ld b,3 call COMPR jp z,TYPOK1 ; TYPOK2: call ILPRNL ; Here if ID is OK defb '++ Disk ID Unique.',0 ld a,(MDRIVE) ld hl,CDRIVE cp (HL) ; Prompt if single drive jp nz,TYPOK3 TYPLZ: call ILPRNL defb '-- Reinsert disk TO BE CATALOGED. ',0 call CMDIN cp 'Y' jp z,TYPOK3 ld a,CR call CRTOUT jp TYPLZ ; TYPOK3: call ILPRT defb ' ..Writing disk ID..',0 ; ld a,(CDRIVE) ; Log User 0 and Drive to catalog call SELECA ld e,0 call SETUSR ld de,FCB xor a ld (de),a call MAKEF ; Make the file inc a ; ..check for errors jp nz,DONE01 ; ..Jump if OK call ILPRNL ; Error so print error.. defb '++ No Directory Space for NAME ++',BELL,0 jp AGAIN ; Back to main loop. ; DONE01: ld de,FCB call CLOSF ; ..and now close it call SCROLL ; ..give CRLF jp CATGO0 ; ..and continue. ; ;..... ; Get disk id number, display ; NAMEOK: ex de,hl ; Put (NABUF) in DE inc de ; ..make NABUF + 1 push de LD HL,IDNAME ; Put name in display buffer LD B,7 CALL MOVER inc hl ld b,3 call MOVER pop de LD HL,COUNT1 ; And in count display LD B,7 CALL MOVER inc hl ld b,3 call MOVER ; CALL ILPRTS IDNAME: DEFB ' . ',0 ; call SCROLL xor a ; Reset Disk ID check ld (IDCHEK),a NAME0: LD A,(DRIVE) ;two drives?? OR A JP NZ,OK1 ;yes, proceed ; call SCROLL NAME1: CALL ILPRT ;else ask for system disk DEFB 'Put CATALOG Disk in ' ; MDR1: DEFB 'A: (NO = Exit)',0 ;hot patched at runtime CALL CMDIN ;get a keyboard character cp 'N' jp z,EXITNO ; Exit if NO CP 'Y' ;if yes, update MAST.CAT JP Z,MDR2 ld a,CR ; ..else do CR and reprint prompt call CRTOUT JP NAME1 ;otherwise, ask again ; MDR2: CALL SHOW$Y ;display a 'Y' for yes CALL SCROLL ; OK1: ld a,(MDRIVE) call FRESET ;reset disk, killing r/o status ; ERAS0: CALL SETCAT ;set CATALOG du ; ; Now update mast.cat and set up the files ; call ERASBK ;erase MAST.BAK to save disk space ; AAE: XOR A LD (FCBM_IN+12),A LD (FCBM_IN+32),A LD HL,(BUFFERSIZE) LD (MSTINLEN),HL LD (MSTINPTR),HL call OPMINF ; Open Master Input File INC A jp z,NEWCAT ; AAMM: LD HL,(BUFFERSIZE) LD (MSTOTLEN),HL LD HL,0000H LD (MSTOTPTR),HL call MAKOUT ; Erase Mast.Out and reMake w/Err chks JP z,EXIT ; ..Exit on Errors ; INITRD: ld a,(ERADSK) ; Bypass this if Erase operation or a ; jp nz,ERAS1 ; ; CALL READNA ;"read" disk name LD DE,NADAT+1 ; move it to buffer LD HL,DKNAME LD B,7 CALL MOVER inc HL ; Point to DKNAME+8 LD B,3 CALL MOVER ; ; Read in the names to be ignored (i.e., not cataloged). They are at ; the front of MAST.CAT. They are simply a list of filename.filetype ; (cr/lf) with the first having a ( before it, and the last having a ) ; after it. ; ERAS1: ld a,TRUE ; Show first time through ld (FRSTIM),a xor a ; ..and clear check flags ld (UCHEK),a ld (DCHEK),a ; CALL GETMASTIN ;get the leading '(' JP Z,NOMAST ;if EOF CP '(' JP NZ,NOIGN CALL PUTMASTOUT ; IGNRD: call IGECHO ; Read input and echo to output push af ; Save character ld a,(FRSTIM) ; bypass tag field check if not first time or a jp z,IGNRD0 pop af cp '{' ; If not this, can't check format III0: jp nz,FMISS ; ..(dummied out later) push hl push af ld hl,0 ld (III0),hl ld a,l ld (III0+2),a pop af pop hl cp ';' ; Set for user jp z,III1 cp '|' ; Set for dates jp z,III2 cp '}' ; If end, go compare flags jp nz,IGNRD ; xor a ld (FRSTIM),a ; Turn off first time flag push hl ld hl,DATES ; Load HL with real settings ld a,(DCHEK) cp (hl) jp nz,IIINE inc hl ; ..point at USER ld a,(UCHEK) cp (HL) jp nz,IIINE pop hl jp IGNRD ; OK..return to main loop ; ; Arrive here if conflicts in MAST.CAT and USER/DATES flags ; IIINE: call ILPRNL ; Turn over a new line defb '++ MAST.CAT conflicts with UD settings ++',BELL,0 call ILPRNL defb '==> Change and retry, or Abort (C/A) : ',0 IIINE0: call GETCH cp 'A' jp z,DRWAGN cp 'C' jp nz,IIINE0 call CRTOUT call ILPRNL defb ' Changing UD flags. Restarting catalog action.',0 ld a,(UCHEK) ; Set real flags from check flags ld (USER),a ld a,(DCHEK) ld (DATES),a call CLMOUT ; Close MAST.OUT.. ld de,FCBM_IN ; ..and MAST.CAT call CLOSF jp DRWAGN ; III1: ld a,TRUE ; Detected User flag ld (UCHEK),a jp IGNRD ; III2: ld a,TRUE ; Detected Dates flag ld (DCHEK),a jp IGNRD ; ; Resume main processing of Ignore list ; IGNRD0: pop af ; Restore char pushed above ld c,36 ; Limit of ignore list ld hl,IGNORE ; Set load address ld (IGADDR),hl IGNRD1: ld b,8 ; Length of name ld hl,(IGADDR) IGNRD2: call IGECHO ; Get char (& put Mast.out) cp '.' jp z,IGNN1 cp '*' jp z,IGNN2 cp CR jp z,IGNN3 cp ')' jp z,IGNEND ; table is loaded ld e,a ; Save char ld a,b or a ; Check for name end jp z,IGNRD2 ld (hl),e INC HL dec b ; Countdown name jp IGNRD2 ; IGNN1: ex de,hl call PAD ; Fill remainder w/spaces ex de,hl jp IGNRD3 ; ..and do type ; IGNN2: ld a,b ; Make sure not end or a jp z,IGNRD2 ; ..vector out if so ld a,'?' call FILL ; Fill w/question marks jp IGNRD2 ; IGNN3: ex de,hl call PAD ; Rest of name is spaces ex de,hl ld b,3 ; Set for type fill jp IGNT2 ; ..and null it out ; IGNRD3: ld b,3 ; Length of type field IGNTP: call IGECHO ; Get a char cp '*' jp z,IGNT1 cp CR jp z,IGNT2 cp ')' jp z,IGNEND ; Table is loaded ld e,a ; Save char.. ld a,b or a ; End of field ? jp z,IGNTP ld (hl),e inc hl dec b jp IGNTP ; Loop til done ; IGNT1: ld a,b ; Check for end or a jp z,IGNT1A ld a,'?' call FILL IGNT1A: ld hl,(IGADDR) ; Calc next start addr push bc ld bc,DKSIZE add hl,bc ld (IGADDR),hl pop bc ld (hl),')' ; Insure end of list dec c jp nz,IGNRD1 ; Get next name jp IGNTOO ; ..else show error. ; IGNT2: ex de,hl call PAD ; Fill out w/spaces jp IGNT1A ; ; Table overflow ; IGNTOO: CALL EREXIT DEFB BELL,'++ Too Many IGNORE Names for TABLE ++',0 ; ; Utility to Read and Echo chars during IGNORE table loading ; IGECHO: push bc ; Preserve regs push hl call GETMASTIN jp z,IGNEOF ; Unexpected EOF push af ; Save char.. call PUTMASTOUT ; ..and echo to MAST.OUT pop af ; Restore all pop hl pop bc cp LF ; Don't return Line feeds jp z,IGECHO ret ; ; Ignore names have been read into table ok ; IGNEND: ex de,hl ; Preserve present addr.. ld hl,(IGADDR) ; ..and calc next entry.. ld bc,DKSIZE add hl,bc ex de,hl IGNEN0: ld a,l sub e ld a,h sbc a,d jp z,IGNENX ; when equal, exit.. ld (hl),' ' ; ..else fill w/spaces inc hl jp IGNEN0 ; IGNENX: ld (hl),')' ; Show end of IGNORE list call IGECHO ; Get rid of CR at end ld a,LF ; ..and add an LF call PUTMASTOUT ld a,(IDCHEK) ; If checking ID, quit here or a ret nz ; ; If this is an ERASE disk operation, Continue, else bypass and catalog ; ld a,TRUE ; Set flag to print status at end.. ld (PRFSIZ),a call STPRMP ; ..and print status message ld a,(ERADSK) ; or a ; jp z,NAMELP ; Not an erase, jump to catalog ; ERAS2: call READMI ; Read master file input ld a,(MIEOFLG) ; or a ; jp nz,ALLDONE ; Close output file and return ld hl,FCB+TYPF+1 ; ld de,MIDSK+TYPF ; ld b,3 ; call COMPR ; See if disk name and type match jp nz,ERAS2A ; ..no match, output & continue call DELONE ; Inc delete count jp ERAS2 ; ..read next record ; ; ERAS2A: ld hl,MIDAT ; Write Mast-In to Output file call WRITEMO ; jp ERAS2 ; Read the next record. ; ; ..... ; ; MAIN CATALOGING LOOP: Prime the buffers ; NAMELP: CALL READNA ;"read" name into nadat MASTLP: CALL READMI ;read master into midat ; ; If EOF on both files, we are all done ; COMPLP: LD A,(NAEOFLG) ;name file EOF? OR A JP Z,NOTEOF ;..no LD A,(MIEOFLG) ;master in EOF? OR A JP NZ,ALLDONE ;yes, that is it ; NOTEOF: LD a,(MASTSIZE) ld b,a LD DE,NADAT LD HL,MIDAT CALL COMPR JP Z,EQUAL JP C,WRITEN ; ; Master is lower - write it if for another disk ; LD B,DKSIZE LD DE,MIDSK LD HL,DKNAME CALL COMPR push af call Z,DELONE ;deleting MIDAT pop af jp z,MASTLP ld hl,MIDAT ; Write Master rec to Output CALL WRITEMO JP MASTLP ; ;..... ; Name is lower - write it ; WRITEN: ld hl,NADAT CALL WRITEMO ; call ADDONE ; Show that name was added CALL READNA ;read next name JP COMPLP ; ; Both files equal ; EQUAL: ld hl,MIDAT ; Write Mast.In to Mast.Out call WRITEMO JP NAMELP ;read both ; ;..... ; All done - write EOF to output, ask if more to do ; ALLDONE: call BBBB ; Moved to subroutine ld a,(IMMED) ; Check for immediate execution.. or a jp z,DRWAGN ; ..Back to menu if not ld a,(SCRLIN) ; Position Cursor ld d,a ld e,0 call SETCUR call SCROLL call ALDON0 ; If Immed, print file counts.. jp EXIT ; ..and quit ; ;........................................................ ; Routines for reading Names from sorted NABUF buffer | ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;..... ; "Read" one name record from buffer to NADAT buffer ; READNA: ld hl,(namptr) ;get ptr to next name ld e,(hl) inc hl ld d,(hl) inc hl ld (namptr),hl ;save new ptr addr ex de,hl ld (BUFPTR),hl ;set buffer ptr LD HL,NADAT ;destination buffer LD B,NAMEREC CALL RDNAC ;read characters ; ld a,(USER) or a LD HL,UDAT ; If User.. jp z,US004 ld b,2 ; ..read separator & user # call RDNAC ; US004: ld a,(DATES) or a jp z,DS005 ld a,(USER) ; Don't add delim if User has put one. or a jp nz,US004A ld b,4 ; If no user, read delim as well jp US004B ; US004A: ld b,3 ; ..If not, read all 3 US004B: call RDNAC ; ; If this is a name not to be cataloged, read the next ; DS005: LD hl,IGNORE ;get ignore table ; IGNLP: ld a,(hl) cp ')' ; End of table ? ret z ld (IGADDR),hl ; ..save current start ex de,hl LD HL,NADAT LD B,DKSIZE ;# of characters to match ; call COMPIG ; Are they same ? jp z,READNA ; If so, delete by reading next ld bc,DKSIZE ld hl,(IGADDR) ; Calc next address add hl,bc jp IGNLP ; ..and check. ; ;..... ; "Read" number of chars in (B) into buffer addressed by (HL). ; Set EOF flag as appropriate. ; RDNAC: LD A,(NAEOFLG) ;EOF on names? OR A JP NZ,NAEOF ;yes, pad with 0FFH PUSH HL PUSH BC CALL GETNAM ;get from buffer, not disk POP BC POP HL LD (HL),A INC HL DEC B JP NZ,RDNAC RET ; NAEOF: LD a,0FFH call FILL LD (NAEOFLG),A RET ; ;..... ; Return single char from sorted names buffer. Set EOF if end. ; GETNAM: LD HL,(BUFPTR) ;get pointer to NABUF LD A,(HL) ;get next character INC HL ;bump the pointer LD (BUFPTR),HL cp 0FFH ; Check for end-of-file ret nz ld (NAEOFLG),a ; ..Store if so. RET ; ;................................................... ; Routines controlling reading of Master-In File | ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;..... ; Read complete master-in record into MIDAT buffer. ; READMI: LD HL,MIDAT CALL MINAME ;get file name LD (HL),',' ;separator INC HL CALL MINAME ;get disk name ; ld a,(USER) or a ld hl,MIUSR jp z,US006 LD A,(MASDEL) ;delimiter CP ';' jp nz,US006 ; No user areas ld (hl),a ; Save correct delimiter inc hl push hl CALL GETMASTIN pop hl LD (HL),A ;save user number inc hl ld a,(DATES) ; Check for Dates.. or a jp nz,US006A ld hl,JUNK ; ..else dump delimiter in JUNK ld b,1 jp RDMIC ; US006: ld a,(DATES) or a ret z ld a,(USER) ; If no user.. or a jp nz,US006A ld (hl),'|' inc hl US006A: ld b,3 midlop: push bc push hl ; Preserve addr & counter call GETMASTIN sub '0' ; Make binary rlca ; ..and move to hi byte rlca rlca rlca and 0F0H ; ..mask lo byte ld c,a push bc ; Preserve the value. call GETMASTIN sub '0' ; ..make next digit binary and 0FH pop bc or c ; ..combine with hi digit pop hl pop bc ld (hl),a inc hl ; point to next dec b jp nz,midlop jp CLDELM ; ..and clear delimiter ; ;..... ; Read complete entry to memory addressed by (HL) ; MINAME: LD B,8 CALL RDMIC ;get characters LD B,3 ; fall thru to... ;..... ; Read (B) chars into memory addressed by (HL) ; RDMIC: LD A,(MIEOFLG) OR A JP NZ,MIEOF PUSH HL PUSH BC ; GETMI: CALL GETMASTIN CP LF ;ignore LF JP Z,GETMI POP BC POP HL CP ',' JP Z,MIEND CP '.' JP Z,MIEND ; ld c,a ld a,(USER) or a ld a,c jp z,US007 CP ';' JP Z,MIEND ; US007: ld c,a ; save A ld a,(DATES) or a ld a,c jp z,DS007 cp '|' jp z,MIEND ; DS007: CP CR JP Z,MIEND CP EOF JP Z,MIEOF LD (HL),A INC HL DEC B JP NZ,RDMIC CLDELM: PUSH BC PUSH HL CALL GETMASTIN ;get delimiter LD (MASDEL),A ;save delimiter POP HL POP BC CP EOF ;EOF? RET NZ LD (MIEOFLG),A RET ; MIEND: LD (MASDEL),A LD A,' ' jp FILL ; MIEOF: LD a,0FFH call FILL LD (MIEOFLG),A ;show EOF RET ; ;..... ; Read single char from Master-In file, setting EOF and delimiters. ; GETMASTIN: LD HL,(MSTINLEN) EX DE,HL LD HL,(MSTINPTR) LD A,L SUB E LD A,H SBC A,D JP C,AADD LD HL,0 LD (MSTINPTR),HL ; AAB: EX DE,HL LD HL,(MSTINLEN) LD A,E SUB L LD A,D SBC A,H JP NC,AAD LD HL,(MSTINADR) ADD HL,DE EX DE,HL call SDMA ; Set DMA address call RDMINF ; Read Master Input file OR A JP NZ,AAC LD DE,TBUF LD HL,(MSTINPTR) ADD HL,DE LD (MSTINPTR),HL JP AAB ; AAC: LD HL,(MSTINPTR) LD (MSTINLEN),HL ; AAD: call DFLTAD ; Set default DMA addr. LD HL,0000H LD (MSTINPTR),HL ; AADD: EX DE,HL LD HL,(MSTINADR) ADD HL,DE EX DE,HL LD HL,(MSTINLEN) LD A,L OR H LD A,EOF RET Z ; LD A,(DE) LD HL,(MSTINPTR) INC HL LD (MSTINPTR),HL RET ; ;.................................................. ; Routines to support writing to Master-Out file | ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;..... ; Write complete record addressed by (HL) to Output File ; deleteing spaces. Also bump count of entries written. ; WRITEMO: push hl ; Save entry record address LD HL,COUNT+3 call BUMP pop hl ; ld b,8 ; Output file name call WRMOL ld a,'.' ; ..seperator push hl call PUTMASTOUT pop hl ld b,12 ; ..file type, comma and disk name call WRMOL ld a,'.' ; ..sep for disk name/typ push hl call PUTMASTOUT pop hl ld b,3 ; ..disk type call WRMOL ld a,(USER) ; Check for user and/or date ld c,a ld a,(DATES) or c jp z,WRCRLF ; ..Exit here if neither ld a,(hl) ; get separator inc hl push hl call PUTMASTOUT pop hl ld a,(USER) ; Check users flag or a jp z,WRDATS ld a,(hl) ; ..Output user # inc hl push hl call PUTMASTOUT pop hl ld a,(DATES) ; Check for dates or a jp z,WRCRLF ; WRDATS: ld b,3 ; 3 chars in memory date WDLOOP: push bc push hl ld a,(hl) ; Output 2 ASCII for each BCD dig. push af rrca rrca rrca rrca call MAKHEX call PUTMASTOUT pop af call MAKHEX call PUTMASTOUT pop hl pop bc inc hl ; Point next dec b jp nz,WDLOOP ; ..repeat til done. WRCRLF: LD A,CR CALL PUTMASTOUT LD A,LF jp PUTMASTOUT ; ;..... ; Put string of (B) length addr by (HL) to MasterOut deleting spaces. ; WRMOL: LD A,(HL) CP ' ' ;null character? JP Z,WRSKIP PUSH BC PUSH HL CALL PUTMASTOUT POP HL POP BC WRSKIP: INC HL ;point to next character DEC B JP NZ,WRMOL ;loop until done ret ; ;..... ; Write single char in (A) to Master Out File. ; PUTMASTOUT: ;buffered write of (A) PUSH AF LD HL,(MSTOTLEN) EX DE,HL LD HL,(MSTOTPTR) LD A,L SUB E LD A,H SBC A,D JP C,AAM LD HL,0000H LD (MSTOTPTR),HL ; AAI: EX DE,HL LD HL,(MSTOTLEN) LD A,E SUB L LD A,D SBC A,H JP NC,AAL LD HL,(MSTOTADR) ADD HL,DE EX DE,HL call SDMA ; Set DMA Addr call WRTOUT ; Write Master Output Record JP Z,EXIT LD DE,128 ; Logical sector size LD HL,(MSTOTPTR) ADD HL,DE LD (MSTOTPTR),HL JP AAI ; AAL: call DFLTAD ; Set Default DMA Addr LD HL,0000H LD (MSTOTPTR),HL ; AAM: EX DE,HL LD HL,(MSTOTADR) ADD HL,DE EX DE,HL POP AF LD (DE),A LD HL,(MSTOTPTR) INC HL LD (MSTOTPTR),HL RET ; ;..... ; Fill rest of 256-byte block with EOF, close and rename MAST.OUT ; BBBB: LD A,EOF ; EOF character CALL PUTMASTOUT ; BBBB0: LD HL,(MSTOTPTR) LD A,L AND 7FH JP NZ,CCCC LD (MSTOTLEN),HL ; CCCC: LD A,EOF PUSH AF CALL PUTMASTOUT POP AF JP NZ,BBBB0 jp CLSMST ; Close Mast.Out & rename, Flag errors ; ;------------------------------------------------------: ; Miscellaneous Status and error reporting routines. | ;------------------------------------------------------: ;..... ; Routines to support status updates during catalog operations. ; STPRMP: ld a,(LEADIN) ; Check for screen installation or a ret z ; quit if none ld de,4*256+31 ; Position cursor for msg start call SETCUR call ILPRT defb 'Deleted :' DLNUM: defb ' ',0 ld a,(ERADSK) ; Quit here if delete operation or a ret nz call ILPRT defb ' Added :' ADNUM: defb ' ',0 ret ; ;..... ; Bump ADDED count or print Added name ; ADDONE: ld a,(LEADIN) ; See which routine to use or a jp z,ADDON0 ld hl,ADNUM+3 call BUMP ; Bump count ld de,4*256+55 call SETCUR ld hl,ADNUM jp HLPRT ; Print Added number ; ADDON0: LD DE,ADDMSG LD HL,NADAT jp MESG ; ADDMSG: DEFB 'Add: ',0 ; ;..... ; Bump DELETED count or print Deleted name ; DELONE: ld a,(LEADIN) ; See which routine to use or a jp z,DELON0 ld hl,DLNUM+3 call BUMP ; Bump count ld de,4*256+40 call SETCUR ld hl,DLNUM jp HLPRT ; Print Deleted number ; DELON0: LD DE,DELMSG LD HL,MIDAT jp MESG ; DELMSG: DEFB 'Del: ',0 ; ;..... ; Bump the count in text messages. ; BUMP: LD A,(HL) ;get count digit CP ' ' JP NZ,BUMPNB LD A,'0' ; BUMPNB: INC A LD (HL),A CP '9'+1 ;time to carry? ret nz ;no, done LD (HL),'0' DEC HL JP BUMP ; ;..... ; Print completed file count and disk ID ; ALDON0: xor a ; Turn off stat print flag ld (PRFSIZ),a ; CALL ILPRT DEFB 'MAST.CAT has ' COUNT: DEFB ' entries',0 ld a,(ERADSK) or a ret nz ; No disk ID if erase call ILPRT defb ' with disk: ',0 CALL ILPRTS defb '-' COUNT1: DEFB ' . ',0 ret ; ;..... ; Set Drive holding MAST.CAT and change prompts. ; SETMDRV: ld a,(MDRIVE) ; Get Drive for MAST.CAT ld hl,CDRIVE cp (hl) ; Same drive? ld a,0 jp z,SETM0 dec a SETM0: ld (DRIVE),a jp nz,SETM1 ; Jump if nulti-drive system ld a,(MDRIVE) add a,'A' ; Make ASCII code ld (DR1),a ld (CDR1),a ld (MDR1),a call DISKA ; tell them to leave a disk in Drive A: call ILPRNL defb 'The DISK TO BE CATALOGED and the CATALOG SYSTEM DISK',0 call ILPRNL defb 'will alternately be placed in Drive ' DR1: defb 'A:',0 ; Hot-patched at run-time jp SCROLL ; SETM1: ld a,(CDRIVE) ; Hot patch message texts with add a,'A' ; ..drive to be cataloged.. ld (CDR1),a ld a,(MDRIVE) ; ..and MAST.CAT drive add a,'A' ld (MDR1),a ; ; Tell them to leave disk in drive A:? ; Disk message ; DISKA: ld a,(CDRIVE) ; Drive A: for catalog disk? or a ret z ; Done if so ld a,(MDRIVE) ; Drive A: for MAST.CAT? or a ret z ; Done if so call ILPRT defb 'A Scratch Disk Must Remain In Drive A:',0 jp SCROLL ; ;..... ; Miscellaneous consolidated error messages. ; NOMAST: CALL EREXIT DEFB BELL,'++ Missing Or Empty MAST.CAT ++',0 ; NOIGN: CALL EREXIT DEFB BELL,'++ No IGNORE Names In MAST.CAT ++',0 ; IGNEOF: call ILPRNL DEFB BELL,'++ EOF Reading For IGNORE Names.',0 call EREXIT DEFB 'May Be Missing ")" After Last Name ++',0 ; FMISS: call ILPRNL defb BELL,'++ Missing Format record in Ignore section ++',0 call EREXIT defb ' See MAST.DOC for how to setup this record.',0 ; ;--------------------------------------------- ; Routines to support command line parsing | ;--------------------------------------------- ;..... ; Main Command Line Parsing routine. Loops til no more chars ; PARSE: call GTNOSP ; Get first non-space char ret z PARSE0: cp '<' ; Get disk to Catalog ? jp z,PARS01 cp '>' ; Put to MAST.CAT drive/user ? jp z,PARS02 cp '$' ; Format options ? jp z,PARS03 jp PARSE ; Back to main loop ; PARS01: call SRCDSK ; Set Disk to Catalog PARSEV: ret z call GTSPAC ; Scan until space jp PARSE ; PARS02: call DSTDSK ; Set Disk for MAST.CAT jp PARSEV ; PARS03: call GETOPT ; Get DB Options jp PARSEV ; ; Set Disk Drive to be Cataloged. ; SRCDSK: call GTCCHR ret z cp 'A' ret c cp 'Z'+1 ret nc sub 'A' ; make drive letter binary ld (CDRIVE),a call GTCCHR ret z cp ':' jp z,GTCCHR ret ; ; Set Destination Disk Drive for MAST.CAT ; DSTDSK: call GTCCHR ret z call NUMCK jp nc,DSTDS0 ; If number, process user cp ':' jp z,GTCCHR cp 'A' ; Make sure it's a letter jp c,GTCCHR cp 'Z'+1 jp nc,GTCCHR sub 'A' ; Make drive binary ld (MDRIVE),a call GTCCHR ; Drive set, check for user ret z call NUMCK jp nc,DSTDS0 cp ':' jp z,GTCCHR ret ; DSTDS0: call GETDIG ; Get the digit push af ; ..save while move ld a,(TUSER) ; Get number ld (MUSER),a pop af ret ; ; Get MAST.CAT Format symbols ; GETOPT: xor a ; Set both FALSE ld (USER),a ld (DATES),a GETOPX: call GTCCHR ; Get first ret z cp 'D' ; DATES ? jp z,GETOP1 cp 'U' ; USERS ? ret nz ld a,TRUE ; Set USER true ld (USER),a jp GETOPX ; GETOP1: ld a,TRUE ; Set DATES true ld (DATES),a jp GETOPX ; ; Get command line char, return in uppercase ; GTCCHR: ld a,(CBUFF) ; Any char left ? or a ret z ; ..ret if not dec a ld (CBUFF),a ld hl,(CMDPTR) ld a,(hl) ; Get character inc hl ; ..advance ptr ld (CMDPTR),hl UPPER: cp 'a' ; Make uppercase jp c,GTRET cp 'z'+1 jp nc,GTRET and 5FH GTRET: or a ret ; ; Get previous character ; GTBAK1: ld hl,(CMDPTR) ; Decrement pointer.. dec hl ld (CMDPTR),hl ld hl,CBUFF ; and increment char count inc (hl) ret ; ; Get char while skipping over spaces ; GTNOSP: call GTCCHR ret z cp ' ' jp z,GTNOSP ret ; ; Read command line until space detected. ; GTSPAC: cp ' ' ret z call GTCCHR ret z jp GTSPAC ; ; Gather binary number from command line decimal digits ; GETDIG: call GTBAK1 ; First backup one char ld e,0 ; Initialize counter GETDI0: call GTCCHR ; Get character jp z,GETDIX ; ..exit if null cp ' ' jp z,GETDIX ; ..or space call NUMCK ; Is it a digit ? jp c,GETDIX sub '0' ; ..Yes, so process ld b,a ld a,e ; Multiply old digit times 10 add a,a ; * 2 add a,a ; * 4 add a,e ; * 5 add a,a ; * 10 add a,b ; Add in new digit ld e,a jp GETDI0 ; GETDIX: push af ld a,e ld (TUSER),a ; Store User area for file pop af or a ret ; ;..... ; Extract filename.typ from TBUF, precede with dash in FCB. ; GTNAME: ld de,FCB+1 ld b,8 ; Up to eight cnars in name ld hl,CBUFF+1 ; ..set input pointer ld (CMDPTR),hl GTNAM0: call GTCCHR ; Get character jp z,GTNAM4 cp ' ' ; End if space jp z,GTNAM4 cp '.' ; Start of type ? jp z,GTNAM2 ld (de),a inc de dec b jp nz,GTNAM0 ; loop til all chars read GTNAM1: call GTCCHR ; Name too long if here, scan til sep. jp z,GTNAM9 cp '.' jp nz,GTNAM1 ; GTNAM2: call PAD GTNAM9: ld b,3 ld de,FCB+TYPF+1 ; Type goes here GTNAM3: call GTCCHR jp z,PAD ld (de),a inc de dec b jp nz,GTNAM3 ret ; GTNAM4: call PAD jp GTNAM9 ; Now pad type ; PAD: ld a,b or a ret z ld a,' ' ld (de),a inc de dec b jp PAD ; ;=============================================== ;; Miscellaneous Support Routines || ;=============================================== ;..... ; Move subroutine (DE)=>(HL), length in (B) ; MOVER: LD A,(DE) AND 7FH ;strip LD (HL),A INC DE INC HL DEC B JP NZ,MOVER RET ; ;..... ; MOVNC subroutine (DE)=>(HL), length in (B). This version strips the ; hi-order bit, if set. It also filters out commas which might other- ; wise mess up the database. ; MOVNC: LD A,(DE) AND 7FH ;strip the hi-order bit CP ',' ;is it a comma? JP NZ,MN1 ;jump if not LD A,'/' ;else change to slash ; MN1: LD (HL),A INC DE INC HL DEC B JP NZ,MOVNC RET ; ;..... ; Fill memory addressed by (HL) with value in 'A' for 'B' bytes ; FILL: ld (hl),a inc hl dec b jp nz,FILL ret ; ;..... ; Fill (HL) with value in 'A' thru DE value ; FILL16: ld b,a FIL16A: ld (hl),b inc hl ld a,e sub l ld a,d sbc a,h jp nc,FIL16A ret ; ;..... ; Compare routine (DE)<=>(HL), length in (B) ; COMPR: LD A,(DE) CP (HL) RET NZ ;ret with non zero set INC DE INC HL DEC B JP NZ,COMPR RET ;zero set, shows = ; ;..... ; Compare routine (DE)<=>(HL) with ambiguous match, len in B ; COMPIG: ld a,(de) cp '?' ; This matches all jp z,COMPI0 cp (hl) ret nz ; ..return non-zero if .ne. COMPI0: inc de inc hl dec b jp nz,COMPIG ret ; ;..... ; Get free disk space; plug it into the phantom file. Since number of ; blocks on disk is DSM+1, get DSM. ; FRESPC: CALL CKCPM3 ;go calculate free space if CP/M 3.0 LD HL,(DPBADDR) ;retrieve adr. of disk parameter block LD DE,5 ;dsm is at DPB+5 ADD HL,DE LD E,(HL) ;low byte of DSM INC HL LD D,(HL) ;high byte of DSM EX DE,HL ;'HL'=DSM INC HL ;block=DSM+1 LD (TBTR),HL ;save total bits to read ; ; Get code for bytes per block, where 1=1024, 2=2048, 3=4096, etc. ; LD HL,(DPBADDR) ;recover DPB address INC HL ;bsh is at DPB+2 INC HL LD A,(HL) ;BSH is 3-7, SUB 2 ;make it 1-5 CP 5+1 ;check for over 5 JP NC,NONSTAN ;if so, it is non-standard CP 1 ;check for under 1 JP C,NONSTAN ;if so, it is non-standard LD (BLKSIZE),A ;save the block size ; ; Find allocation vector and count the bits reset. ; LD HL,(TBTR) EX DE,HL ;'DE'=total of all vector bits to read push de ; ..To be sure LD C,ALLVEC ;tell 'BDOS' to get address of CALL BDOS ; the allocation vector in 'HL' pop de ; NXTBYT: LD A,(HL) ;get a byte of allocation vector LD C,8 ;it has eight bits, right? ; ROTAT: RLCA ;move a bit to carry CALL NC,COUNTIT ;not set? it'S A FREE BLOCK DEC DE ;count the bit just checked PUSH AF ;save the bit pattern LD A,D ;have we done the whole OR E ; allocation vector? JP Z,KFREE ;finished here, if so POP AF ;restore the bit pattern DEC C ;count a bit done JP NZ,ROTAT ;more bits this byte? do another INC HL ;done with byte? bump pointer, JP NXTBYT ; and get the next byte ; COUNTIT: PUSH HL ;save the allocation vector pointer LD HL,(BLKSFRE) ;increment the 'BLOCKS FREE' count INC HL LD (BLKSFRE),HL POP HL ;restore the pointer RET ; ;..... ; Free space on disk is block size times number of free blocks. ; KFREE: POP AF ;clean the stack LD A,(BLKSIZE) ;get block size LD HL,(BLKSFRE) ;get free blocks ; MULT: DEC A ;free space=free blocks JP Z,CONDEC ; times block size ADD HL,HL JP MULT ; ;..... ; Calculate free disk space if CP/M 3.0 ; CKCPM3: LD C,CPMVER ;check version # CALL BDOS LD A,L CP 30H ;version 3.0? RET C ;use normal method if not CP/M 3.0 POP HL ;remove 'CALL CKCPM3' from stack LD C,CURDSK CALL BDOS LD E,A LD C,46 ;CP/M 3.0 compute free space call CALL BDOS LD C,3 ;answer is 3 bytes long (24 bits) ; FREE30: LD HL,TBUF+2 ;answer is locted here LD B,3 ;convert to 'K' length OR A ; FREE31: LD A,(HL) RRA LD (HL),A DEC HL DEC B JP NZ,FREE31 ;loop for 3 bytes DEC C JP NZ,FREE30 ;shift 3 times LD HL,(TBUF) ;get result in 'K' JP CONDEC ;display result ; NONSTAN: CALL EREXIT DEFB BELL,'++ Can''t Read Free Disk Space ++',0 ; ;..... ; Arrive here with 'HL' = free disk space. Convert to decimal and store. ; CONDEC: LD B,0 ;leading zero flag LD DE,-10000 CALL CONDC1 LD DE,-1000 CALL CONDC1 LD DE,-100 CALL CONDC1 LD DE,-10 CALL CONDC1 LD A,L ADD A,'0' CALL CONDC4 ;print it LD A,'k' JP CONDC4 ;print it, finished ; ;... ; Subtract until negative ; CONDC1: LD C,'0'-1 ;count in ASCII ; CONDC2: INC C ADD HL,DE JP C,CONDC2 ; ; Too many, add one back. ; LD A,D ;get two's complement CPL ; of two's complement LD D,A ; to get value to LD A,E ; add back CPL LD E,A INC DE ADD HL,DE ; ; Arrive here with decimal digit in 'C' ; LD A,C ;get count in 'A' CP '1' ;zero? JP NC,CONDC3 ;no LD A,B ;yes, is it a leading zero? OR A LD A,C ;get digit to 'A' JP NZ,CONDC4 ;not leading zero, store it LD A,'+' ;convert leading zero JP CONDC4 ; CONDC3: DEC B ;set no leading zero flag ; CONDC4: PUSH HL ;save value LD HL,(FREPTR) ;point to current 'NABUF' slot LD (HL),A ;store the digit INC HL ;bump the pointer LD (FREPTR),HL ;save it POP HL ;recover value RET ; ; Check for ASCII digit in range '0'-'9'. Return Carry set if not ; NUMCK: cp '0' ret c cp '9'+1 ccf ret ; ; Convert Low Nybble in A-register to Hex ASCII digit ; MAKHEX: and 0FH ; Mask off Hi Nybble add a,90H daa adc a,40H daa ret ; ;----------------------------------------------------- ; Disk Access Commands Consolidated here. ;----------------------------------------------------- ; ; Fast Disk Reset - Plu*Perfect Systems' code ; ; fast_reset the drive in (A) and relog it in ; FRESET: ld (reqdrv),a ld c,a ld a,(DEFRES) ;does user want a general reset? or a jp nz,fresall ;yes push bc ;save drive request ld c,LOGINV call bdos ld (logged),hl pop bc call shftr and 01H jp z,flogit ;it's not logged in ld a,(reqdrv) ld b,0 ld hl,(logged) ld a,l jp fres2 fres1: ld c,1 call shftr fres2: and 01H jp z,fres3 ld a,(reqdrv) cp b jp nz,fres4 fres3: inc b ld a,b cp 16 jp c,fres1 ; fresall: ld c,RESET ; nothing else logged in, call bdos ; ...do a general reset jp flogit ; ;have a 2nd logged drive, switch to it ; fres4: ld e,b call SELECT ld hl,1 ;construct bit vector for requested drv ld a,(reqdrv) ld c,a call shftl ex de,hl ld c,RESDRV ;log it out call bdos ; flogit: ld a,(reqdrv) ;now log it in SELECA: ld e,a SELECT: ld c,SELDSK jp bdos ; reqdrv: defb 0 ;requested drive logged: defw 0 ;logded drives vector ; ; shift hl left (C) bits ; SHFTL: inc c shftl1: dec c ret z add hl,hl jp shftl1 ; ; shift hl right (C) bits ; SHFTR: inc c shftr1: dec c ret z ld a,h or a ;clear cy rra ;bit 0 to cy ld h,a ld a,l ;cy to bit 7 rra ld l,a jp shftr1 ; ;----------------- ; ; Set CATALOG drive & user ; SETCAT: ld a,(MDRIVE) call SELECA ld a,(MUSER) ld e,a jp SETUSR ; ; Set Default DMA Address for transfers ; DFLTAD: ld de,TBUF SDMA: ld c,SETDMA jp BDOS ; ; Get/Set User routine. ; GETUSR: ld e,0FFH SETUSR: ld c,G$SUSR jp BDOS ; ; Erase MAST.BAK, and general purpose File Erase ; ERASBK: ld de,FCBBAK ; Erase Mast.BAK to save disk space ERASF: ld c,ERASE jp BDOS ; ; Read Master Input file, and General Purpose File Read ; RDMINF: ld de,FCBM_IN READF: ld c,READ jp BDOS ; ; Open Master Input File, and General Purpose File Open ; OPMINF: ld de,FCBM_IN OPENF: ld c,OPEN jp BDOS ; ; Write Master Output File, and General Purpose File Write ; WMOUTF: ld de,FCBM$OUT WRITEF: ld c,WRITE jp BDOS ; ; Create/Make New Master Output File, and General Purpose Create ; MKMOUT: ld de,FCBM$OUT MAKEF: ld c,MAKE jp BDOS ; ; Close Master Output File, and General Purpose File Close ; CLMOUT: ld de,FCBM$OUT CLOSF: ld c,CLOSE jp BDOS ; ;..... ; Close MAST.OUT with Error Reporting, then Perform renaming of ; MAST.CAT to MAST.BAK, and MAST.OUT to MAST.CAT. ; CLSMST: call CLMOUT ; Attempt to close MAST.OUT INC A JP NZ,MSTREN ; Jump if No errors, & Rename call ILPRNL defb BELL,'++ Cannot Close MAST.OUT ++',0 MSTREN: LD HL,FCBM_IN LD DE,FCBBAK CALL SRENAM ; Move names in position & Rename LD HL,FCBM$OUT LD DE,FCBM_IN jp SRENAM ; Move more and rename again ; SRENAM: PUSH HL LD BC,16 ADD HL,BC SRENML: LD A,(DE) LD (HL),A INC DE INC HL DEC C JP NZ,SRENML POP DE LD C,RENAME jp BDOS ;..... ; Make/Create the MAST.OUT file with Error Reporting ; MAKOUT: XOR A ; Clean FCB LD (FCBM$OUT+12),A LD (FCBM$OUT+32),A LD DE,FCBM$OUT ; Erase existing MAST.OUT call ERASF call MKMOUT ; Make new MAST.OUT INC A ret nz ; Return if OK with Zero flag reset call ILPRNL defb '++ No Directory Space',0 jp WRTERR ; Jump to finish error message. ;..... ; Write a record to MAST.OUT with Error Reporting ; WRTOUT: call WMOUTF ; Write the sector or a jp z,WRTOU1 ; Reset Zero flag and return on OK call ILPRNL defb '++ Disk Full',0 WRTERR: call ILPRT ; Finish up error message defb ' : MAST.OUT ++',BELL,0 xor a ; Set zero for errors ret ; WRTOU1: inc a ret ; ;----------------------------------------------------- ; Command Support routines trapped from CRTIN routine. ;----------------------------------------------------- ; ; <^D> Change Drive to be cataloged. ; CMDDRV: ld de,1*256+2 ; Col 2, line 1 ld hl,DRVSTR ; Load command string call SHOSCR call ILPRT defb '==> Enter Drive to Catalog : ',0 call GETCH ; Get letter cp 'A' ; Don't Change if not letter jp c,CMDDRX cp 'Z'+1 jp nc,CMDDRX call CRTOUT sub 'A' ; ..make binary ld (CDRIVE),a ; ..and store CMDDRX: jp ENDCMD ; Exit properly ; DRVSTR: defb 'RIVE CHANGE',0 ; ;..... ; <^L> Log Drive/User location of MAST.CAT. ; CMDMST: ld de,1*256+17 ; Col 17, line 1 ld hl,MSTSTR ; Get Active string call SHOSCR call ILPRT defb '==> MAST.CAT on Drive/User (DU) : ',0 ld e,0 ; Initialize counter call GETCH cp CR jp z,CMDMX ; Quit w/No changes if CR.. cp ' '+1 jp c,CMDMX ; Quit if space or control chars. call NUMCK ; Check for number jp nc,CMDMS0 ; ..Process User area if so cp 'A' ; Make sure it is letter.. jp c,CMDMX cp 'Z'+1 jp nc,CMDMX ; ..quit if not.. call CRTOUT sub 'A' ld (MDRIVE),a ; Else save drive CMDMS1: call GETCH ; Get next character call NUMCK ; ..See if number jp c,CMDMSX ; Exit if not number CMDMS0: call CRTOUT ; ..else echo char sub '0' ; make binary ld b,a ld a,e ; last result add a,a ; * 2 add a,a ; * 4 add a,e ; * 5 add a,a ; * 10 add a,b ; Add last digit ld e,a ; ..and store jp CMDMS1 ; CMDMSX: ld a,e ; Get user area.. ld (MUSER),a ; ..and Store CMDMX: jp ENDCMD ; MSTSTR: defb 'OG MAST.CAT',0 ; ;..... ; <^F> Change Database Format ; CMDFMT: ld de,1*256+49 ; Col 49, Line 1 ld hl,FMTSTR ; Get active string call SHOSCR call ILPRT defb '==> Add USER Field (Y/N) : ',0 call CRTIN cp 'N' ; Check response ld a,FALSE ; ..preload NO push af call z,SHOW$N pop af jp z,CMDFM0 call SHOW$Y ld a,TRUE CMDFM0: ld (USER),a call ILPRNL defb '==> Add DATE Field (Y/N) : ',0 call CRTIN cp 'N' ; Check response ld a,FALSE ; ..and preload NO push af call z,SHOW$N pop af jp z,CMDFM1 call SHOW$Y ld a,TRUE CMDFM1: ld (DATES),a ; Save DATES flag jp ENDCMD ; ..and Exit ; FMTSTR: defb 'ORMAT (UD)',0 ; ;..... ; <^R> Remove designated Disk ID from MAST.CAT ; CMDERA: ld de,1*256+65 ; Offset to line 1, Col 65 ld hl,ERASTR ; Get active string call SHOSCR call ILPRT defb '==> Remove all entries for Disk.. (3-char .TYP) : -.',0 call GTYPFCB ; Read in type and format call ILPRNL defb '==> Are you sure you want to remove these entries (Y/N) ? ',0 call CRTIN cp 'N' push af call z,SHOW$N pop af jp z,ENDCMD ld a,TRUE ld (ERADSK),a ; Flag to show we are erasing call SHOW$Y jp CATGO ; ..and ERASE all references to it ; ERASTR: defb 'EMOVE VOL.',0 ; ; <^I> Initialize MAST.CAT file on disk ; CMDINIT:ld de,1*256+33 ; Offset to line 1, Col 33 ld hl,INTSTR ; Get active string call SHOSCR ; ..highlight call ILPRT defb '==> Are You Sure ? (Y/N) : ',0 call CRTIN cp 'N' jp z,CMDINO ; Exit if NO call SHOW$Y xor a ; Nothing in Ignore list ld (IGNCNT),a ; ; Set proper disk and user area ; call SETCAT ld de,FCBM_IN ; Check for existing MAST.CAT ld c,SRCHF call BDOS inc a jp z,CMDINZ ; ..not found, skip msg ; call ILPRNL defb BELL,'** Existing MAST.CAT will be renamed MAST.BAK **',0 call SCROLL call SETCAT ; Reselect drive/user ; ; Start byu Erasing MAST.OUT, and Creating a new one ; CMDINZ: call MAKOUT call ILPRNL defb ' ==> Enter Files you do NOT want in catalog. ' defb '(single exits)',0 call SCROLL ; ld hl,(TDBUFF) ; Build IGNORE list here ld (MSTOTADR),hl ; ..so set MAST.OUT pointers ld de,1024 ; Give 1K buffer size add hl,de ld (MSTOTLEN),hl ld hl,0000 ld (MSTOTPTR),hl ld a,'(' ; Open IGNORE list call PUTMASTOUT ld a,'{' ; ..start Flag field call PUTMASTOUT ld a,(USER) or a jp z,CMDIN0 ld a,';' call PUTMASTOUT CMDIN0: ld a,(DATES) or a jp z,CMDIN1 ld a,'|' ; Add Dates sep and Curyr call PUTMASTOUT ld a,(CURYR) ; ..and current year push af rrca rrca rrca rrca ; Put high digit in position call MAKHEX call PUTMASTOUT pop af call MAKHEX call PUTMASTOUT CMDIN1: ld a,'}' ; Show end of Mask string call PUTMASTOUT ld hl,TIMFIL ; Output !!!TIME&DAT string CMDIN2: call CMDIST ld a,(IGNCNT) ; Bump count inc a cp 36+1 ; Have we entered too many ? jp z,CMDIN8 ; ..say so. ld (IGNCNT),a ; ld a,':' ; Give prompt call CRTOUT ld hl,CBUFF xor a ld (hl),a inc hl ld (hl),a call INLINE ; Get next entry ld hl,CBUFF ld a,(hl) ; Anything there ? or a jp z,CMDIN9 inc hl jp CMDIN2 ; ; Print ending warning. Fall thru to end. ; CMDIN8: call ILPRT defb '++ Reached ''Ignore'' limit...closing.',0 ; ; Now Close it and rename the files. ; CMDIN9: ld a,')' call PUTMASTOUT call WRCRLF call BBBB jp CMDINX ; CMDINO: call SHOW$N CMDINX: jp ENDCMD ; Exit ; ;..... ; Move string to MAST.OUT buffer. End on terminating zero. ; CMDIST: push hl ; Save pointer call SCROLL call WRCRLF ; Give opening newline pop hl CMDIS0: ld a,(hl) or a ret z push hl ; Save pointer call PUTMASTOUT pop hl inc hl jp CMDIS0 ; ..continue til done. ; TIMFIL: defb '!!!TIME&.DAT',0 ; INTSTR: defb 'NITIALIZE',0 ; ;..... ; Support routine to position cursor, show comd and scroll ; SHOSCR: call SHOCMD ; Show the command ld a,(SCRLIN) ; Get current line ld d,a ld e,0 call SETCUR ; Position cursor jp SCROLL ; ;-------------------------------------------------------- ; Keyboard Input routines Consolidated here. ;-------------------------------------------------------- ; Basic direct Console read routine ; GETCH: push hl ; Save regs push de push bc GETCH0: ld c,TRMIO ; Use CP/M 2.2 direct method ld e,0FFH ; ..for input call BDOS or a jp z,GETCH0 pop bc pop de pop hl and 7FH ; Strip MSB if there jp UPPER ; ..Return Uppercase ; ;..... ; Gets a character from the keyboard while sensing for Command ; character indicators. ; CMDIN: ld hl,PRMPYN ; Print ready msg call HLPRT call CRTINT ; console read with time update cp 'L'-40H ; Log MAST.CAT Drive ? jp z,CMDMST cp 'I'-40H ; Initialize MAST.CAT ? jp z,CMDINIT cp 'D'-40H ; Change Drive ? jp z,CMDDRV cp 'F'-40H ; Change Database Format ? jp z,CMDFMT cp 'R'-40H ; Erase Disk records ? jp z,CMDERA cp 'Z'-40H ; Redraw screen ? jp z,DRWAGN RET ; PRMPYN: defb ' Ready? (Y/N) : ',0 ; ;..... ; Read Console direct while sensing and updating clock. ; CRTINT: ld a,(LEADIN) or a ; No time if can't address cursor jp z,CRTIN TIMLOP: ld a,255 ; Set clock timer ld (TIMER),a call RDTIM ; ..Read clock and display ld a,(SCRLIN) ; ..Reposition cursor to active line ld d,a ld e,49 ; ..in right column call SETCUR ; ..and Set It. TIMLO1: ld c,TRMIO ; See if character ready ld e,0FFH ; ..via direct read call BDOS or a jp nz,CRTIM ; Jump to process if present ld b,0 ; ..Do a little pause TIML02: dec b jp nz,TIML02 ld a,(TIMER) ; Time to read yet ? dec a ld (TIMER),a jp nz,TIMLO1 jp TIMLOP ; CRTIM: and 7FH ; Do preprocess of char call UPPER jp CRTIN0 ; ..now finish ; ;..... ; Get a character from the keyboard. ; CRTIN: call GETCH ; Basic console read CRTIN0: CP 'C'-40H ;CTL-c? JP Z,CRTNO ;if yes, abort cp CR ; Carriage return ? jp z,CRTYES cp ' ' ; Space ? jp z,CRTYES CP 'X'-40H ;CTL-x? ret nz ; ..return if not ; CRTNO: ld a,'N' ; Show 'N' on exit for other chars RET ; CRTYES: ld a,'Y' ; Show 'Y' for Yes RET ; ;..... ; Read in a string and load the first 3 chars as TYPE in FCB ; GTYPFCB: ld hl,CBUFF ld (hl),2 inc hl ld (hl),'-' inc hl ld (hl),'.' inc hl call INLINE ; Read name and type into Default buffer jp GTNAME ; ..and format in FCB ; ;..... ; Input a character string to memory in uppercase deleting cntl chars ; INLINE: call GETCH cp BS ; Process backspace jp z,INBKSP cp DEL ; ..also Delete jp z,INBKSP ld (hl),0 ; In case of end cp CR ; End ? ret z call LEGAL ; Check for illegal chars jp nz,INLIN0 ld a,BELL call CRTOUT ; Ring bell on error jp INLINE ; INLIN0: ld (hl),a ; save char ld a,(CBUFF) inc a ; Bump char count cp 30 ; Limit reached ? jp z,INLINE ld (CBUFF),a ld a,(hl) call CRTOUT ; Echo char if under limit inc hl jp INLINE ; INBKSP: ld a,(CBUFF) ; Already at start ? or a jp z,INLINE dec a ld (CBUFF),a dec hl ld a,BS call CRTOUT ld a,' ' call CRTOUT ld a,BS call CRTOUT jp INLINE ; ; Check for illegal chars in name.typ. Return NZ if OK, else Z ; LEGAL: cp '-' jp z,LEGOK cp '/' jp z,LEGOK cp '.' jp z,LEGOK cp '*' jp z,LEGOK cp '?' jp z,LEGOK cp '0' jp c,LEGNO cp '9'+1 jp c,LEGOK cp '@' jp c,LEGNO cp 'Z'+1 jp c,LEGOK LEGNO: xor a ret ; LEGOK: or a ret ; ;-------------------- End Console Input ------------------------ ; ; Report error message, turn off Immediate, and return to menu ; EREXIT: call SCROLL ; Add CRLF POP hl ; Get message address call HLPRT ; ..and print it call SCROLL xor a ld (IMMED),a jp AGAIN ;..... ; Exit after saying Goodbye on CRT ; EXITNO: call ILPRT defb '..Good Bye.',0 ; EXIT: CALL CRLF CALL CRLF ld a,(CUSER) ; Reset user to entry ld e,a call SETUSR ld a,(CURDRV) ; Reset entry drive call SELECA JP 0000H ; To CP/M return address ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Console Output routines consolidated here for convenience. ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; Print message in 'DE', then name in 'HL' ; MESG: PUSH HL MESG1: ld a,(de) ; Get character or a jp z,MESG0 ; .. quit if terminator inc de call CRTOUT ; .. and display it jp MESG1 ; MESG0: POP HL LD B,12 ;name,'.',type ; MESGL: PUSH HL PUSH BC LD A,(HL) ;get character CP ' ' CALL NZ,CRTOUT ;display the character ; MESGS: POP BC POP HL INC HL DEC B JP NZ,MESGL jp SCROLL ;..... ; CRLF: CALL ILPRT ;carriage ret - line feed DEFB CR,LF,0 RET ;..... ; ; Move to New line and fall thru to Inline Print routine ILPRNL: call SCROLL ; ..and fall thru... ;..... ; Inline print subroutine ; ILPRT: EX (SP),HL ;get starting address of string to 'HL' call HLPRT inc hl ; Bump past ending 0 ex (sp),hl ; ..return addr to top of stack ret ; ; Print Zero-terminated string addressed in HL register pair ; HLPRT: LD A,(HL) OR A ret z call CRTOUT ; Show character on CRT INC HL jp HLPRT ;..... ; Inline print subroutine, does not show spaces ; ILPRTS: EX (SP),HL ;get starting address of string to 'HL' ; ILPLPS: LD A,(HL) CP ' ' ;ignore spaces JP Z,ILPLPT CALL CRTOUT ;display the character ; ILPLPT: INC HL LD A,(HL) OR A JP NZ,ILPLPS INC HL EX (SP),HL ;return addr to top of stack RET ;..... ; Displays one character on the CRT ; CRTOUT: PUSH AF ;save the character push de push hl LD C,TRMIO LD E,A ;get the character into 'E' reg. CALL BDOS ;show the character on the crt pop hl pop de POP AF ;get the character back RET ; ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Full-Screen oriented routines, and terminal attribute procs. ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; Print Horizontal line across full screen width. ; HLINE: ld a,(TWIDTH) ; Get defined width dec a ; ..-1 ld b,a HLINLP: ld hl,HCSTR ; Get char (or string) push bc call HLPRT ; ..print it pop bc dec b jp nz,HLINLP ret ; ; Set Cursor to row = 'D', Column = 'E' registers ; Checks for valid screen addressing. ; SETCUR: ld a,(LEADIN) ; See if cursor cntls present or a ret z ; ..Exit here if not ; push hl ; Save HL ld hl,LEADIN ; Send lead string call HLPRT ld a,(FASTFLG) or a jp nz,FSETDE ; ld a,(ROWFIRST) or a ld hl,ROWBIAS jp nz,ROW1 inc hl ; Point at col bias ld a,d ; Exchange order of coordinates ld d,e ; ..make D = col.. ld e,a ; ..E = row. ROW1: push de ; Save coordinate values ld a,d ; A = 1st coord to send call PUTCOORD ; ..send it. ; ld hl,MIDSTR ; Mid string call HLPRT ; ; Now the 2nd coordinate. pop de ; Restore coordinates ld a,(ROWFIRST) or a ld hl,COLBIAS jp nz,ROW2 dec hl ; Row Bias ROW2: ld a,e ; ..A = 2nd coord to send call PUTCOORD ; ld hl,TAILSTR ; Tail String call HLPRT ; ..output it pop hl ret ; Exit.. ; ; A = Binary value of coordinate to send ; HL --> Bias to be added ; PUTCOORD: add a,(HL) ; Add the bias ld e,a ; Save result in E ld a,(BINARY) or a jp z,PUTASCII ld a,(COMPFLG) ; Complement if needed xor e jp CRTOUT ; ; Put coordinates as ASCII digit(s) ; PUTASCII: ld a,e ; Get value back DECOUT: push bc ; ..Save BC ld b,0 ; Tens digit counter PLP: sub 10 jp c,PDONE inc b jp PLP ; PDONE: add a,10 ; Add back for underflow push af ; ..Save low digit ld a,b ; ..Get tens or a call nz,OUTASC pop af ; Retrieve digits call OUTASC pop bc ; Restore BC ret ; OUTASC: add a,'0' ; Make ASCII jp CRTOUT ; ; Fast toutine when row, col order, binary, no complementing, ; no MID and TAIL strings. ; (Kaypro, Heath, etc.) ; FSETDE: ld a,(ROWBIAS) add a,d call CRTOUT ld a,(COLBIAS) add a,e call CRTOUT pop hl ; Restore HL saved at beginning ret ;..... ; Insert Line on screen. ; ILINE: ld hl,INSLINSTR jp HLPRT ; ;..... ; Delete a Line on the screen. ; DLINE: ld hl,DELLINSTR jp HLPRT ; ;..... ; Start Highlighting area of the screen. ; HILIT: ld hl,HILITSTR jp HLPRT ; ;..... ; End Highlighting area of the screen. ; UHILIT: ld hl,UNHILITSTR jp HLPRT ; ;..... ; Clear to End-Of-Line ; CLEOLN: ld hl,CLREOLSTR jp HLPRT ; ;..... ; Clear to End-Of-Screen ; CLEOSCR: ld hl,CLREOSSTR ;7/18 jp HLPRT ; ;..... ; Check for cursor addressing, and CRLF if none. ; CHKCRLF: ld a,(LEADIN) ; If null in leadin, then no screen or a ; installation has been performed.. ret nz jp CRLF ; ..so do CRLF ; ;..... ; Paint lines on main window of screen. ; SCROLL: ld a,(THEIGHT) ; Compare to last line on screen ld b,a ld a,(SCRLIN) ; See if on last line inc a ld (SCRLIN),a cp b jp c,SCROL0 ; OK, bypass clear call RDTIM ; Read clock and print time ld a,6 ld (SCRLIN),a ld d,a ld e,0 call SETCUR ld hl,CLREOSSTR ; Clear to end-of-screen call HLPRT ld d,5 ; Set cursor to end of line.. ld a,(TWIDTH) ; ..above top available dec a ld e,a call SETCUR SCROL0: jp CRLF ; Roll up a new line and quit ; ;..... ; Highlight command tails in On-line Help when active. ; Unhighlight on exit. Enter with Command + 2 address in DE ; SHOCMD: ld a,(LEADIN) ; Only do if can address cursor or a ret z SHOCM1: push hl ; ..and save string addr call SETCUR call HILIT pop hl ; Retrieve string addr call HLPRT ; ..and print jp UHILIT ; ; Exit routine. Redraw screen if terminal installed. ; ENDCMD: ld a,(LEADIN) ; Do only if can address cursor or a jp z,AGAIN ; jp DRWAGN ; ..and exit back to main loop ; ;+ + + + + + + + + + + End Screen Interface + + + + + + + + + + + ; ; Spell out answers for space bar and Return key depressions ; SHOW$Y: call ILPRT defb 'YES',0 ; Spell YES on the CRT ret ; SHOW$N: call ILPRT defb 'NO',0 ; Spell NO on the CRT ret ; ;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; Screen Drawing routines consolidated here. ;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; Draw six lines of pre-determined information on top of screen. ; DRAWSCR: ld hl,CLRSCRSTR ; Clear screen and home call HLPRT ld de,0000 ; Set cursor to home call SETCUR CALL ILPRT DEFB 'MCAT Cataloger v 5.' defb versno,revno,0 ; ld a,(DSFLAG) ; See if DateStamper installed or a jp z,NODSTP call ILPRT defb ' - for- DateStamper',0 ; NODSTP: call CRLF ; ; Now print On-line Help ; ld de,1*256+0 ; Position cursor where we are push de ; ..get set for later call CMDD00 defb '^D',0 CMDD00: pop hl call SHOCM1 ; Highlight Karat and ist char. call ILPRT CMDD: defb 'rive Change ',0 pop de push de ld e,15 call CMDM00 defb '^L',0 CMDM00: pop hl call SHOCM1 call ILPRT CMDM: defb 'og MAST.CAT ',0 pop de push de ld e,31 call CMDI00 defb '^I',0 CMDI00: pop hl call SHOCM1 call ILPRT CMDI: defb 'nitialize ',0 pop de push de ld e,47 call CMDF00 defb '^F',0 CMDF00: pop hl call SHOCM1 call ILPRT CMDF: defb 'ormat (UD) ',0 pop de ld e,63 call CMDE00 defb '^R',0 CMDE00: pop hl call SHOCM1 call ILPRT CMDE: defb 'emove Vol.',0 ; ; Draw separation line (third line - 2) ; call CRLF call HLINE ; Draw a horizontal line ; ; Print Fourth status line (line - 3) ; call CRLF call ILPRT defb 'Catalog Drive : ',0 ld a,(CDRIVE) add a,'A' ; Make ASCII call CRTOUT call ILPRT defb ' ',0 ; Spacing chars ld de,3*256+29 ; Position to 30th column call SETCUR ld hl,VCSTR ; Print Vertical separator call HLPRT call ILPRT defb ' Format ===> ',0 call ILPRT defb 'FN.FT ',0 ld a,(USER) or a jp z,US001 CALL ILPRT DEFB '/User ',0 US001: ld a,(DATES) or a jp z,US001A call ILPRT defb '-Date',0 ; ; Print fifth line for Catalog and MAST.CAT drive IDs (line - 4) ; US001A: call CRLF call ILPRT defb 'MAST.CAT on DU : ',0 ld a,(MDRIVE) add a,'A' call CRTOUT ld a,(MUSER) call DECOUT ; ..and print in decimal ld de,4*256+29 ; Print vert sep char call SETCUR ld hl,VCSTR call HLPRT ; ; Do another horizontal line (sixth line - 5) ; call CRLF call HLINE ; ..And draw another line ld a,(SCRLIN) ; Restore saved cursor line ld d,a ld e,0 jp SETCUR ; ..and quit ; ;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; DateStamper Support routines ;+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; ; Load date from !!!TIME&.DAT into ASCII field at (HL) ; Use Created date or default if no Modified field ; Use NUL if neither, or no time&date field (Z on entry) ; GTFDAT: ex de,hl ;save ptr to destn ld hl,ZERO3 ; use NUL if no date (Z set) jp z,gtfda1 ld hl,(TDPTR) ; Get current pointer to dates gtfda1: ex de,hl ;restore in proper locns inc de inc de ; -> day MBCDAT: ld a,(de) ; Move 3 chars reversing order ld (hl),a inc hl dec de ld a,(de) ld (hl),a inc hl dec de ld a,(de) ld (hl),a inc hl ret ; ;..... ; Convert packed BCD date in BCDBUF to 6 ASCII digits ; in ASCDAT ; ASCONVRT: ld de,BCDBUF+2 ld hl,ASCDAT ASCON1: call DODIGIT ; Convert day & store dec de call DODIGIT ; Convert Month & store dec de ; ..fall thru to year & ret. ; DODIGIT: ld a,(de) ; Get BCD digit rrca ; ..rotate Hi to low rrca rrca rrca call DODIG1 ; Do first nybble.. ld a,(de) ; ..fall thru to second. DODIG1: call MAKHEX ; Convert low Nybble to Hex digit ld (hl),a ; store it.. inc hl ; ..and go to next digit ret ; ;..... ; Print Date to CRT in the form of DD MMM YY from the ASCDAT string. ; DATLIN: ld hl,ASCDAT ld a,(hl) inc hl call CRTOUT ld a,(hl) inc hl call CRTOUT ld a,' ' ; Space seperator call CRTOUT ld a,(hl) sub '0' ; Find index to Month ld e,a add a,a ; *2 add a,a ; *4 add a,e ; *5 add a,a ; *10 ld e,a inc hl ld a,(hl) inc hl ; Point to YEAR (Hi) push hl ; ..and save sub '0' add a,e dec a cp 12 ; Check invalid index jp c,P6a ; ..bypass if OK..else.. ld a,12 ; Show Invalid month. P6a: ld e,a ld d,0 ld l,e ld h,d add hl,hl ; Correct for table entry length add hl,de ld de,MONTHS ; ..and add to table add hl,de ld b,3 ; Months are three letters P6loop: ld a,(hl) push bc call CRTOUT pop bc inc hl dec b jp nz,P6loop ; ..Loop til done ld a,' ' call CRTOUT ld a,'1' call CRTOUT ld a,'9' call CRTOUT pop hl ; Restore YEAR (Hi) ld a,(hl) inc hl call CRTOUT ; Print year ld a,(hl) call CRTOUT jp SCROLL ; ;..... ; Execute routine to get Current date from operator. ENTDAT: call ILPRNL ; No clock so enter Current date defb ' The year has been set to 19',0 ld a,(curyr) call CRTDIG ; Print BCD digit on screen ; ; Get date input with BELL prompt. Also Bell on retries. ; call SCROLL TRYMOR: call ILPRT defb CR,BELL,' Enter date to set : -- ' defb 'mo/da : __/__',BS,BS,BS,BS,BS,0 ld hl,BCDBUF ; Get Date buffer address ld a,(curyr) ; Get static year ld (hl),a inc hl ; Point to month ld (hl),0 ; ..and zero to start call GETNIB call GETNIB ld a,(hl) ; Get month or a ; ..Zero is not allowed jp z,TRYMOR cp 13H ; Test range jp nc,TRYMOR ld (MONTH),a ; Save for days check push hl ld a,'/' call CRTOUT ; Print seperator pop hl inc hl ; Now point to Day ld (hl),0 ; ..and zero to start call GETNIB call GETNIB ld a,(hl) ; Get days input or a ; ..again, no zero jp z,TRYMOR ld c,a ld a,(MONTH) ld hl,DAYS add a,l ld l,a jp nc,NNCC inc h ; Now pointing to max days NNCC: ld a,c dec a ; N - 1 cp (hl) ; Test if bigger than max jp nc,TRYMOR jp SCROLL ; New line for formatting..Exit ; ;..... ; Manual date entry support code ; GETNIB: push hl RETRY: call GETCH ; Use direct console IO cp BS ; Is char Backspace ? jp c,CANCEL cp 07FH ; ..or DELete ? jp z,CANCEL call NUMCK ; Check for number in range jp c,BDIN call CRTOUT ; Now echo the character pop hl ; Return HL pointer and 0FH ; Crunch HI Nybble ld c,a ld a,(hl) ; Get byte add a,a add a,a add a,a add a,a ; ..shift to HI nybble or c ; ..OR in Lo byte ld (hl),a ret ; BDIN: ld a,BELL ; Ring BELL on error call CRTOUT jp RETRY ; ..Try again ; CANCEL: pop hl pop hl ; Clear stack.. jp TRYMOR ; ..and back for more ; MONTH: defb 0 ; Save input month ; ; Pad impossible HEX offsets ; DAYS: defb 00H,31H,29H,31H,30H,31H,30H defb 31H,31H,30H,00H,00H,00H,00H defb 00H,00H,31H,30H,31H ; ;..... ; Read !!!TIME&.DAT file to TBUF, and ; verify checksum of block. Check EOF of file ; Move 3-char dates to TDBUF. ; RDTIMFIL: call DFLTAD ; set tbuf dma ld de,TDFCB ; Check for !!!TIME&.DAT file ld c,SRCHF call BDOS inc a jp nz,HASTD ; Jump if found call ILPRNL defb '++ No ',0 call TDERR call ILPRNL defb ' Default NULL date will be used',0 call SCROLL NOTD: ld a,NO ; Show No Time&Date file ld (TDFLG),A ret ; ; Open !!!TIME&.DAT for reading. Calc. correct sector count. ; HASTD: ld hl,(NAMES) ; # directory entries ld a,l ; Test for partial td sector and 07H ; ..modulo 8 push af ld c,3 call shftr ; # td sectors = DIRMAX/8 pop af jp z,hastd0 inc hl ; Bump for partially empty final sector hastd0: inc hl ; pre-increment ld (TDCNT),hl ; & save count ; ld de,TDFCB call OPENF ; Open the file inc a ; ..check for error jp nz,HASTD1 ; ..Jump if OK call ILPRNL ; ...Else ERROR defb ' ++ Unable to Open ',0 call TDERR jp NOTD ; ; Buffered read of Time&Dat file to tbuf. ; HASTD1: ld hl,(TDCNT) ; Count down # td sectors dec hl ; ld a,h or l ret z ; Counted out ld (TDCNT),hl ; ld de,TDFCB ; Read a sector call READF or a ; ..check for errors push af ; Save flag status ld hl,TBUF push hl call z,CKSUM ; If good read, check errors pop hl pop af ret nz ; all done ; ld b,8 ; do 8 time-date entries TDLP1: push bc push hl ex de,hl ; de = start of time-date entry ld hl,10 ; Offset to Modified field add hl,de ld a,(hl) or a ; Is there a valid entry? jp nz,hastd3 ; ..jump if so ex de,hl ; ..else check Created field ld a,(hl) or a jp nz,hastd3 ; Jump if valid ld hl,zero3 ; Fill date field w/zeros ; hastd3: ex de,hl ;source to de ld hl,(TDPTR) ;destination ld b,3 hastd4: ld a,(de) ; must be 8-bit move ld (hl),a inc de inc hl dec b jp nz,hastd4 ld (TDPTR),hl ;update ptr pop hl pop bc ld de,16 ;point at next time-date entry add hl,de dec b jp nz,TDLP1 jp HASTD1 ; ZERO3: defb 0,0,0 ;zero date entry TDERR: call ILPRT defb '!!!TIME&.DAT File ++',BELL,0 ret ; ; Calculate checksum of 127-byte record and return with result ; in A register, and HL pointing to last byte in 128-byte record. ; CKSUM: push hl ; Save buffer address ld b,127 xor a ; Initially 0 CKSU1: add a,(hl) ; ..binary add of bytes inc hl dec b jp nz,CKSU1 ; ..loop til done cp (hl) ; Compare to filed sum pop hl ; ..restore buffer addr ret z ; Return if OK ; call ILPRNL defb '++ Checksum Error in ',0 ld (TDPTR),hl ; Save buffer addr of last read pop bc ; Clear AF data on stack.. pop bc ; ..and RET to read jp TDERR ; ..via error routine ; ;..... ; Read clock and print on upper-right of screen ; RDTIM: ld a,(LEADIN) or a ret z ; Forget it if no screen addressing.. ld a,(DSFLAG) or a ret z ; ..or DateStamper not installed ld a,(RELCLK) ; Check for Relative clock.. or a ret nz ; ..and quit if so ld a,(BCDBUF+3) ; If "Relative" clock.. or a ; ..then don't read, else.. call p,GTDATE ; Read the clock ld a,(TWIDTH) ; OK, so position cursor sub 10 ld e,a ld d,2 ; On third line call SETCUR call HILIT ; Do it Highlighted ld hl,BCDBUF+3 ld a,(hl) rla ld a,(hl) jp c,RELTIM ; MSB set means Relative time call CRTDIG ; Do hours inc hl ld a,':' call CRTOUT ld a,(hl) call CRTDIG jp UHILIT ; RELTIM: sub 80H ; Strip bias push af inc hl ; Get Low order byte ld l,(hl) pop af ; ..and Hi one ld h,a ld a,'+' ; RELCHAR call CRTOUT ld de,-1000 ; Print 1000's call RDIGIT ld de,-100 ; ..100's call RDIGIT ld de,-10 ; ..10's call RDIGIT ld a,l ; ..and Ones add a,'0' call CRTOUT ld a,TRUE ; Show relative clock read once ld (RELCLK),a jp UHILIT ; Turn off highlighting and quit ; RDIGIT: ld b,'0' ; Start with ASCII 0 DIGLP: push hl ; Save current remainder add hl,de ; ..subtract jp nc,DIGEX ; Quit on overflow pop af ; ..Throw away remainder inc b ; ..bump digit jp DIGLP ; ..and loop til overflow ; DIGEX: pop HL ; Restore remainder ld a,b jp CRTOUT ; Print digit and quit ; ;..... ; Print BCD digit in A-register as two digits on CRT. ; CRTDIG: push af ; Save digit rrca ; Rotate BCD digits rrca rrca rrca call MAKHEX ; Convert to ASCII.. call CRTOUT ; ..and Print pop af ; Restore original call MAKHEX jp CRTOUT ; Print and return ; ;..... ; Error mesage text if attempting to catalog under CP/M versions other ; than 2.2 with DateStamper selected. ; BADVR1: call EREXIT defb BELL,CR,LF defb '++ FATAL ERROR - Date cataloging requires CP/M 2.2 ++' defb CR,LF,CR,LF,0 ; ;..... ; ckclkz.asm 6/26/85 ;============================================================ ; exit: HL = 0, Z set if no clock ; HL = DateStamper clock entry, Z reset if clock present ; CLKADD is also set, so DSCLK can be called hereafter ; ; ; The logic for finding the clock is as follows+ ; ; 1. Use BDOS version number call to check for DateStamper version >= 2.0 ; Call with E = 'D'. ; If DateStamper is installed, function returns H = 'D', L = 22H ; and DE = address of clock. ; ; 2. If version number test fails, check for DateStamper version 1. ; The DateStamper clock address is located from the ; BDOS patch at LOGDR1+1 and is (LOGDR1+1) - 49H. ; ; The checks must be done in this order to maintain compatibility ; with all DateStamper versions and non-standard BDOS systems. ; GETVFN equ 12 ; BDOS version function DSID equ 'D' ; DateStamper ID for getversion call ; CKCLK: ld e,DSID ; Special parameter for ld c,GETVFN ; getversion call call BDOS cp 22H ; Must be 2.2 jp nz,NOCLK ld a,h cp DSID ; If H == DSID, ex de,hl ; ..then clock addr was in DE jp z,CLKA ; Set it & return HL = CLKADD, NZ ; ; Else test for BDOS patch ; ; Exit: NZ is test satisfied, HL = clock addr ; Z, HL = 0 if not ; ld hl,(0001H) ; Start at wb ptr ld a,l ; Test for BIOS jmp vector cp 3 ; ..aligned on page boundary jp nz,NOCLK ; If not, can't find BDOS ; ; ENTER: H = Page of presumed BIOS base ; ; Internal BDOS addresses relative to base of BDOS ; LOGDR1 EQU 0C42H ; 'jmp 06a3' in standard cp/m 2.2 HILOGD EQU 0CH LOLOGD EQU 042H BITMAP EQU 06A3H ; Addresses to be checked LOBITM EQU 0A3H HIBITM EQU 06H DELTAP EQU (HILOGD-HIBITM) ; GETVER EQU 0C7EH ; 'mvi a,022H' in standard CP/M 2.2 ; CLKOFF EQU 42H+7H ;offset to DateStamper clock from (LOGDR1+1) ; BIOSWB EQU 0E03H ; BIOS warmboot address ; TSTCLK: ; ; Test for Version 1 BDOS patch in standard 2.2 BDOS ; ld b,h ; Save B = BIOS base page ld de,GETVER+1-BIOSWB ; Check for CP/M 2.2 vers byte add hl,de ld a,(hl) cp 22H jp nz,NOCLK ; Not standard CP/M 2.2 BDOS ; ; Version byte shows 2.2. Check for DateStamper patch at LOGDR1 ; ; Unpatched 2.2 std bdos: JMP BITMAP ; Patched std bdos : JMP dsaddress ; other : unknown ; LD DE,LOGDR1+1-GETVER-1 ADD HL,DE ; point at addr word LD E,(HL) ; DE = D/S addr, if resident ld a,e cp LOBITM ; Check low byte INC HL LD D,(HL) jp nz,CHECK2 ld a,d ; check Hi byte add a,DELTAP ; Page difference in rel. addresses cp h jp nz,CHECK2 ; NOCLK: ld hl,0 ; Standard, unpatched 2.2 BDOS ==> No clock jp CLKA ; ; Address differs from std. 2.2 bdos. ; Check whether it is internal to the bdos. ; CHECK2: ld a,b ; Base page of BIOS sub d ccf jp nc,STDCLK ; External addr above BDOS sub 0EH ; Page length of BDOS jp c,NOCLK ; External addr below BDOS ; STDCLK: LD HL,-CLKOFF ; Calc. entry to DateStamper clock ADD HL,DE ; CLKA: LD (XCLKADD+1),HL ;set addr in ram for clock calls ld a,h or l ; Z if no clock RET ; ; Read the DateStamper clock ; ; ENTER: HL -> 6-byte buffer for date/time ; EXIT : If NO clock: HL = 0, No CY (clear) ; If clock: HL = Entering HL, CY set ; current time at (HL)...(HL+5) ; DSCLK: ex de,hl ; Buffer ptr to DE ld hl,(XCLKADD+1) ;do we have a resident clock? ld a,h or l ret z ; Return HL = 0, Z set ex de,hl ; Buffer ptr to HL XCLKADD: call 0000 ;call DateStamper clock scf ;cy is a clock ret ; ; get bcd date&time ; ; exit: hl = 0, Z set if no DateStamper clock ; hl = bcd buffer, Z reset if DateStamper clock ; GTDATE: ld hl,(XCLKADD+1) ; Check presence of clk ld a,h or l ret z ;return hl = 0 (no clock) ld hl,BCDBUF push hl call DSCLK pop hl ;return ptr to bcd buffer ld a,h or l ;nz ret ; ;..... ; Error message text if attempting to catalog all user areas while ; running under a pre 2.0 cp/m release. ; BADVERS: CALL EREXIT DEFB BELL,CR,LF DEFB '++ FATAL ERROR - No user areas in this CP/M verion ++' DEFB CR,LF,CR,LF,0 ; ;----------- End DateStamper Code ---------------------- ; DEFS 80 ;stack space (40 levels) ; STACK: DEFB 0,0 ;..... ; AMB: DEFB '???????????',0 ;to return all directory entries, NADAT: DEFB 'XXXXXXXXYYY,' DKNAME: DEFB ' ' DKSIZE EQU $-DKNAME ;size of disk name ; NAMEREC EQU ($-NADAT)-DKSIZE-1 ; With NO CRLF at end. TYPF EQU 8 ; Offset to NADAT/MIDAT type ; UDAT: DEFB ' ' ;user number defb '---' ; MIDAT: DEFB 'XXXXXXXXYYY,' MIDSK: DEFB 'XXXXXXXXYYY' ; MASTREC EQU $-MIDAT ; MIUSR: DEFB ';z' ;user number defb 'dmy' ; FTFRE: DEFB 'FRE' ;phantom file type RET ; ;-----------DateStamper Constants---------------- ; TDCNT: defw 0 ; Sector count for td file ASCDAT: defb '999999' ; Current date (dummy) MONTHS: defb 'JanFebMarAprMayJunJulAugSepOctNovDecXXX' TDFCB: defb 0,'!!!TIME&DAT',0 defs 23 ;..... ; FCBM_IN: DEFB 0,'MAST CAT' DEFB 0 DEFS 20 ; MSTINADR: DEFS 2 ;input buffer start address MSTINLEN: DEFS 2 ;input buffer length MSTINPTR: DEFS 2 ;input buffer pointer address ;..... ; FCBM$OUT: DEFB 0,'NEW CAT' DEFB 0 DEFS 20 ; BUFFERSIZE: DEFS 2 ;buffer input/output size MSTOTADR: DEFS 2 ;output buffer start address MSTOTLEN: DEFS 2 ;output buffer length MSTOTPTR: DEFS 2 ;output buffer pointer address ;..... ; FCBBAK: DEFB 0,'MAST BAK' DEFB 0 DEFS 20 ; ;..... ;------------------------------- ; UNINITIALIZED DATA AREA ;------------------------------- ; ; Ignore file-name table overlays help code, since only one or the other ; would be used in any run. ; IGNORE: DEFS 1 ;dummy end of table mark stored here DEFS IGNSIZE ;ignore table ; NAMES: DEFS 2 ; Number of Directory Entries CMDPTR: defs 2 ; Pointer to command line arguments ; CBUFF: defs 32 ; Buffer for command tail parsing ; JUNK: defs 2 ; Place to copy trash PRFSIZ: defs 1 ; Flag to say print file stats ERADSK: defs 1 ; Flag to show disk name erasure operation IDCHEK: defs 1 ;-Flag to exit read code for ID checking ; NAMSIZE: DEFS 1 ; Size of Name entries MASTSIZE: DEFS 1 ; Size of Master file records ; SCRLIN: defs 1 ; Currently active screen line number IMMED: defs 1 ; Flag if immediate execution desired ; CURDRV: defs 1 ; Current drive to restore on exit ; DATES: defs 1 ; Local storage of default flag USER: defs 1 ; Local storage of default flag ; CDRIVE: DEFS 1 ;drive for disk to be cataloged MDRIVE: DEFS 1 ;drive for MAST.CAT must follow CDRIVE DRIVE: DEFS 1 ;flag for both drives the same ; CUSER: defs 1 ; Place to save current user on entry MUSER: defs 1 ; User area for MAST.CAT TUSER: defs 1 ; Temporary User hold area ; TIMER: defs 1 ; Timer for clock updating FRSTIM: defs 1 ; Flag to show first time pass UCHEK: defs 1 ; User field check byte DCHEK: defs 1 ; Dates field check byte ; FCT: DEFS 2 ;file count TFCT: DEFS 2 ;file count for this sort pass BUFPTR: DEFS 2 ;name buffer pointer NAEOFLG: DEFS 1 ;name buffer EOF flag MIEOFLG: DEFS 1 ;master in EOF flag MASDEL: DEFS 1 ;master name file delimited character ; BLKSIZE: DEFS 1 ;block size code BLKSFRE: DEFS 2 ;free blocks DPBADDR: DEFS 2 ;disk parameter block address EXMASK: DEFS 1 ;extent mask TBTR: DEFS 2 ;total bits to read in allocation vector FREPTR: DEFS 2 ;phantom file pointer IGNCNT: defs 1 ; Counter for Ignore files in ^I IGADDR: defs 2 ; Temp addr for loading IGNORE names TDBUFF: defs 2 ; Pointer to start of 3-BYTE dates ; buffer shared by ptrs for sort NAMPTR: DEFS 2 ; pointer to sorted name ptrs ; ;------------------------------------------------------------------ ; Variables used by Date Stamping routines ;------------------------------------------------------------------ ; BCDBUF: defs 6 ; DateStamper buffer DSFLAG: defs 1 ; Flag for presence of DateStamper TDPTR: defs 2 ; Pointer into !!!TIME&.DAT buffer TDFLG: defs 1 ; Flag to show !!!TIME&.DAT exists RELCLK: defs 1 ; Flag to show clock is "Relative" ; NABUF: defs 0 ; Start of Names buffer ; ;------------------------------------------------------------------ ; ORG IGNORE ; ; Help code and text overlays ignore table in a normal run ; HELP: call CRLF ld hl,HELPM ; Set starting address ld a,(THEIGHT) ; Get lines per screen cp 7 ; Must have at least 8 lines jp nc,HELP1 ; ..jump if OK ld a,7 HELP1: ld e,a ; Save it in E HELP2: ld d,1 ; Start at the beginning HELP3: call HLPRT inc hl ; ..Point past ending 0 ld a,(hl) ; If next char = 0.. or a jp z,EXIT1 ; ..then quit push de push hl call CRLF pop hl pop de inc d ; Printed 1 line, bump counter ld a,d cp e jp c,HELP3 call ILPRT ; Print prompt defb '[more]',0 call GETCH ; Wait for any character ld a,CR call CRTOUT ; ..overwrite prompt jp HELP2 ; ..and loop ; HELPM: defb 'CATALOGING your disk system with MCAT Version 5:',0 defb ' ',0 defb ' When no cursor commands are defined, MCAT operates ' defb 'in a',0 defb 'line-oriented mode. With cursor controls defined, ' defb 'operation',0 defb 'becomes screen-oriented with "windows". Cataloging ' defb 'with file',0 defb 'DATEs requires Plu*Perfect''s DateStamper(tm) program, ' defb 'and will',0 defb 'catalog MODIFIED, CREATED, or a null date for each file.',0 defb ' ',0 defb ' Three files, usually all on the same disk, are ' defb 'needed :',0 defb ' 1) MAST.CAT (Master Catalog Database)',0 defb ' 2) MCAT.COM (The executable Cataloging Program)',0 defb ' 3) XCAT.COM (A program to interpret and display ' defb 'MAST.CAT)',0 defb ' ',0 defb ' MAST.CAT can be created with your editor, or from ' defb 'within MCAT',0 defb 'with Control-I. When created with Control-I, MAST.CAT ' defb 'will',0 defb 'contain special flag data (e.g. "{;|85}"), and optional ' defb 'file',0 defb 'names which will not be cataloged. Up to 35 names can be ' defb 'added',0 defb 'to this "Ignore" list. The flag data MUST be present as ' defb 'the first',0 defb 'entry in the "Ignore" list. See MCAT.DOC for details.',0 defb ' ',0 defb ' All disks to be cataloged need a special "volume ID"' defb ' file.',0 defb 'This uses "-" as the first character in the name, and can ' defb 'have',0 defb 'both name and type fields, but the name will be ignored. ' defb 'as :',0 defb ' A>SAVE 0 B:-.012',0 defb ' The "volume ID" can be added from MCAT if an attempt is ' defb 'made',0 defb 'to catalog an un-named disk.',0 defb ' ',0 defb ' When MCAT is executed, it reads the disk directory and ' defb 'puts',0 defb 'each file name into memory, then alphabetizes the list. ' defb 'It',0 defb 'then updates MAST.CAT with the new names or deletes those ',0 defb 'previously listed that are no longer on that disk.',0 defb ' ',0 defb ' The disk drive to catalog can be selected from ' defb 'within MCAT',0 defb 'with Control-D, or when the program is called. EXAMPLE :',0 defb ' A>MCAT