title LT30 Types/Extracts/Uncrunch/USQ/UNLZH LBR/Files (17 Jul 1991) ; ver equ 30; Current version number ; ; LT types normal, lzh-encoded, crunched or squeezed files, either directly ; or from .LBR members. Wild cards access a series of library members. ; ; Recommended Assembler/Linker - SLRMAC and SLRNKP. Others will work, ; but normally require a two pass link operation and file truncation ; to avoid generating useless uninitialized data space in the code file. ; ; SLRMAC LTxx/R ; SLRNKP LTxx/N,/A:100,/J,LTxx,UNLZH,UNC,/E ; ; For other linkers see the documentation in BUFFERS. To check your ; methods first assemble and link this release and compare the object ; files. If they are different you do not have the full technique. ; ;--------------------------------------------------------------------- ; updates ; ; 17 Jul 91 Incorporated version 2.0 of LZH encoding. This program is ; v30 necessary to decode files encoded with version 2.0 of LZH ; compression, but will AUTOMATICALLY handle files encoded with ; version 1.x LZH encoding. Added appropriate documentation changes. ; Added instruction to reset MSB in output FCBs. ; Corrected error message pointer for UNC & UNL errors ; (sent garbage to screen). ; -R Warren ; Sysop, Elephant's Graveyard ; San Diego, CA (619)270-3148 ; ; 02 Sep 89 Added ability to handle LZH-encoded files (extensions ; v29 of the form .?Y?). Added appropriate docs. No functional ; changes to the program, otherwise. ; -R Warren ; Sysop, Elephant's Graveyard ; San Diego, CA (619)270-3148 ; ; ; **** DIATRIBE **** ; 18 May 88 Reformatted again, and repaired. If Mr Hoff wishes to ; v28 to reformat this source I wish he would retain such for ; his own benefit, and not foul the distributed version. ; He ingeniously makes it virtually impossible to detect the ; changes made using a text comparator. If this request is ; a problem to him he is welcome to call me at the number ; below. V27 had totally lost any indication of what file ; was being typed, and without a convenient comparison I ; had to restore from V25. Thus V26 changes have been lost. ; and I do not know whether V26 or V27 was the problem. ; I also request that Mr. Hoff refrain from removing my ; comments in the future (I have restored my comments to ; version 25 below). Will all modifiers kindly refrain from ; altering the file dates of modules that have not changed. ; For example, UNC.REL and UNC.SLR are still the '86 versions. ; LBR distributions can use LSETDATE, and ARCs are automatic. ; The gain from a large value of REC is miniscule and prevents ; use on systems with limited memory. V28 does not produce ; extra lines between extractions to file now, and this was ; done with less, not more, code. ; ; THINGS to be done: Incorporate checksum testing of results; ; slave ZCPR linkages to Z3ENV if on ZCPR system (signal ; is non-zero environment pointer). I hope to have a ; DOS+/CCP+ version that respects the ENV for wheel/user ; levels some time. ; ; If I am mistaken as to the culprit, I apologize for the ; vented spleen. - C.B. Falconer ; ; 05/11/88 Rewrote display section when extracting files to disk. Was ; v27 triple spacing with no tabulation. Was unsightly if library ; had more than 1-2 files. (Still under 5k.) If TPA is under ; 48k, might need to change "REC" from 128 to 96 or even 64. ; - Irv Hoff, Sysop ; PRACSA Sysop RCPM ; ; 04/15/88 When typing a crunched file with a comment attached, it was ; v26 running off the end of the screen, to display the uncrunched ; file name with comment. - Ed Minton ; Columbus, OH ; ; 10 Apr 88 Reformatted to my original system, which shows the action ; v25 of conditionals clearly. Someone had reformatted the ; entire source, and I suspect the promulgator of a certain ; reformatting program. There is no need to keep conditionals ; un-nested, since linking requires a reasonable assembler ; (not ASM) anyhow. Added .OVR type prohibition. ; Wheel control is now unified, with a single patch point. ; Now organized so that all options are patchable - Set maxusr ; to 0ffh to use the ZCPR mxusr value. Pausecheck on every ; character is now an option (useful for Braille). The ; conditionals should be used only where a smaller object ; file is required for some reason, not for configuration. ; Space has been reserved for ZCPR addicts (environment). ; ** PATCH POINTS HAVE CHANGED (for the last time??!!). ; I have also restored some of the "regs affected" comments ; which had been removed. Please update and maintain them, ; they greatly ease future modifications. ; I have attached a slightly later version of UNC, functionally ; identical, but 5 bytes shorter. ; I am glad to see many people actively enhancing this. When ; originally released I did not expect it to attain such ; popularity. Too bad it grew over 4k. Now should add the ; checksum tests. ; - C.B. Falconer (203) 281-1438 ; ; 02/18/88 Fixed bug in PARSE4 routine. If no USER AREA specified for ; v24 disk output then it defaulted to input file user area rather ; than the CURRENT user area. Modified to allow abort during ; disk output. Added $U command line option to allow disk ; output of squeezed/crunched files WITHOUT unsqueeze/uncrunch. ; (see the NOUQZ byte added to the patch area at 103H). ; Added REC equate to allow more than one sector in the file ; output buffer to reduce wear and tear on floppy drives. ; - Tom Head ; ; 08/12/87 Fixed to properly handle 0-length files. Modified to ; v23 check for pause and abort from console after every typed ; character rather than at the end of each line. This was ; necessary to prevent loss of data on some very slow ; terminals such as the one I use, and to enable the typing ; of a file with no linefeeds to be aborted. Also fixed the ; tab expansion routine to work correctly with files con- ; taining unusual control characters such as backspace, and ; made the "turn up one line" feature more foolproof. ; - Howard Goldstein ; ; 07/30/87 Added the long needed ZCPR/ZCMD support of maximum user ; v22 area. When the UZCPR option is set, the page 0 value ; will be examined to determine if the requested user area ; is within the allowable range. This is primarily useful ; on RCP/M's (but I suspect that is where LT is primarily ; used). Added code to allow overriding the line counter ; and user area restrictions when the wheel is active. ; - Gary Inman, Sysop ; West Los Angeles RCP/M ; ; 07/21/87 When at a [more] pause, the space bar now turns up one ; v21 line at a time. LTxx is often used on RCPM systems as ; their general purpose TYPE.COM program. This makes it ; compatible with UNARC16. These two programs are used ; in the popular LUX program to type ASCII files in ARC, ; ARK or LBR files. I have always liked this feature in ; UNARC16 and decided to add it to LT20. I believe most ; users will find this quite useful and hope CB Falconer ; does not mind my adding this feature. This version is ; a little over 4k. If this makes any problem, just use ; an earlier version. - Irv Hoff, Sysop ; PRACSA RCPM ; ; 07/17/87 Able to use wheel byte in conjunction with OUTFLG flag. ; v20 One byte added in ddt modifiable area at program start. ; WHLFLG and/or WHEEL now tested in conjunction with the ; OUTFLG flag eliminating need for two copies of program ; when used on a remote system. Found that it would not ; assemble properly using M80/L80 because of YES/NO, now ; corrected. Restored program name, version number, and ; author credit. Other minor mods to keep code size <4k. ; - G.F. Reding [72436,45] ; ; 06/10/87 Change to only display characters between "[" and "]" in ; v19 the header of crunched files as other characters in this ; area are reserved. Removed the redundant "IF NOT UNCR" ; (marked ";;;;") following an "ELSE" which prevented LT18 ; from being assembled in its distributed form. Slight text ; changes to keep <4k. - Steven Greenberg ; ; 12/28/86 Allows access to .LBR files > 512k. Was using CPM 1.4 ; v18 variety of direct access. Mods to keep under 4k total. ; Should CP/M v1.4 check and refusal. ; - C.B. Falconer ; ; 12/13/86 Prevent junk file names on "LT fn.t d:" where fn.t is not ; v17 squeezed or crunched. Thanks to Bill Duerr for calling my ; attention to this. Set default "drvsup" to all drives. ; Fixed OUTFLF usage when extract false, per Frank Whitman. ; - C.B. Falconer ; ; 11/24/86 Using UNC module, executable on 8080. Can extract all ; v16 files to disk. Needed because NULU 1.51 cannot uncrunch ; during extractions. Disk extraction ignores "BADTBL". ; For RCPM use, assemble with the "extract" equate set to ; NO. Clean-ups. - C.B. Falconer ; ; 11/17/86 Added ability to extract to a file with "LT lbr d:fn.ft", ; v15 where the "d:" signifies extraction. 01Ah is EOF, so not ; suitable for binary files. The code has become a mess to ; preserve the ability to generate minimum version. ; - C.B. Falconer ; ; 86/11/15 Added hooks to include Steve Greenbergs UNCR system. These ; v14 are guarded by 'UNCR' equate to setup options. Use requires ; linking and creation of relocatable object. Any uncrunching ; requires a Z80 cpu. - C.B. Falconer ; ; 02/12/86 Added expansion of UCSD style "dle/code" indentation codes. ; v13 These also appear in the PASCALP system. ; - C.B. Falconer ; ; 12/05/84 Stole some features from TYPELxx '?' for forbidden file ; v12 type table, list output enable on du version, location of ; BADTBL for patching. Checked "LIMITT" and "LMITL" options ; functioning with wild cards. Version display shows options ; enabled. Added bit vector for drives available. Added du ; option under "DUSPEC" conditional. The minimum version ; remains under 0500h bytes, with options disabled. If an ; operator is already logged into a drive/user area then that ; drive/user area remains available even though the configured ; restrictions should prevent it. This allows for privileged ; users. John Doe can't get there at all. ; - C.B. Falconer ; ; 12/04/84 Deleted unused variables and labels, also variables that ; v11 are better kept on the stack. Arranged for LBRFCB to be ; fully initializable via parameter, for straight type. ; Thus: ; A>LT fname.typ ; ; will type/unsqueeze FNAME, while "LT LBRFILE component" ; extracts as before. - C.B. Falconer ; ; 10/02/84 Adapted from Steven R. Holtzclaw's "LUXTYP (06/10/83)" ; v10 for independent use without the complete LUX system. ; Eliminated Z80-only opcodes. Added file searches. Added ; simple usage message, assembly time constants to eliminate ; limits on lines and file types, ^Z stops pauses. CRT lines ; measured acrossfiles. ; - C.B. Falconer ; ; --------------------------------------------------------------------- ; aseg ; Needed for M80, ignored by SLRMAC, else ignore error ; no equ 0; For conditional assembly yes equ not no; (Some assemblers don't like 0FFh) ; ; -------- Configuration ------- ; Assembly time configurable areas. Each increases COM file size. extract equ yes; *File extraction ability, wheel controllable rec equ 32; Sectors in file output buffer. DO NOT make ; too large, else uncruncher wont work ; limitl equ yes; Yes allows output line limits limitt equ yes; Yes allows file type restriction duspec equ yes; Use DU style drive/user specifications xpnd equ yes; Expand UCSD style "DLE/code" indentation codes paws equ no; Check pause/abort on each output char (braille) ; ; Next is used with EXTRACT so that 1 copy only needed for RCPM systems ; Note: the wheel also over-rides the line count restriction, if any whlat equ 0; Location of wheel byte, 0 disables wheel check ; (usually 03eh, patch into option area) ; Value only used to set this word (1 place) ; ; For added security on RCP/M's to prevent access to files outside ; the callers permitted drive user areas. See whlat above also mxdrv equ 03dh; Location of max drive byte mxusr equ 03fh; Location of max user byte ; ; Configurable values. Also see "DRVSUP" configurable vector pagsz equ 20; Default lines per CRT page lnmax equ 0; 0 for no limit, else max file size (to 255) noctrl equ yes; Yes to prevent control char. output usrmax equ 15; Maximum user area accessible ; 0-15 for CP/M 3, 0-31 for CP/M 2.2 or DOSPLUS ; ZCPR . . SPECIAL VALUE - 0ffh causes ZCPR mxusr to be ; loaded into maxusr. ; ------- END configuration equates -------- ; ; Ascii control chars bell equ 07h bs equ 08h tab equ 09h lf equ 0ah cr equ 0dh dle equ 010h eof equ 01ah sqzdle equ 090h; special in squeezed/crunched files ; ; CP/M-DOS+ system values bdos equ 0005h fcb1 equ 05ch fcb2 equ 06ch cmdln equ 080h ; ; BDOS calls cio equ 6; Direct console I/O setdrv equ 14 open equ 15 close equ 16 srchf equ 17 delete equ 19 fread equ 20 fwrt equ 21 make equ 22 getdrv equ 25 setdma equ 26 gsuser equ 32; Get/set user frdran equ 33; Read random record ; cseg ; ; Linkages to unc module extrn unc, endu entry getbyt, out ; ; Linkages to UNLZH module extrn unl entry glzhun,plzhun ; ; -------------- ; PROGRAM BEGINS ; -------------- begin: jmp start; past configuration area ; ; Unused, but space reserved to fix patch locations db 'Z3ENV'; Special signature db 1; External environment @env: dw 0; And ZCPR can patch this location ; ; Configuration values, even if unused via "limit" options ; These may be patched to configure the COM file at installation whladr: dw whlat; Non-zero if wheel controlled pagsiz: db pagsz; Lines per page, 0 = no pauses maxlin: db lnmax; Max lines to type, 0 = unlimited typflg: db limitt; 0 for all file types, else selective pawsfg: db paws; To check pause on each output char. ctlflg: db noctrl; Non zero allows control char print altdrv: db 0; Alternate drive to search, 0 = none maxusr: db usrmax; Max accessible user, for du entries ; Set 0ffh to use ZCPR mxusr value drvsup: dw 1111111111111111b; Vector of available drives ; ABCDEFGHIJKLMNOP-; Drive ids (No N..P under PascalP) ; (example) 1100000000001000B; (shown set for A, B and M drives) nouqz: db 0; 0 to allow unsqueezing/uncrunching ; of files during disk output. The $U ; command line option will toggle this. xpdle: db NOT noctrl; Set NO = 0 to suppress DLE expansion. ; Useful if noctrl is set NO. db 0; spare for future use ; ; '?' matches any character. Alpha order for convenience only, ; a complete sequential scan is done. An existing name can be ; made to disappear by setting its high order bit somewhere. if limitt; Table of invalid file types badtbl: db 'ABS'; Intended to disable db 'ARC'; =================== db 'ARK' db 'BAD' db 'CRL' db 'C?M'; COM, CQM, CZM, CPM (v20 executes on PCs) db 'E?E'; EXE, EQE, EZE (MSDOS executable) db 'IRL' db 'I?T'; INT, IQT, IZT db 'LBR' db 'O??'; OBJ, OQJ, OZJ, OVL, OVR etc db 'P?D'; PCD, PQD, PZD (executable by RUNPCD) db 'TX#' db 'RBM' db 'R?L'; REL, RQL, RZL db 'S?R'; SLR, SQR, SZR (SLR format rel files) db 'SYS' db 0,0,0 db 0,0,0; Spares, for user configuration db 0,0,0 db 0; Table end marker endif; limitt start: lxi h,0; Set up HL for add to stack shld memcnt; Zero the memory count dad sp; Add stack pointer shld stack; Keep stack contents lxi sp,stack; Set up local stack lda maxusr inr a; Special 0ffh max causes lda mxusr; revision to mxusr jz start1 sta maxusr; Revise if ZCPR user system start1: lxi d,lbrbuf mvi a,setdma; Do all I/O thru this buffer call sys ; " " if extract mvi a,' ' sta outfcb+1; Default none endif; extract ; " " if duspec; Parse the command line call parse lda savusr call sguser; Set the user access endif; duspec ; " " call lbropn; Set up the library name buffer push psw; Save extract/type flag jnz start2; Type only lhld memcnt; Get member count mov a,l; Get member count lsb ora h; Any members? lxi d,nfound jz exeunt; No - exit ; " " start2: lxi d,sign1; Give name, version, credit call tstrc pop psw jnz dump; Type only ; " " ; Per component loop next: call initlp; Initialize the "next" loop call getmem; Get next member FCB jc exit; All done... call lbrset; Set up to read the library file ; " " ; Input setup, do the extraction and/or unsqueezing dump: if limitt; Test the type of file call tsttyp endif; limitt ; " " call get2hl; Get the first 2 bytes from the file jnz zerprt; Special processing for 0-length file ; " " ; This allows disk output WITHOUT any unsqueezing or uncrunching. push h lxi h,outflg; File output flag lda nouqz; No unsq/uncr flag ana m; If (no unsq/uncr) AND (disk output) pop h jnz asprt; Then skip uncompression routines. ; " " mvi a,076h cmp l jnz asprt; Not squeezed - print an ascii file mvi a,0ffh cmp h jz dumpsq; Squeezed, dump it dcr a; To 0feh cmp h jz dumpcr; Crunched, dump it dcr a; To 0fdh cmp h jnz asprt; Not compressed - print an ascii file ; " " ; Output from a LZH compressed file call nmshow; Show actual name etc, absorb header lhld namptr; Free memory area, above names call unl; UNLZH.REL. Uncompress lxi d,badfile jc donem; something went wrong jmp done ; " " ; Output from a crunched file dumpcr: call nmshow; Show actual name etc, absorb header lhld namptr; Free memory area, above names call unc; UNC.REL. Uncrunch lxi d,badfile jc donem; something went wrong jmp done ; ; Output from a squeezed component dumpsq: call get2hl; Get and discard the next 2 bytes call nmshow; Actual name, and absorb header call sqsetu; Setup the squeezed file ; " " ; List a squeezed component sqloop: call getsqb; Get a byte from the file jc done; Eof - get next file name in queue call crtype; Else print the char jmp sqloop; And loop for more ; ; Show UNSQ/UNCR member name, etc. Optionally revise output name. ; This has the side function of absorbing the sqz/crn header. ; a,f,b,d,e,h,l nmshow: lxi d,ffsep call tstr; Make the file-file seperator ; " " if extract lxi h,outfcb+1 mvi b,11 nmshw1: mvi m,' '; Pre-blank the output name inx h dcr b jnz nmshw1 mov m,b lxi d,outfcb+1 mvi b,8; Size of name field endif; extract ; " " ; This section types the filename to the console and puts it into ; "OUTFCB". A null character terminates all header processing. Other ; characters after filename are ignored, unless they follow a "[" ; character. These will be echoed to the console, until either a null ; character is detected (terminate processing) or a "]" character is ; detected (start scanning for null again). nmshw2: push d; Filename area of OUTFCB call lbrget; Get character from the file pop d; Restore pointer ora a; Check for null jz nmshw9; If found, terminate header processing cpi '[' jz nmshw7; "[", go display "stamp" text cpi '.'; Was the character a "."? jnz nmshw3; If not update cnt, display char, put in FCB call ctype; "." is displayed, but not put into FCB mvi b,3; set filename char counter to "3" ; " " if extract; lxi d,outfcb+9; adv filename dest pointer accordingly endif; extract ; " " jmp nmshw2; Continue processing filename ext chars nmshw3: inr b; Check filename character limit dcr b; jz nmshw6; If down to zero, exit this section ani 07fh; Strip MS bit before placing in FCB call ctype; Else display char ; " " if extract; stax d; put char in the FCB if appropriate endif; extract ; " " inx d; Bump filename dest pntr dcr b; Count it jmp nmshw2; Continue filename processing ; ; Filename has been fully processed. Continue header analysis. nmshw4: call ctype; (entry here to display extra char) ; " " nmshw5: call lbrget ora a; Loop swallows characters until either jz nmshw9; a null or a "[" char is detected ; " " nmshw6: cpi '[' jnz nmshw5 ; " " nmshw7: mvi a,' '; "[" found. Insert blank for aesthetics call ctype mvi a,'['; But display the "[" char as well nmshw8: call ctype call lbrget cpi ']'; Loop to display characters to the con- jz nmshw4; sole until a null or a "]" is found ora a jnz nmshw8 ; " " ; All paths to here have a=0 and z flag set nmshw9: if extract call outtst; Test if output to disk cnz opnout; If to file, create it (outfcb), set nz endif; extract ; " " cz crlflf; only when typing ret ; ; Output an unsqueezed file/component. ; zerprt: sta zerlen; Save zero length file flag ; " " asprt: if extract push h lda outfcb+1; Kludge to prevent file copying sui ' ' jnz asprt0 lxi h,nouqz ora m; If we override unsq/uncr jnz abort; we would trash the screen. sta outflg; i.e. a zero, following fails asprt0: call outtst; Test if output to disk cnz opnout; If to file, create it (outfcb), sets nz pop h cz crlflf; if typing. Opened output has set nz else; not extract call crlflf; we are typeing endif; not extract ; " " lda zerlen ora a jnz done; Don't type anything for 0-length file mov a,l; Print push h call crtype; First pop h; (file out clobbers hl) mov a,h; Two ; " " asprt1: call crtype; Bytes call lbrget; Get a byte from the file jz asprt1; Not eof, print and get more jmp done ; ; Done, send message donem: call tstr ; " ' ; Done, no message done: lxi sp,stack; SP uncertain here - reset the stack ; " " if extract call outtst; Test if output to disk cnz fclose; close file if so endif; extract ; " " jmp next ; ; Initialize the "next" loop ; a,f,b,h,l initlp: lda paglns ora a jnz initl1; Paging was not stopped sta lincn1; Else clear for fresh start lda pagsiz sta paglns; Restart any page pauses initl1: lxi h,zeros; Fill flag area with zeros mvi b,lastz-zeros; Count of zeroes to load xra a; Fill (HL) up for (B) with zeroes initl2: mov m,a; Put a byte inx h; Next location dcr b jnz initl2; Fill all 11 bytes ret ; ; Open the FILENAME.LBR file and the MEMBER.EXT files, returns Z-flag ; for library extraction, NZ for pure type ; lbropn: mvi b,12; Field size for .LBR file lxi h,fcb1; Move first file FCB lxi d,lbrfcb; To LBRFCB call move xra a; Set ext & rec # to 0 for proper open sta lbrext sta lbrsno lxi h,fcb2+1; Source is member FCB name, no drive mov a,m; First member character cpi ' '; Is it a space or control ? jc helper; Control, exit with help jz tfile; Space, type one file only lxi d,memnam; Move FCB2 to MEMNAM mvi b,11; Bytes to move call move; Member name to local area ; " " ; Open the .LBR file lxi h,'BL' shld lbrtyp; Force .LBR type mvi a,'R' sta lbrtyp+2 call fopnlb; Open .LBR file inr a; Open ok? jz nofile; Failure, abort with help ; " " ; Read the first record of the library directory call lbread; Read a sector lhld lbrbuf+14; Get directory size ; " " ; Test for a valid library file lda lbrbuf ora a; Test first byte lxi d,corrpt jnz exeunt; Non-zero, bad .LBR file ; " " ; Read the next library directory record lbrop5: push h; Save DIRSIZE cnz lbread; Read a sector, except 1st pass ; " " ; Search for the member name in the library directory lxi h,lbrbuf; Process first entry call addmem; To memory buffer lxi h,lbrbuf+20h; Process second entry call addmem; To memory buffer lxi h,lbrbuf+40h; Process third entry call addmem; To memory buffer lxi h,lbrbuf+60h; Process fourth entry call addmem; To memory buffer pop h; Count of dir entries dcx h; -1 mov a,h; Zero directory entries left ? ora l jnz lbrop5; Now read another directory sector ret ; ; The second parameter is missing, just type the main file, ; returns NZ flag to signal no library extraction ; tfile: lxi d,lbrfcb+1 ldax d dcx d cpi ' ' jz helper call fopenf inr a jz nofile ; " " if limitt inx d xchg lxi d,memfcb mvi b,11 call move; Name to memnam for checking endif; limitt ; " " call initlp; Other one pass initializers ori 0ffh; Set NZ flag jmp initpt; Set up pointers, leave NZ flag ; ; Setup access to the library component ; a,f,b,d,e,h,l lbrset: lxi d,mbrmsg call tstrc lxi h,memfcb; Index member FCB ; " " if extract push h lxi d,outfcb+1 mvi b,11; Set default output file name call move; (will revise if squeezed/crunched) xra a stax d; And clear extent field pop h endif; extract ; " " call fname mov e,m; Get member starting record LSB inx h mov d,m; And MSB push d; Save inx h mov e,m; Get member size LSB inx h mov d,m; And MSB xchg; Into 'HL' inx h; +1 shld rcnt; Save it in record count pop h; Restore starting record number shld lbrrno xra a sta lbrrno+2; Set random rcd no sta lbrext call fopnlb; Open the LBR file again inr a jz preeof; Should not happen mvi a,frdran call sys; Do a random read to put in sequential ora a jnz preeof; No such record ; " ' ; Initialize pointers to read from LBRFCB ; a,h,l (flags preserved) initpt: mvi a,080h sta chrcnt; Set char count to force read lxi h,lbrbuf-1 shld bufptr ret ; ; Get a byte from the .LBR member. GETBYT for UNCREL. GLZHUN for UNLZH use ; a,f,d,e,h,l glzhun: getbyt: lbrget: lda chrcnt; Get pointer inr a; Point to next position sta chrcnt; Put pointer back jp lbrge1; Buffer not empty call zbuff; Empty, reset pointers, read sector lhld rcnt; Get record count dcx h; -1 shld rcnt; Set new record count mov a,l ora h jz lbrge2; If all records read call lbread; Read a sector ora a jnz lbrge2; If read was unsuccessful ; " " lbrge1: lhld bufptr inx h shld bufptr mov a,m; No - get the next byte cmp a; Set zero - no error ret ; lbrge2: mvi a,0ffh ora a ret; Return non-zero for error ; ; Zero the buffer pointers (for reaccess from start) ; a,f,h,l zbuff: xra a; Empty, read another record sta chrcnt; Clear the character count lxi h,lbrbuf-1 shld bufptr ret ; ; Read a sector from library file ; a,f,d,e lbread: mvi a,fread lxi d,lbrfcb; .LBR FCB jmp sys; Read a block, and exit ; ; Get 2 bytes from input file into HL ; a,f,d,e,h,l get2hl: call lbrget; Get a byte from the input file rnz; May be an empty component push psw call lbrget; Get a byte from the input file mov h,a pop psw; first byte of the pair mov l,a ret ; nofile: lxi d,nofmsg jmp exeunt ; helper: lxi d,signon; Give name, version, credit call tstr lxi d,usage; Give help menu call tstrc call qwhl lxi d,whlusg cnz tstrc; Added help when wheel enabled jmp exit; without wasting CRT space. ; preeof: lxi d,eofmsg ; " " ; Error exit, crlf and message (DE)^ exeunt: call tstrc; Print message ; " " exit: if duspec; Restore entry conditions call restor endif; duspec ; " " lhld stack sphl; Restore original stack ret; --exit-- to cp/m ; if extract ; Close any output file ; a,f,d,e,h,l fclose: lda bytes; Get bytes in current sector ora a jz fcls2; None lhld outptr; Get buffer pointer fcls1: mvi m,eof; Put in EOF inx h; Bump pointer inr a; And byte count jp fcls1; Fill out sector with EOF lda sector inr a sta sector; Bump sector count fcls2: call fput; Write buffer, maybe lda outusr; Shift to output user call sguser lxi d,outfcb mvi a,close call sys lda inuser jmp sguser; Restore and exit ; ; Put character (TOS) to file. Unclean hook for CRTYPE. ; a,f,h,l fputch: pop psw; Get char. to ACC. lhld outptr; Pointer mov m,a; Put char in buffer inx h shld outptr; Update pointer lda bytes inr a sta bytes; Update bytes in this sector rp; Exit if not full sector xra a sta bytes; Init. byte count lda sector inr a sta sector; Update sectors in buffer cpi rec; Buffer full? rnz; Exit if not ; " " ; Write output buffer to file ; a,f,h,l fput: push d lda outusr; User for output file call sguser call pbuf; Write the sectors lxi d,lbrbuf mvi a,setdma; Back to input buffer call sys lda inuser; Restore input user call sguser ; " " ; This code allows aborting a disk file output call cistat; Check for console input jz fput2; Continue if none cpi 'C'-40h jz abort; Abort on CTL-C fput2: pop d; Else continue ret ; ; Unload the stored buffer (up to rec sectors long) ; a,f,d,e,h,l pbuf: lda sector; Get sector count inr a; Prepare for upcomming DCR A lxi h,outbuff; Start of output buffer shld outptr; Init. byte pointer pbuf1: shld dmaadd; and write address dcr a sta sector; Update sector count rz; Exit if none left to write push psw; Save sector count xchg; Setup DE mvi a,setdma; Write address call sys lxi d,outfcb mvi a,fwrt; Now write it call sys ora a jnz fullup; Write error, abort everything lhld dmaadd lxi d,128; Get next write address dad d pop psw; Get sector count jmp pbuf1; And loop endif; extract ; ; Output to CRT or file. Entry name "out" for UNC or UNCREL, 'plzhun' for ; UNLZH or UNL use ; CRT output tracks column and line. ; a,f,e,h,l plzhun: out: crtype: if extract push psw call outtst; Test if output to disk jnz fputch pop psw endif; extract ; " " ; Not creating a file, this char goes to the console. cpi eof jz done; EOF on 01Ah for ASCII output ; " " if xpnd push psw lda dleflg ora a jnz crtyp6 pop psw cpi dle jnz crtyp1 lda xpdle ora a jnz crtyp5 mvi a,dle endif; xpnd ; " " crtyp1: ani 7fh; Make sure its ASCII push psw; Save the character call cout lda pawsfg ora a cnz pauser; For slow terminals (Braille, etc) pop psw; Restore character cpi lf; Was it a line feed rnz; No - continue call qwhl; Load wheel byte if enabled jnz crtyp2; Bypass line count tests on wheel ; " " if limitl; Check for too many lines typed lda lincnt; Advance line counter inr a sta lincnt mov b,a; Line number in 'B' lda maxlin; Max number of lines to type ora a; Test flag jz crtyp2; If null function cmp b; Else compare to max lines lxi d,excess jz donem; Announce too much endif; limitl ; " " crtyp2: lda lincn1; Get line counter mov b,a; Keep in 'B' lda paglns; Number of lines per page dcr a; Decrement and test flag jm pauser; Function is null cmp b; Compare to lines per page jnc pauser; If not at maximum count xra a; Clear lines counter sta lincn1 lxi d,more call tstr; Announce the pause call pause; Get input from console cpi ' '-eof; Space for line at a time? jnz crtyp3 mov a,b; Get original line count back dcr a; And set to "one line left" sta lincn1 crtyp3: lxi d,clean call tstr; Clear out the "[more]" ; " " ; Check for user pause or abort ; a,f,e (unless aborted) pauser: call cistat; Check the keyboard call pschk cpi 'S'-40h; CTL-S to pause? jz pause ani 5fh cpi 'S' rnz; Not CTL-S, return ; " " ; Returns input-01Ah. Aborts on c,C,^C or k,K,^K - next on CTL-X, etc. ; a,f,e pause: call cistat; Check the keyboard jz pause; Nothing yet so wait call pschk sui eof rnz; Not ^Z sta paglns; End pauses permanently on ^Z ret ; if xpnd crtyp6: xra a; Indentation expansion sta dleflg pop psw sui ' ' rc rz; Else 'A' is count of spaces to send crtyp7: sta dlecnt mvi e,' ' call cout3 lda dlecnt dcr a jnz crtyp7 crtyp5: sta dleflg ret endif; xpnd ; ; Console status ; a,f,e cistat: mvi a,cio; BDOS function mvi e,0ffh call sys; Direct console in call ora a; Was a key entered ? ret ; ; Pause check for special characters ; a,f (unless aborted) pschk: cpi 'C'-40h; Want to abort? jz abort; If yes, quit cpi 'K'-40h jz abort cpi 'X'-40h; Jumping to next file? jz pschk1 cpi ' '; Space for "line at a time"? rz ani 5fh; Insure in upper case cpi 'C' jz abort cpi 'K' jz abort cpi 'X' rnz; If not, keep going pschk1: call crlf jmp done; Next file on CTL-X ; ; Abort the run with message abort: lxi d,abrmsg jmp exeunt ; ; Output char a to console, expanding tabs, tracking column ; a,f,e cout: mov e,a; Save output character cpi tab jz tabber; Expand a tab cpi cr; Carriage return jnz cout1 xra a; CR sets COLUMN to 0 jmp cout4 cout1: cpi bs; Is char a backspace? jnz cout2 lda column; Backspace sets COLUMN back one dcr a rm; Ignore if at column 0 already jmp cout4 cout2: cpi ' '; jc coute; Other controls don't affect COLUMN ; " " ; Callable entry point here to display e cout3: lda column; Advance column counter inr a cout4: sta column ; " " ; Output e to console if printable coute: call qctl; Test control mov a,e; Get char back jz ctype; no suppression, print the char ret; absorb it, Return to caller ; ; Expand a tab, at least one space emitted tabber: mvi e,' ' call cout3; Print a space lda column ani 7; At next tab stop ? jnz tabber; Yes, continue ret ; ; Test for control char output (from e). Z flag for no suppression. ; a,f qctl: lda ctlflg; Get controls active ora a; Test flag rz; Return if not mov a,e; Get output char cpi ' ' jnc qctl1; Not control, clear flags cpi cr rz cpi bs rz cpi bell rz cpi lf rnz; Non-typable control char qctl1: cmp a; Set Z-flag, typable ret ; if limitt; Test for typable file ; Test for typeable file, abort with message to "DONE" if not ; a,f,b,d,e,h,l tsttyp: lda typflg; Get test flag ora a; Test it rz; Return if ok to type all types ; " " if extract; AND limitt call outtst; Test if output to disk rnz; Return if outputting to disk endif; extract AND limitt ; " " mvi b,3 lxi h,badtbl-3; Index bad file type table tstty1: inx h; Next table address pointer dcr b; Bump loop counter jnz tstty1; Do until at next table entry mov a,m; Get a byte ora a rz; end of table - ok to type this one mvi b,3; 3 char extension lxi d,memfcb+8; Index file name extension tstty2: ldax d; Get a byte from extension ani 7fh; Strip any file attribute bits cmp m jz tstty3; Match, continue scan mov a,m cpi '?'; '?' in table matches all jnz tstty1; No match, next entry tstty3: inx h; Bump table address pointer inx d; Bump extent pointer dcr b; Bump counter jnz tstty2; Continue for 3 chars lxi h,memfcb+8; User name lxi d,cant call tstr; "CAN't type a '" mvi b,3; 3 byte file type tstty5: mov a,m; Get byte call ctype; Give a chance to abort here inx h; Next byte dcr b jnz tstty5; Type all 3 bytes lxi d,cant2; "' FILE ",CR,LF jmp donem; And do next file endif; limitt ; ; This part is adapted from TYPE109 by David Rand ; a,f,b,c,d,e,h,l getsqb: lda rptcnt; Get repeat flag ora a; Any chars to repeat ? jnz getsq1; Yes - get and count call nxtch; Get a character rc; Eof cpi sqzdle; Repeat byte flag jnz getsq3; No - call nxtch; Yes - get another character rc; EOF ora a; If null jnz getsq2 mvi a,sqzdle; Dle is encoded as dle,0 ret; Return with it, carry clear ; getsq2: dcr a; Bump counter twice jz getsqb; 1 repeat is a null event getsq1: dcr a sta rptcnt; Set repeat count lda rptchr; Return repeat character getsq3: sta rptchr; Set repeat char ora a; Clear any carry, not EOF ret ; ; Next decoded byte from file, ignoring repeat characters ; a,f,b,c,d,e,h,l nxtch: lxi d,0; Pointer @ star of text lda char mov c,a nxtch1: lda numflt ora a jnz nxtch2 push d; Save 'DE' call lbrget; Get a byte from the input file jnz preeof; Not expecting an eof here pop d; Restore 'DE' mov c,a mvi a,8; 'A' is counter nxtch2: dcr a; Bump count sta numflt; Save it mov a,c; Get character rrc; Shift right mov c,a; Save character push psw; Save character lxi h,xlatbl; Index ram area dad d; HL=HL+(4*DE) dad d dad d dad d pop psw; Restore char jnc nxtch3; If no carry inx h inx h nxtch3: mov e,m inx h mov d,m mov a,d ani 80h jz nxtch1 mov a,c sta char mov a,d cpi 0feh; Special end of file ? mvi a,eof; Yes - return with EOF character stc rz; And carry for EOF mov a,e cmc cma ret; With carry clear, not EOF ; ; Set up the translation table for the squeezed file ; a,f,d,e,h,l sqsetu: call get2hl; Get 2 bytes from input file into HL lxi d,xlatbl; Index ram area sqset1: mov a,h; Get MSB ora l; Test LSB rz push h; Save table size counter push d; Save ram area index call get2hl; Get 2 bytes from input file into HL pop d; Restore ram area index xchg; Into 'HL' mov m,e; Save the LSB byte inx h mov m,d; And MSB byte inx h push h; Bump & save pointer call get2hl; Get 2 bytes from input file into HL xchg; Into DE pop h; Restore pointer mov m,e; Save the LSB byte inx h mov m,d; And the MSB byte inx h; Bump pointer xchg; Restore pointer to 'DE' pop h; Restore table size counter dcx h; Decrement it the byte count jmp sqset1; And loop for more ; ; Add a library member to the name queue buffer if a match to MEMNAM ; a,f,b,d,e,h,l addmem: mov a,m; Get first byte of member entry ora a rnz; Non zero - must be deleted or null entry inx h; Go to the second byte push h; Save source address for coming 'LDIR' push h; Save it again mvi b,11; 11 byte filename addme0: mov a,m; Get byte cpi ' ' jnz addme1; Not space - continue inx h; Next char dcr b jnz addme0; Continue searching for spaces pop h; Must be the directory jmp addme4; So abort this one ; addme1: pop h lxi d,memnam; Index member FCB name mvi b,11; 11 byte compare addme2: ldax d; Get byte from member name FCB cpi '?'; '?' matches all entries jz addme3; Match cmp m; Same as member entry? jnz addme4; No - abort this process addme3: inx h inx d dcr b jnz addme2; Compare all 11 bytes lhld namptr; Get destination address xchg pop h; Get source address back again mvi b,15 call move; Move 15 byte block into memory xchg shld namptr; Save name pointer lhld memcnt; Get member number count inx h; Bump it up one shld memcnt; Set next member memory address ret addme4: pop h; Balance stack ret ; ; Get the next member name from the memory name queue buffer, ; return carry set if no more members left ; a,f,b,d,e,h,l getmem: lhld memcnt; Get member count mov a,l ora h stc rz; Zero count - set error condition dcx h; Bump count down shld memcnt; And reset member count lhld nampt1; Get source address for move lxi d,memfcb; Get destination for move mvi b,15; 11 byte filename + 4 byte file info call move; The block shld nampt1; Reset the next source address ora a; Clear any cy ret ; ; Double CRLF to console ; a crlflf: call crlf ; " " ; CR and LF to console ; a crlf: mvi a,cr call ctype mvi a,lf ; " " ; Character to console, preserve all registers, track lines ctype: push psw push d mov e,a cpi lf jnz ctype1 lda lincn1 inr a sta lincn1 ctype1: mvi a,cio; Direct console output call sys pop d pop psw ret ; ; CRLF, then fall through to TSTR ; a,f tstrc: call crlf ; " " ; Output string (DE)^ ; a,f tstr: push d tstr1: ldax d ora a jz tstrx call ctype inx d jmp tstr1 ; tstrx: pop d ret ; if extract ; Query for file purge ; a,f query: push d lxi d,exists call tstr call pause pop d adi eof; Correct output ani 05fh; Upshift call ctype; And echo ; push psw ; call crlf ; pop psw cpi 'Y' ret; Purge wanted if z flag ; ; Open (create) file OUTFCB^. Returns NZ when all well ; a,f,d,e opnout: lda outusr call sguser lxi d,outfcb mvi a,open call sys inr a ora a; Ensure carry reset cnz query; When file already exists jnz done; Abort if not to be purged xra a sta bytes; Reset byte count sta sector; and sector count sta outfcb+32; Reset output record number mvi a,delete call sys; Remove any old file mvi a,make call sys; And create a new one inr a push psw lda inuser call sguser; Go back to input access pop psw rnz; All well ; " " ; Fullup message and abort fullup: lxi d,noroom jmp exeunt; Abort everything endif; extract ; ; Open LBRFCB file ; a,f fopnlb: lxi d,lbrfcb ; " " ; Open file (DE)^, doing any searches, return BDOS response ; a,f fopenf: call fopen cpi 0ffh rnz; Success ldax d ora a mvi a,0ffh; Failure flag rnz; Because a drive was specified lda altdrv; Set system drive and retry stax d; (a zero value causes useless retry) ; " " ; Open file (DE)^, return BDOS response in (A), ; assumes DMA is preset to LBRBUF. ; a,f fopen: if limitt; Ensure non-ambiguous name mvi a,srchf call sys; Search for openee cpi 0ffh rz; Failure, not found push h push d push b lxi h,lbrbuf+1; Copy the non-ambiguous name add a add a; 4* add a add a; 16* add a; 32* add l mov l,a; Index into the DMA area adc h sub l mov h,a; Point to the "found" file mvi b,11 inx d call move; Exact name into FCB pop b pop d pop h endif; limitt ; " " mvi a,open ; " ' ; Execute BDOS function (A), preserve registers ; a,f sys: push h push d push b mov c,a call bdos pop b pop d pop h ret ; ; Move (B) bytes from (HL)^ to (DE)^ ; a,f,b,d,e,h,l move: mov a,m stax d inx h inx d dcr b jnz move ret ; ; List filename from FCB (HL)^ ; a,f,h,l fname: push b mvi b,8; Size of name field fname1: mov a,m; Get a byte ani 07fh cpi ' ' cnz ctype; print non-space inx h; Next char dcr b jnz fname1; Continue name mvi a,'.' call ctype; Print seperator mvi b,3; 3 character extent fname2: mov a,m; Get byte ani 07fh cpi ' ' cnz ctype; print non-space inx h; Next char dcr b jnz fname2; Continue ext pop b ret ; ; This must parse the command line into FCB1 and FCB2, setting the ; appropriate drives and user values, and saving old values. Note that ; this routine should NOT assume that the command line is upshifted, to ; allow use with CCPLUS when the noupshift option is selected, and thus ; enabling use of Software Tools etc. This routine does not deny ; access to the currently logged in drive or user, so that a privileged ; operator can always use the program on his own area, even though ; normally restricted. Note that the fact of logging in establishes ; the existance of the drive unit. if duspec; Parse command line parse: mvi a,getdrv; Save entry drive call sys sta olddrv call getusr; and user values sta oldusr; first so any error restores lxi h,cmdln mov a,m; Line length push h inr a add l mov l,a mvi m,0; Mark line end ; " " ; Check for command line option $U to toggle unsq/uncr flag mvi a,' ' parse1: dcx h cmp m jz parse1; ignore trailing blanks mov a,m ani 05fh cpi 'U' jnz parse4; not $U option dcx h; Backup 3 chars. mov a,m cpi '$' jnz parse4; not $U option dcx h mov a,m cpi ' ' jnz parse4; not delimited, may be part of fname mvi m,0; Found " $U" at end, remove from line lda nouqz; Get flag cma; Toggle it sta nouqz; And put it back ; " " parse4: pop h; line beginning ptr lxi d,fcb1 call skipbl; Skip any leading blanks call setdu jc helper; Bad specification mov b,a lda oldusr cmp b jz parse6; User ok if already logged on to it lda maxusr; Load maximum user value parse5: cmp b jc noacc; Illegal on system parse6: push d mov a,b ; " " if extract sta inuser; Preserve for output flipping endif; extract ; " " sta savusr; Save for later pop d ldax d call chkdv jc noacc; No access or no such drive inx d; Drive is already set call setnam; Setup first file name cnz skipbl; Dont skip past eol marker lxi d,fcb2 xra a stax d; Kill the 2nd drive spec. ; " " if extract sta outflg; Default no output file created endif; extract ; " " call setdu; To skip over any du spec jc helper ; " ' if extract jz parse7; No DU specified mov a,b sta outusr ldax d sta outfcb xra a stax d; Reset drive field. dcr a; To 0ffh sta outflg; Flag doing output else ; NOT extract jnz helper endif; NOT extract ; " " parse7: inx d ; " " ; Parse filename from (HL)^ into FCB at (DE)^ ; Z-flag if end of line reached ; a,f,b,d,e,h,l setnam: mvi b,8 call setfld cpi '.' jnz setnam2; No extension specified inx h setnam2: mvi b,3 ; " " ; Set field length (B) in (DE)^ from (HL)^ up, blank padding, Z- flag ; for end of line. Leave HL pointing to delimiter. (a) := delimiter. ; Truncate any fields longer than expected. ; a,f,b,d,e,h,l setfld: call qdelim; Load and upshift char jz setfld4; Delimiter, go blank pad cpi '*' jnz setfld1 mvi a,'?'; Expand '*' to '?'s jmp setfld2; Without advancing input pointr setfld1: inx h setfld2: stax d inx d dcr b jnz setfld setfld3: call qdelim; Skip to first delimiter jz setfld5; At a delimiter inx h; Else truncate jmp setfld3 setfld4: mvi a,' '; Blank pad stax d inx d dcr b jnz setfld4 setfld5: mov a,m ora a; Z flag for eol only ret ; ; (A) := (HL)^ upshifted. Z flag if a delimiter for file names ; a,f qdelim: mov a,m ani 07fh; Just in case call upshft cpi 07fh rz; A rubout is a delimiter cpi '=' rz cpi ',' rz cpi '_' rz cpi '.' rz cpi ':' rz cpi ';' rz cpi '<' rz cpi '>' rz cpi '[' rz cpi ']' rz cpi ' ' rz rnc; cmp a; All controls are delimiters ret; Including EOL ; ; Skip to non-blank in (hl)^. Z-flag if EOL reached. ; At entry (HL) points to byte previous to first testee. ; a,f,h,l skipbl: inx h mov a,m ora a rz; Empty line, Z-flag cpi ' ' jz skipbl; Skip leading blanks ret; Nz, found something ; ; No access exit noacc: lxi d,illegl jmp exeunt ; ; Parse drive/user from line (HL)^ return user in (A), set drive in (DE)^ ; At exit (HL) points past any drive/user specification. Drive/user ; validity is not checked here. Carry for any error, z-flag for no entry ; a,f,b,c,h,l setdu: mvi a,':'; Scan for ':' call scan; Returns (A) = position jc setdu2; No drive/user specified cpi 4 jnc setdu2; Not in 1st 4 characters, not du spec mov c,a; Save position mov a,m call upshft sui '@' rc; Illegal, catches initial ':' stax d; Preventing any searches unless '@' inx h call getusr; Default, if none specified mov b,a dcr c; Range 0...2 jz setdu1; No user spec mvi b,0 call decin rc; Illegal character dcr c; Range 0..1 jz setdu1; One char in user spec only call decin rc; Illegal character setdu1: ori 1; Reset Z-flag, have values mov a,b inx h; Now point past the ':' ret setdu2: call getusr; No spec, set z flag & default usr cmp a; Set z flag ret ; ; Return current user in (A) ; a,f getusr: mvi a,0ffh ; " " ; Set current user to (A) ; a,f sguser: push d mov e,a mvi a,gsuser call sys pop d ret ; ; Check for valid drive specification (A). Carry for invalid value. ; Uses global "DRVSUP" value and "OLDDRV" values ; a,f chkdv: ora a rz; Default is always ok push h lhld olddrv cmp l pop h; Specific reference to rz; Logged in drive is ok push h lhld drvsup chkdv2: dad h dcr a jnz chkdv2; Shift access bit into carry pop h; Carry for access at this point cmc ret ; ; Incorporate character (HL)^ into the value (E) (decimal). ; Carry for llegal character, else advance (HL). ; a,f,b decin: mov a,m sui '0' rc; Illegal cpi 9+1 cmc rc; Illegal inx h push psw mov a,b add a; 2* add a; 4* add b; 5* add a; 10* mov b,a pop psw add b mov b,a ret ; ; Scan (HL) up for (A) or to EOL (marked by null). ; Return (A) = relative position (0 based), carry if not found. ; a,f scan: push b push h mvi c,-1 dcx h scan1: inx h inr c cmp m jz scan2; Found, carry clear push b; Check for end of string mov c,m; This test occurs after the char test inr c; So that a null will be found. Else dcr c; A null signifies end of string. pop b; Don't play with memory, may be ROM. jnz scan1; Not EOS, continue stc; End of line, not found scan2: mov a,c pop h pop b ret ; ; This restores the entry drive/user value ; a,f,e restor: lda oldusr call sguser lda olddrv mov e,a mvi a,setdrv call sys ret ; ; Upshift (A) ; a,f upshft: cpi 'a' rc cpi 'z'+1 rnc ani 05fh ret endif; duspec ; if extract ; See if we use wheel test. If so, test wheel byte. ; Returns Z set if wheel not set, or no file output, ; else returns with Z not set for output to file. ; a,f outtst: call qwhl rz; wheel not set lda outflg; Get output flag ora a; True for output to file ret endif; extract ; ; Cheek wheel status. WHLADR = 0 acts as if wheel on, else checks ; NZ flag for priviledged operation ; a,f qwhl: push h lhld whladr mov a,m; Gets 0c3 or 0cd at lcn 0 if whladr=0 pop h ora a; Non-zero means priviledged ret ; nfound: db 'Member ' nofmsg: db 'Not found',cr,lf,lf,0 signon: db cr,lf,'LT',ver/10+'0',ver mod 10+'0' db ' [d[u]:]lbr/filename [d[u]:][component] [$u]' db ' by C.B. Falconer',cr,lf sign1: db '^S pause, ^C abort, ^X next' db ' file, ^Z stops paging',0 usage: db cr,lf,' Type/uncrunch/unsqueeze/unLZH ' db 'files or LBR members',cr,lf db ' Drive/user after lbr/filename ' db 'causes file output.',cr,lf db ' $U at end disables unsq/uncr/unlzh ' db 'of compressed files',cr,lf db ' (wildcards permitted)' db cr,lf,lf db 'Examples:',cr,lf db ' B>LT A3:HELLO SOURCE.AZM ' db ' [console] (defaults to HELLO.LBR)',cr,lf db ' A>LT LZHENCOD.DYC ' db ' [console] (handles LZH encoding)',cr,lf db ' A>LT SQUEEZE.DQC ' db ' [console]',cr,lf db ' A>LT HELLO *.* ' db ' [console, all typable]',0 ; ; 2nd part when wheel set or disabled whlusg: db ' B>LT B:HELLO A4:SOURCE.AQM ' db ' [file]',cr,lf db ' B>LT B:HELLO A4:SOURCE.AQM $U' db ' [file with no unsqueeze]',cr,lf db ' A>LT B:CRUNCH.AZM A: ' db ' [file]',0 abrmsg: db cr,lf,'++ ABORTED ++',cr,lf,0 clean: db cr,' ',cr,0; Erase the "more" eofmsg: db 'Early EOF, aborted',0 exists: db ' exists, purge (y/n)? ',0 ffsep: db ' =>> ',0; File-file separator corrpt: db 'LBR file corrupt',0 mbrmsg: db 'Member: ',0 more: db '[more] ',0 badfile:db cr,lf,lf,bell,'Corrupt or unknown format file',cr,lf,0 if limitt cant: db bell," ...Can't type a '",0 cant2: db "' file",cr,lf,0 endif; limitt if extract noroom: db cr,lf,lf,bell,'No space, aborting',0 endif; extract if limitl excess: db bell,'Too long, transfer with KMD',cr,lf,0 endif; limitl if duspec illegl: db bell,'Access denied',cr,lf,0 endif; duspec ; ; ------------------------------------------------------------------- ; dseg ; Link the data segment after the code. Use 2 passes if necessary. ; ; Temporary storage area bufptr: dw 0 chrcnt: db 0 db 0 lincn1: db 0; Lines printed since [more] paglns: db 0; Ln/page before pause, 0 causes setup nampt1: dw endu; NAMBUF namptr: dw endu; NAMBUF rcnt: dw 65535; Maximum. record count for type outptr: dw outbuff; File output buffer ; It is helpful to ensure that the LAST initialized data item ; is NON-ZERO. Eases any final truncation, ensures CCITCRC can run. ;; ; This (uninitialized) portion takes up no space in the code file ; (with reasonable linkers - l80 zero fills) bytes: ds 1; in current outbuff sector sector: ds 1; no. in outbuff filling memcnt: ds 2; members in current library lbrfcb: ds 9 lbrtyp: ds 3 lbrext: ds 20; Lbrfcb+12; file extent lbrsno: ds 1; Lbrfcb+32; sector # lbrrno: ds 3; Lbrfcb+33; random rcd no. memfcb: ds 16 memnam: ds 16 oldusr: ds 1 olddrv: ds 1 savusr: ds 1 if extract inuser: ds 1; To restore after file output outflg: ds 1; Do file output if true outusr: ds 1; Output FCB usr outfcb: ds 33; Output file FCB dmaadd: ds 2; Write address outbuff: ds 128*rec; Output buffer endif; extract ; ; Mark start of zeroed area, per component loop zeros: numflt: ds 1 char: ds 1 rptchr: ds 1; Char to repeat rptcnt: ds 1; Count of repeat characters lincnt: ds 1; Number of lines printed total column: ds 1; Crt column position zerlen: ds 1 if xpnd dleflg: ds 1; Flag a dle just received dlecnt: ds 1; Count of blanks to emit endif; xpnd lastz: ds 64; Mark end of zeroed area, stack space stack: ds 2; Store entry stack pointer lbrbuf: ds 128; Member read buffer xlatbl: ds 258*4 end begin