; OSZ-INFO.ASM Version 1.0 ; by ; Kelly Smith, CP/M-Net (805) 527-9321, August 7, 1983 ; ; Osborne 1 Disk/System Information Display/Lister ; ; This code was essentially derived from three other public domain ; files: SD-48A.ASM by Bruce Ratoff, ODSKLBL.ASM by Dennis ; McFerran, and DOS.ASM by Bill Bolton. ; ; I added the necessary code to make it "transportable" on the ; various OCC 1 monitor PROMs from version 1.3 to 1.44 (if your OCC ; 1 is still way back there at version 1.2, you are out of ; luck...OSZ-INFO will not work for you). Some bugs were fixed ; also from SD-48A... if the 'F' option (see below) was specified ; and no files were present, a '.DIR' file would not be created. ; ; ; ; Usage and Command Options ; ; OSZ-INFO retains all of the same command options as were used in ; SD-48A. Here are some variations on a theme: ; ; A>oz-info <-- display the current logged directory and system ; information, do not display system files, show library files of ; type '.LBR' including their sub-directories, do not reset the ; disk system, and pause on each 'page' display. ; ; A>osz-info A*.* <-- display only files starting with 'A' in ; the current logged directory, do not display system files, show ; library files of type '.LBR' including their sub-directories, ; do not reset the disk system, and pause on each 'page' display. ; ; A>osz-info *.cal <-- display only files of type '.CAL' in the ; current logged directory, do not display system files, show ; library files of type '.LBR' including their sub-directories, ; do not reset the disk system, and pause on each 'page' display. ; ; A>osz-info b:*.* <-- display all files on disk B:, do not ; display system files, show library files of type '.LBR' including ; their sub-directories, do not reset the disk system, and pause on ; each 'page' display. ; ; A>osz-info *.* $n <-- display all files on disk A:, do not ; display system files, show library files of type '.LBR' including ; their sub-directories, do not reset the disk system, and do not ; pause on each 'page' display ('N' means no pause). ; ; A>osz-info *.* $nd <-- display all files on disk A: and B: ; ('D' means all disks), do not display system files, show library ; files of type '.LBR' including their sub-directories, do not ; reset the disk system, and do not pause on each 'page' display. ; ; A>osz-info *.* $nda <-- display all files on disk A: and B:, ; all user directories ('A' means all directories), do not display ; system files, show library files of type '.LBR' including their ; sub-directories, do not reset the disk system, and do not pause ; on each 'page' display. ; ; A>osz-info *.* $ndas <-- display all files on disk A: and B:, ; all user directories, display system files ('S' means display ; files that you have set as '$SYS' files by the CP/M STAT ; program), show library files of type '.LBR' including their sub- ; directories, do not reset the disk system, and do not pause on ; each 'page' display. ; ; A>osz-info *.* $ndasl <-- display all files on disk A: and B:, ; all user directories, display system files, do not show library ; files of type '.LBR' including their sub-directories ('L' means ; exclude files of type '.LBR' from the display), do not reset the ; disk system, and do not pause on each 'page' display. ; ; A>osz-info *.* $ndasl <-- display all files on disk A: and B:, ; all user directories, display system files, do not show library ; files of type '.LBR' including their sub-directories, do not ; reset the disk system, and do not pause on each 'page' display. ; ; A>osz-info *.* $ndaslr <-- display all files on disk A: and ; B:, all user directories, display system files, do not show ; library files of type '.LBR' including their sub-directories, ; reset the disk system ('R' means reset the disks as if you had ; entered a CTRL-C (warm boot) at the keyboard), and do not pause ; on each 'page' display. ; ; A>osz-info *.* $ndaslr <-- display all files on disk A: and ; B:, all user directories, display system files, do not show ; library files of type '.LBR' including their sub-directories, ; reset the disk system, and do not pause on each 'page' display. ; ; A>osz-info *.* $ndaslrf <-- display all files on disk A: and ; B:, all user directories, display system files, do not show ; library files of type '.LBR' including their sub-directories, ; reset the disk system, do not pause on each 'page' display, and ; make a information file that includes everything displayed ('F' ; means write a file named OSZ-INFO.DIR). ; ; A>osz-info *.* $ndaslrfp <-- display all files on disk A: and ; B:, all user directories, display system files, do not show ; library files of type '.LBR' including their sub-directories, ; reset the disk system, do not pause on each 'page' display, make ; a information file that includes everything displayed, and send ; the information to the printer ('P' means print the information) ; as well as the display). ; ; A>osz-info *.* $ndaslrfpu15 <-- display all files on disk A: ; and B:, over-ride the display of all user directories (even ; though its specified with 'A') and display the directory for User ; 15 ('U' and digits 0 to 15 means select a user directory for ; display), display system files, do not show library files of type ; '.LBR' including their sub-directories, reset the disk system, do ; not pause on each 'page' display, make a information file that ; includes everything displayed, and send the information to the ; printer. ; ; Note that all command options must be preceded by a '$' character ; as a command delimiter...and of course, you make mix'n'match the ; command options in any sequence or combination. Here is a sample ; OSZ-INFO.DIR file (many combinations of display will be created ; depending on your OCC 1 disk SETUP, and system SYSGEN size): ; ; Disk Directory ; ; ASM .COM 8k AUTOST .COM 1k CAPTURE .COM 1k ; COPY .COM 5k CRCK .COM 2k DDT .COM 5k ; DISK .COM 3k DISPLAY .COM 2k DOS .COM 1k ; DU .COM 6k ED .COM 7k FIND .COM 1k ; FINDBAD .COM 2k LOAD .COM 2k MLIST .COM 2k ; MOVCPM .COM 11k OCOMPARE.COM 2k OSETAUTO.COM 1k ; OSZ-INFO.COM 5k OSZ-INFO.DIR 0k OSZDEATH.COM 3k ; PIP .COM 8k RCPMLINK.COM 5k SETOKI .COM 1k ; SETUP .COM 6k SKEY .COM 4k SPEED .COM 2k ; SQ .COM 16k STAT .COM 6k SUBMIT .COM 2k ; SYS-LINK.COM 3k SYSGEN .COM 2k SYSTOSYS.COM 5k ; TLX-LINK.COM 3k TYPESQ .COM 8k USQ .COM 12k ; WASH .COM 9k XDIR .COM 3k XSUB .COM 4k ; ZSID .COM 10k ; Disk A, User 0 - 179K in 40 files - 4K free. ; ; APLZCPR2.LBR 20k CAPTURE .COM 1k CPM59 .COM 10k ; ONZCPR21.DOC 4k ONZCPR21.HEX 6k OSZ-INFO.ASM 51k ; OSZ-INFO.COM 5k OSZ-LBL .ASM 13k SID .COM 11k ; XDIR .COM 3k ; ; Library file members for : APLZCPR2.LBR ; Z2APPLE3.HEX 44s Z2APPLE .HEX 44s Z2APPLE1.DQC 21s ; Z2APPLE2.DQC 23s Z2APPLE3.DQC 26s ; ; There are 5 member files in 1 library(s). ; Disk B, User 0 - 124K in 10 files - 59K free. ; ; Special Function Keys ; ; 1 = B:OSZ-INFO *.* $NFU2 ; 2 = TYPE OSZ-INFO.DIR ; 3 = 3 ; 4 = 4 ; 5 = 5 ; 6 = 6 ; 7 = 7 ; 8 = 8 ; 9 = 9 ; 0 = B:OSZ-INFO *.* $NDARF ; ; Device Asignments ; ; Printer type is RS-232 Serial ; Printer protocol is Hardware RTS/DSR ; Auto-scroll is On ; Baud rate is 1200 ; Display screen size is 128 ; Arrow keys are for CP/M ; IEEE-488 device address is 4 ; Auto-start command is "Auto-start on Cold Boot" ; Auto-start filename is AUTOST ; ; CP/M System Addresses ; ; The address of the system BIOS is E100 ; The address of the system BDOS is D300 ; The address of the system CCP is CB00 ; Total TPA space with CCP overlay is D200 ; Total TPA space with CCP intact is CA00 ; ; ; ; Special Function Keys Display ; ; The special function keys are displayed in 1 to 9 then 0 order ; because I prefer to use the "top-row" numeric keys rather than ; the keypad for entry of special function command strings. ; Additionally, embeded carriage returns are displayed as '', ; the ESCape key is displayed as '^[', and any CTRL (Control) keys ; are preceded by a '^' symbol (i.e., CTRL-A will appear as '^A'). ; ; ; ; Device Assignments Display ; ; In particular, note that the "Device Assignments" display may ; offer the following possibilities: ; ; Printer type is [RS-232 Serial] ; [Centronics Parallel] ; [IEEE-488 Parallel] ; ; Printer protocol is [Hardware RTS/DSR] ; [Software ETX/ACK] ; [Software XON/XOFF] ; ; Auto-scroll is [On] ; [Off] ; ; Baud rate is [300] ; [1200] ; ; Display screen size is [52] ; [80] ; [128] ; (or whatever you SETUP from 1 to 128) ; ; Arrow keys are for [CP/M] ; [WordStar] ; ; IEEE-488 device address is [4] ; (or whatever you SETUP from 0 to 255) ; ; Auto-start command is ["Ignore auto-start"] ; ["Auto-start on Cold Boot"] ; ["Auto-start on Warm Boot"] ; ["Auto-start on Cold and Warm Boot"] ; ; Auto-start filename is [AUTOST] ; (or whatever you may have made it) ; ; ; ; Library Files and Library Member Displays ; ; Library files (created from the popular 'LU' Library Utility) of ; filetype '.LBR' will differ in directory display file size format ; from normal file sizes as indicated by 's' (for sector size) ; rather than size in 'k' bytes. This is retained to conform to ; the same display format of the 'LDIR' (Library Directory) program ; when the '-s' command of 'LDIR' is used. ; ; ; ; OSZ-INFO Error Messages ; ; OSZ-INFO will "play back" any invalid command option. For ; example, 'X' is NOT a vaild option and will be displayed as: ; ; Error -> *.* $X? ; ; If you are lucky enough to have a hard disk (i.e., megabytes of ; storage on your OCC 1) with to many directory entries to fit in ; the OCC 1 TPA (and to be sorted) you will get this error message: ; ; Directory to large for memory! ; ; Note: Yes, you can add more drives to this program beyond the ; normal A: and B: drives (up to a maximum of 16 drives as a matter ; of fact). Just add'em in between labels 'lodrv' and 'hidrv' for ; up to and including drive P:, and you can also limit the number ; of user directory "searches" at the same locations up to and ; including User 15. As supplied, OSZ-INFO searches all ; user directories and only drives A: and B:. ; ; If by some stroke of fate you have an invalid library file format ; or a non-library file with a '.LBR' file type, you will get this ; error message: ; ; Not a library file! ; ; Note: Use the 'L' command option to bypass displaying the "bogus" ; '.LBR' file(s). ; ; When using the 'F' option, if you run out of disk space (90K ; bytes on single density or 183K bytes double density) or have ; exceeded the number of allowable directory entries (64 maximum), ; you will get this error message: ; ; Make or Open Error on OSZ-INFO.DIR! ; ; Or alternately you might get this error message when you ; initially had enough space on the disk to make OSZ-INFO.DIR, but ; then exceeded the available disk space: ; ; Write Error on OSZ-INFO.DIR! ; ; Note: If you are using the 'F' command option, OSZ-INFO will ; attempt to erase the "old" OSZ-INFO.DIR file from your disk to ; make room for the "new" one. ; ; Trying to display an invalid user directory (trying to do '$u20' ; for instance) will display the following error message: ; ; User number out of range! ; ; All these error conditions will cause an immediate abort back to ; CP/M until you reconcile the problem(s). No attempt is made to ; determine if a printer is ready if the 'P' option is used...OSZ- ; INFO will just spray text for the printer into the "bit-bucket". ; If you forget to specify a command option (or string of command ; options WITHOUT the '$' command delimeter, all command options ; will be ignored by OSZ-INFO. ; ; ; ; Final Notes on OSZ-INFO ; ; There are some things I don't like about OSZ-INFO...for instance, ; it was necessary to first erase any "old" OSZ-INFO.DIR and then ; make a "new" OSZ-INFO.DIR prior to accumulating the directory ; file sizes (i.e., the actual space used on the disk does not ; reflect the inclusion of space used by OSZ-INFO.DIR when it is ; finally written). This does conform however to the same way that ; the Osborne Computer Corporation supplied 'XDIR' program works ; (also a derivative of Bruce Ratoff's 'SD' program that was ; "hacked" by Thom Hogan). I have several hours in trying to get ; around this problem, but with all the "hacking" by others...the ; 'SD-48A.ASM' program tends to be a lot of "spaghetti code". More ; problems arose then were worth trying to resolve by yet another ; "fix"... ; ; Also, there is no reasonable way to get the directory display to ; fit into 52 columns on that damn tiny OCC 1 display (unless of ; course you have the "80 column kludge" )...so the file size will ; be off the display on the right-hand size (use the CTRL and Left ; Arrow key to see it). ; ; I would appreciate any updates, new found bug fixes (I pounded ; the hell out of this one to get all the (I think) bugs out), or ; suggestions be sent via modem to me here at CP/M-Net (805)-527- ; 9321, with the revision level and changes placed "top-down" in ; the source code (and include your name for the "Hall of Hackers ; Infamy"). ; ; Its a bit sad to see the recent "restrictions" being placed on ; some programs by their authors...or (especially) programs ; supplied in '.COM' file form only because the author does not ; want somebody "writing on their wall" (not to nifty to try to fix ; when they are "buggy")... I believe that public domain software ; is just that...MADE PUBLIC. So use OSZ-INFO any way you ; like...sell it for all I care. My point is, SHARE in the ; information flow via the RCPM systems (or public domain software ; librarys and computer clubs)...there is a tremendous amount of ; information to be gained for all of us so that we may "hone" our ; software skills...so share openly in what you have learned with ; others, such that we ALL benefit. ; ; "Happy Hacking" from Kelly Smith ; ; ; bel equ 7 ; bell lf equ 00ah ; linefeed ff equ 00ch ; formfeed cr equ 00dh ; carriage return esc equ 01bh ; escape ; base equ 0 ; base of standard cp/m system bdos equ 5 ; bdos entry address fcb equ 05ch ; default file control block ; npl equ 3 ; number of names per line lps equ 23 ; number of lines per screen lencol equ 25 ; length of column ; rdchr equ 1 ; read character from console wrchr equ 2 ; write character to console prnchr equ 5 ; print character dspmsg equ 9 ; display message (ending with '$') const equ 11 ; check console status reset equ 13 ; reset disk system seldsk equ 14 ; select disk open equ 15 ; 0ffh=not found close equ 16 ; " " srchf equ 17 ; " " srchn equ 18 ; " " delete equ 19 ; delete file read equ 20 ; not 0 = eof write equ 21 ; not 0 = disk full make equ 22 ; 0ffh = directory full curdsk equ 25 ; get currently logged disk name setdma equ 26 ; set current dma galloc equ 27 ; get address of allocation vector curdpb equ 31 ; get current disk parameters curusr equ 32 ; get currently logged user number ; ; ; org 100h ; start: ; lxi h,0 dad sp ; [HL]=old stack shld stack ; save it lxi sp,stack; get new stack ; mvi e,0ffh ; get current user number mvi c,curusr call cpm ; sta oldusr ; initialize startup user number sta newusr ; and make new user match it sta basusr ; save extra copy for multi-disk directories ; mvi c,curdsk call cpm ; get current disk number sta olddsk ; save for reset if needed ; inr a sta outfcb ; set directory output file drive ; lxi h,fcb mov a,m ; get drive name for directory search ora a ; any specified? jnz start2 ; yes skip next routine lda olddsk ; otherwise, get default disk inr a ; start2: ; mov m,a ; put the absolute drive code in directory fcb ; if at least one option is allowed, scan the command line for the ; option field delimiter. the option field delimiter is considered ; valid only if it is preceded by at least 1 space (otherwise, it ; may be part of the directory filename). any unrecognized options ; or illegal user numbers will be flagged or ignored (see reperr). ; (we scan the command line buffer rather than the 2nd default fcb ; because all 8 options plus a 2 digit user number won't fit in ; the fcb name field). ; lxi h,80h ; set command line buffer pointer mov b,m ; get length of command line buffer ; ; search for the command line delimiter. if not found, assume no options. ; scndol: ; inx h dcr b jm ckrest ; exit if command line buffer empty mov a,m cpi '$' jnz scndol dcx h ; '$' found, make sure space precedes it mov a,m inx h cpi ' ' jnz scndol ; no space, ignore "$" and search again ; ; valid delimiter found. scan the rest of the buffer for options. errors ; past this point will cause an abort if the command line error option is ; enabled. otherwise, the dud option will be ignored and OSZ-INFO will ; attempt to continue stumbling through the rest of the field. ; xchg ; get option field pointer to [DE] ; scnopt: ; inx d ; bump to next option field character dcr b ; dock characters left in option field jm ckrest ; if option field exhausted, exit ; scnagn: ; ldax d ; get the next option character cpi ' ' ; do we have a space? jz scnopt ; ignore it if so lxi h,otbl-1; get base of option lookup table mvi c,oend-otbl+1 ; get length of option lookup table ; nomach: ; inx h ; bump to next option table character dcr c ; are we out of the table? jz ck4usr ; if so, check for user option cmp m ; compare our character with option table jnz nomach ; exit if no match mvi m,0 ; otherwise, activate the flag jmp scnopt ; and go get the next option character ; ; if option character doesn't match the table, see if we have a user ; option. ; ck4usr: ; cpi 'U' jnz clerr ; last option, so bad deal if that ain't it ; uagn: ; inx d ; bump to user number digit dcr b jm clerr ; error if nothing left ldax d ; get decimal digit cpi ' ' ; ignore leading spaces jz uagn sui 30h ; subtract ascii bias jc clerr ; error if < 0 cpi 10 jnc clerr ; error if > 9 sta newusr ; save user number as it may be only 1 digit sta basusr ; duplicate it if multi-disk mode inx d ; bump to possible 2nd digit of user number dcr b jm ckrest ; if no more buffer, exit with complete user number ldax d ; else, check for another digit sui 30h jc scnagn ; if next character not numeric, its not part of user cpi 10 ; number so go check for another option jnc scnagn mov l,a ; save units digit lda newusr ; get tens digit add a ; multiply by 10 mov h,a add a add a add h add l ; combine with units digit sta newusr ; save the total user number sta basusr ; duplicate it if multi-disk mode jmp scnopt ; continue scanning ; ; if command line error option enabled, playback the command line up ; to the character that we gagged on and exit. if reperr is not enabled, ; then continue as if nothing were amiss to avoid acknowledging that ; some options are available. ; clerr: ; xra a inx d ; tag end of command line with terminator stax d call crlf lxi d,errmsg call print lxi h,81h ; playback bad command line to error point ; clelp: ; mov a,m ora a jz clex call type inx h jmp clelp ; clex: ; mvi a,'?' ; tag line with a '?' field call type call crlf ; space down one more line jmp exit ; and return to cp/m ; ; options input or not specified. if reset option specified, reset ; the disk system now. ; ckrest: ; mvi a,'Z'-40h ; clear occ 1 screen call type1 ; lxi d,dirhdg; print directory heading call print ; lda ropflg ; if reset flag set, reset disk system before ora a ; starting to update allocation vectors mvi c,reset cz cpm lda dopflg ; if multi-disk flag set, ora a ; need to set error traps cz swapem ; swap bdos error vector tables ; ; validate drive code and user area numbers from the drive table. ; noopt: ; lxi d,dremsg; get the drive/user error message push d lda fcb ; get directory drive code dcr a ; normalize to range of 0-15 cpi hidrv-lodrv ; compare with maximum drives on-line jnc erxit ; take drive error exit if out of range lxi h,usrmsg; switch to user number error message xthl mov e,a ; use drive code as index into table mvi d,0 lxi h,lodrv ; point to base of drive/user table dad d mov a,m ; get the maximum user number for this drive ani 0fh ; make sure its in range 0-15 sta maxusr ; save it for later lxi h,newusr; point to the directory user area cmp m ; compare it with the maximum jc erxit ; take error exit if user number illegal pop d ; destroy error message pointer lxi h,fcb+1 ; point to name mov a,m ; any specified? cpi ' ' jnz chkfop ; if so, check for file make option ; ; no fcb, make fcb all '?' ; mvi b,11 ; fn+ft count ; qloop: ; mvi m,'?' ; store '?' in fcb inx h dcr b jnz qloop ; chkfop: ; lda fopflg ora a jnz gotfcb ; if file output, fall through with a=0 ; ; if we're not on the first pass, then the output file is already ; open and positioned, so we can skip the open. ; lxi h,opnflg; point to output file open flag cmp m ; a=0, set z if opnflg=0 also jnz gotfcb ; if opnflg not zero, skip open dcr m ; else, make opnflg not zero and open ; ; delete any old OSZ-INFO.DIR and make a new OSZ-INFO.DIR ; lxi d,outfcb; set fcb entry mvi c,delete; delete file function call cpm lxi d,outfcb; set fcb entry mvi c,make ; create the new output file call cpm inr a jnz gotfcb ; continue if open successful ; ; if make or open fails, declare error ; opnerr: ; call erxit db cr,lf,bel,'Make or Open Error on OSZ-INFO.DIR','!'+80h ; wrterr: ; call erxit db cr,lf,bel,'Write Error on OSZ-INFO.DIR','!'+80h ; gotfcb: ; mvi a,'?' ; force wild extent sta fcb+12 call setsrc ; set dma for bdos media change check lxi h,fcb ; point to fcb drive code for directory mov e,m ; get the drive code out of the fcb dcr e ; normalize drive code for select mvi c,seldsk; select the directory drive to retrieve call cpm ; the proper allocation vector mvi c,curdpb; request dpb call bdos inx h inx h mov a,m ; get block shift sta blkshf inx h ; bump to block mask mov a,m sta blkmsk ; get it inx h inx h mov e,m ; get max block number inx h mov d,m xchg shld blkmax ; save it xchg inx h mov e,m ; get directory size inx h mov d,m xchg ; ; calculate number of k free on selected drive now so that the free figure ; will not reflect either the creation or additions to the OSZ-INFO.DIR ; file (which we would probably erase or move anyway). ; shld dirmax ; save max number of entries in directory mvi c,galloc; get address of allocation vector call bdos xchg lhld blkmax ; get its length inx h lxi b,0 ; init block count to 0 ; gspbyt: ; push d ; save alloc address ldax d mvi e,8 ; set to process 8 blocks ; gsplup: ; ral ; test bit jc notfre inx b ; notfre: ; mov d,a ; save bits dcx h ; count down blocks mov a,l ora h jz endalc ; quit if out of blocks mov a,d ; restore bits dcr e ; count down 8 bits jnz gsplup ; do another bit pop d ; bump to next byte of allocation vector inx d jmp gspbyt ; process it ; endalc: ; pop d ; clear allocation vector pointer from stack mov l,c ; copy blocks to [HL] mov h,b lda blkshf ; get block shift factor sui 3 ; convert from sectors to k jz savfre ; skip shifts if 1k blocks, return free in [HL] ; freklp: ; dad h ; multiply blocks by k/blk dcr a jnz freklp ; savfre: ; shld freeby ; save the free space for output later ; ; reenter here on subsequent passes while in the all-users mode ; settbl: ; lhld dirmax ; get directory maximum again inx h ; directory size is dirmax+1 dad h ; double directory size lxi d,order ; to get size of order table dad d ; allocate order table shld tbloc ; name table begins where order table ends shld nextt xchg lhld bdos+1 ; make sure we have room to continue mov a,e sub l mov a,d sbb h jnc outmem lda newusr ; get user area for directory mov e,a mvi c,curusr; get the user function call cpm ; and set new user number ; ; look up the fcb in the directory ; lxi h,0 shld count ; initialize match counter shld totfil ; " total file counter shld totsiz ; " total size counter call setsrc ; set dma for directory search mvi c,srchf ; get 'search first' function jmp look ; and go search for 1st match ; ; read more directory entries ; mordir: ; mvi c,srchn ; search next look: ; lxi d,fcb call cpm ; read directory entry inr a ; check for end (0ffh) jz sprint ; if no more, sort and print what we have ; ; point to directory entry ; dcr a ; undo prev 'inr a' ani 3 ; make modulus 4 add a ; multiply. add a ; by 32 because add a ; each directory add a ; entry is 32 add a ; bytes long lxi h,base+81h ; point to buffer (skip to fn/ft) add l ; point to entry adi 9 ; point to sys byte mov l,a ; save (can't carry to h) lda sopflg ; did user request sys files? ora a jz sysfok mov a,m ; get sys byte ora a ; check bit 7 jm mordir ; skip that file ; sysfok: ; mov a,l ; go back now sui 10 ; back to user number (alloc flag) mov l,a ; [HL] points to entry now lda newusr ; get current user cmp m jnz mordir ; ignore if different inx h ; ; move entry to table ; xchg ; entry to [DE] lhld nextt ; next table entry to [HL] mvi b,12 ; entry length (name, type, extent) ; tmove: ; ldax d ; get entry char ani 7fh ; remove attributes mov m,a ; store in table inx d inx h dcr b ; more? jnz tmove inx d inx d ; point to sector count ldax d ; get it mov m,a ; store in table inx h shld nextt ; save updated table addr xchg lhld count ; bump the number of matches made inx h shld count lxi h,13 ; size of next entry dad d xchg ; future nextt is in [DE] lhld bdos+1 ; pick up tpa end mov a,e sub l ; compare nextt-tpa end mov a,d sbb h jc mordir ; if tpa end > nextt then loop back for more ; outmem: ; call erxit ; exit if directory too large db cr,lf,bel,'Director to large for memory','!'+80h ; ; sort and print ; sprint: ; call setsrc ; return to file search dma and user number lhld count ; get file name count mov a,l ora h ; any found? jz prtotl ; exit if no files found push h ; save file count sta supspc ; enable leading zero suppression ; ; initialize the order table ; lhld tbloc ; get start of name table xchg ; into [DE] lxi h,order ; point to order table lxi b,13 ; entry length ; bldord: ; mov m,e ; save low order address inx h mov m,d ; save high order address inx h xchg ; table addr to [HL] dad b ; point to next entry xchg xthl ; save tbl address, fetch loop counter dcx h ; count down loop mov a,l ora h ; more? xthl ; restore tbl address, save counter jnz bldord ; yes, go do another one pop h ; clean loop counter off stack lhld count ; get count shld scount ; save as number to sort dcx h ; only 1 entry? mov a,l ora h jz done ; yes, so skip sort ; ; this sort routine is adapted from software tools by Kernigan and Plaugher ; lhld scount ; number of entries ; l0: ; ora a ; clear carry mov a,h ; gap=gap/2 rar mov h,a mov a,l rar mov l,a ora h ; is it zero? jz done ; then none left mov a,l ; make gap odd ori 01 mov l,a shld gap inx h ; i=gap+1 ; l2: ; shld i xchg lhld gap mov a,e ; j=i-gap sub l mov l,a mov a,d sbb h mov h,a ; l3: ; shld j xchg lhld gap ; jg=j+gap dad d shld jg mvi a,12 ; compare 12 chars call compare ; compare (j) and (jg) jp l5 ; if a(j)<=a(jg) lhld j xchg lhld jg call swap ; exchange a(j) and a(jg) lhld j ; j=j-gap xchg lhld gap mov a,e sub l mov l,a mov a,d sbb h mov h,a jm l5 ; if j>0 goto l3 ora l ; check for zero jz l5 jmp l3 ; l5: ; lhld scount ; for later xchg lhld i ; i=i+1 inx h mov a,e ; if i<=n goto l2 sub l mov a,d sbb h jp l2 lhld gap jmp l0 ; ; sort is all done, print entries ; done: ; lhld count shld lcount lxi h,0 shld lbtotl shld lmtotl lxi h,order ; initialize order table pointer shld nextl shld nextt jmp newlin ; start new line and output the files ; ; output the directory files we've matched. ; entry: ; lhld count dcx h ; dock file count shld count mov a,h ; is this the last file? ora l jz okprnt ; if count=0, last file so skip compare ; ; compare each entry to make sure that it isn't part of a multiple ; extent file. go only when we have the last extent of the file. ; push b ; save npl call ckabrt ; check for abort code from keyboard lhld nextt mvi a,11 call compr ; does this entry match next one? pop b ; recall npl jnz okprnt ; no, print it inx h inx h ; skip since highest extent comes last in list shld nextt jmp entry ; loop back for next lowest extent ; ; valid entry obtained, spit it out. ; okprnt: ; lhld nextt ; get order table pointer mov e,m ; get low order address inx h mov d,m ; get high order address inx h shld nextt ; save updated table pointer xchg ; table entry to [HL] mvi b,8 ; file name length call typeit ; type filename mvi a,'.' ; period after fn call type mvi b,3 ; display 3 characters of filetype call typeit ; ; compute the size of the file and update our summary datum. ; mov e,m ; get extent number mvi d,0 inx h mov a,m ; get sector count of last extent xchg dad h ; number of extents times 16k dad h dad h dad h xchg ; save in [DE] lxi h,blkmsk add m ; round last extent to block size rrc rrc ; convert from sectors to k rrc ani 1fh mov l,a ; add to total k mvi h,0 dad d lda blkmsk ; get sectors/blk-1 rrc rrc ; convert to k/blk rrc ani 1fh cma ; use to finish rounding ana l mov l,a xchg ; save file size in [DE] lhld totsiz dad d ; add to total used shld totsiz lhld totfil ; increment file count inx h shld totfil xchg ; get back file size ; ; if report size enabled, output the size of the individual file. ; call decprt ; go print it mvi a,'k' ; and follow with k size call type ; ; one file output, test to see if we have to output another one. ; lhld count ; get current file counter and test it mov a,h ora l jz prtotl ; if no more files, exit to summary output ; ; at least one more file to output, can we put it on the current line? ; dcr c push psw cnz space ; if room left, output the space character pop psw jnz entry ; and go output another file ; ; current line full, start a new one. ; newlin: ; mvi a,npl mov c,a ; reset names per line counter call crlf ; space down to next line mvi a,3 ; if printing less than 4 wide cmp c jz nwla lda fcb ; precede new line with drive name adi 'A'-1 call type call typusr mvi a,':' ; tag header with a colon and a space call space ; and exit back to entry ; nwla: ; jmp entry ; go back and output another file ; ; ; ; print hl in decimal with leading zero suppression ; decprt: ; sub a ; clear leading zero flag sta lzflg lxi d,-1000 ; print 1000's digit call digit lxi d,-100 ; etc. call digit lxi d,-10 call digit mvi a,'0' ; get 1's digit add l jmp type ; digit: ; mvi b,'0' ; start off with ascii 0 ; diglp: ; push h ; save current remainder dad d ; subtract jnc digex ; quit on overflow pop psw ; throw away remainder inr b ; bump digit jmp diglp ; loop back ; digex: ; pop h ; restore pointer mov a,b cpi '0' ; zero digit? jnz dignz ; no, type it lda lzflg ; leading zero? ora a mvi a,'0' jnz type ; print digit lda supspc ; get space suppression flag ora a ; see if printing file totals rz ; yes, don't give leading spaces jmp space ; leading zero, print space ; dignz: ; sta lzflg ; set leading zero flag so next zero prints jmp type ; and print digit ; ; ; ; show total space and files used ; prtotl: ; lda lopflg ora a jz prtot1 lhld totfil ; how many files did we match? mov a,h ora l cnz prtlmem ; skip the library check if we didn't find any ; prtot1: ; xra a ; get a zero to. sta supspc ; suppress leading spaces in totals lhld totfil ; how many files did we match? mov a,h ora l jz nxtusr ; skip the summary if we didn't find any push h ; save totfil sta fndflg ; set file found flag lxi d,totms1; print " drive " call print lda fcb adi 'A'-1 call type ; output the drive code lxi d,totms2; print ", user " call print call typusr ; output the user number lxi d,totms3; print " contains " call print lhld totsiz ; print total k used by files matched call decprt lxi d,totms4; print "k in " call print pop h ; recall totfil call decprt ; print number of files matched lxi d,totms5; print " files with " call print call prtfre ; output free space remaining and " free." ; ; directory for one user area completed. if all users option is ; selected, then go do another directory on the next user number ; until we exceed the maximum user number for the selected drive. ; nxtusr: ; lda aopflg ; if not all users mode, skip next ora a jnz nxtdsk call ckabrt ; check for user abort first lda maxusr ; no abort, get maximum user number lxi h,newusr; bump directory user number inr m cmp m ; does next user number exceed maximum? jnc settbl ; continue if more user areas to go lda basusr ; reset base user number for the mov m,a ; next directory search ; ; directory for all user areas completed.if the multi-disk option ; is enabled and selected, reset to the base user area and repeat ; the directory for next drive on-line until we either exceed the ; drives in our lodrv-hidrv table, or the bdos shuts us down with ; a select or bad sector error, which will be intercepted back to ; the exit module. ; nxtdsk: ; lxi h,fndflg; get file found flag mov a,m mvi m,0 ; clear file found flag for next drive ora a jnz ndsk ; continue if at least 1 file found lda fcb ; stash ascii directory drive in no file msg adi 'A'-1 sta nofms2 lxi d,nofms1; print "no file on ? - " call print lxi d,totms2; print ", user " call print call typusr ; output the user number lxi d,totms3; print " - " call print call prtfre ; tag with free message ; ndsk: ; lda dopflg ; if multi-disk not selected, skip next ora a jnz dirend call ckabrt ; check for user abort first mvi a,hidrv-lodrv ; get maximum drive code to search lxi h,fcb ; bump directory fcb drive code inr m cmp m ; does next disk exceed maximum? jnc noopt ; search next disk if not ; dirend: ; jmp spfkey ; all done, now do special function keys ; ; ; ; print the user number of the directory in decimal ; typusr: ; lda newusr cpi 10 ; if user number > 9 print leading 1 jc dux mvi a,'1' call type lda newusr ; print low digit of user number sui 10 ; dux: ; adi '0' jmp type ; ; ; ; force new line on video and check for page pause ; crlf: ; mvi a,cr ; send cr call type mvi a,lf ; send lf jmp type ; exit to caller from type ; ; ; ; separate the directory output on a line with a space ; space: ; mvi a,' ' ; fall through to type ; ; output character in [A] to console, and optionally to printer and/or ; the output file. ; type: ; push b push d push h push psw ; save the character to output call type1 ; send it to console pop psw ; restore the output character ani 7fh ; strip parity bit on character ; ; test file output mode and skip to page pause test if not active. ; mov b,a ; save stripped character to [B] lda fopflg ; is file output active? ora a jnz nowrit ; go check for page pause if not ; ; file output mode active, make sure we have room in buffer to add ; next character. if buffer full, write out current record first ; and then start a new record with current character. ; lhld bufpnt ; get current buffer pointer lda bufcnt ; get buffer capacity remaining ora a jnz putbuf ; continue if buffer not full call setfop ; set the dma address lxi d,outfcb; otherwise, write the current buffer out mvi c,write call cpm ora a jnz wrterr ; take write error exit if disk full or r/o lxi h,outbuf; reset buffer pointer mvi a,128 ; reset buffer capacity ; putbuf: ; mov m,b ; shove character to next buffer position inx h ; bump buffer pointer shld bufpnt ; save it dcr a ; dock count of characters left in buffer sta bufcnt ; save it ; nowrit: ; mov a,b ; recall stripped character ani 7fh ; strip parity bit on character mov e,a ; setup list output call mvi c,prnchr lda popflg ; test printer flag ora a cz cpm ; print character if flag true mov a,e ; recall character cpi lf ; do we have a lf? jnz typret ; exit if not lda nopflg ; is the page pause function disabled? ora a jz typret ; exit if so lda lincnt ; get line count inr a ; bump it cpi lps ; are we at the end of the screen? jc noteos ; skip if not lxi d,eosmsg; else, display pause message mvi c,dspmsg; without checking for lfs call bdos call cinput ; wait for character cpi 'C'-40h jz exit ; abort on CTRL-C lxi d,eraline ; erase eosmsg display line mvi c,dspmsg call bdos xra a ; reset line count ; noteos: ; sta lincnt ; save new line count ; typret: pop h ; exit from type pop d pop b ret ; ; ; ; output character ; type1: ; mov e,a ; get character into bdos entry register mvi c,wrchr jmp bdos ; call conout via the bdos ; ; ; ; print a string at [HL] of length [B] ; typeit: ; mov a,m ; get character in string call type ; type it to console (and maybe printer) inx h ; bump pointer dcr b ; debump character count jnz typeit ; go again, if all characters not printed ret ; all done, return ; ; ; ; print string pointed to by [DE] terminated with last byte high on console. ; print: ; ldax d ; get character in string push psw ; save for high bit test ani 7fh ; strip high bit call type ; type it to console (and maybe printer) pop psw ; get character ora a ; set flags rm ; return if high bit set inx d ; bump pointer to next byte jmp print ; repeat til high bit character found ; ; ; ; fetch character from console (without echo) ; cinput: ; lhld base+1 mvi l,9 call gohl ani 7fh ret ; ; ; ; check for a CTRL-C or CTRL-S entered from the keyboard. jump to ; exit if CTRL-C, pause on CTRL-S. ; ckabrt: ; lhld base+1 mvi l,6 ; check status of keyboard call gohl ; any key pressed? ora a rz ; no, return to caller call cinput ; get character cpi 'C'-40h ; CTRL-C? jz exit ; if CTRL-C then quit cpi 'S'-40h ; CTRL-S? rnz ; no, return to caller call cinput ; yes, wait for another character cpi 'C'-40h ; might be CTRL-C jz exit ; exit if CTRL-C, else fall thru and continue ret ; ; ; ; kludge to allow call to address in [HL] ; gohl: pchl ; ; ; ; entry to bdos saving all extended registers ; cpm: ; push b push d push h call bdos pop h pop d pop b ret ; ; ; ; for file output mode, return to old user area and set dma for ; the file output buffer. ; setfop: ; lda oldusr ; get user number at startup mov e,a mvi c,curusr call cpm ; reset the old user number lxi d,outbuf; move dma from search buffer into the jmp set2 ; output buffer ; ; ; ; move disk buffer dma to default buffer for directory search operations ; and bdos media change routines. ; setsrc: ; lxi d,base+80h ; set2: ; mvi c,setdma jmp cpm ; ; ; ; print the amount of free space remaining on the selected drive ; prtfre: ; lhld freeby ; get space left before adding to master.dir call decprt ; print k free lxi d,totms6; print " free." jmp print ; ; ; ; compare routine for sort ; compr: ; push h ; save table addr mov e,m ; load low order inx h mov d,m ; load high order inx h mov c,m inx h mov b,m ; ; [BC], [DE] now point to entries to be compared ; xchg mov e,a ; get count ; cmplp: ; mov a,m ani 7fh mov d,a ldax b ani 7fh cmp d inx h inx b jnz noteql ; quit on mismatch dcr e ; or end of count jnz cmplp ; noteql: ; pop h ret ; condition code tells all ; ; ; ; swap entries in the order table ; swap: ; lxi b,order-2 ; table base dad h ; *2 dad b ; + base xchg dad h ; *2 dad b ; + base mov c,m ldax d xchg mov m,c stax d inx h inx d mov c,m ldax d xchg mov m,c stax d ret ; ; ; ; new compare routine ; compare: ; lxi b,order-2 dad h dad b xchg dad h dad b xchg mov c,m inx h mov b,m xchg mov e,m inx h mov d,m xchg mov e,a ; count ; cmplpe: ; mov a,m ani 7fh mov d,a ldax b ani 7fh cmp d inx b inx h rnz dcr e jnz cmplpe ret ; ; ; ; error exit ; erxit: ; mvi a,0ffh sta fopflg ; disable file output mode on error call crlf ; space down pop d ; get pointer to message string call print ; print it call crlf ; space down ; ; exit - all done, restore stack ; exit: mvi c,const ; check console status call cpm ora a ; character waiting? mvi c,rdchr cnz cpm ; gobble up char ; lda dopflg ; if they were swapped ora a cz swapem ; lda ropflg ; if disk system was reset cpi 'R' lda olddsk ; get default disk at startup mov e,a mvi c,seldsk; reselect it cz cpm ; ; exit - all done , restore stack ; exit1: ; lhld stack ; get old stack pointer sphl ; move back to old stack ret ; and return to ccp ; ; ; ; trap bdos select and sector error vectors to our own intercept ; routine so we can catch a reference to an illegal drive. ; swapem: ; lhld bdos+1 ; get pointer to base of bdos mov a,l sui 6 ; check if pointing directly to bdos jz swapok ; continue if true mvi a,'D' ; undo option request for multi-disk sta dopflg ; swapok: ; mvi l,9 ; point to sector error vector lxi d,vectbl; exchanging with our own vector table mvi a,4 ; 4 bytes to swap ; swaplp: ; mov b,m ; get byte from [HL] xchg mov c,m ; get byte from [DE] mov m,b ; put byte from [HL] xchg mov m,c ; put byte from [DE] inx h ; bump exchange pointers inx d dcr a ; dock counter jnz swaplp ; continue swapping til done ret ; ; ; ; recovery point from intercepted bdos select and bad sector errors. ; dskerr: ; lxi sp,stack; get out of bdos's stack jmp exit ; and exit back to ccp ; ; ; ; subroutines to read library file directory ; prtlmem: ; lxi h,order ; initialize order table pointer shld nextl xra a sta lncnt ; entryl: ; lhld lcount mov a,h ; is this the last file? ora l jz lbexit ; if count=0, last file so return dcx h ; dock file count shld lcount push b call ckabrt ; check for abort code from keyboard lhld nextl mvi a,11 call compr ; does this entry match next one? pop b jnz lbrtst ; no, print it inx h inx h ; skip since highest extent comes last in list shld nextl jmp entryl ; loop back for next lowest extent ; ; exit library member printing ; lbexit: ; lhld lmtotl mov a,h ora l rz push h ; save member count xra a ; get a zero to. sta supspc ; suppress leading spaces in totals lxi h,npl lda lncnt cmp m cnz crlf lxi d,contm ; print "there are " call print pop h ; get total member count back call decprt lxi d,mfiles ; print "members in " call print lhld lbtotl call decprt lxi d,libr call print ret ; ; valid entry obtained, spit it out. ; lbrtst: ; lhld nextl ; get order table pointer mov e,m ; get low order address inx h mov d,m ; get high order address inx h shld nextl ; save updated table pointer lxi h,8 dad d call cklbr jnz entryl push d lxi h,lncnt mvi a,npl cmp m cnz crlf lxi h,lfmsep; print "library file members for : " mvi b,29 call typeit pop h push h mvi b,8 ; file name length call typeit mvi a,'.' ; period after fn call type mvi b,3 ; display 3 characters of filetype call typeit call crlf pop h ; ; saves the library file name into lbrfcb ; lda fcb lxi d,lbrfcb; to stax d inx d mvi b,11 ; len call move ; do the move xchg mvi b,25 ; clmfcb: ; mvi m,0 inx h dcr b jnz clmfcb call setldma lxi d,lbrfcb; point to file mvi c,open ; get function call cpm ; open it mvi c,read lxi d,lbrfcb call cpm call setfop lxi h,lbbuf mov a,m ora a jz ckldir ; check directory present? ; badlbr: ; lxi h,nlbrf mvi b,25 call typeit ; lmlexi: ; call lbclose jmp entryl ; nlbrf: ; db 'Not a library file!',cr,lf,'$' ; ; ; ; close the library file ; lbclose: ; lxi d,lbrfcb mvi c,close call cpm ret ; ; ; ; setldma - set the library file dma address ; setldma: ; lda newusr ; get user area for directory mov e,a mvi c,curusr; get the user function call cpm ; and set new user number lxi d,lbbuf mvi c,setdma call cpm ret ; ; ; ; ckldir - check to see if there indeed is a lbr file ; ckldir: ; mvi b,11 ; len of file name mvi a,' ' ; space inx h ; ckdlp: ; cmp m jnz badlbr dcr b inx h jnz ckdlp ; ; the first entry in the lbr directory is indeed blank. ; now see if the directory size is >0 ; mov e,m ; file starting location low inx h ; must be zero here mov a,m ; file starting location high ora e ; must be zero here also jnz badlbr inx h mov e,m ; get library size low inx h ; point to library size high mov d,m ; get library size high mov a,d ora e ; library must have some size jz badlbr dcx d xchg shld slfile lhld lbtotl inx h shld lbtotl mvi a,npl sta lncnt ; reset names per line counter mvi b,3 lxi h,17 dad d mvi a,npl sta lncnt ; reset names per line counter jmp lmtest ; lfmlop: ; lhld slfile ; get mov a,l ora h jz lmlexi dcx h shld slfile call setldma mvi c,read lxi d,lbrfcb call cpm call setfop mvi b,4 ; get file count per sector lxi h,lbbuf ; get buffer starting address ; lmtest: ; mov a,m ; get member open flag ora a ; test for open jz prmnam ; lmtesa: ; lxi d,32 ; member not open get offset dad d ; to next and add it in. dcr b ; is buffer empty ? jnz lmtest ; no so test next entry jmp lfmlop ; yes get next buffer. ; prmnam: ; push h ; print member name and size push b call ckabrt ; check for abort code from keyboard lxi h,lncnt mvi a,npl cpi 3 ; if printing less than 4 wide jz prmna1 lda lbrfcb ; precede new line with drive name adi 'A'-1 call type call typusr mvi a,':' ; tag header with a colon and a space call space ; and exit back to entry ; prmna1: ; pop b pop h push h push b inx h mvi b,8 ; file name length call typeit mvi a,'.' ; period after fn call type mvi b,3 ; display 3 characters of filetype call typeit inx h inx h mov e,m inx h mov d,m xchg ; ; if report size enabled, output the size of the individual file. ; call decprt ; go print it mvi a,'s' ; and follow with s size call type ; ; at least one more file to output, can we put it on the current line? ; lhld lmtotl inx h shld lmtotl lda lncnt dcr a sta lncnt push psw cnz space ; if room left, output the space character, pop psw pop b pop h jnz lmtesa ; and go output another file ; ; current line full, start a new one. ; mvi a,npl sta lncnt ; reset names per line counter call crlf ; space down to next line jmp lmtesa ; ; ; ; move characters from 'hl' to 'de' length in 'b' ; move: ; mov a,m ; get a char stax d ; store it inx h ; to next "from" inx d ; to next "to" dcr b ; more? jnz move ; yes, loop ret ; no, return ; ; ; ; test file extent for lbr ; cklbr: ; push h push d push b xchg lxi h,lbrtyp mvi c,3 ; cklbl: ; ldax d ani 7fh cmp m jnz cklbx inx h inx d dcr c jnz cklbl cklbx pop b pop d pop h ret ; ; ; printit: ; mov a,m call type inx h dcr b jnz printit ret ; ; ; ; routine to find and print character assignments of the function keys ; spfkey: ; lxi d,spfkhdg ; print heading call print mvi a,11 ; set up to accept 11 addresses lhld base+1 ; get address of top of function key table lxi d,07dh ; create offset to it dad d ; we now point to last address ; again: ; mov d,m ; move lsb into [D] dcx h mov e,m ; move msb into [E] dcx h push d ; stack for later dcr a jnz again ; get another key pop h ; save key 0 for last shld savaddr ; start addr for key 0 pop h shld savlength ; end addr for key 0 push h ; save start addr for next key ; newkey: ; pop h ; recover start address pop b ; recover next address mov a,c ; sub l ; determine length of command push b ; save next address for later sta lengthflag ; store length of command push h lda entryflag ; determine column of print cpi 0 ; jnz goprint ; if col 1, print it lda lengthflag ; if not compute adj length mov c,a mov b,a mov a,m ; countchr: ; cpi cr ; if the character is a cr jnz nocr ; add 3 to counter inr c ; because it will be printed inr c ; as instead of one inr c ; print position ; nocr: ; cpi 1bh ; if the character is a control jc countmor ; character add one for the print inr c ; position for the ^. ; countmor: ; inx h dcr b mov a,m jnz countchr mov a,c cpi lencol jc goprint mvi a,1 sta entryflag ; goprint: ; lxi h,adder inr m xchg call print lda lengthflag pop h ; printmor: ; mov e,m ; get a character to print push psw push h mvi a,cr ; if a cr then print cmp m jz crchar mvi a,1bh ; if not, is it a control cmp m ; character...if so print ^ in jnc prnctl ; front of it. mov a,e ; get original character call type ; if neither..just print it ; crretrn: ; pop h pop psw inx h dcr a jnz printmor ; test for end of command push psw lda entryflag cpi 0 ; then print cr/lf first jz lastentry mvi a,0 ; if not fix counter sta entryflag lda lengthflag cpi lencol ; check to see if its too long jnc lastentry ; if so then cr/lf call crlf ; print a cr/lf jmp nuprint ; lastentry: ; mvi a,1 ; fix column counter sta entryflag call crlf ; print a cr/lf ; nuprint: ; pop psw lxi h,flag1 ; get ready to see if mov a,m ; key 0 has been printed cpi 0 ; if so.... jz devs ; now figure out hardware devices lxi h,adder ; if not test for last key mov a,m cpi '9' ; if not key #9, then jnz newkey ; go back and get another lxi h,flag1 ; get ready to print key 0 dcr m ; so set flag1 so we'll know lxi h,adder ; also set key number mvi m,02fh ; so that when its incremented lhld savlength ; later it'll be a '0' push h ; then get the beg and end lhld savaddr ; addresses for key 0 push h ; and stack them.... jmp newkey ; now go back and print it. ; ; ; ; figure out and display status of hardware devices ; devs: ; lxi d,devasgn ; heading for device assignments call print lxi d,prntyp; heading for printer type call print lhld base+1 ; get bios warm boot address lxi d,063h ; add offset to get to 'iobite' content dad d mov a,m ; get printer type byte push h ; save the location cpi 040h ; serial printer? lxi d,serprnt cz print ; if so, tell'em its the serial printer cpi 080h ; parallel printer? lxi d,parprnt cz print ; if so, tell'em its the parallel printer cpi 0c0h ; IEEE-488 printer? lxi d,prnt488 cz print ; tell'em its the IEEE-488 printer ; lxi d,protcol ; heading for printer protocol call print pop h ; get the position inx h ; onward to the printer protocol... mov a,m ; get protocol type push h ; save the location cpi 0 ; hardware handshake? lxi d,hwdprnt cz print ; if so, tell'em hardware handshake cpi 1 ; qume with ETX/ACK? lxi d,etxack cz print ; if so, tell'em software ETX/ACK handshake cpi 2 ; diablo XON/XOFF? lxi d,xonxoff cz print ; tell'em software XON/XOFF handshake ; lxi d,autscrl ; heading for auto scroll type call print pop h ; get the position inx h ; onward to the auto scroll status mov a,m ; get auto scroll type push h ; save the location cpi 0 ; zero means auto scroll is off lxi d,ascrlof cz print ; if so, tell'em auto scroll is off cpi 0ffh ; all ones mean that auto scroll is on lxi d,ascrlon cz print ; if so, tell'em auto scroll is on ; lxi d,baud ; heading for baud rate call print pop h ; get the position inx h ; onward to the baud rate status mov a,m ; get baud rate type push h ; save the location cpi 055h ; 1200 baud? lxi d,b1200 cz print ; if so, tell'em 1200 baud cpi 056h ; 300 baud? lxi d,b300 cz print ; if not, tell'em 300 baud ; lxi d,scnsiz ; heading for screen size call print pop h ; get the position inx h ; onward to the screen size push h ; save position mov a,m ; get display screen size lxi h,0 ; force low byte display only mov l,a ; size into [L] to print decimal value of [HL] call decprt ; do decimal output ; lxi d,arrowkys ; heading for arrow keys type call print pop h ; get position lxi d,15h ; offset to arrow keys base pointer dad d ; add offset mov e,m ; get low byte address pointer to [E] inx h ; bump to high byte address pointer mov d,m ; get high byte address pointer to [D] xchg ; absolute address in [HL] points to arrow keys base mov a,m ; just get first key (will either be ^K or ^E) push psw ; save key cpi 'K'-40h ; cp/m arrow keys? lxi d,cpmkeys cz print ; if so, tell'em arrow keys are for cp/m pop psw ; get key cpi 'E'-40h ; wordstar arrow keys? lxi d,wskeys cz print ; if not cp/m arrow keys, it will be wordstar keys ; lda base+2 ; get high byte of bios base address cpi 0e5h ; 1.3 bios? jz noieeeadr ; if so, IEEE-488 so bypass printing of it lxi d,ieeeadr ; heading for IEEE-488 device address call print lhld base+1 ; get bios warm boot address lxi d,086h ; add offset to get to 'IEEE-488 device address' content dad d mov a,m ; get IEEE-488 device address lxi h,0 ; force low byte display only mov l,a ; size into [L] to print decimal value of [HL] call decprt ; do decimal output ; noieeeadr: ; lxi d,autcmd ; heading for auto-start command call print lhld base+1 ; get bios warm boot address mov a,h ; get high byte of bios base address cpi 0e5h ; 1.3 bios? lxi d,086h ; make offset to 'auto-start command' for 1.3 bios jz bios13 ; now test bios version, use offset in [DE] lxi d,099h ; make offset to 'auto-start command' for 1.4 bios ; bios13: ; dad d mov a,m ; get auto-start command type byte push h ; save the location cpi 0 ; ignore auto-start? lxi d,autst0 cz print ; if so, tell'em the system ignores auto-start cpi 1 ; auto-start on cold boot? lxi d,autst1 cz print ; if so, tell'em the system auto-starts on cold boot cpi 2 ; auto-start on warm boot? lxi d,autst2 cz print ; if so, tell'em the system auto-starts on warm boot cpi 3 ; auto-start on cold and warm boot? lxi d,autst3 cz print ; if so, tell'em the system auto-starts on either boot ; lxi d,autfile ; heading for auto-start filename display call print pop h ; get the position inx h ; onward to the auto-start filename display... mov b,m ; get filename length inx h ; point to auto-start filename ; prnname: ; mov a,m ; get character from auto-start filename call type ; type it inx h ; bump pointer in filename dcr b ; one less character to display jnz prnname ; print until all characters exhausted ; ; figure out and display addresses of the cp/m system bios, bdos, ccp, tpa ; lxi d,prnsys ; print cp/m system addresses heading call print lxi d,prnbios ; print bios heading call print lda base+2 call prnhex lxi d,prn00 ; print low byte address as '00' call print ; lxi d,prnbdos ; print bdos heading call print lda bdos+2 call prnhex lxi d,prn00 ; print low byte address as '00' call print ; lxi d,prnccp ; print ccp heading call print lda bdos+2 sui 008h call prnhex lxi d,prn00 ; print low byte address as '00' call print ; lxi d,prntpao ; print tpa overlay heading call print lda bdos+2 sui 1 call prnhex lxi d,prn00 ; print low byte address as '00' call print ; lxi d,prntpai ; print tpa intact heading call print lda bdos+2 sui 9 call prnhex lxi d,prn00 ; print low byte address as '00' call print ; ; formfeed if printer option ; lda popflg ; get printer option flag ora a ; set flags mvi e,ff ; make formfeed mvi c,prnchr; print character cz cpm ; do it if flag zero ; ; we've finished all of our outputting. flush the remainder of the ; output buffer and close the file before going to exit routine. ; lxi h,opnflg; get file open status then reset flag to mov a,m ; force reopen on next pass mvi m,0 ora a jz endinfo ; skip closing OSZ-INFO.DIR if it wasn't opened lxi h,bufcnt mov a,m ; retrieve number of unflushed characters in buffer mvi m,128 ; force bufcnt to empty status for next drive ora a ; if bufcnt=128, buffer empty so set sign bit jm cloze ; close OSZ-INFO.DIR if buffer is empty jz flush ; write last record to OSZ-INFO.DIR if buffer full lhld bufpnt ; otherwise, pad unused buffer with CTRL-Zs ; putagn: ; mvi m,'Z'-40h inx h dcr a jnz putagn ; continue padding til buffer filled out ; flush: ; lxi d,outfcb; flush the last output buffer mvi c,write call cpm ora a jnz wrterr ; cloze: ; lxi d,outfcb; close the output file mvi c,close call cpm ; endinfo: ; jmp exit1 ; exit, all done ; ; ; ; subroutine to print byte in [A] in hexadecimal ; prnhex: ; push psw rlc rlc rlc rlc call prnhex1 pop psw ; prnhex1: ; ani 00fh cpi 10 jnc alpha adi '0' call type ret ; alpha: ; adi '7' call type ret ; ; ; ; subroutine to print a control character when it's needed ; prnctl: ; push h mvi a,'^' call type pop h mov a,m adi 40h call type lxi h,lengthflag inr m jmp crretrn ; ; ; ; subroutine to print when carriage return is encountered ; crchar: ; lxi d,crsymb call print lxi h,lengthflag inr m inr m inr m jmp crretrn ; ; ; crsymb: ; db ''+80h ; dirhdg: ; db cr,lf,' Disk Directory',cr,lf+80h ; spfkhdg: ; db cr,lf,' Special Function Keys',cr,lf,lf+80h ; devasgn: ; db cr,lf,' Device Asignments',cr,lf+80h ; prnsys: ; db cr,lf,lf,' CP/M System Addresses',cr,lf+80h ; prntyp: ; db cr,lf,'Printer type is',' '+80h ; protcol: ; db cr,lf,'Printer protocol is',' '+80h ; autscrl: ; db cr,lf,'Auto-scroll is',' '+80h ; baud: ; db cr,lf,'Baud rate is',' '+80h ; scnsiz: ; db cr,lf,'Display screen size is',' '+80h ; arrowkys: ; db cr,lf,'Arrow keys are for',' '+80h ; cpmkeys: ; db 'CP/','M'+80h ; wskeys: ; db 'WordSta','r'+80h ; ieeeadr: ; db cr,lf,'IEEE-488 device address is',' '+80h ; autcmd: ; db cr,lf,'Auto-start command is',' '+80h ; autfile: ; db cr,lf,'Auto-start filename is',' '+80h ; serprnt: ; db 'RS-232 Seria','l'+80h ; parprnt: ; db 'Centronics Paralle','l'+80h ; prnt488: ; db 'IEE-488 Paralle','l'+80h ; hwdprnt: ; db 'Hardware RTS/DS','R'+80h ; etxack: ; db 'Software ETX/AC','K'+80h ; xonxoff: ; db 'Software XON/XOF','F'+80h ; ascrlon: ; db 'O','n'+80h ; ascrlof: ; db 'Of','f'+80h ; b1200: ; db '120','0'+80h ; b300: ; db '300',cr,lf+80h ; autst0: ; db '"Ignore auto-start','"'+80h ; autst1: ; db '"Auto-start on Cold Boot','"'+80h ; autst2: ; db '"Auto-start on Warm Boot','"'+80h ; autst3: ; db '"Auto-start on Cold and Warm Boot','"'+80h ; prn00: ; db '0','0'+80h ; prnbios: ; db cr,lf,'The address of the system BIOS is',' '+80h ; prnbdos: ; db cr,lf,'The address of the system BDOS is',' '+80h ; prnccp: ; db cr,lf,'The address of the system CCP is',' '+80h ; prntpao: ; db cr,lf,'Total TPA space with CCP overlay is',' '+80h ; prntpai: ; db cr,lf,'Total TPA space with CCP intact is',' '+80h ; savaddr: ; ds 2 ; savlength: ; ds 2 ; lengthflag: ; db 0 ; entryflag: ; db 1 ; flag1: ; db 1 ; adder: ; db 30h,' =',' '+80h ; lfmsep: ; db cr,lf,'Library file members for : ' ; lbrtyp: ; db 'LBR' ; dremsg: ; db 'Dis','k'+80h ; ; eosmsg: ; db bel,esc,')' db ' Press any key to continue:' db esc,'(',cr,'$' ; eraline: ; db esc,'T$' ; errmsg: ; db 'Error -','>'+80h ; nofms1: ; db cr,lf,'No file on ' ; nofms2: ; db ' ',' '+80h ; totms1: ; db cr,lf,'Disk',' '+80h ; totms2: ; db ', User',' '+80h ; totms3: ; db ' -',' '+80h ; totms4: ; db 'K in',' '+80h ; totms5: ; db ' files -',' '+80h ; totms6: ; db 'K free','.',cr,lf+80h ; usrmsg: ; db bel,'User number is out of range','!'+80h ; contm: ; db cr,lf,'There are',' '+80h ; mfiles: ; db ' member files in',' '+80h ; libr: db ' library(s)','.'+80h ; fndflg: ; db 0 ; flag whether any files matched ; lincnt: ; db 0 ; count of lines printed on screen ; ; drive code/user area lookup table ; lodrv equ $ ; mark beginning of drive/user table ; db 15 ; maximum user area for drive a (0-15) db 15 ; " " " " " b (0-15) ; hidrv equ $ ; mark end of drive/user table ; ; ; ; option field lookup table. ; otbl equ $ ; mark start of option table ; aopflg: ; db 'A' ; display all user directories ; dopflg: ; db 'D' ; multiple-disk directory search ; fopflg: ; db 'F' ; write file OSZ-INFO.DIR ; lopflg: ; db 'L' ; do not print library files or members ; nopflg: ; db 'N' ; no pause on page display ; popflg: ; db 'P' ; printer and console output option ; ropflg: ; db 'R' ; disk reset option ; sopflg: ; db 'S' ; display system files option ; oend equ $ ; mark end of option table ; ; end of option lookup table ; vectbl: ; dw dskerr ; bdos sector error intercept vector dw dskerr ; bdos select error intercept vector ; bufpnt: ; dw outbuf ; pointer to next location in output buffer ; bufcnt: ; db 128 ; number of bytes left in output buffer ; opnflg: ; db 0 ; file open flag for all user file output ; outfcb: ; db 0,'OSZ-INFODIR',0 db 0,0,0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0,0,0 ; outbuf: ds 128 ; output file buffer ; ; ; ; uninitialized data area ; basusr: ; ds 1 ; dupe of original directory user number to search ; blkmax: ; ds 2 ; highest block number on drive ; blkmsk: ; ds 1 ; sec/blk - 1 ; blkshf: ; ds 1 ; number shifts to mult by sec/blk ; count: ; ds 2 ; entry count ; dirmax: ; ds 2 ; highest file number in directory ; freeby: ; ds 2 ; contains number of k left on directory drive ; gap: ; ds 2 ; sort routine storage ; i: ; ds 2 ; sort routine storage ; j: ; ds 2 ; sort routine storage ; jg: ; ds 2 ; sort routine storage ; lzflg: ; ds 1 ; 0 when printing leading zeros ; maxusr: ; ds 1 ; maximum user number for drive from lookup table ; newusr: ; ds 1 ; contains user number selected by "$u" option ; nextt: ; ds 2 ; next table entry ; olddsk: ; ds 1 ; holder for currently logged-in drive ; oldusr: ; ds 1 ; contains user number upon invocation ; scount: ; ds 2 ; number to sort ; supspc: ; ds 1 ; leading space flag for decimal routine ; tbloc: ; ds 2 ; pointer to start of name table ; totfil: ; ds 2 ; total number of files ; totsiz: ; ds 2 ; total size of all files ; lmtotl: ; dw 0 ; lbtotl: ; dw 0 ; lncnt: ; db 0 ; lcount: ; dw 0 ; nextl: ; dw 0 ; slfile: ; dw 0 ; lbrfcb: ; ds 36 ; lbbuf: ; ds 80h ; ds 60 ; stack area ; stack: ; ds 2 ; save old stack pointer here ; order equ $ ; order table starts here ; ; ; end start