; PROGRAM: VFILER ; VERSION: 3.0 ; DATE: 26 June 84 ; AUTHOR: Richard Conn ; PREVIOUS VERSIONS: 2.0 (18 Sep 83), 1.8 (17 Sep 83) ; PREVIOUS VERSIONS: 1.7 (9 Sep 83), 1.6 (18 Aug 83), 1.5 (20 July 83) ; PREVIOUS VERSIONS: 1.4 (19 July 83), 1.3 (18 July 83) ; PREVIOUS VERSIONS: 1.2 (18 July 83), 1.1 (17 July 83), 1.0 (16 July 83) ; DERIVATION: From FILER (Version 1.6) by Richard Conn ; FILER from DISK7, Version 7.6C, by Frank Gaude' ; z3env equ 0f400h VERS EQU 30 ;version number ; VFILER is copyright (c) 1983, 1984 by Richard Conn ; All Rights Reserved ; VFILER may be used freely by the ZCPR3 Community ; VFILER is a screen-oriented, ZCPR3-specific file utility. It can not be ; installed to run under conventional CP/M. VFILER ; extensively employs cursor addressing to position a pointer on the ; screen, allow the user to manipulate the pointer (up, down, right, left, ; next screen, previous screen, GOTO file). The pointer points to files ; in the current user directory and displays the user's position dynamically ; on the screen. Once pointing to a file, user commands can be used to ; manipulate the file (delete, copy, view on console, print on printer, tag ; for later copy or delete, and untag). In the way of being ZCPR3-specific, ; VFILER can chain to external programs via the MCL and then return (ala ; MENU), and it recognizes Named Directories (so the user can log into B:, B4:, ; and MYDIR:, for example). ; VFILER is installed by Z3INS. ; VFILER works with ZCPR3 only, with 32k or more of RAM. File copy ; functions are faster with large amounts of RAM. ; VFILER can be assembled for use with a Z80 or 8080 microprocessor. ; ; SYSLIB, Z3LIB, and VLIB References ; ext z3vinit,cls,gotoxy,ereol,envptr,getcrt,getprt,vprint ext z3log,retud ext fi0$open,f0$get,dutdir ext sksp,putcl,getmdisk ext cin,cout,caps,lout,crlf,lcrlf,pafdc,phlfdc ext pfind,dnscan ext getsh,getcl1,qshell,shpush,getzrun,putzex,putcst ext getefcb,shpop,getsh2,getfn2,getshm,putshm ext codend ; ; Basic Definitions ; TRUE EQU 0FFH ;define true and.. FALSE EQU 0 ;..false. ; DIM EQU 1 ;GOTO DIM BRIGHT EQU 2 ;GOTO BRIGHT ; ; User-Customized Definition ; VFNAME MACRO ;;Name of VFILER DB 'VFILER' ENDM VFNFILL MACRO ;;Spaces to fill out name to 8 chars DB ' ' ENDM ; Z80 EQU TRUE ;TRUE to use Z80 Instructions BIHELP EQU TRUE ;TRUE to provide built-in help info WARMBOOT EQU FALSE ;set TRUE to warmboot on exit DEFALPHA EQU TRUE ;set TRUE to alpha by name and type, FALSE for ; ... type and name by default EPS EQU 18*4 ;N lines x 4 cols per screen ; EPS = Entries Per Screen TAGCH EQU 't' ;character used to mark tagged files ; ; Command Line Builder Constants ; FPESC EQU '%' ;escape char FPDISK EQU 'D' ;disk only (D) FPUSER EQU 'U' ;user only (U) FPFILE EQU 'F' ;file name only MNOTE EQU '#' ;denotes comment area in macro file UIN1 EQU 27H ;single quote for user input UIN2 EQU 22H ;double quote for user input ; ; Cursor Positioning Addresses ; EPSLINE EQU (EPS/4)+4 ;position of last line of EPS BANADR EQU 1*256+24 ;banner address CURHOME EQU 3*256+1 ;home address of cursor BOTADR EQU 24*256+1 ;bottom of screen CPMADR EQU EPSLINE*256+1 ;command prompt message CPADR EQU EPSLINE*256+22 ;command prompt ERADR EQU (EPSLINE+1)*256+15 ;error message FSADR EQU ERADR ;file size message FNADR EQU 1*256+62 ;address of current file name DUADR EQU 1*256+4 ;address of current DU ; ; System Functions ; RDCON EQU 1 WRCON EQU 2 PUNCH EQU 4 LIST EQU 5 DIRCON EQU 6 RDBUF EQU 10 CONST EQU 11 RESETDK EQU 13 LOGIN EQU 14 OPEN EQU 15 CLOSE EQU 16 SRCHF EQU 17 SRCHN EQU 18 ERASE EQU 19 READ EQU 20 WRITE EQU 21 MAKE EQU 22 REN EQU 23 INQDISK EQU 25 SETDMA EQU 26 INQALC EQU 27 ATTR EQU 30 GETPARM EQU 31 SGUSER EQU 32 COMPSZ EQU 35 ; ; System Addresses ; OS$BASE EQU 000H ;system base.. CCP EQU 800H ;..and 'ccp' length in bytes. GET EQU 0FFH ;get user area e-reg value BDOS EQU OS$BASE+05H FCB EQU OS$BASE+5CH FCBEXT EQU FCB+12 FCBRNO EQU FCB+32 FCB2 EQU OS$BASE+6CH TBUF EQU OS$BASE+80H TPA EQU OS$BASE+100H ; ; ASCII Definitions ; CTRLC EQU 'C'-'@' ;..control-C.. CTRLD EQU 'D'-'@' CTRLE EQU 'E'-'@' CTRLR EQU 'R'-'@' CTRLS EQU 'S'-'@' ;..XOFF.. CTRLX EQU 'X'-'@' BS EQU 08H ;..backspace.. TAB EQU 09H ;..tab.. LF EQU 0AH ;..linefeed.. FF EQU 0CH ;..formfeed.. CR EQU 0DH ;..carriage return.. CAN EQU 18H ;..cancel.. EOFCHAR EQU 1AH ;..end-of-file.. CTRLZ EQU 1AH ;..clear screen.. ESC EQU 1BH ;..and escape character. ; ; MACROS TO PROVIDE Z80 EXTENSIONS ; MACROS INCLUDE: ; ; BR - JUMP RELATIVE ; BRC - JUMP RELATIVE IF CARRY ; BRNC - JUMP RELATIVE IF NO CARRY ; BRZ - JUMP RELATIVE IF ZERO ; BRNZ - JUMP RELATIVE IF NO ZERO ; BJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO ; BR MACRO ?N ;;JUMP RELATIVE IF Z80 .z80 jr ?N .8080 ELSE jmp ?N ENDIF ENDM ; BRC MACRO ?N ;;JUMP RELATIVE ON CARRY IF Z80 .z80 jr c,?N .8080 ELSE jc ?N ENDIF ENDM ; BRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY IF Z80 .z80 jr nc,?N .8080 ELSE jnc ?N ENDIF ENDM ; BRZ MACRO ?N ;;JUMP RELATIVE ON ZERO IF Z80 .z80 jr z,?N .8080 ELSE jz ?N ENDIF ENDM ; BRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO IF Z80 .z80 jr nz,?N .8080 ELSE jnz ?N ENDIF ENDM ; BJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO IF Z80 .z80 djnz ?N .8080 ELSE dcr b jnz ?N ENDIF ENDM ; ; END OF Z80 MACRO EXTENSIONS ; ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; Once Environment is Initialized, One of Three Major Functions ; will be Performed: ; 1. VFILER will be installed as a Shell if invoked explicitly ; by user command ; 2. The VFILER Function will be performed if VFILER is invoked ; by ZCPR3 as a Shell and ZEX is not Running ; 3. A Command Line will be Input by VFILER from ZEX and Passed ; on to ZCPR3 without Processing ; call z3vinit ;initialize the ZCPR3 Env and the VLIB Env ; ; Set Opsys Stack Pointer ; if not WARMBOOT lxi h,0 ;clear hl-pair then.. dad sp ;..add stack address. shld stack endif ;not warmboot ; ; Check to see if VFILER was executed as a shell ; call qshell ;get and test message from ZCPR3 jz runsh ;execute shell procedures ; ; Initialize VFILER as a Shell ; call shtest1 ;there must be a shell stack call shtest2 ;there must be a command line buffer ; ; FUNCTION 1: Set Up VFILER as a Shell ; Run Shell Via Exit to Opsys ; call getefcb ;determine name of program brz shgo1 ;name not given, so use default inx h ;pt to name lxi d,filercmd ;define name of program mvi b,8 call moveb ;copy name shgo1: call idu ;set initial disk/user lxi h,filercmd ;establish shell call shpush ;push onto shell stack brnz shgo2 ;error? ; ; Establish File Selection ; call getfn2 ;setup file name lxi d,11*3 ;use 4th system file dad d lxi d,fcb+1 ;pt to FCB xchg mvi b,11 ;copy 11 chars call moveb lxi h,joker ;make wild if FCB is empty mvi b,11 ;11 chars ldax d ;check first char cpi ' ' cz moveb ; ; Print Done Message ; call vprint db ' Shell Installed',0 mvi b,0 ;shell message 0 mvi a,0 ;no wait call putshm ;set shell message jmp chain2 ;set IDU into command line and go ; ; Error in Shell Stack Installation ; shgo2: cpi 2 ;shell stack full brnz shgo3 call vprint db ' Shell Stack Full',0 ret shgo3: call vprint db ' Shell Entry Size',0 ret ; ; VFILER was invoked as a Shell ; Check for ZEX Input in Progress ; runsh: call getzrun ;check ZEX message byte jnz zexrun ;process ZEX command line if ZEX running ; ; FUNCTION 2: Run VFILER and Perform Main Function ; mvi a,0 ;set no shell message call putcst call setup ;init buffers and pointers call stackset ;setup stack ; ; Process Initial Help if Available and Requested ; if BIHELP ;built-in help available? lda fcb+1 ;check for initial help cpi '/' brnz runsh1 call helpmsg ;print help message call sak ;strike any key to continue br runsh2 runsh1: endif ;BIHELP ; ; Check for Delay Before Resuming VFILER and Delay if Set ; mvi b,0 call getshm ;get shell message 0 ani 80h ;check MSB cnz sak ;pause for input ; ; Begin VFILER Processing ; runsh2: call stackset ;reset stack call fload ;load files push psw call setscr ;set up screen display variables pop psw brnz runsh4 ;continue if OK ; ; Entry Point to Log Into New Dir and Resume ; runsh3: call logdir ;error - log into another dir br runsh2 ; ; Entry Point for Command Processing ; Display Screen and Input/Process Command ; runsh4: call stackset ;reset stack call refresh ;refresh screen display ; ; Display Current File and Input/Process Command ; loopfn: call loopfn1 ;print current file name ; ; Input/Process Command ; loop: call stackset ;reset stack call loopfn2 ;get command from user call loopfn3 ;process command in A br loop ;continue ; ; Set Stack Pointer ; stackset: pop d ;get return address lhld crctbl ;top of stack sphl ;start local stack push d ;return address on new stack ret ; ; Check for Presence of Shell Stack ; shtest1: call getsh ;get shell stack data rnz pop psw ;clear stack call vprint db 'No Shell Stack',0 ret ; ; Check for Command Line ; shtest2: call getcl1 ;get command line data rnz pop psw ;clear stack call vprint db 'No Cmd Line',0 ret ; ; FUNCTION 3: Run ZEX on Top of VFILER ; Accept Command Line and Pass it to ZCPR3 ; zexrun: call vprint ;print prompt db 'VFILER> ',0 mvi a,1 ;tell ZEX that it is prompted call putzex call getcl1 ;pt to command line buffer mov a,l ;set ptr to first char adi 4 mov c,a mov a,h aci 0 mov b,a ;BC pts to first char mov m,c ;store low inx h mov m,b ;store high inx h ;pt to char count xchg ;... in DE mvi c,rdbuf ;input line via BDOS push d ;save ptr call bdos pop h ;pt to char count inx h mov e,m ;get char count inx h ;pt to first char push h ;save ptr mvi d,0 ;DE=char count dad d xra a ;A=0 mov m,a ;store ending 0 pop h ;pt to first char call putzex ;resume ZEX (A=0) call putcst ;set command status to normal (A=0) ret ;return to opsys ; ;************************************************** ; ; CRT Routine for VFILER ; VCLS: CALL CLS ;try to clear the screen RNZ ;OK if done PUSH H ;save regs PUSH B CALL GETCRT ;get CRT Data INX H ;get number of lines on screen MOV B,M ;B=number of lines VCLS1: CALL CRLF ;new line BJNZ VCLS1 POP B ;restore regs POP H RET ; ; EREOL Routine for VFILER ; VEREOL: CALL EREOL ;try to erase to EOL RNZ ;OK if done PUSH B ;save count MVI A,' ' ;space out CALL VEREOL1 ;send B spaces POP B ;get count MVI A,BS ;backspace in VEREOL1: CALL COUT ;send char BJNZ VEREOL1 ;count down RET ; ; Setup Screen Display Variables ; SETSCR: LXI H,CURHOME ;set cursor home SHLD CURAT LHLD RING ;set ring position ; ; Entry to Reset Ring Position at HL ; SETSCR1: SHLD RINGPOS ; ; Entry to Reset Local Ring Position at HL ; SETSCR2: SHLD LOCBEG ;front of ring LXI D,EPS*13 ;new end? DAD D XCHG LHLD RINGEND ;end of ring XCHG CALL CMPDEHL BRC SETSCR3 XCHG SETSCR3: XCHG SHLD LOCEND RET ; ; Display file name of current file ; LOOPFN1: LXI H,FNADR ;position cursor for file name print CALL GOTOXY LHLD RINGPOS ;pt to current file name INX H ;pt to first char JMP PRFN ;print file name ; ; Get command from user and clear error line if any ; LOOPFN2: CALL ATCMD ;position at command prompt CALL DKEYIN ;wait for character from keyboard PUSH PSW ;save command LDA ERMFLG ;error message? ORA A ;0=no CNZ ERCLR ;erase old error message POP PSW ;get command RET ; ; Process Command ; LOOPFN3: CPI MNOTE ;command summary BRZ CPROCM CPI '0' ;macro? BRC CPROC0 CPI '9'+1 ;macro? BRNC CPROC0 CPROCM: CALL CMACRO ;process macro command MOV B,A ;save command CALL ERMSG DB 'No U Fct ',0 MOV A,B ;get macro digit JMP COUT ;return for loop processing CPROC0: CALL CTPROC ;process command or return if not found CALL ERMSG DB 'Invld Cmd: ',0 MOV A,B ;get char CPI ' ' ;expand if less than space BRNC CPROC1 MVI A,'^' ;control CALL COUT MOV A,B ;get byte ADI '@' ;convert to letter CPROC1: JMP COUT ;return for loop processing ; ; SET UP BUFFERS ; SETUP: CALL RETUD ;get home DU MOV A,B STA H$DR ;home drive MOV A,C STA H$U$A ;home user area CALL CODEND ;start of free space LXI D,100H ;256 bytes/unit DAD D SHLD CRCTBL ;table for CRC list et al DAD D DAD D ;allow 512 bytes SHLD CMDBUF ;command line buffer MVI M,64 ;64 bytes in line LXI D,70 ;arbitrary beyond EOL DAD D SHLD DUM$FCB ;dummy FCB INR H MVI L,0 ;next page SHLD BUFENTRY ;free space to end of TPA ; ; Set CRT/Printer Data ; CALL GETCRT ;CRT DATA MOV A,M STA CWIDTH ;WIDTH INX H MOV B,M INX H MOV A,M STA CTPP ;TEXT MOV C,A MOV A,B ;TOTAL NUMBER OF LINES SUB C DCR A ;1 LESS STA CSPP ;LINES TO SKIP CALL GETPRT ;PRINTER DATA MOV A,M STA LWIDTH ;WIDTH INX H MOV B,M INX H MOV A,M STA LTPP ;TEXT MOV C,A MOV A,B ;TOTAL NUMBER OF LINES SUB C STA LSPP ;LINES TO SKIP INX H MOV A,M STA LFFEED ;CAN FORM FEED? ; ; Begin Further Inits ; XRA A STA HELPDISP ;no help display yet ; MVI A,DEFALPHA ;alpha by name and type STA ALPHA ; LHLD ENVPTR ;pt to ZCPR3 Env Desc LXI D,80H+10H ;pt to cursor commands DAD D LXI D,CTABLE ;pt to area MVI B,4 ;4 commands CURINIT: MOV A,M ;get command STAX D ;put it INX H ;pt to next INX D INX D INX D BJNZ CURINIT ; CALL IDU ;set initial disk/user CALL LOGRDU ;log into it ; LHLD BUFENTRY ;base address SHLD RING ;beginning of ring ; LXI H,CURHOME ;home address for cursor SHLD CURAT ; CALL GETMDISK ;get max disk number (1-N) ADI '@' ;convert to ASCII (A-P) STA MAXDR ;set letter ; RET ; set initial disk/user IDU: LXI D,FCB ;log into DU specification CALL Z3LOG ;perform login IDU1: CALL RETUD ;get current DU in BC MOV A,C ;get current user CALL IDU$USET ;set it MOV A,B ;get current disk CALL IDU$DSET ;set it RET IDU$USET: STA C$U$A ;..store as current and.. STA O$USR ;..as original for exit. STA R$U$A ;..requested user area RET IDU$DSET: STA C$DR STA R$DR ;requested disk RET ; check for existance of file whose first 12 FCB bytes are pted to by DE ; return with A=0 if not found, A=0FFH if found FILECHK: LXI H,S$FCB ;copy into FCB XCHG MVI B,12 ;12 bytes CALL MOVE ;copied into S$FCB XCHG ;HL pts to FCB CALL INITFCB ;init FCB LXI D,S$FCB ;pt to FCB JMP FFIND ; ; Select drive and user area (system reset for disk change on-the-fly) ; LOGDIR: CALL CPRMPT ;prompt to get drive/user selection DB 'Login DIR (X to Exit): ',0 CALL DEF$D$U LOG1: CALL LOGRDU ;set current and log in JMP CRLF ;new line and exit ; ; Actually log into DU requested ; LOGRDU: LDA R$DR ;make requested disk current STA C$DR CALL RESET ;reset disk system LDA R$U$A ;establish requested area.. STA C$U$A ;..as current area. CALL SET$USR LXI H,0 ;initialize tagged.. SHLD TAG$TOT ;..file size accumulator. RET ; ; Define current drive and user area with full error trapping. ; (Check validity of user area entry first, then drive validity, then proceed) ; DEF$D$U: LHLD CMDBUF ;pt to command line buffer INX H INX H MVI B,20 ; # of blanks to.. CALL FILL ;..clear 'cmdbuf'. LHLD CMDBUF ;get DU selection from.. XCHG MVI C,RDBUF ;..console buffer read. CALL BDOS CALL CONVERT ;make sure alpha is upper case LHLD CMDBUF ;pt to possible drive INX H INX H CALL SKSP ;skip over leading spaces MOV A,M ;check for no input ORA A JZ LOOP MOV A,M ;check for exit CALL CAPS CPI 'X' BRNZ DEFDU1 INX H ;check for space or EOL MOV A,M DCX H ANI 7FH ;mask MSB CPI ' '+1 JC OS$CCP ;abort DEFDU1: CALL DNSCAN ;look for DU or DIR form and return DU BRZ ERRET ;error MOV A,B ;return disk and user STA R$DR INR A ;set FCB STA FCB MOV A,C STA R$U$A RET ; ; Error return and recovery from command cancellation ; ERRET: CALL ERMSG DB 'DIR Entry Error',0 JMP LOOP COMCAN: LDA CANFLG ;check for nature of abort ORA A ;..from.. JZ RUNSH2 ;no file found, so run the shell again JMP RUNSH4 ;..error/command abort. ; ; find file along path (file FCB pted to by DE) ; on return, A=0FFH if found, A=0 if not found, and flags set ; FFIND: MVI A,0FFH ;look in current dir also JMP PFIND ;path search from Z3LIB ; log in default directory DLOGIN: LDA C$DR ;disk in B MOV B,A LDA C$U$A ;user in C MOV C,A ;fall thru to SLOGIN ; log in DU in BC SLOGIN: PUSH H ;save regs PUSH D PUSH B MOV A,C ;set user CALL SET$USR POP B MOV A,B ;set disk CALL SET$DR POP D ;restore regs POP H RET ; e x i t ; return to ccp ; ; Entry point for VFILER exit ; OS$CCP: CALL SHPOP ;clear shell stack ; ; Entry point for command line exec ; OS$CCP1: LDA O$USR ;get and set original.. CALL SET$USR ;..user area and.. LXI D,TBUF ;..tidy up.. MVI C,SETDMA ;..before going home. CALL BDOS IF WARMBOOT JMP OS$BASE ENDIF ;warmboot IF NOT WARMBOOT LHLD STACK ;put pointer.. SPHL ;..back to 'sp'. RET ;return to ccp ENDIF ;not warmboot ; ; FLOAD loads the files into the buffer, setting up the ring ; Return with NZ if load OK, Z if no files loaded ; FLOAD: CALL FRESTOR ;get bytes remaining on drive (decode default) ; ; Set up file name from System File 4 ; Select all files if no entry in System File 4 ; CALL GETFN2 ;pt to first system file name LXI D,11*3 ;pt to 4th file name DAD D LXI D,FCB+1 ;pt to FCB MVI B,11 ;11 bytes CALL MOVEB LXI H,JOKER ;..treat as '*.*' with 'joker'.. MVI B,11 ; # of characters to move LDAX D ;get first char of file name CPI ' ' ;if space, fill with *.* CZ MOVEB ;set field to *.* LDAX D ;get first char of file name CPI '/' ;if opt, fill with *.* CZ MOVEB ; ; Build ring with filename positioned in default FCB area ; MVI C,SETDMA ;initialize dma address.. LXI D,TBUF ;..to default buffer. CALL BDOS XRA A ;clear search 'fcb'.. STA FCBEXT ;extent byte.. STA FCBRNO ;..and record number. LXI D,FCB ;default FCB for search CMA STA CANFLG ;make cancel flag true MVI C,SRCHF ;..of first occurrence. CALL BDOS INR A ; 0ffh --> 00h if no file found BRNZ SETRING ;if found, branch and build ring. STA CANFLG ;make log-cancel toggle false (0) CALL ERMSG ;else say none found, fall thru to log. DB 'No File Found',0 XRA A ;Set Error Code RET ; establish ring (circular list) of filenames SETRING: LHLD RING ;initialize ring pointer SHLD RINGPOS ;start --> current position of ring ; put each found name in ring. a-reg --> offset into 'tbuf' name storage TO$RING: DCR A ;un-do 'inr' from above and below ADD A ;times 32 --> position index ADD A ADD A ADD A ADD A ADI TBUF ;add page offset and.. MOV L,A ;..put address into.. MVI H,0 ;..hl-pair. LDA FCB ;get drive/user designator and.. MOV M,A ;..put into 'fcb' buffer. XCHG LHLD RINGPOS ;pointer to current load point in ring XCHG MVI B,12 ;move drive designator and name to ring CALL MOVE XCHG ;de-pair contains next load point address MVI M,' ' ;space for potential.. INX H ;..tagging of files for mass copy. SHLD RINGPOS ;store and search.. MVI C,SRCHN ;..for next occurrence. LXI D,FCB ;filename address field CALL BDOS INR A ;if all done, 0ffh --> 00h. BRNZ TO$RING ;if not, put next name into ring. ; ; All filenames in ring -- setup ring size and copy-buffer start point ; LHLD RINGPOS ;next load point of ring is start of buffer SHLD RINGEND ;set ring end.. SHLD BUFSTART ;..and copy-buffer start. PUSH H LHLD RING LXI D,13 ;compare 'ringend' (tab base+13) DAD D XCHG POP H CALL CMPDEHL BRNZ SORT ;sort if more than one file in ring XRA A ;set NZ for Return DCR A RET ; ; Sort ring of filenames ; SORT: LHLD RING ;initialize 'i' sort variable and.. SHLD RINGI LXI D,13 ;..also 'j' variable. DAD D SHLD RINGJ SORTLP: LHLD RINGJ ;compare names 'i & j' XCHG LHLD RINGI PUSH H ;save position pointers.. PUSH D ;..for potential swap. LDA ALPHA ;check for type of alphabetization ORA A ;if Zero, alpha by type and name JZ SORTTN ; sort by file name and type MVI B,12 ; # of characters to compare CALL CMPSTR ;do comparison BR NOCMP ;final test ; sort by file type and name SORTTN: PUSH H ;save ptrs PUSH D LXI B,9 ;pt to type DAD B XCHG DAD B XCHG MVI B,3 ;3 chars in file type CALL CMPSTR ;compare type POP D ;get ptrs POP H BRNZ NOCMP ;final test PUSH H PUSH D MVI B,8 ;8 chars in file name INX H ;pt to first INX D CALL CMPSTR ;compare name POP D ;get ptrs POP H BRNZ NOCMP ;final test LDAX D ;final compare and fall thru CMP M ; final test for swapping purposes NOCMP: POP D POP H MVI B,13 BRNC NOSWAP ; ; Swap if 'j' string larger than 'i' ; SWAP: MOV C,M ;get character from one string.. LDAX D ;..and one from other string. MOV M,A ;second into first MOV A,C ;first into second STAX D INX H ;bump swap pointers INX D BJNZ SWAP NOSWAP: LHLD RINGJ ;increment 'j' pointer LXI D,13 DAD D SHLD RINGJ XCHG ;see if end of 'j' loop LHLD RINGEND CALL CMPDEHL JNZ SORTLP ;no, so more 'j' looping. LHLD RINGI ;bump 'i' pointer LXI D,13 DAD D SHLD RINGI DAD D ;set start over 'j' pointer SHLD RINGJ XCHG ;see if end of 'i' loop LHLD RINGEND CALL CMPDEHL JNZ SORTLP ;must be more 'i' loop to do ; ; Sort done -- initialize tables for fast crc calculations ; CALL INITCRC ; ; Calculate buffer maximum available record capacity ; B$SIZE: LXI B,0 ;count records LHLD BDOS+1 ;get 'bdos' entry (fbase) IF NOT WARMBOOT LXI D,-(CCP) DAD D ENDIF ;not warmboot DCX H XCHG ;de-pair --> highest address of buffer LHLD BUFSTART ;start address of buffer (end of ring list) B$SIZE2: INX B ;increase record count by one PUSH D LXI D,128 ; 128-byte record DAD D ;buffer address + record size POP D CALL CMPDEHL ;compare for all done BRNC B$SIZE2 ;more will fit? DCX B ;set maximum record count less one MOV A,B ;memory available for copy? ORA C BRNZ B$SIZE3 ;yes, buffer memory space available. CALL ERMSG DB 'No Room',0 XRA A ;Error code RET B$SIZE3: MOV L,C ;store.. MOV H,B ;..maximum.. SHLD REC$MAX ;..record count. XRA A ;return NZ for OK DCR A RET ; ; left to right compare of two strings (de-pair points to 'a' string; ; hl-pair, to 'b'; b-reg contains string length.) ; CMPSTR: LDAX D ;get an 'a' string character and.. CMP M ;..check against 'b' string character. RNZ ;if not equal, set flag. INX H ;bump compare.. INX D ;..pointers and.. DCR B ; (if compare, set as equal.) BRNZ CMPSTR ;..do next character. RET ; ; COMMAND: MACRO (0-9) ; Process macro command ; CMACRO: PUSH PSW ;save digit LXI H,MACFCB ;set up name of macro file LXI D,S$FCB PUSH D MVI B,12 ;12 chars CALL MOVE XCHG CALL INITFCB ;init FCB POP D ;pt to FCB CALL FFIND ;search along path for file BRNZ CMFOUND ;file found POP PSW ;clear stack POP D ;clear ret address CALL ERMSG DB 'File ',0 LXI H,MACFCB+1 CALL PRFN ;print file name CALL VPRINT DB ' NOT Found',0 JMP LOOP ; found macro file CMFOUND: CALL SLOGIN ;log in LXI D,S$FCB ;pt to FCB CALL FI0$OPEN ;open for byte-oriented input POP PSW ;get command MOV C,A ;... in C ; new line CMFL1: CALL F0$GET ;get first char of line JNZ CMFLERR ;EOF encountered CMP C ;match? BRZ CMFL3 ; skip out line CMFL2: CALL F0$GET ;skip out line JNZ CMFLERR CPI LF ;EOL? BRNZ CMFL2 BR CMFL1 ; found command CMFL3: MVI A,MNOTE ;macro note? CMP C JZ CMFLNOTE PUSH D LHLD CRCTBL ;buffer for command line LXI D,256 ;+256 DAD D POP D ; skip leading blanks in command line CMFL4: CALL F0$GET ;get next char BRNZ CMFL6 ;mark end of buffer and go CPI ' ' ;skip leading blanks BRZ CMFL4 ; load command line into buffer CMFL5: ANI 7FH ;mask char CPI CR ;EOL? BRZ CMFL6 CPI CTRLZ ;EOF? BRZ CMFL6 CPI FPESC ;file pted to? JZ CMFLIF CPI UIN1 ;user input? BRZ CMFL5A CPI UIN2 BRZ CMFL5A CMFL50: MOV M,A ;store char INX H ;pt to next CMFL51: CALL F0$GET ;get next char BRZ CMFL5 BR CMFL6 ; print prompt to user and get input CMFL5A: PUSH H ;save buffer ptr CALL CPRMPT ;at command prompt line DB 0 CMFL5B: CALL F0$GET ;get next char BRNZ CMFL5B1 ANI 7FH ;mask CPI UIN1 ;end of prompt? BRZ CMFL5C CPI UIN2 BRZ CMFL5C CPI CR ;end of prompt? BRZ CMFL5C CPI CTRLZ ;eof? BRZ CMFL5C CALL COUT ;send char BR CMFL5B CMFL5B1: MVI A,CTRLZ ;eof CMFL5C: PUSH PSW ;save offending char LHLD BUFSTART ;pt to buffer MVI M,128 ;128 char in line INX H ;set no chars MVI M,0 DCX H ;pt to count XCHG MVI C,RDBUF ;get line from user CALL BDOS LHLD BUFSTART INX H ;pt to count MOV A,M ;get count INX H ;pt to first char PUSH H ;save ptr ADD L MOV L,A MOV A,H ACI 0 MOV H,A ;HL pts to after last char MVI M,0 ;store ending zero POP H ;HL pts to first char of line POP PSW ;get char POP D ;DE pts to next char in buffer MOV B,A ;char in B CMFL5D: MOV A,M ;copy chars ORA A ;zero=done BRZ CMFL5E STAX D ;put char INX H ;pt to next INX D BR CMFL5D CMFL5E: XCHG ;HL pts to next char in buffer MOV A,B ;check offending char CPI UIN1 ;user input? BRZ CMFL51 CPI UIN2 BRNZ CMFL5 BR CMFL51 ; complete buffer and test for content CMFL6: MVI M,0 ;store ending 0 PUSH D LHLD CRCTBL ;pt to first char in line LXI D,256 DAD D POP D MOV A,M ;get first char ORA A ;empty? BRNZ CMFL7 ; error return CMFLERR: PUSH B CALL DLOGIN ;return home POP B MOV A,C ;invalid command RET ; try to chain CMFL7: PUSH H ;save ptr CALL DLOGIN ;return home POP H CALL CHAIN ;chain to command line pted to by HL JMP LOOP ; print documentation built into the macro file CMFLNOTE: CALL VCLS ;new screen MVI C,0 ;set tab counter CMFLN1: CALL F0$GET ;get next char BRNZ CMFLN4 ;done ANI 7FH ;mask CPI CTRLZ ;eof=done BRZ CMFLN4 CPI TAB ;tab process BRZ CMFLN2 CALL COUT ;print char CPI CR ;new line? BRZ CMFLN3 INR C ;new pos CPI LF BRNZ CMFLN1 DCR C ;back up position count BR CMFLN1 CMFLN2: MVI A,' ' ;space over for tab CALL COUT INR C ;incr position MOV A,C ;done? ANI 7 ;every 8 BRNZ CMFLN2 BR CMFLN1 CMFLN3: MVI C,0 ;bol for CR BR CMFLN1 CMFLN4: LHLD RINGPOS ;print current file INX H CALL PRFN CALL VPRINT DB ' Enter Digit or RETURN - ',0 CALL DKEYIN POP D ;get ret address CPI '0' ;in range? JC RUNSH4 CPI '9'+1 ;in range? JNC RUNSH4 PUSH D ;replace ret address JMP CMACRO ; insert file pted to (% prefix command) CMFLIF: CALL F0$GET ;get next char JNZ CMFL6 CPI FPESC ;doubled? JZ CMFL50 LXI D,CMFL51 ;return address PUSH D ;... on stack ANI 5FH ;capitalize CPI FPFILE ;file only? BRZ CMFLIF1 CPI FPDISK ;disk only? BRZ CMFLIF2 CPI FPUSER ;user only? BRZ CMFLIF3 CALL CMFLIF2 ;Disk CALL CMFLIF3 ;User MVI M,':' ;separator INX H ;fall thru to file name CMFLIF1: XCHG ;save ptr to next LHLD RINGPOS ;pt to current file INX H MVI B,8 ;8 chars in filename CALL CMFL5X MVI A,'.' ;put dot STAX D INX D MVI B,3 ;3 chars max CALL CMFL5X XCHG ;HL pts to next RET CMFLIF2: LDA C$DR ;store disk ADI 'A' MOV M,A INX H ;pt to next RET CMFLIF3: LDA C$U$A ;user CPI 10 ;less than 10? BRC CMFLIF32 MVI B,'0' ;compute 10's CMFLIF30: SUI 10 ;subtract 10's BRC CMFLIF31 INR B BR CMFLIF30 CMFLIF31: ADI 10 MOV M,B ;store 10's INX H CMFLIF32: ADI '0' ;store 1's MOV M,A INX H RET CMFL5X: MOV A,M ;get char CPI ' ' BRZ CMFL5X1 STAX D ;put char INX H ;pt to next INX D BJNZ CMFL5X RET CMFL5X1: INX H ;advance BJNZ CMFL5X1 RET ; ; Process command from table ; CTPROC: MOV B,A ;command in B LXI H,CTABLE ;pt to table MOV A,M ;any cursor commands? ORA A JNZ CTPR1 LXI H,CTAB1 ; ; Command table scanner ; HL = Table ; B = Command Letter ; CTPR1: MOV A,M ;get table command char ORA A ;end of table? RZ ;done if so CMP B ;match? BRZ CTPR2 INX H ;skip to next entry INX H INX H BR CTPR1 CTPR2: INX H ;pt to address MOV A,M ;get low INX H MOV H,M ;get high MOV L,A XTHL ;address on stack RET ;"jump" to routine ; Command Table CTABLE: DB 0 ;user cursor positioning DW UP DB 0 DW DOWN DB 0 DW FORWARD DB 0 DW REVERSE CTAB1: DB CTRLC ;if exit, then to opsys DW OS$CCP DB CTRLR ;screen refresh? DW RUNSH4 DB CTRLE ;system cursor positioning DW UP DB CTRLX DW DOWN DB CTRLD DW FORWARD DB CTRLS DW REVERSE DB CR ;nop DW LOOP DB '+' ;jump forward DW JUMPF DB '-' ;jump backward DW JUMPB DB ' ' ;go forward DW FORWARD DB BS ;back up? DW REVERSE DB 'A' ;alphabetize? DW ALPHASW DB 'C' ;copy a file? DW FCOPY DB 'D' ;delete a file? DW FDEL DB 'F' ;show file size? DW FSIZE DB 'G' ;group operation? DW GROUP$OP DB 'H' ;external help? DW EXTHELP DB 'J' ;jump to a file? DW GOTO DB 'N' ;log-in another drive? DW RUNSH3 DB 'P' ;output file to 'list' device? DW LSTFILE DB 'Q' ;screen refresh? DW RUNSH4 DB 'R' ;rename? DW RENAME DB 'S' ;free bytes on.. DW DSTAT ;..requested drive? DB 'T' ;if tag, put TAGCH in.. DW TAG ;..front of cursor. DB 'U' ;remove TAGCH from.. DW UNTAG ;..in front of cursor? DB 'V' ; 'view' file at console? DW VIEW DB 'Z' ;run ZCPR3 command DW RUNZCPR3 ; IF BIHELP ;built-in help? DB '?' ;help DW HELP DB '/' ;help also DW HELP ELSE DB '?' ;help DW EXTHELP DB '/' ;help also DW EXTHELP ENDIF ;BIHELP ; DB 0 ;end of table ; h e l p (menu) IF BIHELP ;built-in Help? HELPMSG: CALL VPRINT DB CR,LF,CR,LF DB ' ' DB '-- Tagging Commands -- --------- File Operat' DB 'ions ----------',CR,LF DB ' ' DB ' T - ',DIM,'Tag File',BRIGHT DB ' C - ',DIM,'Copy File',BRIGHT,' ' DB 'D - ',DIM,'Delete File',BRIGHT,CR,LF DB ' ' DB ' U - ',DIM,'Untag File',BRIGHT DB ' F - ',DIM,'File Size',BRIGHT,' ' DB 'R - ',DIM,'Rename File',BRIGHT,CR,LF DB ' ' DB ' G - ',DIM,'Group ' DB 'Copy/Delete/FSize/Tag/Untag',BRIGHT,CR,LF DB CR,LF DB ' ' DB '-- File Print & View -- --- User Functions ---',CR,LF DB ' -- Cursor -- ' DB 'P - ',DIM,'Print',BRIGHT DB ' V - ',DIM,'View',BRIGHT DB ' 0-9 - ',DIM,'Execute',BRIGHT,' ',MNOTE,' - ',DIM,'Help' DB BRIGHT,CR,LF DB ' ^E ' DB CR,LF DB ' ^ ' DB '-- Movement Commands -- ---- Miscellaneous ----',CR,LF DB ' ^S <-+-> ^D ' DB ' - ',DIM,'File Forward' DB BRIGHT,' A - ',DIM,'Toggle Alpha Sort',BRIGHT,CR,LF DB ' v ' DB ' - ',DIM,'File Backward' DB BRIGHT,' H - ',DIM,'Help File',BRIGHT,CR,LF DB ' ^X ' DB ' + - ',DIM,'Screen Forward',BRIGHT DB ' N - ',DIM,'New DIR',BRIGHT,CR,LF DB ' ' DB ' - - ',DIM,'Screen Backward',BRIGHT DB ' S - ',DIM,'Disk Status',BRIGHT,CR,LF DB ' -- Screen -- ' DB ' J - ',DIM,'Jump to a File',BRIGHT DB ' Z - ',DIM,'ZCPR3 Command',BRIGHT,CR,LF DB ' ^A ',DIM,'Left',BRIGHT,' ' DB ' Q - ',DIM,'Refresh Screen',BRIGHT DB ' ^C - ',DIM,'Exit',BRIGHT,CR,LF DB ' ^F ',DIM,'Right',BRIGHT,' ' DB 0 RET HELP: LDA HELPDISP ;toggle flag CMA STA HELPDISP JMP RUNSH4 ;refresh screen and restart ENDIF ;BIHELP ; ; COMMAND: H ; EXTHELP: CALL CPRMPT DB 'Read Help File (Y/N)? ',0 CALL CIN CALL CAPS CPI 'Y' JNZ LOOPFN CALL ERMSG DB DIM,'Chaining to Help File ...',BRIGHT,0 LXI H,MOREHELP ;run HELP Command CALL CHAIN ;chain to it JMP LOOPFN ; ; COMMAND: A ; ; Toggle alphabetize switch and reload files ; ALPHASW: LDA ALPHA ;toggle flag CMA STA ALPHA CALL CPRMPT ;tell user what is happening DB 'Sorting by File ',0 LDA ALPHA ;get flag ORA A ;check it BRZ ASWTN CALL VPRINT DB 'Name and Type',0 JMP RUNSH2 ASWTN: CALL VPRINT DB 'Type and Name',0 JMP RUNSH2 ;reload files ; ; COMMAND: Z ; ; Execute ZCPR3 command line ; RUNZCPR3: CALL ERMSG ;position at error message line DB 0 LXI H,H$DR ;pt to Home Drive (followed by Home User) CALL PRDU ;print DU CALL VPRINT ;print prompt DB '> ',0 PUSH D LHLD CRCTBL ;use last half of CRC Table LXI D,256 DAD D POP D MVI M,126 ;store length of line INX H MVI M,0 ;store count DCX H ;pt to beginning XCHG ;DE pts to buffer PUSH D MVI C,RDBUF ;Read Line from User CALL BDOS POP H INX H ;pt to char count MOV E,M INX H ;pt to first char MVI D,0 ;set no high-order offset PUSH H ;save current ptr for later DAD D MVI M,0 ;store ending zero POP H ;pt to first char of command line MOV A,M ;abort if no first char ORA A JZ LOOP CALL CHAIN ;chain to it JMP LOOPFN ;continue ; chain to command pted to by HL ending in zero CHAIN: CALL PUTCL ;store command line BRNZ CHAIN1 CALL ERMSG DB 'CL Err',0 RET CHAIN1: MVI B,0 ;set shell message 0 MVI A,80H ;enable wait CALL PUTSHM CHAIN2: LDA C$DR ;get current disk ADI 'A' ;convert to ASCII STA FILE$D ;store in proper place LDA C$U$A ;get current user LXI H,FILE$U ;store user number MVI C,'0' ;set char CHAIN3: SUI 10 ;convert to ASCII BRC CHAIN4 INR C ;increment 10's char BR CHAIN3 CHAIN4: MOV M,C ;store 10's digit char INX H ;pt to 1's digit ADI 10+'0' ;add back for 1's digit MOV M,A ;store 1's digit char CALL GETSH2 ;pt to shell buffer LXI D,8 ;skip 8 chars (VFILER Name) DAD D LXI D,FILE$D ;place DU XCHG MVI B,5 ;store 5 chars (duu:0) CALL MOVEB JMP OS$CCP1 ;run command line ; ; COMMAND: G ; ; Group operation ; GROUP$OP: CALL CPRMPT DB 'Group Cmd (Copy, Delete, File Sizes, Tag, Untag)? ',0 CALL KEYIN ;get response MOV B,A ;command in B LXI H,GTABLE ;pt to table CALL CTPR1 ;process command JMP LOOP ;resume if not found ; ; Group Command Table ; GTABLE: DB 'C' DW MASS$COPY DB 'D' DW MASS$DEL DB 'F' DW MASS$FSIZE DB 'T' DW MASS$TAG DB 'U' DW MASS$UNTAG DB 0 ;end of table ; ; COMMAND: GU ; MASS$UNTAG: MVI B,' ' ;untag char ; ; Common Entry Point for Mass Untag/Tag - B = Untag/Tag Char ; MUTLOOP: LHLD RINGPOS ;move to tag LXI D,12 DAD D MOV M,B ;set tag byte INX H ;pt to next SHLD RINGPOS XCHG ;done? LHLD LOCEND CALL CMPDEHL BRNZ MUTLOOP LXI H,CURHOME ;reset cursor SHLD CURAT LHLD LOCBEG ;set ring position JMP JFW0 ;reset screen from LOCBEG ; ; COMMAND: GT ; MASS$TAG: MVI B,TAGCH ;tag char BR MUTLOOP ;do work ; ; COMMAND: U ; UNTAG: MVI B,' ' ;set tag byte ; ; Common Entry Point for Untag/Tag - B = Untag/Tag Char ; UT: LHLD RINGPOS ;move back one.. LXI D,12 ;..character position.. DAD D ;..and check tagging status. MOV M,B ;if file previously tagged, remove.. CALL REFFN ;refresh file name JMP FORWARD ; ; COMMAND: T ; TAG: MVI B,TAGCH ;tag char BR UT ;do tag ; ; Refresh file name with new tag ; REFFN: CALL CLRCUR ;clear cursor MVI A,' ' ;one more space CALL COUT LHLD RINGPOS ;reprint file name INX H CALL PRFN MOV A,M ;print tag JMP COUT ; ; COMMAND: GF ; MASS$FSIZE: CALL WORKMSG ;print 'Working' msg LXI H,0 ;zero total SHLD TAG$TOT LHLD RINGPOS ;save ring position SHLD SRINGPOS LHLD RING ;set new ring position SHLD RINGPOS ; ; Main Loop to Compute File Sizes ; MASS$FS: LHLD RINGEND ;at end of ring? XCHG LHLD RINGPOS CALL CMPDEHL ;same if so BRZ MASS$FS2 LXI D,12 ;pt to tag DAD D MOV A,M ;get tag INX H ;pt to next file CPI TAGCH ;tagged? BRNZ MASS$FS1 ;skip if not tagged ; ; Compute Size of Tagged File ; PUSH H ;save ptr to next file CALL SIZER ;compute file size XCHG ;size in DE LHLD TAG$TOT ;get total DAD D SHLD TAG$TOT ;new total POP H ;get ptr to next file MASS$FS1: SHLD RINGPOS ;set ptr to next file BR MASS$FS ; ; File Size Accumulation Done - Print Result ; MASS$FS2: LHLD SRINGPOS ;restore ring position SHLD RINGPOS CALL FSNOTE ;print file size message CALL VPRINT ;print specific DB 'Tagged Files is ',0 LHLD TAG$TOT ;get total BR FSIZE1 ;print size in HL and return ; ; COMMAND: F ; ; determine and display file size in kilobytes -- round up to next disk ; allocation block -- accumulate tagged file summation ; FSIZE: CALL SIZER ;compute file size of current file PUSH H ;save value CALL FSNOTE ;print file size message LHLD RINGPOS ;print file name INX H CALL PRFN CALL VPRINT ;print trailer DB ' is ',0 POP H ;get size ; ; Print file size in HL and exit to screen ; FSIZE1: CALL PHLFDC ;print value in HL as floating MVI A,'K' ;print suffix CALL COUT JMP LOOPFN ;resume ; ; Compute File Size at RINGPOS ; Return Size in HL ; SIZER: CALL RINGFCB ;move name to 's$fcb' ; ; Determine file record count and save in RCNT ; MVI C,COMPSZ LXI D,S$FCB CALL BDOS LHLD S$FCB+33 SHLD RCNT ;save record count and.. LXI H,0 SHLD S$FCB+33 ;..reset opsys ; ; Round up to next disk allocation block ; LDA B$MASK ;sectors/block - 1 PUSH PSW ;save 'blm' MOV L,A XCHG LHLD RCNT ;..use here. DAD D ;round up to next block MVI B,3+1 ;convert from.. CALL SHIFTLP ;..records to kilobytes. POP PSW ;retrieve 'blm' RRC ;convert.. RRC ;..to.. RRC ;..kilobytes/block. ANI 1FH CMA ;finish rounding ANA L MOV L,A ;hl-pair contains # of kilobytes RET ; ; COMMAND: - (Previous Screen) ; JUMPB: LXI H,CURHOME ;set cursor home SHLD CURAT LHLD RING ;at front? XCHG LHLD LOCBEG CALL CMPDEHL BRZ JUMPBW ;back up and wrap around SHLD LOCEND ;set new end LXI D,-EPS*13 ;back up DAD D SHLD LOCBEG ;new beginning SHLD RINGPOS ;new position JMP RUNSH4 JUMPBW: LHLD LOCBEG ;at first screen? XCHG LHLD RING ;pt to first element of ring CALL CMPDEHL BRZ JBW0 ;advance to end LXI H,-EPS*13 ;back up DAD D ;first element of new local ring BR JFW0 JBW0: LXI D,EPS*13 ;pt to next screen DAD D XCHG LHLD RINGEND CALL CMPDEHL XCHG BRZ JBW1 BRC JBW0 JBW1: LXI D,-EPS*13 DAD D ;pt to first element of new local ring BR JFW0 ; ; COMMAND: + (Next Screen) ; JUMPF: LXI H,CURHOME ;set cursor to home SHLD CURAT LHLD LOCEND ;see if Local End <= Ring End XCHG LHLD RINGEND CALL CMPDEHL BRZ CMDLOOP LHLD LOCEND ;new screen starting at LOCEND BR JFW0 ; ; Reset to Beginning of RING and Resume Command Looping ; CMDLOOP: CALL SETSCR ;reset all screen pointers CMDLRET: JMP RUNSH4 ; ; Reset RING Position to HL ; JFW0: CALL SETSCR1 ;reset RINGPOS on ... BR CMDLRET ; ; Reset Local Ring to HL ; JFW0A: CALL SETSCR2 ;reset LOCBEG on ... BR CMDLRET ; ; COMMAND: ' ', Left-Arrow ; FORWARD: CALL CLRCUR ;clear cursor CALL FOR0 ;position on screen and in ring CALL SETCUR ;set cursor JMP LOOPFN ; advance routine FOR0: LHLD RINGPOS ;at end of loop yet? LXI D,13 ;i.e., will we be at end of loop? DAD D XCHG LHLD LOCEND CALL CMPDEHL ;compare 'present' to 'end' BRNZ FORW ;to next print position CALL CUR$FIRST ;position cursor LHLD LOCBEG ;set position pointer to beginning and.. SHLD RINGPOS RET FORW: LHLD RINGPOS ;advance in ring LXI D,13 DAD D SHLD RINGPOS ;new position CALL CUR$NEXT ;position cursor RET ; ; COMMAND: BS, Right-Arrow ; REVERSE: CALL CLRCUR ;clear cursor CALL REV0 ;position on screen and in ring CALL SETCUR ;set cursor JMP LOOPFN ; Back Up Routine REV0: LHLD LOCBEG XCHG LHLD RINGPOS ;see if at beginning of ring CALL CMPDEHL BRNZ REV1 ;skip position pointer reset if not.. CALL CUR$LAST ;end of local ring LHLD LOCEND ;set to end +1 to backup to end LXI D,-13 DAD D SHLD RINGPOS RET REV1: CALL CUR$BACK ;back up 1 REV2: LHLD RINGPOS LXI D,-13 ;one ring position.. DAD D ;..backwards. SHLD RINGPOS RET ; ; COMMAND: Up-Arrow ; UP: CALL CLRCUR ;clear cursor LHLD RINGPOS ;see if wrap around LXI D,-13*4 ;4 entries DAD D XCHG LHLD LOCBEG ;beginning of local screen CALL CMPDEHL BRC UP2 ;wrap around MVI B,4 ;back up 4 entries UP1: PUSH B ;save count CALL REV0 ;back up in ring and on screen (no print) POP B ;get count BJNZ UP1 BR DOWN1A UP2: LHLD RINGPOS ;advance to beyond end LXI D,13*4 DAD D XCHG LHLD LOCEND ;compare to local end XCHG CALL CMPDEHL BRZ DOWN1A ;at end, so too far BRC DOWN1A ;beyond end, so back up SHLD RINGPOS ;new ring position LHLD CURAT ;advance cursor INR H ;next line SHLD CURAT BR UP2 ; ; COMMAND: Down-Arrow ; DOWN: CALL CLRCUR ;clear cursor LHLD RINGPOS ;see if wrap around LXI D,13*4 ;4 entries DAD D XCHG LHLD LOCEND ;end of local screen XCHG CALL CMPDEHL BRZ DOWN2 ;wrap around BRC DOWN2 ;wrap around MVI B,4 ;forward 4 entries DOWN1: PUSH B ;save count CALL FOR0 ;advance in ring and on screen (no print) POP B ;get count BJNZ DOWN1 DOWN1A: CALL SETCUR ;set cursor JMP LOOPFN DOWN2: LHLD CURAT ;preserve column MOV B,L ;column number in B LXI H,CURHOME ;home position SHLD CURAT ;set new position LHLD LOCBEG ;beginning of local ring SHLD RINGPOS ;new ring position DOWN3: LHLD CURAT ;check for at top of column MOV A,L ;get col CMP B ;there? BRZ DOWN1A LHLD RINGPOS ;advance in ring LXI D,13 ;13 bytes/entry DAD D SHLD RINGPOS LHLD CURAT ;get cursor position LXI D,19 ;advance 19 bytes/screen entry DAD D SHLD CURAT BR DOWN3 ; ; COMMAND: S ; ; Determine remaining storage on requested disk ; DSTAT: CALL CPRMPT DB 'Status of Disk (Letter): ',0 CALL KEYIN ;get char PUSH PSW CALL CRLF POP PSW SUI 'A' ;convert to number JC LOOP MOV B,A ;... in B LDA MAXDR ;compare to max SUI 'A' CMP B JC LOOPFN MOV A,B ;get disk STA R$DR ;requested drive CALL RESET ;..login as current. CALL FRESTOR ;determine free space remaining CALL PRINT$FRE ;print value LDA C$DR ;login original as.. CALL SET$DR ;..current drive. JMP LOOPFN ; ; COMMAND: GD ; MASS$DEL: CALL CPRMPT DB 'Mass Delete (Y/N/V=Verify)? ',0 CALL KEYIN ;get response CPI 'Y' BRZ MD1 CPI 'V' JNZ LOOP ;return to position MD1: STA MDFLG ;set flag STA MASSOP ;NZ=Mass Delete JMP MASS$RUN ; ; COMMAND: D ; FDEL: XRA A ;set no mass operation STA MFLAG CALL DELETE ;delete file ; ; Was Deletion Done? Abort if Not ; LDA DELCODE ;0=not done ORA A JZ LOOPFN ;abort if not ; ; Reset Local Display ; LHLD LOCEND ;move in end LXI D,-13 DAD D SHLD LOCEND XCHG LHLD RINGPOS ;position beyond end of ring? CALL CMPDEHL BRNZ FDEL1 ; ; Cursor Beyond End of Display ; CALL CUR$BACK ;back up cursor LHLD LOCEND ;reset position LXI D,-13 DAD D SHLD RINGPOS FDEL1: LHLD LOCEND ;get local end XCHG ;... in DE LHLD LOCBEG ;erased all local files? CALL CMPDEHL JZ CMDLOOP ;reset JMP JFW0A ;rescreen from LOCBEG ; ; Delete filename at RINGPOS ; DELETE: XRA A STA DELCODE ;set deletion not done CALL RINGFCB ;get file name LDA MFLAG ;mass operation? ORA A ;0=no BRZ DEL2 ;do delete ; ; Test for Verify on Mass Delete ; LDA MDFLG ;verify? CPI 'V' BRNZ DEL1 ;delete without verify ; ; Verify and Delete only if Approved ; CALL CPRMPT DB 'Delete ',0 CALL PRFNS ;print file name in S$FCB CALL VPRINT DB ' (Y/N)? ',0 CALL KEYIN CPI 'Y' RNZ ;abort if not approved ; ; Delete File (Mass Operation) ; DEL1: LDA MDFLG ;mass operation - verify on? CPI 'V' BRZ DEL2 CALL ERMSG ;print information for mass del w/o verify DB 'Deleting File ',0 CALL PRFNS ; ; Delete File in S$FCB ; DEL2: LXI H,S$FCB ;set file to R/W CALL ATTRIB RZ ;abort LXI D,S$FCB ;point at delete 'fcb' MVI C,ERASE ;erase function CALL BDOS INR A BRNZ DELCL ;close up erased position FNF$MSG: CALL FNF1 ;show error message JMP LOOPFN ; ; Close up erased position ; DELCL: MVI A,0FFH STA DELCODE ;set deletion done LHLD RINGPOS ;prepare move up pointers PUSH H LXI D,13 ;13 bytes/entry DAD D ;de-pair = 'to' location POP D ;hl-pair = 'from' location ; ; Move 13-byte ring entries from HL to DE ; MOVUP: XCHG ;HL=dest PUSH H ;check if at end LHLD RINGEND ;get old end pointer CALL CMPDEHL ;check against current end location POP H XCHG ;DE=dest BRZ MOVDONE ;must be at end of ring MVI B,13 ;one name size CALL MOVE ;move one name up BR MOVUP ;go check end parameters ; ; Move Complete ; MOVDONE: LHLD RING ;see if ring is empty XCHG SHLD RINGEND ;set new ring end if all moved CALL CMPDEHL ;..(listend --> listpos --> ring) RNZ CALL ERMSG DB 'List Empty',0 JMP RUNSH3 ;go to drive/user area with files ; ; COMMAND: R ; ; Set-up to rename file at cursor position -- scan keyboard buffer and ; move filename to destination FCB (DFCB) ; RENAME: LHLD RINGPOS ;move name from ring to rename 'fcb' LXI D,D$FCB ;place to move name MVI B,12 ;amount to move CALL MOVE CALL CPRMPT ;new name prompt DB 'Rename File to: ',0 LXI D,D$FCB+16 ;pt to FCB to fill CALL FILENAME ;get file name LXI H,D$FCB+1 ;check for any wild cards -- none permitted MVI B,11 ;11 bytes WILDCHK: MOV A,M ;get char INX H ;pt to next CPI '?' ;wild? BRZ WILDFND BJNZ WILDCHK ; copy old file status bit ($r/o or $sys) to new filename CPYBITS: LXI D,D$FCB+1 ;first character of old name.. LXI H,D$FCB+17 ;..and of new name. MVI B,11 ; # of bytes with tag bits CBITS1: LDAX D ;fetch bit of old name character ANI 128 ;strip upper bit and.. MOV C,A ;..save in b-reg. MVI A,7FH ;mask for character only ANA M ;put masked character into a-reg ORA C ;add old bit MOV M,A ;copy new byte back INX H ;bump copy pointers INX D BJNZ CBITS1 ; check if new filename already exists. if so, say so. then go ; to command loop without moving ring position LDA D$FCB ;copy new name to source 'fcb' STA S$FCB MVI B,11 LXI H,D$FCB+17 ;copy new name to.. LXI D,S$FCB+1 ;..source 'fcb' for existence check. CALL MOVE LXI H,S$FCB+12 ;clear 'fcb' system.. CALL INITFCB ;..fields. LXI D,S$FCB ;search to see if this file exists MVI C,SRCHF ;search first function CALL BDOS INR A ; 0ffh --> 00h if file not found BRZ RENFILE ;to rename, if duplicate doesn't exists. CALL ERMSG ;announce the situation DB 'File Already Exists',0 JMP COMCAN ;try again? ; wild char found in file name -- error WILDFND: CALL ERMSG DB 'AFN NOT Allowed',0 JMP COMCAN ; copy new name into ring position RENFILE: LHLD RINGPOS ;get ring position pointer INX H ;pt to name PUSH H ;save ptr XCHG LXI H,D$FCB+17 ;point at new name and.. MVI B,11 CALL MOVE ;..move. LHLD CURAT ;get current position on screen LXI D,4 ;advance 4 chars DAD D CALL GOTOXY POP H ;get ptr CALL PRFN ;print file name MOV A,M ;print tag CALL COUT LXI D,D$FCB ;rename 'fcb' location MVI C,REN ;rename function CALL BDOS INR A ; 0ffh --> 00h if rename error JNZ LOOP ;if okay, proceed, else.. JMP FNF$MSG ;..show no-file msg. ; get file name from user and process into FCB pted to by DE FILENAME: PUSH D ;save ptr LHLD CMDBUF ;command line location XCHG MVI C,RDBUF ;console read-buffer function CALL BDOS CALL CONVERT ;capitalize alpha POP H ;set to null drive MVI M,0 ;..required by 'bdos'. INX H ; initialize new filename field with spaces PUSH H ;save start pointer MVI B,11 ; # of spaces to 'blank' CALL FILL POP H XCHG LHLD CMDBUF ;put length.. INX H MOV C,M ;..in c-reg. INX H XCHG ;de-pair --> buffer pointer and hl-pair.. CALL UNSPACE ;..--> 'fcb' pointer. remove leading spaces. ; extend buffer to spaces beyond command length EXTEND: PUSH H MOV L,C ;double-byte remaining length MVI H,0 DAD D ;to buffer end +1 MVI M,' ' ;force illegal character end POP H ; start filename scan SCAN: MVI B,8 ; 8 characters in filename SCAN1: CALL CKLEGAL ;get and see if legal character JC COMCAN ;all of command line? CPI ' ' ;see if end of parameter field RZ ;rename file CPI '.' ;at end of filename BRZ SCAN2 ;process filetype field CPI '*' ;rest wild? BRZ SCAN1B MOV M,A ;put character into destination 'fcb' INX H BJNZ SCAN1 ; entry if eight characters without a 'period' SCAN1A: CALL CKLEGAL ;scan buffer up to period or end RC ;no extent if not legal CPI ' ' ;end of parameter field? RZ CPI '.' BRNZ SCAN1A ;do till end or period BR SCAN2A ;continue at correct place ; make rest of entry wild SCAN1B: MVI M,'?' ;fill with ?'s INX H BJNZ SCAN1B LDAX D ;get next char INX D ;pt to after dot CPI '.' ;must be dot JNZ COMCAN ;cancel if not BR SCAN2A ; build filetype field SCAN2: INX H ;advance ptr to file type field BJNZ SCAN2 SCAN2A: MVI B,3 ;length of filetype field SCAN3: CALL CKLEGAL ;get and check character BRC SCAN4 ;name done if illegal CPI ' ' ;end of parameter field? BRZ SCAN4 CPI '.' ;check if another period BRZ SCAN4 CPI '*' ;rest wild? BRZ SCAN4B MOV M,A INX H BJNZ SCAN3 ;get next character BR SCAN4A SCAN4: INX H ;advance to end of type field BJNZ SCAN4 SCAN4A: CALL INITFCB ;..and zero counter fields. RET SCAN4B: MVI M,'?' ;make wild INX H BJNZ SCAN4B BR SCAN4A ;complete rest ; ; COMMAND: J ; GOTO: CALL CPRMPT DB 'Jump to Filename: ',0 LXI D,D$FCB ;pt to FCB CALL FILENAME ;get file name LHLD RING ;pt to first element of ring SHLD RINGPOS ;set position SHLD LOCBEG ;set local beginning PUSH H LHLD CRCTBL ;pt to CRC Table MVI M,0 ;set local counter POP H GOTOL: CALL GOTOCOMP ;compare BRZ GOTOF ;we are there PUSH H LHLD CRCTBL ;pt to table INR M MOV A,M POP H CPI EPS BRNZ GOTOL1 LHLD CRCTBL ;zero first entry MVI M,0 LHLD LOCBEG ;reset local beginning LXI D,EPS*13 DAD D SHLD LOCBEG GOTOL1: LHLD RINGPOS ;advance to next entry LXI D,13 DAD D SHLD RINGPOS ;new position XCHG ;position in DE LHLD RINGEND ;check for completion CALL CMPDEHL ;compare current position with end of ring BRNZ GOTOL LHLD RING ;pt to first element SHLD RINGPOS ;set position CALL FNF1 ;print message JMP CMDLOOP GOTOF: LHLD LOCBEG ;we have local beginning PUSH H XCHG ;ring location in DE LXI H,CURHOME ;set cursor ptr SHLD CURAT GOTOF0: LHLD RINGPOS ;at position? CALL CMPDEHL BRZ GOTOF1 LXI H,13 ;advance location DAD D PUSH H CALL CUR$NEXT ;advance cursor POP D ;pt to next ring position BR GOTOF0 GOTOF1: POP H ;pt to local ring JMP JFW0A ;process GOTOCOMP: LHLD RINGPOS ;pt to current entry INX H ;pt to first char of file name LXI D,D$FCB+1 ;pt to first char of new file MVI B,11 ;11 bytes GOTOC1: LDAX D ;get char CPI '?' ;match? BRZ GOTOC2 CMP M ;match? RNZ ;no match GOTOC2: INX D ;pt to next INX H BJNZ GOTOC1 RET ; ; COMMAND: V ; ; Type file to console with pagination set to 'lps' -- single-line scroll ; using bar , to cancel, any other key to page screen. ; VIEW: CALL VCLS CALL VPRINT DB CR,LF,DIM,' Cancels, Turns Up One Line, ' DB 'Other Keys Page Screen',BRIGHT,CR,LF,LF,0 MVI A,1 ;initialize.. STA LPSCNT ;..lines-per-screen counter. STA VIEWFLG ; 'view' paginate if not zero MVI A,WRCON ;write console out function BR CURRENT ;to common i/o processing ; ; COMMAND: P ; ; Send file to logical list device -- any keypress cancels ; LSTFILE: CALL CPRMPT DB 'Print on LST Device (Y/N)? ',0 CALL KEYIN ;get response CPI 'Y' JNZ LOOP CALL ERMSG DB 'Printing ',0 LHLD RINGPOS ;pt to file name INX H CALL PRFN ;print it MVI A,1 ;one for.. STA VIEWFLG ;..output to printer. DCR A ;zero for.. STA LPSCNT ;..lines-per-page counter MVI A,LIST ;out to 'list' device function and fall thru ; output character for console/list/punch processing CURRENT: STA CON$LST ;save bdos function ; output file to console/printer/punch CALL RINGFCB ;position name to 'fcb' XCHG ;HL pts to S$FCB CALL INITFCB ;set 'fcb' for use LXI D,TBUF ;set to use default dma buffer MVI C,SETDMA ;address set function CALL BDOS LXI D,S$FCB ;open file for reading MVI C,OPEN ;file open function code CALL BDOS INR A ; 0ffh --> 00h if open not okay BRNZ ZEROCR ;if not okay, show error message. ; ; File Not Found Error ; FNF: CALL FNF1 ;print file not found message JMP LOOP ; ; Print File Not Found Message ; FNF1: CALL ERMSG DB 'File NOT Found',0 RET ; ; Continue ; ZEROCR: XRA A STA S$FCB+32 ;zero file 'current record' field STA CHARCNT ;zero char count for tabbing CALL PHEAD ;print heading if output to LST device READMR: LXI D,S$FCB ;point at file 'fcb' for reading MVI C,READ ;record read function CALL BDOS ORA A ;check if read okay BRNZ CURDONE ;eof? LXI H,TBUF ;point at record just read MVI B,128 ;set record character counter to output READLP: MOV A,M ;get a character ANI 7FH ;force to 'ascii' CPI EOFCHAR ;see if end-of-file BRZ CURDONE ;back to ring loop if 'eof' MOV E,A ;put character for 'bdos' call PUSH B PUSH H PUSH D ; (character in e-reg) LDA CON$LST ;get function for punch/list/console output MOV C,A MOV A,E ;check char CPI TAB ;tabulate? BRNZ NOTAB MVI E,' ' ;space over TABL: PUSH B ;save key regs PUSH D CALL BDOS POP D ;get key regs POP B CALL INCCCNT ;increment char count ANI 7 ;check for done at every 8 BRNZ TABL BR TABDN NOTAB: CALL BDOS ;send character CALL INCCCNT ;increment char count TABDN: LDA VIEWFLG ;if 'view'.. ORA A POP D ;get char in E in case PAGER is called CNZ PAGER ;..check for 'lf'. MVI E,GET ;get status or char MVI C,DIRCON ;console status function CALL BDOS ;status? POP H POP B ANI 7FH ;if character there, then abort.. CNZ CANVIEW ;already got char INX H ;if not, bump buffer pointer. BJNZ READLP ;no, more in present record. BR READMR ;yes, get next record. CURDONE: LDA CON$LST ;console? CPI WRCON CZ BOTTOM ;prompt for user JMP RUNSH4 ;refresh screen and continue user input PAGER: MOV A,E ; (character in e-reg) CPI LF RNZ XRA A ;zero char count STA CHARCNT LDA CON$LST ;printer or console? CPI LIST ;check for printer BRZ PAGEP LDA CTPP ;get number of lines of text per screen MOV B,A ;... in B LDA LPSCNT ;is counter.. INR A ;..at.. STA LPSCNT ;..limit.. CMP B ;..of lines-per-screen? RC ;no, return. XRA A ;yes, initialize.. STA LPSCNT ;..for next screen full. CALL VPRINT DB ' ',DIM,'[View More...]',BRIGHT,CR,0 ;show msg line CALL DKEYIN ;wait for keyboard input CPI ' ' ;see if bar.. PUSH PSW CALL VPRINT DB ' ',CR,0 ;clear above msg line POP PSW BRNZ CANVIEW ;..if not, see if cancel. LDA CTPP ;set for single line DCR A STA LPSCNT ;..scroll and.. RET ;..return for one more line. PAGEP: LDA LTPP ;get number of lines of text per page MOV B,A ;... in B LDA LPSCNT ;is counter.. INR A ;..at.. STA LPSCNT ;..limit.. CMP B ;..of lines-per-screen? RC ;no, return. XRA A ;zero for.. STA LPSCNT ;..lines-per-page counter LDA LFFEED ;form feed available? ORA A ;0=no JZ PRFEED CALL LCRLF ;new line MVI A,FF ;send form feed char CALL LOUT JMP PHEAD ;print header and done PRFEED: LDA LSPP ;number of lines to skip MOV B,A ;number of lines to skip MVI C,LIST ;LST output PAGELST: CALL LCRLF ;new line on LST BJNZ PAGELST JMP PHEAD ;print heading and done CANVIEW: CPI CTRLC ;^C? JZ COMCAN RET ;return for another page INCCCNT: LDA CHARCNT ;increment char count INR A STA CHARCNT RET PHEAD: LDA CON$LST ;printing to printer? CPI LIST RNZ LXI H,HEADMSG ;print heading PHEAD1: MOV A,M ;get char ORA A ;done? BRZ PHEAD2 CALL LOUT ;send to printer INX H ;pt to next BR PHEAD1 PHEAD2: LXI H,S$FCB+1 ;pt to file name MVI B,8 ;8 chars CALL PHEAD3 MVI A,'.' ;dot CALL LOUT MVI B,3 ;3 more chars CALL PHEAD3 CALL LCRLF ;new line CALL LCRLF ;blank line RET PHEAD3: MOV A,M ;get char CALL LOUT ;LST it INX H ;pt to next BJNZ PHEAD3 RET ; ; COMMAND: GC ; ; Copy files tagged using the 't' command. auto-erase if file exists ; on requested destination drive or in user area. ; MASS$COPY: CALL ERMSG DB 'Mass Copy',0 XRA A ;A=0 STA MASSOP ;set operation to mass copy ; ; Main Entry Point for Mass Operation of Copy or Delete ; On entry, MASSOP = 0 if copy, 0FFH if delete ; MASS$RUN: LHLD RINGPOS ;save position SHLD SRINGPOS LHLD RING LXI D,-13 ;back up to before first ring element DAD D SHLD RINGPOS ;set position ; ; Set Flags for First Time Thru and Mass Operation ; XRA A ;A=0 STA FIRST$M ;set for prompt for dest with first file DCR A ;A=0FFH STA MFLAG ;this is a mass operation ; ; Main Mass Operation Loop ; MASS$OLP: LHLD RINGPOS ;re-entry point for next file LXI D,13 ;advance to next DAD D SHLD RINGPOS XCHG ;at ring.. ; ; Check for Loop Completion -- DE = Current RINGPOS ; MASS$OLP1: LHLD RINGEND ;..end yet? CALL CMPDEHL ;compare present position with end BRZ MASS$OLX ;done ; ; Check for Tagged File at RINGPOS ; LHLD RINGPOS ;get position LXI D,12 ;get 1st possible tag location DAD D MOV A,M ;get tag CPI TAGCH BRNZ MASS$OLP ;not tagged, so skip ; ; Select Mass Operation ; LDA MASSOP ;get type of mass operation ORA A ;0=COPY BRZ MASS$OC ;do copy ; ; Do Mass Delete - Current File Delete ; CALL DELETE ;delete filename at RINGPOS ; ; Advance to Next File if Delete Aborted ; LDA DELCODE ;deletion done? ORA A ;0=no BRZ MASS$OLP ;skip to next if not ; ; Stay at Current File if Delete Done - Ring was Compressed by Delete ; LHLD RINGPOS ;get current ring position XCHG ;... in DE (don't advance) BR MASS$OLP1 ;loop until thru ring list ; ; Do Mass Copy - Current File Copy ; MASS$OC: CALL COPY ;do copy BR MASS$OLP ;loop until thru ring list ; ; Exit Mass Operation Loop ; MASS$OLX: LHLD SRINGPOS ;reset ring position SHLD RINGPOS LDA MASSOP ;if delete, restart ORA A ;NZ=delete JNZ RUNSH2 LHLD LOCBEG ;copy, so reset local ring JMP JFW0A ;rescreen ; ; COMMAND: C ; ; Copy source file at current 'ring' position to another drive. set-up ; fcb's and buffer area and check for correct keyboard inputs. contains ; auto-crc file copy verification. ; FCOPY: ; ; Set Flags for First Time Thru and No Mass Copy ; XRA A ;A=0 STA FIRST$M ;set for prompt for destination STA MFLAG ;not a mass copy ; ; Do Copy ; CALL COPY ;do copy of file at RINGPOS ; ; Advance to Next File ; JMP FORWARD ;advance to next file ; ; Copy File at RINGPOS ; COPY: LXI H,0 ;initialize storage for.. SHLD CRCVAL ;..'crc' working value. CALL RINGFCB ;move from 'ring' to 'sfcb' LXI H,S$FCB+12 ;set pointer to source extent field CALL INITFCB MVI B,32 ;copy source 'fcb' to destination 'fcb' LXI H,S$FCB+1 ;from point.. LXI D,D$FCB+1 ;..to point.. CALL MOVE ;..move across. LXI D,S$FCB ;open file for reading MVI C,OPEN ;open function CALL BDOS INR A ; 0ffh --> 00h if bad open JZ FNF ;file not found ; ; Source File is Open -- If first time thru, get dest dir ; COPY2: LDA FIRST$M ;by-pass prompt, drive/user compatibility.. ORA A ;..test, and disk reset after.. BRNZ COPY3M ;..1st time thru in mass-copy mode. DCR A ;A=0FFH STA FIRST$M ;set not first time any more CALL CPRMPT ;prompt for drive selection DB 'Copy to DIR: ',0 CALL DEF$D$U ; ; Check to ensure that either drives or user areas are different ; LDA FCB ;get requested drive from 'fcb' and.. MOV B,A ;..put into b-reg for.. LDA S$FCB ;..comparison CMP B BRNZ COPY3 ;branch if different LDA R$U$A ;requested user area --> rua MOV B,A LDA C$U$A ;current user area --> cua CMP B BRNZ COPY3 CALL ERMSG ;if not, show error condition: DB 'Src DIR = Dest DIR',0 JMP LOOP ;try again? ; ; First File Copy - Reset System ; COPY3: CALL RESET ;make sure disk is read/write CALL DLOGIN ;return home ; ; Nth File Copy - Copy without Resetting System ; COPY3M: LDA FCB ;put requested drive into.. STA D$FCB ;..place in destination fcb (used to log in) LDA R$U$A ;toggle to.. CALL SET$USR ;..requested user area. LXI D,D$FCB ;search for duplicate MVI C,SRCHF ; 'search first' function CALL BDOS INR A ;if not found, 0ffh --> 00h. then.. BRZ COPY5 ;go to 'make' function for new file. LDA MFLAG ;auto-erase.. ORA A ;..if.. BRZ COPY4M ;..in mass-copy mode. CALL ERMSG ;If found, ask to replace: DB 0 LXI H,D$FCB+1 CALL PRFN CALL VPRINT DB ' Exists on Dest -- Erase (Y/N)? ',0 CALL KEYIN ;get answer CPI 'Y' ;if yes, then delete and copy ... BRZ COPY4M ;... else fall thru to CUA$LOG and exit ; ; Log into Current User Area ; CUA$LOG: LDA C$U$A ;reset to current user area JMP SET$USR ;set user and return to caller ; ; Erase destination file and proceed ; COPY4M: ; ; Set File Attributes ; LXI H,D$FCB ;pt to FCB CALL ATTRIB ;clear bytes in FCB and set attr of file BRZ CUA$LOG ;return to caller if R/W not permitted ; ; Delete old file at dest ; LXI D,D$FCB ;delete file already existing MVI C,ERASE ;erase function CALL BDOS ; ; Create new file at dest ; COPY5: LXI D,D$FCB ;create new file and open for writing MVI C,MAKE ;make function CALL BDOS INR A ;if directory full, 0ffh --> 00h. BRNZ COPY6 ;if not, branch. CALL ERMSG DB 'Dest Dir Full',0 JMP LOOPFN ;if error, back to ring processor. ; ; Perform Copy ; COPY6: CALL CPRMPT DB 'Copying File ',0 LXI H,D$FCB+1 ;print file name CALL PRFNSX CALL VPRINT DB ' to ',0 LDA D$FCB ;print dest DU ADI '@' CALL COUT ;print disk LDA R$U$A ;get user CALL PAFDC ;print user MVI A,':' CALL COUT XRA A ;clear 'eof'.. STA EOFLAG ;..flag. COPY6A: CALL CUA$LOG ;current user area LXI H,0 ;clear current-record.. SHLD REC$CNT ;..counter. LHLD BUFSTART ;set buffer start pointer.. SHLD BUF$PT ;..to begin pointer. ; ; read source file -- fill buffer memory or stop on 'eof' -- update 'crc' ; on-the-fly ; COPY7: LHLD BUF$PT ;set dma address to buffer pointer XCHG ; de-pair --> dma address MVI C,SETDMA CALL BDOS LXI D,S$FCB ;source 'fcb' for reading MVI C,READ ;record read function CALL BDOS ORA A ; 00h --> read okay BRZ S$RD$OK DCR A ;eof? BRZ COPY8 ;yes, end-of-file, set 'eof' flag. CALL ERMSG DB 'Read Error',0 JMP LOOPFN ; ; Read OK - Update CRC ; S$RD$OK: LHLD BUF$PT MVI B,128 COPY7A: MOV A,M ;get character and.. CALL UPDCRC ;..add to 'crc' value. INX H DCR B BRNZ COPY7A ;loop 'till record read finished ; ; Update Buffer Ptr and Record Count ; LHLD BUF$PT ;bump buffer pointer.. LXI D,128 ;..by.. DAD D ;..one.. SHLD BUF$PT ;..record. LHLD REC$CNT ;bump buffer.. INX H ;..record count and.. SHLD REC$CNT ;..store. XCHG ;ready to compare to.. ; ; Check for Full Buffer ; LHLD REC$MAX ;..maximum record count (full-buffer). CALL CMPDEHL ;compare BRNZ COPY7 ;if not full, get next record. BR COPY9 ;full, start first write session. ; ; Indicate end-of-file read ; COPY8: MVI A,TRUE ;set 'eof' flag STA EOFLAG ; ; Write source file from memory buffer to destination ; COPY9: LDA R$U$A ;set user to requested.. CALL SET$USR ;..area. LHLD BUFSTART ;adjust buffer pointer.. SHLD BUF$PT ;..to start address. COPY10: LHLD REC$CNT ;buffer empty? MOV A,H ORA L BRZ COPY11 ;buffer empty, check 'eof' flag. DCX H ;dec buffer record count for each write SHLD REC$CNT LHLD BUF$PT ;set up dma address PUSH H ;save for size bump XCHG ;pointer in de-pair MVI C,SETDMA CALL BDOS POP H LXI D,128 ;bump pointer one record length DAD D SHLD BUF$PT LXI D,D$FCB ;destination file 'fcb' MVI C,WRITE ;write record function CALL BDOS ORA A ; 00h --> write okay BRZ COPY10 ;okay, do next record. else.. CALL ERMSG ;..say disk write error. DB 'Copy Disk Full',0 ; ; Error in Write -- Delete Destination File and Abort ; C$ERA: LXI D,D$FCB ;delete.. MVI C,ERASE ;..partial.. CALL BDOS ;..from directory. JMP LOOPFN ;back to ring ; ; Destination Buffer Written - Check for End ; COPY11: LDA EOFLAG ;buffer all written, check for 'eof'. ORA A JZ COPY6A ;branch to read next buffer full LXI D,D$FCB ;point at 'fcb' for file closure MVI C,CLOSE CALL BDOS INR A ;if no-close-error then.. BRNZ CRC$CMP ;..compare file crc's. CALL ERMSG DB 'Copy Close Error',0 JMP C$ERA ; ; Read Destination File and Compare CRCs ; CRC$CMP: LHLD CRCVAL ;transfer 'crc' value to.. SHLD CRCVAL2 ;..new storage area. LXI H,0 ;clear working storage.. SHLD CRCVAL ;..to continue. LXI D,TBUF MVI C,SETDMA CALL BDOS LXI H,D$FCB+12 CALL INITFCB LXI D,D$FCB MVI C,OPEN CALL BDOS INR A ; 0ffh --> 00h if bad open JZ BADCRC ;if bad open, just say 'bad-crc'. XRA A ;zero 'fcb'.. STA D$FCB+32 ;..'cr' field. CRCWF1: LXI D,D$FCB MVI C,READ CALL BDOS ORA A ;read okay? BRZ D$RD$OK ;yes, read more. DCR A ;eof? BRZ FINCRC ;yes, finish up and make 'crc' comparison. CALL ERMSG DB 'Copy Read Error',0 JMP LOOP ; ; Block Read OK - Update CRC ; D$RD$OK: LXI H,TBUF MVI B,128 CRCWF2: MOV A,M ;get character to.. CALL UPDCRC ;..add to 'crc' value. INX H BJNZ CRCWF2 BR CRCWF1 ; ; Read Complete - Check CRCs ; FINCRC: LHLD CRCVAL ;put written-file 'crc' into.. XCHG ;..de-pair. LHLD CRCVAL2 ;put read-file 'crc' and.. CALL CMPDEHL ;..compare 'de/hl' for equality. BRNZ BADCRC ;if not zero, show copy-error message. CALL VPRINT ;if zero, show 'verified' message. DB ' -- Verified',0 JMP CUA$LOG ;return to current user and return to caller ; ; Error on Copy ; BADCRC: CALL CUA$LOG ;return to current user CALL ERMSG DB ' -- CRC Error',0 JMP LOOP ;abort ; ; clear attributes of file (HL) and set attributes on disk ; return code of 0FFH (NZ) indicates OK to proceed, 0 (Z) indicates abort ; ATTRIB: PUSH H ;save regs PUSH H PUSH D LHLD DUM$FCB ;init FCB LXI D,12 ;12 bytes in DAD D POP D CALL INITFCB LHLD DUM$FCB ;pt to dummy FCB XCHG ;... in DE POP H MVI B,12 ;copy PUSH D CALL MOVE POP D ;pt to FCB MVI C,SRCHF ;look for file CALL BDOS INR A ;file not found = 0 POP H RZ ;abort if no file PUSH H ;save ptr DCR A ;adjust RRC ;right 3 bits to indicate offset into BUFF RRC RRC LXI H,TBUF ;pt to buffer ADD L ;pt to FCB of file ADI 9 ;pt to R/O Byte MOV L,A MOV A,M ;get byte ANI 80H ;extract R/O Bit BRZ ATTRIB0 CALL ERMSG DB 0 POP H PUSH H INX H ;pt to file name CALL PRFN ;print file name CALL VPRINT DB ' is R/O -- Erase (Y/N)? ',0 CALL KEYIN CPI 'Y' JZ ATTRIB0 POP H XRA A ;error return RET ATTRIB0: POP H ;get ptr PUSH H ;save ptr INX H ;pt to first char MVI B,11 ;11 Bytes ATTRIB1: MOV A,M ;get byte ANI 7FH ;mask it MOV M,A ;put byte INX H ;pt to next DCR B ;count down JNZ ATTRIB1 POP D ;pt to FCB MVI C,ATTR CALL BDOS XRA A DCR A ;no error return RET ; ;************************************************** ; ; CRC subroutines ; ; initialize tables for fast crc calculations INITCRC: LHLD CRCTBL MVI C,0 ;table index GLOOP: XCHG LXI H,0 ;initialize crc register pair MOV A,C PUSH B ;save index in c-reg MVI B,8 XRA H MOV H,A LLOOP: DAD H BRNC LSKIP MVI A,10H ;generator is x^16 + x^12 + x^5 + x^0 as.. XRA H ;..recommended by ccitt for asynchronous.. MOV H,A ;..communications. produces the same.. MVI A,21H ;..results as public domain programs.. XRA L ;..chek, comm7, mdm7, and modem7. MOV L,A LSKIP: BJNZ LLOOP POP B XCHG ;de-pair now has crc, hl pointing into table. MOV M,D ;store high byte of crc.. INR H MOV M,E ;..and store low byte. DCR H INX H ;move to next table entry INR C ;next index BRNZ GLOOP RET UPDCRC: PUSH B ;update 'crc'.. PUSH H ;..accumulator.. LHLD CRCVAL ;pick up partial remainder XCHG ;de-pair now has partial MVI B,0 XRA D MOV C,A LHLD CRCTBL DAD B MOV A,M XRA E MOV D,A INR H MOV E,M XCHG SHLD CRCVAL POP H POP B RET ; ;************************************************** ; ; WORKHORSE Routines ; ; conin routine (waits for response) ; KEYIN: CALL CIN ;get input CALL CAPS ;capitalize JMP COUT ;echo ; direct console input w/o echo (waits for input) DKEYIN: CALL CIN ;get char from BIOS JMP CAPS ;capitalize ; convert keyboard input to upper case CONVERT: LHLD CMDBUF ; 'current keyboard buffer length'.. INX H MOV B,M ;..to b-reg. MOV A,B ORA A ;if zero length, skip conversion. JZ COMCAN CONVLP: INX H ;point at character to capitalize MOV A,M CALL CAPS MOV M,A ;put back into buffer BJNZ CONVLP RET ; ; Fill buffer with 'spaces' with count in b-reg ; FILL: MVI M,' ' ;put in space character INX H BJNZ FILL ;no, branch. RET ; ; Ignore leading spaces (ls) in buffer, length in c-reg. ; UNSPACE: LDAX D ;get character CPI ' ' RNZ ;not blank, a file is entered. INX D ;to next character DCR C JZ COMCAN ;all spaces --> command recovery error BR UNSPACE ; ; Check for legal filename character -- return with carry set if illegal ; CKLEGAL: LDAX D ;get character from de-pair INX D ;point at next character CPI ' ' ;less than space? RC ;return carry if unpermitted character PUSH H PUSH B CPI '[' ;if greater than 'z', exit with.. BRNC CKERR ;..carry set. MVI B,CHR$TEND-CHR$TBL LXI H,CHR$TBL CHR$LP: CMP M BRZ CKERR INX H BJNZ CHR$LP ORA A ;clear carry for good character POP B POP H RET CKERR: POP B POP H STC ;error exit with carry set RET CHR$TBL: DB ',',':',';','<','=','>' ;invalid character table CHR$TEND: DS 0 ; ; Print file name in S$FCB ; PRFNSX: PUSH H ;save regs PUSH B BR PRFNS0 PRFNS: PUSH H ;affect only PSW PUSH B LXI H,S$FCB+1 PRFNS0: CALL PRFN ;print file name POP B ;restore POP H RET ; ; Print file name pted to by HL ; PRFN: MVI B,8 ;8 chars CALL PRFNS1 MVI A,'.' CALL COUT MVI B,3 ;file type and fall thru PRFNS1: MOV A,M ;get char CALL COUT INX H ;pt to next BJNZ PRFNS1 RET ; ; Copy filename from RINGPOS to SFCB ; RINGFCB: LHLD RINGPOS ;move name from ring to source 'fcb' LXI D,S$FCB ;place to move filename and.. MVI B,12 ;..amount to move (fall thru to MOVE) ; ; move subroutine -- move b-reg # of bytes from hl-pair to de-pair ; MOVE: MOV A,M ;get hl-pair referenced source byte ANI 7FH ;strip attributes STAX D ;put to de-pair referenced destination INX H ;fix pointers for next search INX D BJNZ MOVE RET MOVEB: PUSH H ;SAVE HL, DE PUSH D CALL MOVE POP D ;RESTORE DE, HL POP H RET ; ; Initialize FCB system fields (entry with hl-pair pointing to FCB) ; INITFCB: MVI B,21 ;fill ex, s1, s2, rc, cr counters with zeros. INITLP: MVI M,0 ;put zero (null) in memory INX H BJNZ INITLP RET ; ; Disk system reset -- login requested drive ; RESET: MVI C,RESETDK ;reset system CALL BDOS LDA R$DR ;make requested drive.. SET$DR: MOV E,A ;..current MVI C,LOGIN JMP BDOS ;return to caller ; ; Set/reset (or get) user area (call with binary user area in a-reg) ; SET$USR: MOV E,A ;user number in E GET$USR: MVI C,SGUSER JMP BDOS ;return to caller ; ; Compare de-pair to hl-pair and set flags accordingly ; CMPDEHL: MOV A,D ;see if high bytes set flags CMP H RNZ ;return if not equal MOV A,E CMP L ;low bytes set flags instead RET ; ; Shift hl-pair b-reg bits (-1) to right (divider routine) ; SHIFTLP: DCR B RZ MOV A,H ORA A RAR MOV H,A MOV A,L RAR MOV L,A BR SHIFTLP ; ; Determine free storage remaining on selected drive ; FRESTOR: MVI C,INQDISK ;determine current drive CALL BDOS ;returns 0 as a:, 1 as b:, etc. INR A ;make 1 --> a:, 2 --> b:, etc. STA FCB MVI C,GETPARM ;current disk parameter block CALL BDOS INX H ;bump to.. INX H MOV A,M ;..block shift factor. STA BSHIFTF ; 'bsh' INX H ;bump to.. MOV A,M ;..block mask. STA B$MASK ; 'blm' INX H ;bump to.. INX H ;..get.. MOV E,M ;..maximum block number.. INX H ;..double.. MOV D,M ;..byte. XCHG SHLD B$MAX ; 'dsm' MVI C,INQALC ;address of allocation vector CALL BDOS XCHG ;get its length LHLD B$MAX INX H LXI B,0 ;initialize block count to zero GSPBYT: PUSH D ;save allocation address LDAX D MVI E,8 ;set to process 8 bits (blocks) GSPLUP: RAL ;test bit BRC NOT$FRE INX B NOT$FRE: MOV D,A ;save bits DCX H MOV A,L ORA H BRZ END$ALC ;quit if out of blocks MOV A,D ;restore bits DCR E ;count down 8 bits BRNZ GSPLUP ;branch to do another bit POP D ;bump to next count.. INX D ;..of allocation vector. BR GSPBYT ;process it END$ALC: POP D ;clear alloc vector pointer from stack MOV L,C ;copy # blocks to hl-pair MOV H,B LDA BSHIFTF ;get block shift factor SUI 3 ;convert from sectors to thousands (k) BRZ PRT$FRE ;skip shifts if 1k blocks FREK$LP: DAD H ;multiply blocks by k-bytes per block DCR A ;multiply by 2, 4, 8, or 16. BRNZ FREK$LP PRT$FRE: SHLD DISKSP ;save disk space RET ; ; Print free space on disk ; PRINT$FRE: CALL ERMSG ;position and set flags DB 0 LHLD DISKSP CALL PHLFDC ; # of free k-bytes in hl-pair CALL VPRINT DB 'K Bytes on Disk',0 RET ; ;************************************************** ; ; MESSAGE Routines ; ; Print VFILER Banner ; BANNER: CALL VCLS ;clear screen LXI H,BANADR CALL GOTOXY CALL VPRINT ;print banner DB 'VFILER, Version ' DB VERS/10+'0','.',(VERS MOD 10)+'0' IF Z80 DB ' ',DIM,'[Z80 Code]',BRIGHT ELSE DB ' ',DIM,'[8080 Code]',BRIGHT ENDIF DB 0 RET ; ; Home the Cursor ; CUR$FIRST: LXI H,CURHOME ; HOME ADDRESS SHLD CURAT ; SET CURSOR POSITION JMP GOTOXY ; ; Last File Position ; CUR$LAST: LHLD RINGPOS ; ADVANCE SHLD LOCPOS ; SET LOCAL POSITION CL0: LXI D,13 DAD D XCHG LHLD LOCEND ; END OF LOCAL RING? CALL CMPDEHL RZ XCHG ; NEW POSITION SHLD LOCPOS PUSH H ; SAVE POSITION CALL CUR$NEXT ; ADVANCE CURSOR POP H ; GET POSITION BR CL0 ; ; Advance the Cursor ; CUR$NEXT: LHLD CURAT ; COMPUTE NEW POSITION MOV A,L ; CHECK FOR NEW LINE ADI 19 ; SIZE OF EACH ENTRY CPI 70 BRNC CN1 ; ADVANCE TO NEXT LINE MOV L,A ; NEW POSITION SHLD CURAT JMP GOTOXY CN1: MOV A,H ; GET LINE LXI H,CURHOME ; GET COL MOV H,A ; SET LINE AND FALL GO TO CUR$DOWN SHLD CURAT BR CUR$DOWN ; ; Back Up the Cursor ; CUR$BACK: LXI H,CURHOME ; GET HOME XCHG ; ... IN DE LHLD CURAT CALL CMPDEHL ; COMPARE BRZ CUR$LAST ; GOTO END IF LAST MOV A,L ; CHECK FOR FIRST COL CMP E BRZ CB1 SUI 19 ; BACK UP ONE COL MOV L,A SHLD CURAT ; NEW POS JMP GOTOXY CB1: MOV A,E ; GET HOME COL ADI 19*3 ; GET LAST COL MOV L,A DCR H ; PREV LINE SHLD CURAT JMP GOTOXY ; ; Move Cursor Down One Line ; CUR$DOWN: LXI H,CURHOME ; GET HOME ADDRESS MOV B,H ; LINE IN B LHLD CURAT ; GET CURRENT ADDRESS INR H ; MOVE DOWN MOV A,H ; CHECK FOR TOO FAR SUB B CPI EPS/4 BRNC CD1 SHLD CURAT ; OK, SO SET POSITION JMP GOTOXY CD1: MOV A,L ; GET COL LXI H,CURHOME MOV L,A SHLD CURAT JMP GOTOXY ; ; Refresh Screen ; REFRESH: LHLD CURAT ; SAVE CURSOR AND RING POSITIONS SHLD SCURAT LHLD RINGPOS SHLD SRINGPOS CALL BANNER ; PRINT BANNER ; IF BIHELP ;built-in help? LDA HELPDISP ;DISPLAY HELP? ORA A ;0=NO BRZ REF1 CALL HELPMSG ;PRINT HELP MESSAGE BR REF2 REF1: ENDIF ;BIHELP ; CALL DISPFILES ; DISPLAY FILES REF2: LXI H,DUADR ; DU ADDRESS CALL GOTOXY LXI H,C$DR ; PT TO CURRENT DRIVE (FOLLOWED BY CUR USER) CALL PRDU ; PRINT DU:DIR> LXI H,CPMADR ; COMMAND PROMPT MESSAGE CALL GOTOXY CALL VPRINT ; PROMPT WITH DRIVE PREFIX DB DIM DB 'Command (? = ',0 LDA HELPDISP ; IN HELP NOW? ORA A ; 0=NO BRZ REF3 CALL VPRINT DB 'Files',0 BR REF4 REF3: CALL VPRINT DB 'Help',0 REF4: CALL VPRINT DB ')?',BRIGHT,0 LHLD SCURAT ; RESTORE CURSOR AND RING POSITIONS SHLD CURAT LHLD SRINGPOS SHLD RINGPOS CALL SETCUR ; RESTORE CURSOR ON SCREEN RET ; ; Print DU pted to by HL ; PRDU: PUSH H ; SAVE REGS PUSH B MOV A,M ; GET DRIVE MOV B,A ADI 'A' ; CONVERT TO LETTER CALL COUT INX H ; PT TO USER MOV A,M ; GET USER MOV C,A CALL PAFDC ; PRINT USER AS FLOATING MVI A,':' ; PRINT COLON CALL COUT CALL DUTDIR ; SCAN NAMED DIRECTORY TABLE BRZ PRDU2 ; NO NAME? MVI B,8 ; PRINT NAME PRDU1: MOV A,M ; GET CHAR CPI ' ' ; DONE IF SPACE ENCOUNTERED BRZ PRDU3 CALL COUT INX H BJNZ PRDU1 BR PRDU3 PRDU2: CALL VPRINT DB 'Noname',0 PRDU3: POP B ; RESTORE REGS POP H RET ; ; Refresh File Display ; DISPFILES: CALL CUR$FIRST ; POSITION CURSOR AT FIRST POSITION LHLD LOCBEG ; PT TO FIRST FILE NAME SHLD LOCPOS ; SAVE LOCAL POSITION DSPF1: LHLD LOCEND ; AT END? XCHG LHLD LOCPOS CALL CMPDEHL JZ CUR$FIRST ; POSITION AT FIRST ENTRY AND RETURN MVI B,4 ; 4 SPACES MVI A,' ' DSPF2: CALL COUT BJNZ DSPF2 PUSH H ; SAVE CURRENT LOCAL POSITION IN RING INX H ; PT TO FILE NAME CALL PRFN ; PRINT FILE NAME MOV A,M ; PRINT TAG CALL COUT POP H ; GET CURRENT LOCAL POSITION LXI D,13 DAD D SHLD LOCPOS CALL CUR$NEXT ; ADVANCE CURSOR BR DSPF1 ; ; Position Cursor at CURAT ; SETCUR: LDA HELPDISP ; NOGO IF IN HELP DISPLAY ORA A RNZ LHLD CURAT CALL GOTOXY CALL VPRINT DB '-->',0 RET ; ; Clear Cursor ; CLRCUR: LDA HELPDISP ; NOGO IF IN HELP DISPLAY ORA A RNZ LHLD CURAT CALL GOTOXY CALL VPRINT DB ' ',0 RET ; ; Command Prompt ; CPRMPT: LXI H,CPADR ; GET ADDRESS MPRINT: PUSH H ; SAVE ADDRESS CALL GOTOXY PUSH B MVI B,76-(CPADR MOD 255) CALL VEREOL ; ERASE TO EOL POP B POP H ; GET ADDRESS CALL GOTOXY ; POSITION CURSOR JMP VPRINT ; PRINT MESSAGE AND RETURN ; ; Working Message ; WORKMSG: CALL ERMSG DB DIM,'Working ...',BRIGHT,0 RET ; ; Error Message ; ERMSG: MVI A,0FFH ; SET ERROR MESSAGE FLAG STA ERMFLG LXI H,ERADR ; GET ADDRESS BR MPRINT ; ; Print File Size Info ; FSNOTE: CALL ERMSG ; USE THIS ROUTINE DB 'Size of ',0 RET ; ; Position for File Size Print ; ATFS: LXI H,FSADR+13 ; POSITION FOR PRINT OF FILE SIZE JMP GOTOXY ; ; Clear Error Message ; ERCLR: XRA A ; CLEAR FLAG STA ERMFLG LXI H,ERADR ; POSITION CALL GOTOXY PUSH B MVI B,76-(ERADR MOD 255) CALL VEREOL ; ERASE TO EOL POP B RET ; ; Position at Command Prompt and Clear It ; ATCMD: LXI H,CPADR ; POSITION CALL GOTOXY PUSH B MVI B,76-(CPADR MOD 255) CALL VEREOL ; CLEAR MESSAGE POP B LXI H,CPADR ; REPOSITION JMP GOTOXY ; ; Position at Bottom of Screen and Prompt for Continuation ; BOTTOM: LXI H,BOTADR ; POSITION CALL GOTOXY ; ; Prompt for Continuation ; SAK: CALL VPRINT DB DIM,'Strike Any Key -- ',BRIGHT,0 JMP KEYIN ; ; S T O R A G E ; ; Initialized ; HEADMSG: DB 'File: ',0 MOREHELP: DB 'HELP ' ;HELP Command for further info VFNAME ;VFILER Name DB 0 MACFCB: DB 0 VFNAME ;VFILER Name VFNFILL ;Filler DB 'CMD' FILERCMD: VFNAME ;VFILER Name VFNFILL ;Filler DB ' ' ;one space FILE$D: DB 'x' FILE$U: DB 'xx' DB ':' ;colon DB 0 JOKER: DB '???????????' ;*.* equivalent FIRST$M: DB FALSE ;1st time thru in mass-copy mode MFLAG: DB TRUE ;multiple file copy flag-->0 for mass copy TAG$TOT: DW 0 ;summation of tagged file sizes CMDBUF: DS 2 ;command buffer maximum length, usage, and.. ; ; Uninitialized ; STACK: DS 2 LWIDTH: DS 1 ;WIDTH OF LINE LTPP: DS 1 ;LINES OF TEXT PER PAGE LSPP: DS 1 ;LINES TO SKIP PER PAGE LFFEED: DS 1 ;PRINTER CAN FORMFEED? (0=NO) CWIDTH: DS 1 ;WIDTH OF SCREEN CTPP: DS 1 ;LINES OF TEXT PER SCREEN CSPP: DS 1 ;LINES TO SKIP PER SCREEN ALPHA: DS 1 ;alphabetization flag (0=type and name, 0FFH= ;...name and type) B$MAX: DS 2 ;highest block number on drive B$MASK: DS 1 ;sec/blk-1 BSHIFTF: DS 1 ;# of shifts to multiply by sec/blk BUFENTRY: DS 2 ;buffer start BUF$PT: DS 2 ;copy buffer current pointer.. BUFSTART: DS 2 ;..and begin pointer. CANFLG: DS 1 ;no-file-found cancel flag C$DR: DS 1 ;'current drive' C$U$A: DS 1 ;'current user area' (must follow C$DR) CHARCNT: DS 1 ;character count for tab expansion CON$LST: DS 1 ;bdos function storage CRCTBL: DS 2 ;tables for 'crc' calculations CRCVAL: DS 2 ;2-byte 'crc' value of working file and.. CRCVAL2: DS 2 ;..of finished source read-file. CURAT: DS 2 ;current cursor position DELCODE: DS 1 ;deletion code (0=delete not done) D$FCB: DS 33 ;fcb for destination file/new name if rename DISKSP: DS 2 ;space remaining on disk DUM$FCB: DS 2 ;dummy FCB for file attributes DRLET: DS 1 ;scratch for drive letter EOFLAG: DS 1 ;file copy loop 'eof' flag ERMFLG: DS 1 ;error message present flag H$DR: DS 1 ;home drive H$U$A: DS 1 ;home user area (must follow H$DR) HELPDISP: DS 1 ;display help screen (0=no) LPSCNT: DS 1 ;lines-per-screen for 'view' LOCBEG: DS 2 ;local beginning of ring LOCEND: DS 2 ;local end of ring LOCPOS: DS 2 ;local ring position (temp) MASSOP: DS 1 ;mass file operation code (0=no) MAXDR: DS 1 ;max driver letter MDFLG: DS 1 ;mass delete verify flag O$USR: DS 1 ;store initial user area for exit R$DR: DS 1 ;'requested drive' RCNT: DS 2 ;# of records in file and.. REC$CNT: DS 2 ;..currently in ram buffer. REC$MAX: DS 2 ;maximum 128-byte record capacity of buffer RING: DS 2 ;ptr to beginning of ring RINGI: DS 2 ;ring sort pointer RINGJ: DS 2 ;another ring sort pointer RINGEND: DS 2 ;current ring end pointer RINGPOS: DS 2 ;current ring position in scan R$U$A: DS 1 ;'requested user area' SCURAT: DS 2 ;save cursor position S$FCB: DS 36 ;fcb for source (random record) file SRINGPOS: DS 2 ;save ring position T$DR: DS 1 ;temp disk TEST$RT: DS 1 ;intermediate right-justify data T$U$A: DS 1 ;temp user T$UN$FG: DS 1 ;tag/untag file summation switch USER: DS 1 ;temp user buffer VIEWFLG: DS 1 ;00h-->to list/punch else to crt 'view' END