org 100h true: equ -1 false: equ not true eof: equ 1ah dle: equ 90h bdos: equ 5 buffer: equ 80h fcb: equ 50h begin: hell: lxi h,0 dad sp shld ccpstack lxi sp,stack lhld bdos+1 mvi l,0 lxi d,-1700h dad d shld topmem call ilprt db 13,10,'USQ Version 1.19 Dave Rand 07/28/1983',0 mvi c,25 call bdos sta current xra a ;default to no prompt sta pract lda buffer ora a jnz ok ;if no filespec, print instructions inst: call ilprt db 13,10,'Use: USQ afn [afn afn ...] [destination drive:]',0 mvi a,255 ;show prompt mode active sta pract in1: call ilprt db 13,10,'*',0 lxi h,buffer mvi m,120 xchg mvi c,10 call bdos lda buffer+1 ora a jz in1 sta buffer mov e,a mvi d,0 lxi h,buffer+2 push h dad d mvi m,0 pop h lxi d,buffer+1 in2: mov a,m stax d ora a jz ok call convuc stax d inx h inx d jmp in2 convuc: cpi 'a' rc cpi 'z'+1 rnc ani 5fh ret ok: lda pract ora a jz nosel mvi a,13 call bdos lda current mov e,a mvi c,14 call bdos nosel: lxi h,80h lxi d,locl lxi b,80h call ldir mvi c,25 call bdos sta current inr a sta destd lxi d,locl+1 ex1: call non$blnk ;point to first valid char jz inst ;wups... no char to be had! mul1: xchg shld nxtchr lxi h,0 shld max1 lxi h,filespecs ;point to begin of wildcard table parse: push h call make$fcb ;make FCB please! lda fcb+1 cpi ' ' jnz par2 call ilprt db 13,10,'Output drive = ',0 lda fcb sta destd adi '@' call conout call ilprt db ':',0 jmp par1 par2: pop h call buildam ;build amb file table shld lastmem push h lhld max1 dad d shld max1 par1: lhld nxtchr pl1: mov a,m cpi ' ' inx h jz pl2 ora a jz pl3 jmp pl1 pl2: shld nxtchr xchg call non$blnk pl3: pop h jnz parse ;all done? gt1: ;Name ok, any wildcards match? lhld max1 mov a,l ora h jnz cont ;yep, can continue call errext db 13,10,'No file(s) found.',0 cont: lhld lastmem shld sob shld eob xchg lhld topmem mov a,h sub d mov h,a mov a,l sbb e mov l,a ;hl now has total memory free. Divide in half. xra a mov a,h rar mov h,a mov a,l rar mov l,a ;see if enuf memory. dcr h mov a,h ora a jnz memok call errext db 13,10,13,10,'Out of memory. Use more specific filenames.',0 memok: xchg lhld lastmem dad d shld endmem inr h inr h mvi l,0 shld sob1 shld sob1a lhld topmem shld eob1 main: lxi h,filespecs main1: lxi d,ifcb lxi b,12 call ldir push h push d pop h inx d mvi m,0 lxi b,38-13 call ldir lxi d,ifcb mvi c,15 call bdos inr a jz mainr sysok: call ilprt db 13,10,0 call pfcb lhld lastmem shld sob shld eob push h call getw lxi d,0ff76h call cmpdehl pop h jz usq call ilprt db ' is not a squeezed file.',13,10,0 mainr: lxi sp,stack-2 lhld max1 dcx h shld max1 mov a,h ora l pop h jnz main1 jmp usq7 ;this is start of baseline USQ code usq: xra a ;force init char read sta numlft sta rcnt ;and zero repeats usq1: call getw ;get cksum, and store shld filecrc call ilprt db ' -> ',0 lxi h,buffer ;get name of orig. file, usq2: push h call get1 ;display, and store it pop h ;for filename parse push psw call convuc mov b,a pop psw mov a,b mov m,a jnz mainr ora a jz usq3 push h call conout pop h inx h jmp usq2 usq3: lxi h,buffer ;parse orig. name from shld nxtchr ;buffer. Create FCB call make$fcb lxi h,fcb lxi d,dfcb lxi b,1+8+3 call ldir lda destd sta dfcb lxi h,dfcb+1+8+3 lxi d,dfcb+1+8+3+1 lxi b,38-13 mvi m,0 call ldir lxi d,dfcb push d mvi c,19 call bdos pop d mvi c,22 call bdos inr a jnz usq3a call errext db 13,10,'No directory space. Aborting.',0 usq3a: call getw shld numvals lxi d,258 call cmpdehl jc usq3b call errext db 13,10,'Files has illegal decode size. Aborting.',0 usq3b: lxi d,table usq4: shld max mov a,h ora l jz usq5 push d call getw pop d xchg mov m,e inx h mov m,d inx h push h call getw xchg pop h mov m,e inx h mov m,d inx h xchg lhld max dcx h jmp usq4 usq5: lxi h,0 usq6: push h call getnxt pop h jnz usq8 mov e,a mvi d,0 dad d push h call put1 pop h jmp usq6 usq8: xchg lhld filecrc call cmpdehl push psw call flush lxi d,dfcb mvi c,16 call bdos inr a jnz usq9 call errext db 13,10,'Close failed...',0 usq9: pop psw jz mainr call ilprt db 13,10,'ERROR - Checksum error in file ',0 call pfcb usq7: lxi sp,stack lda pract ora a jnz in1 lxi sp,0 ccpstack: equ $-2 ret errext: pop h mov a,m ora a jz usq7 inx h push h call conout jmp errext conout: ani 127 mov e,a mvi c,2 call bdos ret cmpdehl: mov a,h cmp d rnz mov a,l cmp e ret ilprt: pop h mov a,m ora a inx h push h rz call conout jmp ilprt get1: lhld eob xchg lhld sob call cmpdehl jz get1r mov a,m inx h shld sob cmp a ret get1r: lhld lastmem shld sob shld eob get1r1: push h xchg mvi c,26 call bdos lxi d,ifcb mvi c,20 call bdos pop h ora a jnz get1r2 lxi d,128 dad d xchg lhld endmem call cmpdehl xchg jnc get1r1 get1r2: shld eob xchg lhld sob call cmpdehl jnz get1 mvi a,255 ora a ret put1: mov c,a lhld eob1 xchg lhld sob1 call cmpdehl jz put1s mov m,c inx h shld sob1 ret put1s: push b call flush pop b mov a,c jmp put1 flush: lhld sob1a xchg lhld sob1 call cmpdehl rz xchg put1sa: push h xchg mvi c,26 call bdos mvi c,21 lxi d,dfcb call bdos ora a jnz put1sc pop h lxi d,128 dad d xchg lhld sob1 xchg call cmpdehl jc put1sa lhld sob1a shld sob1 ret put1sc: call errext db 13,10,'Disk full. Aborting.',0 getw: call get1 jnz badr push psw call get1 jnz badr mov h,a pop psw mov l,a ret badr: call ilprt db 13,10,'Premature EOF on file... aborted.',0 jmp mainr getnxt: lda rcnt ;see if in the middle of ora a ;repeat sequence... jz getn7 dcr a sta rcnt lda last cmp a ret getn7: call getn4 cpi dle jnz getn5 call getn4 ora a jnz getn6 mvi a,dle ;dle is encoded as dle,0 cmp a ret getn6: dcr a dcr a sta rcnt lda last cmp a ret getn5: sta last cmp a ret getn4: lxi d,0 ;pointer @ sot lda char mov c,a getn1: lda numlft ora a jnz getn2 push d call get1 jnz badr pop d mov c,a mvi a,8 getn2: dcr a sta numlft mov a,c rrc mov c,a lxi h,table jnc getn3 inx h inx h ;add 2 to point to right node getn3: dad d dad d dad d dad d ;ok.. pointing close to right plc.. mov e,m inx h mov d,m mov a,d ani 128 jz getn1 mov a,c sta char mov a,d cpi 254 ;is special eof? mvi a,eof jz geteof ;yup mov a,e cma cmp a ret geteof: pop h ora a ret ;end of baseline USQ code buildam: equ $ lxi d,0 ;none found yet push d push h lda fcb ora a jz build1 mov e,a dcr e mvi c,14 call bdos build1: mvi c,17 lxi d,fcb call bdos pop h pop d inr a ;any found? jnz loop buildr: push h push d lda current mov e,a mvi c,14 call bdos pop d pop h ret loop: inx d push d push h dcr a add a add a add a add a add a lxi h,buffer mov e,a mvi d,0 dad d pop d inx h lda fcb stax d inx d mvi b,11 ldir2: mov a,m stax d inx h inx d dcr b jnz ldir2 xchg push h mvi c,18 lxi d,fcb call bdos pop h pop d inr a jnz loop jmp buildr pfcb: lda ifcb ora a jz print1 mov b,a ;New! lda current inr a cmp b jz print1 mov a,b ;New... adi 'A'-1 call conout mvi a,':' call conout print1: lxi h,ifcb+1 mvi c,8 print1a: push h push b mov a,m cpi ' ' jz print1b call conout print1b: pop b pop h inx h dcr c jnz print1a mvi a,'.' call conout lxi h,ifcb+1+8 mvi c,3 print2a: push h push b mov a,m cpi ' ' jz print2b call conout print2b: pop b pop h inx h dcr c jnz print2a ret MAKE$FCB: ; ;Create a FCB in FCB ;'NEXT$CHAR' is saved pointing to the next character ;following the string set up as a file NAME.TYPE. ; ;For example, the SAVE command finds the ascii string ;corresponding to the ntmber of decimal records to write ;as a file name in the first 16 bytes of the fcb, and ;the name of the file to created in the second 16 bytes ;of the fcb. ; MAKE1$FCB: LXI H,FCB ;point to ccp's fcb PUSH H ;save char pointer once LHLD NXTCHR ;get pointer to next char in buffer XCHG ;put buffer pointer in CALL NON$BLNK ;get next non-blank char in acc POP H LDAX D ORA A JZ NO$DRV SBI '@' MOV B,A INX D LDAX D CPI ':' JZ YES$DRV DCX D NO$DRV: LDA current inr a ;@1.02 MOV M,A JMP GET$NAME ; YES$DRV: MOV M,b INX D ; ;The next 8 characters in the CCP$FCB are to be a file ;name. Transfer the contents of the CON$BUF, checking ;for reserved characters and ambigious name char ('*' or '?') ;filling with blanks or '?' as required. ; GET$NAME: MVI B,8 GET1$NAME: CALL TEST4RES JZ FIL$SPC INX H CPI '*' JNZ NOT$AMB MVI M,3FH JMP KEEP$CNT ; NOT$AMB: MOV M,A INX D KEEP$CNT: DCR B JNZ GET1$NAME FIND$RES: CALL TEST4RES JZ PUT$TYPE INX D JMP FIND$RES ; FIL$SPC: INX H MVI M,' ' DCR B JNZ FIL$SPC ; ;The next three characters in the CCP$FCB are to be the ;file type. Transfer the contents of CON$BUF checking ;for reserved characters and ambigious characters ('*' or '?') ;Fill with '?'s as required. ; PUT$TYPE: MVI B,3 CPI '.' JNZ FIL2$SPC INX D PUT2$TYPE: CALL TEST4RES JZ FIL2$SPC INX H CPI '*' JNZ XFER$TYPE MVI M,'?' JMP KEEP2$CNT ; XFER$TYPE: MOV M,A INX D KEEP2$CNT: DCR B JNZ PUT2$TYPE ; ;We have a FILENAME.TYPE, so now find the next reserved ;character in the command string so we can save NEXT$CHAR ;below ; FIND1$RES: CALL TEST4RES JZ FILL$NULL INX D JMP FIND1$RES ; FIL2$SPC: INX H MVI M,' ' DCR B JNZ FIL2$SPC ; ;Set the file extent (byte 12 of fcb) and the ;unused bytes (13 and 14) of the fcb to zero ; FILL$NULL: MVI B,3 FILL1$NULL: INX H MVI M,0 DCR B JNZ FILL1$NULL ; ;We are almost finished. Save pointer of the next character ;in the console buffer, count the number of ambigious char's ;in the filename.type, and return with the count in acc and ;the flags set ; XCHG SHLD NXTCHR RET ; ;Test char at for reserved characters 'SPACE', ;'EQUALS', 'UNDERLINE', 'PERIOD', 'COLON', 'SEMI-COLON', ;'LEFT-ARROW', 'RIGHT-ARROW', and return with zero set, ;if found. If the character is less than an ascii SPACE, ;and exit is made to the ECHO$BUF routine which will ;print the error prompt and echo the buffer ; TEST4RES: LDAX D ;get (DE) in acc ORA A ;set the flags RZ ;get back if null CPI ' ' ;is it less than a SPACE? RZ ;if ' ', then get back CPI '=' RZ ;if '=', get back CPI '_' RZ ;if '_', get back CPI '.' RZ ;if '.', get back CPI ':' RZ ;if ':', get back CPI ';' RZ ;if ';', get back CPI '<' RZ ;if '<', get back CPI '>' Ret ;if '>', get back ; ;Search the character string pointed by until ;a non-blank char or null is found. If a null is ;found, return with ZERO flag set. Otherwise return ;with the char in the acc and pointing to it. ;(null is placed at end of command string by convert ;routine) ; NON$BLNK: LDAX D ;get next char ORA A ;set flags RZ ;get back if null CPI ' ' ;is it a space? RNZ ;no, then get back INX D ;bump the pointer JMP NON$BLNK ;loop ldir: mov a,m stax d inx h inx d dcx b mov a,b ora c jnz ldir ret numvals: dw 0 max: dw 0 numlft: db 0 char: db 0 last: db 0 rcnt: db 0 lastmem: dw 0 max1: dw 0 nxtchr: dw 0 current: db 0 endmem: dw 0 topmem: dw 0 sob: dw 0 eob: dw 0 sob1: dw 0 sob1a: dw 0 eob1: dw 0 destd: db 0 pract: db 0 filecrc: dw 0 ifcb: ds 40 dfcb: ds 40 locl: ds 80h ds 100 stack: equ $ table: ds 258*4 filespecs: equ $ end begin  ifcb: ds 40 dfcb: ds 40 locl: ds 80h ds 100 stack: equ $ table: ds 258*4 files