; ; TCSELCECT - Display a menu of available extended TCAPs, allowing the user ; to choose the appropriate one to be loaded to the ENV, as well as installing ; the TCAP into a .Z3T file or . . . a program supporting Jay Sage's proposed ; TCAP header. (See The Computer Journal #52) ; ; by Brian Moore GEnie: BRIAN-CPM ; 1048 Lincoln, #1 ; Eugene, OR 97401 ; (503) 687-8531 ; ; Credit for the concept behind this program goes to Chris McEwen, Jay Sage, ; and Ian Cottrell. ; ; Since I make no claim to the concept behind this program, I can't very well ; claim a copyright on it, can I? Therefore, this is released into the public ; domain. I will ask that if you choose to modify and re-release it that you ; check with one of the above first. If something is done one way, there is ; probably a good reason. (At least, there should be.) See the explanation ; down-code as to why I can't clear the screen on startup -- even if a TCAP is ; present. ; ; Usage: ; TCSELECT menu-driven TCap selection/installation ; TCSELECT -filename menu-driven selection, install into filename.COM ;* TCSELECT 12 load terminal #12's definition into ENV ;* TCSELECT TVI914 load TVI914.Z3T into ENV ; TCSELECT -filename 12 load terminal #12's definition into filename.COM ; TCSELECT -filename TVI914 load TVI914.Z3T into filename.COM ; TCSELECT + menu-driven selection, extract .Z3T file ; TCSELECT +filename menu-driven selection, extract to filename.Z3T ; TCSELECT + ANSI extract ANSI TCAP to ANSI.Z3T ; TCSELECT // display this message ; ; *'d items require ZCPR3, others will work under CP/M 2.2, 3.0 and ZCPR3 ; options to install .COM files will only work under Z3 if the wheel byte is ; set. They will ALWAYS work under CP/M (though I may change this). ; ; On ZCPR3 systems, the terminal selected is returned in Register 0, ; (configurable). ; ; Version 3.2b bem replaced an "or a" that for some reason got deleted. ; ; Version 3.2a bem Added extract ability (again, based on comments received ; in a GEnie Real Time Conference with Jay). ; ; Version 3.1a bem Added terminal Alias support per Jay's recommendations ; Also added "fast jump" movement by alowing # keys to select a given ; menu screen. ; ; Version 3.0d bem Fixed bug noted by Jay and Howard Goldstein -- selecting a ; non-existant terminal by name no longer crashes things (the problem was in ; the count-down through the possible terminals). Also fixed problem with ; not setting the result code properly when choosing a terminal from the ; menus, as well as a problem with the confirmation of a menu selection. ; ; Version 3.0c bem Added confirmation for terminal selection per Ian's request. ; ; Version 3.0b bem Fixed some odd bugs ; ; Version 3.0a Brian Moore Rewrite from scratch of Richard Conn's ; original program. ; NO equ 0 YES equ not NO N equ NO Y equ YES ifp1 DEBUG set NO endif ; General purpose DEBUG accept for far too much verbosity: .accept 'turn on DEBUGging stuff? (y/N)', DEBUG .request Z3LIB extrn z3init, zfname, pfind, getwhl, putreg, dundr, getpat extrn getqui .request SYSLIB4 extrn print, cin, crlf, pfn2, sksp, isdigi, eval10, pafdc extrn LUINIT, LUOPEN, luclos, LUREAD, setdma, cout, isalnu extrn pstr, logud, retud, f$open, f$close, getfs, r$read extrn r$writ, f$read, caps, bbline, codend, issp, instr extrn f$mopen,f$write, f$delete if DEBUG extrn phl4hc endif ; ; Misc ASCII equates cr equ 'M'-40h lf equ 'J'-40h eof equ 'Z'-40h .z80 cseg jp start envstring: db 'Z3ENV' ; Look for this in other programs. db 1 ; this, too env: dw 0 ; dw 100h ; for type-3 compatibility db 'TCSELE30' ; ZCNFG filename db 0 ; null for end of string ;---------------------------------------- ; The following will be installable via ZCNFG when I get a round tuit. ;---------------------------------------- TermReg: db 0 ; Register for returning term number TCAPpath: db 1 ; use path for library if Z3 Z3Ttype: db 'Z3T' ; file type for tcaps COMtype: db 'COM' ; (may be a weirdo...) TCAPLBRUser: db 0 ; user/ for TCAP library TCAPLBRDrive: db 0 ; drive TCAPLIBNAME: db 'Z3TCAP LBR' ; <--- name of TCAP file TCAPmenu: db 'TCAPMENUTXT' ; <--- name of menu within file ConfirmFlag: db 1 ; confirm TCAP choice ;---------------------------------------- ; This is the start of the main program. Note that _even_if_ there is a TCAP ; in memory, we can not rely on it to be a valid indicator of what the user's ; terminal can do. We can display the name of it, or test it, but we should ; _not_ automatically assume it is valid! (We could send the wrong codes to ; the terminal and really muck things up!) ;---------------------------------------- start: ld (stack),sp ; ld sp,stack ; ; ; ld hl,(env) ; Check the ENV pointer ld a,h ; If we are uninstalled, or l ; then we don't have Z3! ld (have_Z3),a ; flag if we have Z3 jr nz,gotz3 ; ld hl,intenv ; look at our psuedo-ENV gotz3: call z3init ; and initialize the Z3 Environment call retud ; get our current DU: ld (DefUser),bc ; Save default drive for later call logo ; Identify ourselves ld hl,(05dh) ; ld de,-'//' ; add hl,de ; ld a,h ; or l ; jp z,instruct ; ; Zero out the RAM we need (the FCB's being 0 is our sign that they are ; not specified by the user, so this is VERY important!) ld hl,Zero_Start ld de,Zero_Start + 1 ld bc,Zero_End - Zero_Start - 1 ld (hl),0 ldir ; ; Check the command line for what we should do . . . ; (remember: no cheating! We have to work with CP/M2.2!) ld hl,81h ; point to the start of the command parseloop: call sksp ; skip over space characters ld a,(hl) ; or a ; jr z,parsedone ; figure out what the user specified cp '-' ; - for a .COM file jr z,parseCOMname ; cp '+' ; + to extract a standalone .Z3T jr nz,trynumber ; see if this is a numeric or .Z3T parseZ3Tname: inc hl ; ld de,oZ3Tfcb ; call getfname ; ld a,0ffh ; ld (doextract),a ; jr parseloop ; parseCOMname: inc hl ; skip over the '-' ld de,COMfcb ; must be a filename[.com] call getfname ; parse it for DU:(/DIR: if Z3) jr parseloop ; ;---------------------------------------- trynumber: call isdigi ; is the first character a digit? jr nz,tryZ3t ; nope -- better be a .Z3T filename ld b,h ; save our pointer ld c,l ; just in case it's not a #. call eval10 ; get the number ld a,(hl) ; or a ; end of line? jr z,gotnumber ; cp ' ' ; better be a space jr nz,notnumber ; nope -- try as Z3T gotnumber: ld a,d ; must be <= 255 or a ; jr nz,badTCnum ; ld a,e ; get what we care about ld (TCnum),a ; ld a,-1 ; ld (gavenumber),a ; Flag that we got a #. jr parseloop ; badTCnum: call print ; db 'Bad TCAP number! Must be <= 255',cr,lf,0 jp exit ; ;---------------------------------------- notnumber: ld h,b ; Recover pointer to token ld l,c ; tryz3t: ld de,Z3Tfcb ; call getfname ; jr parseloop ; ;---------------------------------------- ; Done parsing - figure out what we have to do based on what was given on ; the command line ;---------------------------------------- parsedone: if DEBUG call print db 'Done parsing: COMfcb=',0 ld de,COMfcb + 1 call pfn2 call print db ' Z3Tfcb=',0 ld de,Z3Tfcb + 1 call pfn2 call print db ' TC#=',0 ld a,(TCnum) call pafdc endif ld a,(doextract) ; if user asked for extraction... ld b,a ; ld a,(Z3Tfcb + 1) ; and gave us a TCAP name or alias and b ; jr z,parsedone_0 ; ld bc,36 ; Then that is our name for the ld de,oZ3Tfcb ; output file. ld hl,Z3Tfcb ; ldir ; parsedone_0: ld a,(gavenumber) ; Did user specify a number? or a ; jp nz,gettcnum ; get it that way... ld a,(Z3Tfcb + 1) ; specify a .Z3T file? or a ; jp nz,gettcfile ; then get that! ; ; user didn't say what sort of terminal was desired: go through the menus ; for them. ;---------------------------------------- call opentcaplbr ; open up our library call loadmenu ; we'll need the menus manual: xor a ; Start with page #0 of selections ld (screennum),a ; mainloop: ld a,(screennum) ; call displayscreen ; call cin ; Get user's command call docommand ; jr mainloop ; ;---------------------------------------- docommand: call caps ; cp 'Q' ; quick check for Quit jp z,exit ; abort cp 'A' ; Is it in range? jr c,donotalpha ; ld hl,maxitem ; cp (hl) ; jr z,docomm_0 ; jr nc,donotalpha ; ; Okay -- it's something on this menu (A..[maxitem])... get it! docomm_0: sub 'A' ; convert A to 0 ld l,a ; ld h,0 ; add hl,hl ; *2 add hl,hl ; *4 add hl,hl ; *8 add hl,hl ; *16 add hl,hl ; *32 add hl,hl ; *64 ld de,(menuptr) ; get the base of this screen add hl,de ; HL now points to this entry jp gettcmatch ; go deal with it! donotalpha: call isdigi ; fast move to menu #x? jr z,docom_jump ; cp 'C'-40h ; ^C breaks. jp z,exit ; cp 'K'-40h ; ^K breaks. jp z,exit ; cp 'M'-40h ; ^M (RETurn) goes to next screen jr z,docom_next ; cp '+' ; jr z,docom_next ; cp '=' ; jr z,docom_next ; cp '-' ; jr z,docom_prior ; cp '>' ; jr z,docom_next ; cp '.' ; jr z,docom_next ; cp ',' ; jr z,docom_prior ; cp '<' ; jr z,docom_prior ; ret ; ;---------------------------------------- docom_jump: sub '0' ; strip off ASCII bias ld c,a ; save this for a second. ld a,(menucount) ; get the max # of items and 0f0h ; rrca ; rrca ; rrca ; /8 rrca ; /16 = Highest screen # cp c ; are we in range? ld a,(screennum) ; ret c ; return if out of range. ld a,c ; ld (screennum),a ; ret ; docom_next: ld a,(menucount) ; get the number of items total... and 0f0h ; mask off low nybble rrca ; /2 rrca ; /4 rrca ; /8 rrca ; /16 = Highest screen # ld c,a ; ld a,(screennum) ; cp c ; ret z ; Are we at the last screen? inc a ; ld (screennum),a ; ret ; ;---------------------------------------- docom_prior: ld a,(screennum) ; get the screen number or a ; is it 0 ? ret z ; yep -- can't go back dec a ; go back a screen ld (screennum),a ; ret ; and that's it! ;---------------------------------------- gettcnum: if DEBUG call print db 'Getting TCAP by #',0 ld a,(TCnum) ; call pafdc endif call opentcaplbr ; load the library call loadmenu ; we'll need the menu to find the # ld a,(TCnum) ; get the TCAP number we want ;---------------------------------------- ld c,a ; ld a,(menucount) ; ld b,a ld hl,(menudata) jr gettcap_loop_0 ; gettcap_loop: ld de,64 ; add hl,de ; gettcap_loop_0: ld a,(hl) ; cp c ; jr z,gettcmatch ; djnz gettcap_loop ; gettcerr: call print ; dz 'Selected TCAP not found in .LBR!',cr,lf jp manual ; gettcmatch: ld a,(hl) ; ld (TCnum),a ; push hl ; ld de,9 ; add hl,de ; call print ; db 'Selecting ',0 ; call pstr ; call crlf ; pop hl ; inc hl ; point to Z3T name in menudata ld de,Z3Tfcb + 1 ; ld b,8 ; at most 8 characters in filename gettcloop: ld a,(hl) ; or a ; jr nz,gettcldo ; ld a,' ' ; gettcldo: ld (de),a ; inc de ; inc hl ; djnz gettcloop ; gettcbyname: ld hl,Z3Ttype ; ld bc,3 ; ldir ; ld a,(confirmflag) ; or a ; jr z,gettcbyname_0 ; call print ; dz cr,lf,'Is this the right selection? (y/N) ' call cin ; call caps ; cp 'Y' ; jp nz,mainloop ; call crlf ; gettcbyname_0: ld de,tcap_LUD ; ld hl,Z3Tfcb + 1 ; call luopen ; jp nz,gettcerr ; ld hl,lubuf ; call setdma ; call luread ; jp finish ; ;---------------------------------------- NoAlias: call print ; db 'Could not find TCAP.',0 jp manual ; force manual selection ;---------------------------------------- ; look up a TCap file by -ALIAS- This routine added for v3.1 ;---------------------------------------- gettcfile: ld hl,ouralias ; ld (hl),'=' ; put an '=' at the start inc hl ; ld de,z3tfcb+1 ; ld b,8 ; at most 8 chr's to copy gettcfile_0: ld a,(de) ; cp ' ' ; end? jr z,gettcfile_1 ; ld (hl),a ; save it inc de ; inc hl ; djnz gettcfile_0 ; gettcfile_1: ld (hl),'=' ; put in end of pattern inc hl ; ld (hl),0 ; shove in EOS. call opentcaplbr ; we'll need the library open of course gettcf_loop: call aliasloadline ; load the next usable line jr c,noalias ; hit the EOF -- couldn't find alias call checkalias ; is the alias in this line? jr nz,gettcf_loop ; nope -- keep looking ; aliasloadline has already set the TCNUM.... ld de,tcap_LUD ; call luclos ; close it. jp gettcnum ; go get it! checkalias: ld hl,aliasbuffer ; if DEBUG call print ; db cr,lf,'Searching: ',0 push hl call pstr ; display what we're looking for. pop hl endif ld de,ouralias ; jp instr ; all there is to it! loadlineskip: call lugetc ; cp EOF ; scf ; flag EOF ret z ; cp lf ; end of line? (second part of CR/LF) jr nz,loadlineskip ; nope ... keep plowing on. else... ; Load a line from the TCAP file for searching for ALIASes aliasloadline: ld bc,0 ; clear out our terminal # and flag loadline_num: call lugetc ; cp EOF ; EOF? scf ; ret z ; call isdigi ; is it numeric? jr nz,getalias ; sub '0' ; strip off the ASCII bias ld b,a ; save this digit. ld a,c ; get the prior one. add a,a ; *2 add a,a ; *4 add a,c ; *5 add a,a ; *10 add a,b ; add in digits ld c,a ; save it ld b,1 ; flag that we got something jr loadline_num ; and get the next digit getalias: ld a,b ; did we get anything? or a ; jr z,loadlineskip ; nope... ignore the line. ld a,c ; get our terminal number ld (TCnum),a ; save it just in case we have matched! call skipspace ; skip any white space... jr c,loadline_ex ; end of file??? ld hl,aliasbuffer ; point to our buffer (80 chr max) ld (hl),'=' ; shove in an = inc hl ; ld b,78 ; getalias_loop: ld (hl),a ; inc hl ; dec b ; one less character jr z,getalias_ick ; too long! call lugetc ; cp EOF ; jr z,loadline_ex ; abort if early EOF call issp ; is it white? jr nz,getalias_loop ; no -- keep going ld (hl),'=' ; shove in end of pattern inc hl ; ld (hl),0 ; shove in end of string ; Okay, now we have all of our alias string in memory. ; we really don't need anything else... if we match, we have the TCnum, ; and if we don't, we just keep plowing on! So... just skip till the ; end of line in case it's not a match. getalias_eol: call lugetc ; cp EOF ; EOF = done ret z ; cp LF ; same as LF ret z ; jr getalias_eol ; keep going to EOL. getalias_ick: call print ; dz 'Fatal error: TCAP Alias string too long!' jp exit loadline_ex: scf ; flag error ret ; and go away! ;---------------------------------------- NotWheel: call print ; dz 'Not Wheel!' ; jp exit ; ;---------------------------------------- noCOMfile: call print ; dz '.COM file not found!' jp exit ; ;---------------------------------------- ; By this point, we have loaded a TCAP into our buffer... now to figure out ; what to do with it! finish: ld a,(doextract) ; Did user ask to extract? or a ; jp nz,extract ; yep... do it. ld a,(COMfcb + 1) ; was a FCB specified on the command or a ; line? (or do we still have 0 there?) jp z,loadtcap ; installCOM: call getwhl ; Is the user authorized to install? jr z,NotWheel ; Nope -- abort call COMexist ; jr nz,noCOMfile ; installCPM: ld hl,COMbuff1 ; call setdma ; call F$READ ; Read in the first block jr nz,noCOMfile ; can't read the first block?? ; look for Z3ENV header in the .COM file ld hl,envstring ; ld de,COMbuff1 + 3 ; ld b,6 ; 6 bytes to compare testenvloop: ld a,(de) ; cp (hl) ; jp nz,noinstall ; inc hl ; inc de ; djnz testenvloop ; ; (Get the ENV address in the file, and see if that's included ; in the .COM file.) ld hl,(COMbuff1 + 9) ld a,h ; or l ; jp z,noinstall ; Can't install if ENV = 0 ld (COMenv),hl ; ld de,COMfcb ; call getfs ; how big is this file? ld a,h ; ld h,l ; ld l,0 ; hl *= 256 rra ; shift low bit of A into Carry rr h ; shift into Hi of H, lo H into C rr l ; and then into L, HL /=2 ld bc,100h ; add in .COM offset add hl,bc ; and that's the end of the program or a ; clear our carry (why no SUB HL,DE?) ld de,(COMenv) ; get our pointer back... sbc hl,de ; subtract off where the ENV is... jp c,noinstall ; HL > DE file is OK. if DEBUG call print dz '.COM file passed test.' endif ; DE has the address where the ENV goes.... first convert that to ; where the TCAP is... ld hl,80h ; add hl,de ; HL = TCAP in COM ; Now, convert that to a record number (divide by 128) rl l ; get hi-bit of L into Carry ld l,h ; ld h,0 ; HL = HL / 256 sla l ; bring hi-bit of old-L back in rl h ; HL = HL / 128 dec hl ; make into offset-0 push hl ; save our record # ld de,COMfcb ; call r$read ; read in the record ld hl,COMbuff2 ; call setdma ; pop hl ; inc hl ; push hl ; call r$read ; ld hl,lubuf ; ld de,COMbuff1 ; ld a,(COMenv) ; and 7fh ; add a,e ; ld e,a ; ld a,0 ; adc a,d ; ld d,a ; ld bc,80h ; ldir ; pop hl ; ld de,COMfcb ; call r$writ ; write 2nd record dec hl ; push hl ; ld hl,COMbuff1 ; call setdma ; pop hl ; call r$writ ; call f$close ; call print ; dz 'Installed TCAP into ' ld bc,(COMdu) ; call printname ; look up the NDR if any jp exit ; loadtcap: ld a,(Have_Z3) ; Do we have Z3? or a ; Nope... all we can do is install jp z,finish_noz3 ; check to see if it's ok first... ld hl,(env) ; Get ENV address ld bc,128 ; get TCAP segment add hl,bc ; ex de,hl ; Put into DE ld hl,lubuf ; get our staging area ldir ; (BC still = 128) call getqui ; (No worry about CP/M compatibility) jr nz,loadtcap_0 ; call print ; db 'TCAP loaded into environment.',0 loadtcap_0: ld a,(TermReg) ; ld b,a ; ld a,(TCnum) ; call putreg ; Save the ID # selected. jp exit ; noinstall: call print dz cr,lf,'.COM file not compatible with TCSELECT.' jp exit finish_noz3: call print ; we'll have to get the file to install dz cr,lf,'Name of file to install (^C to abort) : ' xor a ; call bbline ; call sksp ; skip spaces... xor a ; (Doesn't really matter under CP/M) ld de,COMfcb ; call zfname ; jr nz,finish_noz3 ; Don't allow ambiguous names. call COMexist ; jp z,installCPM ; It exists - go deal with it! call print ; db 'File doesn''t exist!',0 jr finish_noz3 ; Repeat until we get it! ;---------------------------------------- extract: call getwhl ; is the user the Wheel? jp z,NotWheel ; nope... complain ld a,(oZ3Tfcb + 1) ; was an extraction name given? cp ' ' ; jr nz,extract_0 ; ld bc,11 ; Give us the name that we loaded. ld de,oZ3Tfcb + 1 ; ld hl,Z3Tfcb + 1 ; ldir ; ld a,(DefUser) ; copy in the user area ld (oZ3Tfcb + 13),a; so that we put it in the right place extract_0: ld a,(oZ3Tfcb) ; was a drive specified? or a ; jr nz,extspecdrive ld a,(DefDrive) ; get our default drive back... inc a ; make it 1-16 extspecdrive: dec a ; and then 0-15 (for the above jr) ld b,a ; ld a,(oZ3Tfcb + 13); Get the user # ZFNAME left us. ld c,a ; ld (oZ3Tdu),bc ; save this for display call logud ; go to where the .Z3T should go ld a,(oZ3Tfcb + 9) ; did user specify a type? cp ' ' ; jr nz,exthavetype ; ld de,oZ3Tfcb + 9 ; ld hl,Z3Ttype ; Force a type if none. ld bc,3 ; ldir ; exthavetype: ld de,oZ3Tfcb ; call F$OPEN ; open the file jr nz,extnoexist ; ld bc,(oZ3Tdu) ; call printname ; look up the NDR if any call print ; dz ' exists. Overwrite? (y/N)' call cin ; call caps ; cp 'Y' ; jr z,extkillit ; call print ; dz cr,lf,'Extraction cancelled.' jp exit ; extkillit: call F$DELETE ; extnoexist: call F$MOPEN ; make it and open it ld hl,lubuf ; call setdma ; call F$WRITE ; write our one record call F$CLOSE ; ld bc,(oZ3Tdu) ; call printname ; look up the NDR if any call print ; dz ' extracted.' ; jp exit ; ;---------------------------------------- exit: if DEBUG ld a,(TCnum) call print db 'TCnum after lookup = ',0 call pafdc endif ld sp,(stack) ; ret ; ;---------------------------------------- compare: push hl ; push de ; ld b,8 ; 8 characters to compare comp_loop: ld a,(de) ; cp ' ' ; jr z,comp_try ; cp (hl) ; jr nz,comp_fail ; inc de ; inc hl ; djnz comp_loop ; comp_fail: pop de ; If we fall through, the Z flag is set pop hl ; so we don't need to set it! ret ; comp_try: ld a,(hl) ; Only have a match if it end of menu or a ; data field, too. jr comp_fail ; Golly, Z is now set right! ;---------------------------------------- printname: call printndr ; inc de ; call pfn2 ; dec de ; ret ; ;---------------------------------------- printndr: push hl ; inc b ; Convert to 1..16 format call dundr ; jr z,printndr_1 ; inc hl ; ld b,8 ; printndr_0: inc hl ; ld a,(hl) ; cp ' ' ; end of name? jr z,printndr_2 ; call cout ; output the character of the name djnz printndr_0 ; jr printndr_2 ; printndr_1: ld a,b ; add a,'A' - 1 ; (Drive A = 1, not 0!) call cout ; ld a,c ; call pafdc ; printndr_2: ld a,':' ; call cout ; pop hl ; ret ; ;---------------------------------------- displayscreen: call print ; db cr,lf ; db 'Terminal Menu #',0 call pafdc ; push af ; Save our screen # call print ; db ' of ',0 ; ld a,(menucount) ; and 0f0h ; mask off low nybble rrca ; /2 rrca ; /4 rrca ; /8 rrca ; /16 = Highest screen # call pafdc ; call print ; dz cr,lf ; pop af ; push af ; ld h,a ; ld l,0 ; * 16 * 16 16/screen add hl,hl ; * 32 64/line add hl,hl ; * 64 ld de,(menudata) ; add hl,de ; hl now = start of this menu ld (menuptr),hl ; save this for our interpreter ld de,64 ; ld b,16 ; ld c,0 ; display_loop: call displine ; jr c,dispscreen_0 ; add hl,de ; inc c ; djnz display_loop ; dispscreen_0: call print ; db cr,lf,cr,lf ; dz 'Choose from the above (A-' ld a,c ; add a,'A' - 1 ; ld (maxitem),a ; save the maximum menu item call cout ; call print ; db '), or Q to quit the process.',cr,lf,0 pop af ; get screen # back or a ; is this the first? jr z,dispscreen_1 ; call print ; db "',' or '<' to go to prior menu ",0 dispscreen_1: ld c,a ; ld a,(menucount) ; and 0f0h ; rrca ; rrca ; rrca ; rrca ; cp c ; jr z,dispscreen_2 ; return if we are at last menu. call print ; dz "'.' or '>' to go to next menu." dispscreen_2: call print dz cr,lf,cr,lf,'Your choice: ' ret ; ;---------------------------------------- displine: push hl ; push de ; ld de,9 ; add hl,de ; ld a,(hl) ; or a ; jr z,displerr ; call print ; db ' ',0 ld a,c ; get the item # this is add a,'A' ; ASCII-ize it call cout ; call print ; db ') ',0 ; call pstr ; print the terminal call crlf ; or a ; displexit: pop de ; pop hl ; ret ; displerr: scf ; jr displexit ; ;---------------------------------------- lbrnotfound: call print ; db 'Could not find TCAP library file (',0 ld de,TCAPLIBNAME ; call pfn2 ; Print what we were looking for call print ; db ').',cr,lf,0 ; jp exit ; ;---------------------------------------- opentcaplbr: ld de,tcap_LUD_FCB + 1 ; Copy the LBR name into the library ld hl,TCAPLIBNAME ; definition header. ld bc,11 ; ldir ; ld a,(TCAPpath) ; Search along path for .LBR? or a ; jr z,opentcaplbr_0 ; call getpat ; If there's no path, pfind fails! jr z,opentcaplbr_0 ; so skip pfind even if requested! ld de,tcap_LUD_FCB ; xor a ; call pfind ; jr nz,opentcaplbr_1 opentcaplbr_0: ld bc,(TCAPLBRuser) opentcaplbr_1: call logud ; ld de,tcap_LUD ; call luinit ; Open up our library jr nz,lbrnotfound ; uh-oh... can't do much, can we? opentcapmenu: ld hl,TCAPmenu ; call luopen ; jr nz,openmenuerr ; Couldn't find menu file xor a ; ld (lubytesleft),a ; ret ; openmenuerr: call print ; dz 'Could not find menu file!',cr,lf jp exit ; ;---------------------------------------- loadmenu: ld a,0 ; ld (menucount),a ; ld hl,(6) ; get the top of RAM ld de,- 256 - 2048 ; a little margin for error... add hl,de ; HL points to our safety margin ld (RAMtop),hl ; Save it for reference. call codend ; get the end of program/data ld (MenuData),hl ; ld (menuptr),hl ; loadline: ld c,-1 ; flag that we got no ID # ld b,0 ; gettcapid: call lugetc ; cp 26 ; EOF? jp z,ldmenuexit ; call isdigi ; Is it a digit? jr nz,getz3tname ; no -- go get Z3T name sub '0' ; strip off ASCII bias ld c,a ; hide this digit ld a,b ; add a,a ; *2 add a,a ; *4 add a,b ; *5 add a,a ; *10 add a,c ; add in new digit ld b,a ; jr gettcapid ; getz3tname: ld d,a ; Terminator character is in D ld a,c ; cp -1 ; jp z,skipline ; never got an ID -- skip the line ld hl,(menuptr) ; get our ptr to our table ld (hl),b ; save the terminal ID call skipspace ; jp c,ldmenuexit ; abort if eof. ; Now we're pointing at the new (as of TCSELE31) field specifying aliases ; of the terminal name. We don't store this in memory, as the menu system ; doesn't want or need it, so we can just skip over it. getz3tn_alias: call lugetc ; cp 26 ; EOF breaks things jp z,ldmenuexit ; cp CR ; so does CR jp z,ldmenuexit ; call issp ; skip up until a space character jr nz,getz3tn_alias call skipspace ; and skip past further white jp c,ldmenuexit ; inc hl ; force first chr in ld (hl),a ; ld b,7 ; at most 7 more characters getz3tn_loop: inc hl ; point to FCB for Z3T file call lugetc ; get a character cp 26 ; EOF? jp z,ldmenuexit ; cp cr ; premature CR? jr z,skipline ; ignore bad lines call isalnu ; is it our terminator? jr nz,getdescript ; yep -- get the description ld (hl),a ; djnz getz3tn_loop ; repeat until we run out of characters inc hl ; if 8 character name, no EOS! getdescript: xor a ; shove in an end of string loadmenu_0fill: ld (hl),a ; inc hl ; djnz loadmenu_0fill ; call skipspace ; skip over space between fields jp c,ldmenuexit ; ld hl,(menuptr) ; make sure we realign ld de,9 ; add hl,de ; ld (hl),a ; inc hl ; ld b,64-9 ; max length of line getdesc_loop: call lugetc ; cp cr ; jr z,getdesc_done ; cp 26 ; jr z,getdesc_exit ; ld (hl),a ; inc hl ; djnz getdesc_loop ; getdesc_done: xor a ; put in an end of string ld (hl),a ; ld hl,(menuptr) ; ld de,64 ; add hl,de ; ld (menuptr),hl ; ld a,(menucount) ; inc a ; ld (menucount),a ; ld de,(RAMtop) ; or a ; sbc hl,de ; Are we past the safety limit? jr nc,nomemory ; Yep! ABORT!! skipline: call lugetc ; cp lf ; jp z,loadline ; cp 26 ; EOF? jr nz,skipline ; ldmenuexit: getdesc_exit: ld hl,(menuptr) ; ld de,9 ; add hl,de ; ld (hl),0 ; Shove in a 0 for end of table. ret ; nomemory: call print ; db 'Out of memory!!',0 jp 0 ; just in case, be paranoid. ;---------------------------------------- skipspace: call lugetc ; do we have anything to skip? cp cr ; CR is not good jr z,getmenusk_ex ; cp 26 ; EOF is not good either jr z,getmenusk_ex ; call issp ; Skip past any further white space jr z,skipspace ; or a ; ensure no carry (needed?) ret ; getmenusk_ex: scf ; ret ; ;---------------------------------------- getfname: xor a ; Scan DIR: before DU: call zfname ; jr nz,getfn_err ; ret ; getfn_err: call print ; dz 'Ambiguous filenames not allowed!',cr,lf ret ; ;---------------------------------------- lugetc: ld a,(lubytesleft) ; or a ; jr z,lugetcread ; lugetc_0: dec a ; ld (lubytesleft),a ; push hl ; ld hl,(luptr) ; ld a,(hl) ; inc hl ; ld (luptr),hl ; pop hl ; and 7fh ; strip parity (allows use of WS files) ret ; lugetcread: push de ; push hl ; ld hl,lubuf ; call setdma ; ld de,tcap_LUD ; call luread ; jr nz,lugetcerr ; ld a,128 ; now have a full block available ld hl,lubuf ; ld (luptr),hl ; pop hl ; pop de ; jr lugetc_0 ; lugetcerr: ld a,26 ; simulate EOF if error (carry set scf ; pop hl ; pop de ; ret ; ;---------------------------------------- COMexist: ld a,(COMfcb) ; or a ; jr nz,exisspecdrive ld a,(DefDrive) ; get our default drive back... inc a ; make it 1-16 exisspecdrive: dec a ; and then 0-15 (for the above jr) ld b,a ; ld a,(COMfcb + 13) ; Get the user # ZFNAME left us. ld c,a ; ld (COMdu),bc ; save this for display call logud ; go to where the .COM is ld a,(COMfcb + 9) ; did user specify a type? cp ' ' ; jr nz,exishavetype ; ld de,COMfcb + 9 ; ld hl,COMtype ; Force a type if none. ld bc,3 ; ldir ; exishavetype: ld de,COMfcb ; call F$OPEN ; open the file ret ; ;---------------------------------------- ; Print our signon logo -- remember: we can not rely on having a valid TCAP ; at this point, so we will have to pretend we have a minimal system. (We ; may not even be running under Z-system!) ;---------------------------------------- logo: ld a,(Have_z3) ; CP/M normally returns QUIET - we'd or a ; NEVER id ourself then! So, for jr z,logo_0 ; CP/M, we always ID. call getqui ; ret nz ; logo_0: call print ; db 'TCSELECT v3.2b 93-4-22 BEMoore' db cr,lf,0 ; ret ; ;---------------------------------------- instruct: call print ; db ' Usage:',cr,lf db ' TCSELECT ' db 'menu-driven TCap selection/installation',cr,lf,0 ld a,(have_z3) ; or a ; jp z,instruct_0 ; call print db ' TCSELECT 12 ' db 'load terminal #12''s definition into ENV',cr,lf db ' TCSELECT TVI914 ' dz 'load TVI914 TCAP into ENV',cr,lf instruct_0: call getwhl ; jp z,instruct_1 ; call print db ' TCSELECT -filename ' db 'menu-driven selection, install into filename.COM',cr,lf db ' TCSELECT -filename 12 ' db 'load terminal #12''s definition into filename.COM',cr,lf db ' TCSELECT -filename TVI914 ' db 'load TVI914 TCAP into filename.COM',cr,lf db ' TCSELECT + ' db 'menu-driven selection, extract chosen .Z3T',cr,lf db ' TCSELECT +filename ANSI ' db 'extract ANSI TCAP into filename.Z3T',cr,lf db ' TCSELECT + ANSI ' dz 'extract ANSI TCAP into ANSI.Z3T',cr,lf instruct_1: call print db ' TCSELECT // ' db 'display this message',cr,lf dz cr,lf,cr,lf jp exit ; ; This is included to allow us to use all the nifty Z3 routines without ; a lot of testing for CP/M or Z3. ; ; The environment type tells a Z-System program what kind of information is ; provided in the ENV module and what level of TCAP is supported. Use the ; value 81H if you have an extended TCAP and 80H if you have an older type ; of TCAP. envtyp equ 81h cpumhz equ 4 ; CPU speed in MHz ; Operating system addresses and sizes (you can get the address of the BIOS ; by running the program Z3LOC or by examining the byte stored at address ; 0002. This is the page at which the BIOS starts. The other values will ; follow from that for a normal CP/M system. biospg equ 0d1h ; Page where BIOS starts bios equ 100h * biospg doss equ 28 ; Size of DOS in records dos equ bios - 80h * doss ccps equ 16 ; Size of CCP in records ccp equ dos - 80h * ccps ; Information about drives and user areas available ; PONMLKJIHGFEDCBA drvec equ 0000000000001111B ; Put '1' for each drive highdsk equ 'D' ; Letter of highest drive maxdisk equ highdsk - '@' ; Number of highest drive (A=1) maxuser equ 31 ; Number of highest user area ; Data about console screen and printers crtwid equ 80 ; Width of CRT screen crtlen equ 24 ; Number of lines on screen crtuse equ crtlen -2 ; Number of lines to use prtwid equ 80 ; Printer width prtlen equ 66 ; Printer total length prtuse equ prtlen - 8 ; Printer lines to use prtff equ 1 ; Formfeed flag (1 if recognized) ; --------------------------------------------------------------------------- ; Install the dummy ENV intenv: jp 0 ; Dummy jump address db 'Z3ENV' ; Environment ID db envtyp dw 0 ; external path address db 0 ; number of 2-byte elements in path dw 0 ; RCP address db 0 ; number of 128-byte blocks in RCP dw 0 ; IOP address db 0 ; number of 128-byte blocks in IOP dw 0 ; FCP address db 0 ; number of 128-byte blocks in FCP dw 0 ; NDR address db 0 ; number of 18-byte entries in NDR dw 0 ; ZCPR3 Command Line db 0 ; number of bytes in Command Line dw intenv ; ZCPR3 Environment Descriptor db 2 ; number of 128-byte blocks in Descriptor dw 0 ; Shell Stack address db 0 ; number of shsize-byte entires in Shell Stack db 0 ; size of a Shell Stack entry dw 0 ; ZCPR3 Message buffer dw 0 ; ZCPR3 External FCB dw 0 ; ZCPR3 External Stack db 0 ; quiet flag (1=quiet, 0=not quiet) dw 0 ; address of Wheel Byte db cpumhz ; Processor Speed in MHz db maxdisk ; maximum disk db maxuser ; maximum user db 1 ; 1=OK to accept DU, 0=not OK db 0 ; CRT selection (0=CRT 0, 1=CRT 1) db 0 ; Printer selection (n=Printer n) db crtwid ; width of CRT db crtlen ; number of lines on CRT db crtuse ; number of lines of text on CRT dw drvec db 0 db prtwid ; data for printer db prtlen db prtuse db prtff db 0,0,0,0 dw ccp db ccps dw dos db doss dw bios db 'SH ' ; shell variable filename db 'VAR' ; shell variable filetype db ' ' ; filename 1 db ' ' ; filetype 1 db ' ' ; filename 2 db ' ' ; filetype 2 db ' ' ; filename 3 db ' ' ; filetype 3 db ' ' ; filename 4 db ' ' ; filetype 4 ; Fill unused space with nulls rept 128-($-intenv) db 0 endm dseg ds 80*2 ; an amply large stack stack: ds 2 ; storage for original SP have_z3: ds 1 ; non-zero if Z3 is running ;-------------------------------- Zero_Start: ; Start of RAM to be Zero'd out gavenumber: ds 1 ; user specified TCAP # doextract: ds 1 ; extract a .Z3T file TCnum: ds 1 ; TCAP # to install COMfcb: ds 36 ; FCB for .COM file to install Z3Tfcb: ds 36 ; FCB for .Z3T file to load oZ3Tfcb: ds 36 ; FCB for .Z3T file to extract lubytesleft: ds 1 ; # of bytes left in buffer tcap_LUD: ds 2 ; Length of LBR directory ds 2 ; Next block of current file ds 2 ; # blocks remaining ds 11 ; FN.FT of current file in LBR tcap_LUD_FCB: ds 36 ; FCB for LBR file Zero_End: ;---------------------------------------- ouralias: ds 11 ; same as fname, but with ='s on ends DefUser: ds 1 ; default user at startup DefDrive: ds 1 ; default drive at startup luptr: ds 2 ; pointer to current byte in buffer lubuf: ds 128 ; buffer for library activity COMbuff1: ds 128 ; COMbuff2: ds 128 ; COMenv: ds 2 ; ENV address in installed .COM COMdu: ds 2 ; Drive/User for .COM file oZ3Tdu: ds 2 ; Drive/User for output .Z3T file menuptr: ds 2 ; pointer to our menu table 13C8 menucount: ds 2 ; count of items in menu 0011 maxitem: ds 1 ; max item on this menu screen 50 screennum: ds 1 ; the screen # we are on. 00 RAMtop: ds 2 ; pointer to top of memory aliasbuffer: ds 80 ; buffer for one line's aliases. ;---------------------------------------- ; MenuData: This is our RAM-based menu. Each record is as follows: ; Byte 0 : Terminal ID = a number for programs like PBBS ; Bytes 1-8 : FN portion of TCAP file (assume .Z3T extension) ; Bytes 9-63 : Description of terminal ;---------------------------------------- MenuData: ds 2 ; Rest of RAM for our selections ; (This is indirect, so that SYSLIB4's routines don't ; conflict with this memory... :-() end