; w o r k h o r s e r o u t i n e s (comm723b.asm) ; inline print-string to console ILPRT XTHL ;exchange top of stack and hl-pair and.. ILPLP MOV A,M ;..get text. CALL TYPE ;show (unless quiet mode) INX H ;get next char and test.. MOV A,M ORA A ;..for end of text. JNZ ILPLP XTHL ;set hl-pair RET ; print routine to show softkey strings on console using while ; in terminal mode. also entry at 'textout' used for general string ; typing terminated with '@'. enter with string-address in hl-pair. IF SOFTKEY REVIEW LXI H,SOFTMSG ;address of string table ENDIF ;softkey TEXTOUT MOV A,M CPI '@' ;table-end terminator signals.. RZ ;..return. ORA A ;single-string null (zero) terminator.. CZ CRLF ;..means add newline. CALL TYPE INX H ;bump to next character and.. JMP TEXTOUT ;..loop till '@'. ; cursor return/line feed to console CRLF PUSH PSW MVI A,CR CALL TYPE MVI A,LF CALL TYPE POP PSW RET ; cursor return to console CRONLY PUSH PSW MVI A,CR CALL TYPE POP PSW RET ; constat routine STAT PUSH B PUSH D PUSH H VSTAT CALL $-$ ;constat address from initadr POP H POP D POP B ORA A ; 00h --> not ready RET ; conin routine KEYIN PUSH B PUSH D PUSH H VKEYIN CALL $-$ ;conin address from initadr POP H POP D POP B RET ; type to console with optional list to printer TYPE PUSH PSW PUSH B PUSH D PUSH H MOV C,A ;save char to type/list LDA LISTFLG ;char to printer? ORA A CZ LISTOUT ;yes, out to printer ring-buffer.. MOV E,C MVI C,WRCON ;..then type to console unless.. LDA QFLG ;..quiet mode requested. ORA A CNZ BDOS ;write to console if not quiet mode POP H POP D POP B POP PSW RET ;simply return if 'quiet' ; case conversion -- call with character in a-register UCASE CPI 61H ; < small a? RC ;return if so CPI 7AH+1 ; > small z? RNC ;if so, ignore. ANI 5FH ;otherwise capitalize RET ; wait for keyboard response and display character RESPOND CALL KEYIN CALL UCASE JMP TYPE ; universal delay loop -- call with # of 100 msec in b-reg TIMER PUSH PSW PUSH D TIMER0 LXI D,417*MHZ ; (dcx loop = .1 sec) TIMERLP DCX D MOV A,D ORA E JNZ TIMERLP DCR B ; # of 100 milliseconds JNZ TIMER0 POP D POP PSW RET ; decimal pretty print (h must contain msb; l, the lsb.) DECOUT PUSH PSW PUSH B PUSH D PUSH H LXI B,-10 ;conversion radix LXI D,-1 ;divide by radix DECOU2 DAD B ; (subtract ten) INX D JC DECOU2 LXI B,10 DAD B ;add radix back in once XCHG MOV A,H ORA L ;test for zero CNZ DECOUT ; (recursive call) MOV A,E ADI '0' ;convert from 'bcd' to 'hex' CALL TYPE POP H POP D POP B POP PSW RET ; 16-bit hex output routine DHXOUT PUSH H PUSH PSW MOV A,H ;get ms byte CALL HEXO ;output high order byte MOV A,L ;get ls byte CALL HEXO ;output low order byte POP PSW POP H RET ; 8-bit hex output (left nibble processed, then right) HEXO PUSH PSW ;save to obtain right nibble RAR ;rotate 4 bits right to get 'msp' RAR RAR RAR CALL NIBBLE ;print left nibble POP PSW ;get right nibble NIBBLE ANI 0FH ;mask to isolate nibble ADI 90H ;add offset DAA ; 'decimal adjust' ACI 40H ;add offset DAA JMP TYPE ;ret to caller ; copy contents pointed to by hl-pair to de-pair, count in b-reg. MOVE128 MVI B,128 MOVE MOV A,M STAX D ;copy char to memory at address in de-pair INX H INX D DCR B JNZ MOVE RET ; copy fcb2 to fcb location -- record and extent #'s zero'd MOVEFCB LXI H,FCB+16 LXI D,FCB MVI B,16 ;copy 16 bytes CALL MOVE XRA A ;zero.. STA FCBRNO ;..record and.. STA FCBEXT ;..extent numbers. RET ; copy fcb to fcb3 location MOVE2 LXI H,FCB3 CALL INITFCB LXI H,FCB LXI D,FCB3 MVI B,12 ;copy 1st 12 bytes JMP MOVE ;return to caller from 'move' routine ; initialize file control block INITFCB MVI M,0 ;entry at +2 will leave drive # intact. INX H ;will initialize an fcb.. MVI B,11 ;..pointed to by hl-pair. fills 1st pos LOOP10 MVI M,' ' ;..with 0, next 11 with.. INX H ;..blanks, and last.. DCR B ;..21 with nulls (0's). JNZ LOOP10 MVI B,21 LOOP11 MVI M,0 INX H DCR B JNZ LOOP11 RET ; multiply value in h-reg by value in a-reg (returns with answer ; in hl-pair) MULHA MVI D,0 MOV E,H MOV L,H MVI H,0 MULLP DCR A RZ DAD D JMP MULLP ; divide contents of hl-pair by value in a-reg ; (returns with l-reg containing quotient; h-reg, remainder.) DIVHLA PUSH B MVI B,8 ;shift factor to b-reg MOV C,A ;divisor to c-reg DIV2 XRA A ;clear carry flag and accumulator DAD H MOV A,H SUB C JM DIV3 ;don't borrow on neg results MOV H,A MOV A,L ORI 1 ;borrow 1 MOV L,A DIV3 DCR B JNZ DIV2 POP B RET ; shift hl-pair b-reg bits (-1) to right (divider routine) SHIFTHL MVI B,4+1 ;load for four loops SHIFTLP DCR B RZ ;return when b-reg zeros MOV A,H ORA A ;clear carry and.. RAR ;..rotate right thru carry. MOV H,A ;put back MOV A,L ;rotate lsb and.. RAR MOV L,A ;..put back. JMP SHIFTLP ;loop back ; subtraction subroutine -- returns hl-pair = hl-pair - de-pair SUBDE MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A RET ; compare de/hl-pairs -- set carry/zero flags CMPDEHL MOV A,D ;flags set by high bytes? CMP H RNZ ;if not equal, return. MOV A,E CMP L ;flags set by low bytes instead? RET ; disk-system reset -- allows disk change RESET MVI C,INQDISK ;get current logged-in drive, 25. CALL BDOS STA C$DR ;save current drive designator here.. PUSH PSW ;..and here. MVI C,RESETDK ;reset disk system, 13. CALL BDOS POP PSW ;put current for.. SET$DR MOV E,A ;..selection.. MVI C,LOGIN ;..as default, 14. JMP BDOS ; (returns to caller) ; set/reset (or get) user area (call with binary user area in a-reg) SET$USR MOV E,A GET$USR MVI C,SGUSER JMP BDOS ; set cp/m fcb with command line SETFCB LXI D,CMDBUF LXI H,FCB JMP CMDLINE ; error statement display -- abort to command mode ERXIT MVI A,'Q' ;reset quiet flag (qflg). (allows all.. STA QFLG ;..error msg to show in quiet mode.) CALL CRLF POP H ;address of error msg CALL TEXTOUT ERXIT1 CALL CRLF MVI A,TRUE STA ABORTFLG LDA BATCHFLG ORA A JNZ DONETCB JMP ABORT ;abort other computer ; 'listout' -- entry to printer (list device) ring-buffer LISTOUT MOV A,C ;filter out all control.. CPI HT ;..codes, except cr, lf, and tab, and.. JZ LSTBUFF ;..all graphics characters. CPI CR JZ LSTBUFF CPI LF JZ LSTBUFF CPI 7FH RNC CPI ' ' RC ;fall-thru to 'lstbuff' ; 'lstbuff' puts c-register byte into next position in printer ring- ; buffer. if buffer is full, routine returns with character lost. LSTBUFF LHLD BUFEND ;get end of ring-buffer XCHG ;store in de-pair LHLD BUFRIN ;get last input position and.. INX H ;..point to next character. CALL CMPDEHL ;de/hl-pairs equal? JNZ LBUFF1 ;if not equal, not at end. LHLD BUFBEG ;past end, reset to begin. LBUFF1 XCHG ;save new input position in de-pair LHLD BUFROUT ;get address of last output+1 CALL CMPDEHL RZ ;ring-buffer full -- return to caller. LBUFF2 XCHG ;retrieve new position from de-pair SHLD BUFRIN ;update last input position MOV M,C ;put byte from c-reg into buffer RET ;return to caller ; 'lst' checks list device (printer) status using a direct bios call. if ; busy, quickly returns. pointers are updated before return. LISTST CALL $-$ ;get list status (address from initadr) ORA A ;see if it's busy RZ ;busy, then return. LHLD BUFRIN ;get last input position XCHG ;move to de-pair LHLD BUFROUT CALL CMPDEHL ;de/hl-pairs equal? RZ ;buffer is empty, return. PRTBUF1 INX H ;update pointer and.. PUSH H ;..save. LHLD BUFEND ;get end of ring-buffer.. XCHG ;..put in de-pair. POP H ;restore pointer and.. CALL CMPDEHL JNZ PRTBUF2 LHLD BUFBEG ;was past end, reset to ring beginning. PRTBUF2 SHLD BUFROUT ;store new pointer MOV E,M ;get character to print MVI C,LIST ;cp/m list output function JMP BDOS ;get work done -- ret to caller ; display send/receive characters plus cr, lf, and tab. other ; non-printing characters are shown as ' ^x'. used with secondary ; options 'r', 's', and 'v'. ('q' mode is automatically entered with ; the 'v' option by 'procopt' routine.) SHOW CPI LF JZ TYPEQ CPI CR JZ TYPEQ CPI HT ;horizontal tab JZ TYPEQ CPI ' ' ;display characters.. JC SHOWCTL CPI 7FH ;..from 20h to 7fh. JC TYPEQ SHOWCTL PUSH PSW ;show rest as ' ^x' CALL ILPRTQ DB ' ^',0 POP PSW ADI 40H ;binary --> alpha TYPEQ PUSH PSW ;type to console during quiet/view modes PUSH B ; (also used to type ':' at line beginning.. PUSH D ;..during 'colon-save' of file.) PUSH H MOV E,A MVI C,WRCON JMP BDOSV ; 'ilprtq' is used to console-print selected messages during quiet mode ILPRTQ XTHL ILPLPQ MOV A,M CALL TYPEQ INX H MOV A,M ORA A JNZ ILPLPQ XTHL RET ; display program version number and revision date CAPTION CALL ILPRTQ DW CLS DB ESC,BDIM,'Comm' DB VERS/100+'0','.',VERS MOD 100/10+'0' DB VERS MOD 10+'0',' as of ' DB MONTH/10+'0',MONTH MOD 10+'0','/' DB DAY/10+'0',DAY MOD 10+'0','/' DB YEAR/10+'0',YEAR MOD 10+'0' DB ESC,EDIM,0 RET ; c m d l i n e ; loads a command line addressed by de-pair (max # characters in line in de, ; number of chars in line in de+1, line starts in de+2) into fcb addressed ; by hl-pair. the fcb should be at least 33 bytes in length. the command ; line buffer must have a maximum length at least one more than the greatest ; number of characters that will be needed. CMDLINE PUSH PSW PUSH B PUSH D PUSH H CALL INIT ;fills fcbs with blanks and nulls XCHG ;get start of command line in hl-pair INX H ;address # bytes in cmd line MOV E,M ;load de-pair with # bytes MVI D,0 INX H DAD D ;point to byte after last char.. MVI M,CR ;..in cmd line and store delimiter. POP H ;restore hl- and de-pairs POP D PUSH D PUSH H INX D ;address start of command INX D CALL DRIVE NAME1 MVI C,8 ;transfer first filename to fcb CALL TRANS CPI CR JZ DONEL CPI ' ' ;if space, then start of.. JZ NAME2 ;..second filename. TYPE1 POP H ;filetype must be after.. PUSH H ;..eighth byte of name. LXI B,9 DAD B MVI C,3 ;transfer type of first file CALL TRANS CPI CR JZ DONEL NAME2 LDAX D ;eat multiple spaces.. CPI ' ' ;..between names. JNZ NAME2C INX D JMP NAME2 NAME2C POP H ;second name starts in 16th byte PUSH H ;point hl-pair to this byte LXI B,16 DAD B CALL DRIVE MVI C,8 CALL TRANS CPI CR JZ DONEL TYPE2 POP H ;second type starts in 25th byte PUSH H LXI B,25 DAD B MVI C,3 CALL TRANS DONEL POP H PUSH H INX H ;point to 1st char of 1st name in fcb.. CALL SCANL ;check for * (ambiguous names) POP H PUSH H LXI B,17 ;..then to 1st char of second name in fcb. DAD B CALL SCANL POP H POP D POP B POP PSW RET ; cmdline subroutines: ; initialize fcb with 1 null (for first drive), 11 blanks, and 4 nulls; ; then again fill 1 null (for 2nd drive), 11 blanks, and finally, 4 nulls. INIT PUSH H PUSH B MVI M,0 INX H MVI B,11 MVI A,' ' CALL INITFILL MVI B,5 XRA A CALL INITFILL MVI B,11 MVI A,' ' CALL INITFILL MVI B,4 XRA A CALL INITFILL POP B POP H RET INITFILL MOV M,A INX H DCR B JNZ INITFILL RET DRIVE INX D ;check 2nd byte of filename. if it.. LDAX D ;..is a ":", then drive was specified.. DCX D CPI ':' JNZ DEFDR ;..else zero for default drive .. LDAX D ;..('init' put zero) ANI 5FH SUI 40H ;calculate drive (a=1, b=2,...).. MOV M,A ;..and place it in fcb. INX D ;address first byte of.. INX D ;..in cmd line,.. DEFDR INX H ;..and name field in fcb. RET TRANS LDAX D ;transfer from cmd line to fcb.. INX D ;..up to number of chars specified.. CPI CR ;..by c-reg. keep scanning field.. RZ ;..without transfer until a delimiting.. CPI '.' ;..field char such as '.', blank, or.. RZ ;..c/r (for end of cmd line). CPI ' ' RZ DCR C JM TRANS ;once c-reg is less than zero, keep.. MOV M,A ;..reading cmd line but do not.. INX H ;..transfer to fcb. JMP TRANS SCANL MVI B,8 ;scan filename addressed by hl-pair TSTNAM MOV A,M CPI '*' ;if '*' found, fill in rest of field.. JZ FILL1 ;..with '?' for ambiguous name. INX H DCR B JNZ TSTNAM JMP TSTTYP FILL1 CALL FILL TSTTYP MVI B,3 ;scan and fill type field for name.. TSTTYPL MOV A,M ;..specified above. CPI '*' JZ FILL INX H DCR B RZ JMP TSTTYPL FILL MVI M,'?' ;routine transfers '?' INX H DCR B JNZ FILL RET ; d i r l i s t ; lists directory, 2 or more column file display with storage ; remaining on requested drive shown. DIRLIST CALL CRLF ;turn up lines.. CALL CRLF ;..from command line. CALL SETFCB ;setup cp/m convention cmd line to fcb LXI H,FCB4 ;init.. CALL INITFCB ;..fcb4. LDA FCB2 ;get drive number STA FCB4 LDA FCB2+1 CPI ' ' ;if blank get all names PUSH PSW CZ QSTMARK POP PSW CNZ MOVNAME ;else move name into fcb ; set dma to default cp/m buffer (tbuf) -- do filename search LXI D,TBUF ;default 'tbuf' address MVI C,SETDMA CALL BDOS MVI A,NPL ; 'names per line' into reg-a to indicate.. STA NAMECT ;..'crlf' after 'npl' number of columns. LXI D,FCB4 MVI C,SRCHF ;do first search CALL BDOS INR A ; 0ffh --> 0 if no file(s) found JNZ DIRLOOP CALL ILPRTQ DB '++ File(s) not found ++',0 JMP STORAGE ;still show storage on requested drive DIRLOOP CALL GETADDR ;address returned in hl-pair LXI D,PRTNAME MVI B,8 CALL MOVE INX D MVI B,3 CALL MOVE CALL ILPRTQ PRTNAME DB ' ','.',' ',0 ;print format NEXTSR LXI D,FCB4 MVI C,SRCHN ;do next search CALL BDOS INR A ;if 0ffh --> 0 then.. JZ STORAGE ;..directory-read finished. MOV B,A ;save dir index LDA NAMECT DCR A STA NAMECT ;name count updated CZ CRLF ;terminate line of filenames JNZ FENCE MVI A,NPL ;restart names-per-line count STA NAMECT JMP NOFENCE ;fence not needed FENCE CALL ILPRTQ ;fence if not at end-of-line.. DB ESC,BDIM,' | ',ESC,EDIM,0 ;..if not the last name. NOFENCE MOV A,B ;get dir index back JMP DIRLOOP ; determine storage remaining on default drive STORAGE LDA FCB4 ;get 'requested' drive ORA A JZ DEFAULT DCR A MOV E,A MVI C,LOGIN CALL BDOS DEFAULT MVI C,GETPARM ;current disk parameter block CALL BDOS INX H INX H MOV A,M ;get block shift factor STA BSHIFTF INX H ;bump to block mask MOV A,M ;get it STA BMASK INX H INX H MOV E,M ;get max block number INX H MOV D,M XCHG SHLD BMAX ;put it away MVI C,INQALC ;address of cp/m allocation vector CALL BDOS XCHG ;get its length LHLD BMAX 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 blocks GSPLUP RAL ;test bit JC NOTFRE INX B NOTFRE MOV D,A ;save bits DCX H 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 count.. INX D ;..of allocation vector. JMP GSPBYT ;process it ENDALC POP D ;clear alloc vector pointer from stack MOV L,C ;copy block to hl-pair MOV H,B LDA BSHIFTF ;get block shift factor SUI 3 ;convert from sectors to thousands (k) JZ PRTFREE ;skip shifts if 1k blocks FREKLP DAD H ;multiply blocks by k per block DCR A JNZ FREKLP PRTFREE PUSH H LDA FCB4 ;if drive is default, get.. ORA A JNZ PRNTHD ; (if not, convert 'fcb+0'.) MVI C,INQDISK ;..currently logged-in drive. CALL BDOS INR A ; 0 --> 1 --> 'a' PRNTHD ADI 40H ;make printable STA DRNAME CALL ILPRTQ DB ESC,BDIM,CR,LF,0 POP H CALL DECOUT ; # of free 'k' bytes in hl-pair CALL ILPRTQ DB 'k bytes free on drive ' DRNAME DB ' :',CR,LF,LF,ESC,EDIM,0 LDA C$DR ;return to.. MOV E,A ;..currently.. MVI C,LOGIN ;..logged-in drive. JMP BDOS ; subroutines for dirlist section QSTMARK LXI H,FCB4+1 JOKER MVI A,'?' ;if 'blank' in fcb, put in 11 ?'s. MVI B,11 QSTLP MOV M,A INX H DCR B JNZ QSTLP RET MOVNAME LXI H,FCB2+1 LXI D,FCB4+1 MVI B,11 JMP MOVE GETADDR DCR A ;un-do the 'inr' above ADD A ;times 32 ADD A ADD A ADD A ADD A ADI TBUF+1 ;add dma (tbuf) offset MOV L,A MVI H,CPM$BASE SHR 8 ;base page address RET ; i n b u f ; duplicates cp/m function 10 'read buffer' routine, but does not recognize ; (reason for routine). does allow controls u, r, e, and h (back- ; space). outputs bell if input greater than buffer. ignores leading spaces ; entered. INBUF PUSH PSW PUSH H PUSH B PUSH D ;de-pair must be pushed last DOIT CALL CLEARA ;clear the buffer area POP D ;get address of buffer on retries PUSH D ;restore stack XRA A ;clear a-reg and.. STA LSPFLG ;..set ignore-leading-spaces flag. INX D ;go to address count location (buf+1) STAX D ;initialize with a zero in count byte, then.. INX D ;..get 1st typed, entered character (buf+2). XCHG ;address first buffer byte with hl-pair INBUFA CALL KEYIN ; (waits for char) CALL UCASE CPI CR ;is it --> enter command? JZ INBUFR ;if so, then return. CPI ' ' ;ignore.. JNZ INBUFLP ;..leading-spaces test. MOV B,A ;save entry character LDA LSPFLG ORA A MOV A,B ;restore it JZ INBUFA ;branch if a leading space INBUFLP CPI 7FH ;is it a delete? JZ DELETE CPI 08H ; backspaces.. JZ DELETE ;..over deleted char. CPI 'U'-40H ;is it ? JZ INBUFO ;output #, cr, lf, and start over CPI 'R'-40H ; retypes line JZ RETYPE CPI 'E'-40H ; outputs.. CZ CRLF ;..a cr and a lf. JZ INBUFA CPI ' ' ;only above control characters allowed JC INBUFA MOV B,A ;save keyboard entered character STA LSPFLG ; processed if other char entered 1st XCHG ;save hl-pair in de-pair POP H ;get address of buffer in hl-pair PUSH H ;restore stack INX H ;address count byte INR M ;increase count byte DCX H ;address maximum MOV A,M ;put maximum in a INX H ;address count CMP M ;compare count to maximum JC ALERTL ;if maximum, ring bell and wait for cr. XCHG ;restore buffer pointer to hl-pair MOV M,B ;put inputted character in buffer MOV A,B ;output it CALL TYPE INX H ;bump pointer JMP INBUFA ;get next character DELETE XCHG ;save buffer pointer in de-pair POP H ;address beginning of buffer PUSH H ;restore stack INX H ;address count field MOV B,A ;save delete char, 7fh or 08h. MOV A,M SUI 1 ;decrease count ('sui' sets carry) MOV M,A JC NODEL ;don't delete past begining of buffer XCHG ;restore buffer pointer to hl-pair DCX H ;point to last byte inputted MOV A,B ;get back 7fh or 08h MOV B,M ;get character being deleted MVI M,' ' ;restore blank CPI 08H JZ BKSPC CPI 7FH JNZ INBUFA ;get next character MVI A,08H BKSPC CALL TYPE ;true erase if 08h MVI A,' ' CALL TYPE MVI A,08H CALL TYPE JMP INBUFA NODEL INR M ;don't leave count negative XCHG ;restore pointer to hl-pair JMP INBUFA INBUFO MVI A,'#' ;announces line has been removed CALL TYPE CALL CRLF JMP DOIT RETYPE POP D PUSH D INX D ;point to current number.. LDAX D ;..of characters. MOV B,A MVI A,'#' CALL TYPE CALL CRLF MOV A,B ;test if zero input ORA A JZ INBUFA CTLRLP INX D ;ctrl-r loop LDAX D CALL TYPE ;repeat line DCR B JNZ CTLRLP ;loop till done, length in b-reg. JMP INBUFA ALERTL MVI A,BELL ;alarm for full buffer CALL TYPE DCR M XCHG JMP INBUFA INBUFR CALL CRONLY ;no lf here permits overwrite.. POP D ;..of command line. POP B POP H POP PSW RET CLEARA POP D ;accounts for call POP H ;address buffer in hl-pair PUSH H ;restore.. PUSH D ;..stack MOV B,M ;save maximum in b-reg (from 'cmdbuf') INX H ;point to first.. INX H ;..buffer byte. MVI A,' ' CLEARL MOV M,A INX H DCR B JNZ CLEARL RET ; i n - l i n e c o m p a r e ; compares string addressed by de-pair to string after call (ends with null). ; return with carry set means strings not the same. all registers except ; a-reg are unaffected. ILCOMP XTHL ;point hl-pair to 1st char PUSH D ILCOMPL MOV A,M ;hl-pair points to in-line string ORA A ;if null, end of string. JZ SAME LDAX D CMP M JNZ NOTSAME INX H INX D JMP ILCOMPL NOTSAME XRA A ;if not same, finish thru.. NSLP INX H ;..string so return will.. CMP M ;..go to instruction after.. JNZ NSLP ;..string and not remainder of string. STC SAME POP D INX H ;skip over null terminator XTHL RET ; m u l t i - f i l e a c c e s s ; allows processing of multiple files (i.e. *.asm) from disk. builds the ; correct name in the fcb each time it is called. the command is used in ; programs to process single or multiple files. the fcb is set up with the ; next name, ready to do normal processing (open, read, etc.) when routine ; is called. carry is set if no more names are found. MFNAME PUSH B PUSH D PUSH H MVI C,SETDMA LXI D,TBUF CALL BDOS XRA A STA FCBEXT ; if first time LDA MFFLG1 ORA A JNZ MFNAME1 MVI A,1 STA MFFLG1 ; save requested name -- save original request LXI H,FCB LXI D,MFNAME4 MVI B,12 CALL MOVE LDA FCB STA MFNAME5 ;save disk in curr fcb ; search for first requested name LXI H,MFNAME4 LXI D,FCB MVI B,12 CALL MOVE MVI C,SRCHF LXI D,FCB CALL BDOS ; else JMP MFNAME2 MFNAME1 LXI H,MFNAME5 LXI D,FCB MVI B,12 CALL MOVE MVI C,SRCHF ;search for first LXI D,FCB CALL BDOS ; search for next name LXI H,MFNAME4 LXI D,FCB MVI B,12 CALL MOVE MVI C,SRCHN LXI D,FCB CALL BDOS ; endif MFNAME2 INR A STC ; ret with carry set.. JNZ MFNAME3 STA MFFLG1 ;reset multi-filename flag POP H POP D POP B RET ; ..if name not found. ; move name found to current name MFNAME3 CALL GETADDR PUSH H ;save name pointer LXI D,MFNAME5+1 MVI B,11 CALL MOVE POP H ; move name found to fcb LXI D,FCB+1 MVI B,11 CALL MOVE ; initialize fcb counter fields XRA A STA FCBEXT STA FCBRNO POP H POP D POP B RET ; c o m m o n c r c s u b r o u t i n e s ; clear crc register CLRCRC PUSH H ;reset crc accumulator for new message LXI H,0 SHLD CRCVAL POP H RET ; generate tables for fast crc calculations INITCRC LXI H,CRCTBL MVI C,0 ;table index GLOOP XCHG LXI H,0 ;initialize 'crc' register-pair MOV A,C PUSH B MVI B,8 XRA H MOV H,A LLOOP DAD H JNC LSKIP MVI A,10H XRA H MOV H,A MVI A,21H XRA L MOV L,A LSKIP DCR B JNZ LLOOP POP B XCHG ;de now has crc, hl pointing into table. MOV M,D ;store high byte of crc INR H MOV M,E ;store low byte DCR H INX H ;move to next table entry INR C ;next index JNZ GLOOP RET ; update crc value UPDCRC PUSH PSW PUSH B PUSH D PUSH H LHLD CRCVAL ;get partial remainder and put to.. XCHG ;..de-pair. MVI B,0 ;clear high byte of bc-pair XRA D MOV C,A ;copy data character to c-register LXI H,CRCTBL DAD B MOV A,M XRA E MOV D,A INR H MOV E,M XCHG SHLD CRCVAL ;save to use for next update POP H POP D POP B POP PSW RET ; check crc bytes of received message CHKCRC PUSH H LHLD CRCVAL MOV A,H ORA L POP H RZ MVI A,TRUE RET LINK COMM723C ;chains to 'comm723c.asm' using lasm.com