; ; ; S E C T I O N . M A C ; ; ; 09/04/85 modified for use with ZCPR2 and converted to Zilog ; mnemonics for assembly with Microsoft's M80 Assembler by Max Southall ; Micro/Access, Box 136 Station J, Toronto ; (416) 463 9360 2400/1200/300 ; ; from SECTION.ASM, originally by Ron Fowler, Westland, Michigan 06/27/82 ; ; This program is intended for RCPM systems where ; files are grouped into drive/user area by their ; classification. This program implements a naming ; convention, whereby a caller can move into a ; section by typing its name, rather than the random ; searching formerly needed. If proper equates are set, and ; ZCPR2 is used, the program will not allow changing to ; restricted drives or user areas. A resident or disk-based ; command can be run after a section change if using the ZCPR2 ; external command buffer. If the section name buffer is implemented ; in the BIOS and custom ZCPR2, then the section name can be displayed ; as the prompt. ; ; Syntax is: SECTION [] ; ; If section-name is omitted, a short list of ; available sections is printed. The special ; form "SECTION ?" prints the detailed description ; of each section. ; ; You have to fill in the sections table ; (located near the end of this program) for your ; particular system. ; ;----< Examples of use: >----- ; ; A0>SECTION ZCPR ;changes drive/user to ZCPR area ; B4>SECTION MBASIC ;changes drive/user to mbasic area ; A6>SECTION ;prints short list of sections ; A9>SECTION ? ;prints the detailed list ; false EQU 0 true EQU not false ; ; the following equates may be ; customized to your preference ; zcmd EQU TRUE ;ZCPR2/3 multiple command buffer used? ;If using ZCPR2 command buffer, run command at ;CMD after new section is selected. check EQU TRUE ;check maximum drive and user permitted cmdbuf EQU 0fe80h ;address of zcpr2/3 multiple command buffer ; prompt EQU TRUE ;make prompt section name (must implement sname ;in modified ZCPR2/3 and initialize in BIOS) sname EQU 0f2b0h+49+49 ;address of section name prompt buffer ; maxuser EQU 03fh ;address of maximum user # byte maxdriv EQU 03dh ;address of maximum drive # byte ; descol EQU 15 ;column # where description begins ;(in detailed list) (should be greater ;than longest section name) (but small ;enuf so display is not too long) perlin EQU 4 ;names printed per line in short list tabpos EQU 12 ;tab stops (set mod tabpos) ;should be at least one greater than ;longest section name. ; lines EQU 18 ;line # to pause at so screen doesn't overflow ; ; ZCPR conventions ; cpbase EQU 0 ccpdrv EQU cpbase+4 ;ccp user/drive storage loc bdos EQU cpbase+5 ;system entry point dfcb EQU cpbase+5CH ;default file control block dbuf EQU cpbase+80H ;default buffer tpa EQU cpbase+100H ;base of transient program area coninf EQU 1 ;system call, get console char conotf EQU 2 ;system call, console output printf EQU 9 ;system call, print cons string cstsf EQU 11 ;system call, get console status ; ; character definitions ; cr EQU 13 ;carriage-return code lf EQU 10 ;linefeed code ; ; code begins.... ; .Z80 ;Accept Z80 instruction format ; ORG tpa ; ; pbase: LD HL,0 ;save system stack ADD HL,SP LD (spsave),HL LD SP,stack ;load local stack ; LD A,(ccpdrv) ;get current drive # LD (lastdrv),A ;save PUSH AF ;save it ; gosect: CALL sect ;perform the section function ; back: LD HL,(spsave) ;restore stack for proper return LD SP,HL LD A,(lastdrv) ;check to see if section changed LD B,A LD A,(ccpdrv) CP B RET Z ;no section change, exit but don't warmboot if prompt ld (sname),a ;put drv/usr in sname buffer ld hl,(savecmd) ld de,sname+1 putsname: ld a,(hl) ld (de),a cp 0 jr z,swarm inc hl inc de jr putsname endif swarm: JP cpbase ;CCP will change section at warmboot ; ; ; scan cmd line...if an arg exists, attempt to ; match it in the table. If no arg, dump a list ; of available sections. ; sect: LD A,(dfcb+1) ;is there a cmd-line arg? CP ' ' JP Z,prnqk ;then go print sections out CP '?' ;wants detailed list? JP Z,prntbl ;then go do it ; ; SCAN FOR SECTION & CHANGE IF LEGAL ; LD HL,dbuf ;something there, scan to it ; scanbk: INC HL ; ignoring blanks LD A,(HL) CP ' ' JP Z,scanbk scant: LD (savecmd),HL LD DE,table ;point de to the section table CALL loop scant1: LD HL,(savecmd) LD DE,table1 CALL loop scant2: LD HL,(savecmd) LD DE,table2 CALL loop scant3: LD HL,(savecmd) LD de,table3 CALL loop ; LD DE,matmsg ;print out no-match message LD C,printf CALL bdos ; CALL prnqk ;go give short list RET ; loop: PUSH HL ;save cmd line arg pointer eloop: LD A,(DE) ;test entry against table CP 1 ;end of entry marker? JP NZ,noend ;jump if not LD A,(HL) ;yes, did user cmd terminate also? OR A JP Z,match ;then declare a match JP nomat ;else declare a mismatch noend: CP (HL) JP NZ,nomat ;skip if no match INC HL ;continue with comparison INC DE JP eloop ; ; here when an entry didn't match ; nomat:: LD A,(DE) OR A ;entry terminator? INC DE JP NZ,nomat ;scan through it POP HL ;restore cmd line arg pntr INC DE ;end of entry, skip over user # INC DE ;and drive LD A,(DE) ;end of table? OR A ;(terminated by 0) JP NZ,loop ;go scan another if not ; ; here when no match can be found ; ret ; ; here when a match is found ; match: EX DE,HL ;hl==> user # scmat: INC HL ;scan past description LD A,(HL) ;looking for terminating null OR A JP NZ,scmat INC HL ;skip over terminator LD A,(HL) ;fetch user # SUB '0' ;subtract ascii bias CP 10 ;is it > 15? JP C,scmat2 ;no, so continue on SUB 7 ;remove the rest scmat2:: LD (user),A LD E,A INC HL ;point hl to drive # LD A,(HL) ;fetch drive SUB 'A' ;subtract ascii bias LD (drive),A LD D,A ;save drive # LD A,E ;fetch user number RLC A ;rotate to high nybble RLC A RLC A RLC A OR D ;"or" in the drive POP DE ;clear garbage from stack if check ;if checking maxdrive & user LD (newdrive),A ;save while we check for limits chkd: LD A,(drive) ;check for maximum drive first LD HL,maxdriv INC (HL) CP (HL) JR NC,restrict ;illegal request - don't change section chku: LD A,(user) ;check for maximum user area LD HL,maxuser INC (HL) CP (HL) JR C,okset ;ok - change section ; restrict: LD DE,rstrmsg ;print illegal request message LD C,printf CALL bdos jr cmdret ;return without changing section ; okset: LD A,(newdrive) ;restore request endif ;if checking maxuser & maxdrive ; -- Change user/drive at 04H for the ccp LD (ccpdrv),A ;save drive/user for ccp use ; if zcmd ;if running a command after section change ; LD B,A LD A,(lastdrv) CP B JR Z,cmdret ; ; Place command to run after section change in ZCPR2/3 multiple command buffer ; LD HL,cmd ;address of command to run LD DE,cmdbuf+4 ;place to put command LD (cmdbuf),DE ;store address of command transcmd: LD A,(HL) ;get command letter CP '$' ;end of command delimiter? JR Z,cmdret ;if so, return LD (DE),A ;put cmd letter in cmd buffer INC HL ;bump 'em both INC DE JR transcmd ;do again until finished endif cmdret: POP HL ;dummy clear stack for proper return RET ;return to caller ; ; PRINT QUICK LIST ; prnqk: LD DE,signon LD C,printf CALL bdos prnqk1: LD DE,tblmsg LD C,printf CALL bdos LD HL,table call qloop LD HL,table1 call qloop LD HL,table2 CALL qloop LD HL,table3 CALL qloop ; LD DE,matms2 ;print ending message LD C,printf CALL bdos CALL crlf ; RET ; qloop:: LD B,perlin ;get names-per-line counter qloop2::LD A,(HL) ;end of table? OR A JP Z,qkend ;then go print end msg CALL prathl ;else print the name qscan:: LD A,(HL) ;scan to description terminator INC HL ;(this effectively ignores OR A ; the description) JP NZ,qscan INC HL ;skip over user # INC HL ;and drive # DEC B ;count down line entry counter JP NZ,qtab ;go tab if line not full CALL crlf ;else turn up new line JP qloop ;and continue ; ; tab between entry names ; qtab:: LD A,' ' ;seperate names with tabs CALL type LD A,(column) ;get column # qsub:: SUB tabpos ;test tab position JP Z,qloop2 ;continue if at a tab position JP NC,qsub ;convert mod tabpos JP qtab ;keep tabbing ; qkend: CALL crlf RET ; ; here to print out a list of available section numbers ; prntbl:: LD DE,signon LD C,printf CALL bdos LD A,(dfcb+2) CP 'Z' jr Z,prnt1 CP 'P' jr Z,prnt2 CP 'M' jr Z,prnt3 prtall: LD DE,tblmsg LD C,printf CALL bdos LD HL,table CALL prloop1 CALL prnt1 call prnt2 call prnt3 ret ; prnt1: LD DE,tbl1msg LD C,printf CALL bdos LD HL,table1 CALL PRLOOP1 RET prnt2: LD DE,tbl2msg LD C,printf CALL bdos LD HL,table2 CALL prloop1 RET prnt3: LD DE,tbl3msg LD C,printf CALL bdos LD HL,table3 CALL prloop1 ret prloop1: CALL crlf prloop: LD A,(HL) ;end-of-table? OR A RET Z ;then all done CALL prathl ;print the name tab:: LD A,'.' ;tab over with leader CALL type LD A,(column) ;get column CP descol ;at description column yet? JP C,tab ;then keep tabbing CALL prathl ;print description INC HL ;skip over user # INC HL ;and drive number CALL crlf ;turn up new line ; ; pause for user input before continuing if screen end reached ; PUSH HL ;save HL LD HL,lincount ;current linecount LD A,lines ;# of lines permitted before pause CP (HL) ;max # of lines yet? JR NZ,cprat ;not yet - continue listing ; prtpause: LD DE,pausemsg ;print pause message LD C,printf CALL bdos ; getinp: LD C,coninf ;get user input CALL bdos AND 5FH CP 'N' ;Exit? JR Z,cprat2 CP 'C'-40h JR Z,cprat2 ld c,conotf ld e,cr CALL bdos XOR A ;CR - zero lincount LD (lincount),A JR cprat1 cprat: INC (HL) ;bump line counter cprat1: POP HL ;restore HL ; JP prloop ;and continue printing list cprat2: POP HL POP HL POP HL RET ; ; print message @hl until null or 01 binary ; prathl::LD A,(HL) ;fetch char INC HL ;point past it OR A ;null? RET Z ;then done CP 1 ;1 also terminates RET Z CALL type ;nope, print it CALL break ;check for console abort JP prathl ; ; test for request from console to stop (^C) ; break:: PUSH HL ;save 'em all PUSH DE PUSH BC LD C,cstsf ;get console sts request CALL bdos OR A ;anything waiting? JP Z,brback ;exit if not LD C,coninf ;there, is, get it CALL bdos CP 'S'-64 ;got pause request? LD C,coninf CALL Z,bdos ;then wait for another character CP 'C'-64 ;got abort request? JP Z,quit ;then go abort brback::POP BC ;else restore and return POP DE POP HL RET ; ; request from console to abort ; quit:: LD DE,qmesg ;tell of quit LD C,printf CALL bdos LD HL,(spsave) ;get stack pointer LD SP,HL RET ; qmesg:: DB cr,lf,'==> Aborted',cr,lf,'$' ; ; turn up a new line on display ; crlf:: LD A,cr ;print a return CALL type LD A,lf ;get lf, fall into type ; ; Routine to print char in A on console, ; while maintaining column number. ; type:: PUSH HL ;save everybody PUSH DE PUSH BC LD E,A ;align char for printing PUSH AF ;save char LD C,conotf CALL bdos ;print it POP AF ;restore char LD HL,column ;bump column counter CP lf ;linefeed doesn't chang column JP Z,nochg INC (HL) CP cr ;carriage-return zeroes it JP NZ,nochg ;skip if not cr LD (HL),0 ;is, zero column nochg:: POP BC ;restore & return POP DE POP HL RET ; ; dump heading message ; signon: DB cr,lf,'Micro/Access SECTION 9/4/85',cr,lf,'$' ; tblmsg: DB cr,lf,'Currently available sections:',cr,lf,'$' ; tbl1msg: DB cr,lf,'Current ZCPR-CP/M sections:',cr,lf,'$' ; tbl2msg: DB cr,lf,'Current PC/XT/AT sections:',cr,lf,'$' ; tbl3msg: DB cr,lf,'Current MAC sections:',cr,lf,'$' ; rstrmsg: DB cr,lf,'==> Restricted',cr,lf,'$' ; pausemsg: DB '>>> MORE? - $' ; ; message printed when match failed ; matmsg::DB cr,lf,'==> ??? Section' DB cr,lf,'$' matms2: DB cr,lf,lf,'Type "SECTION " to log into a section.' DB cr,lf DB '"SECTION ?" - detailed list of ALL sections',cr,lf DB '?P - PC/XT/AT sections',cr,lf DB '?Z - 8080/Z80/HD64180 sections',cr,lf DB '?M - MAC sections',cr,lf DB '"SECTION" alone prints available section names' DB cr,lf,'$' ; ; Patch command to execute here ; cmd: DB 'DIR',0,'$' ;command to execute after changing sections ;'$' is to delimit transfer to cmdbuffer, ;cmd itself must always end with 0 for ZCPR2/3. ; ; variables ; spsave: DW 0 ;stack-pointer save savecmd: DW 0 ;pointer to section command in buffer column: DB 0 ;current column # lincount: DB 0 ;current line printed lastdrv: DS 1 ;drive/user before execution newdrive: DS 1 ;requested drive/user drive: DS 1 ;requested drive user: DS 1 ;requested user DS 40 ;the stack ; stack EQU $ ;define it ; ; ; ; ; SECTIONS TABLE (located at end for easy patching with ZSID) ; ; This is the table that defines the sections. Entry format is: ; ; ,sep,,null,user,drive ; ; where is the section name ; sep is a binary 1 used to terminate the match test ; is a one-line-or-less comment printed when ; the list is dumped. Match testing terminates ; before this field. ; null is a binary 0 used to terminate the description ; user is the user number (0-15) of the section (ascii) ; drive is the drive (A-P) number of the section (ascii) ; ; the table ends with a of zero (binary). ; ; Note: be sure to make section names ALL-CAPS, because the ; CCP converts command-line arguments to capitals. The ; description may be in lower case, since it has nothing ; to do with the matching process. ; Also: although the drive and user # is in ascii (for convenience ; in setting up the table), be sure to use caps for the ; drive designation. No error checking is done on the values. ; table: DB 'UPLOADS',1,'Recent User Uploads',0,'0B' DB 'DOCS',1,'Documentation & Text',0,'0C' DB 'TRACE',1,'TRACE Computer Club Related Files',0,'DE' DB 0 ;<<== end of table 0 table1: DB 'APPLE-80',1,'Apple CP/M-ZCPR Programs',0,'5C' DB 'ASM-80',1,'Z80/HD64180 Assembly Language Area',0,'1B' DB 'BBS-80',1,'Remote Communication for ZCPR-CP/M',0,'6B' DB 'C-80',1,'C Language Area for ZCPR-CP/M',0,'3C' DB 'CATS-80',1,'SIG/M, CP/MUG Catalogs',0,'BB' DB 'COMM-80',1,'Modem programs for ZCPR-CP/M',0,'4B' DB 'CPM-86',1,'CP/M-86 Area',0,'2E' DB 'DBASE',1,'DBASEII programs',0,'AC' DB 'EMX',1,'Simon Ewins'' remote message/software system',0,'4C' DB 'S100',1,'Source for Multiflex, other S100',0,'8C' DB 'SYS-80',1,'ZCPR-CP/M System Files',0,'2B' DB 'UTIL-80',1,'ZCPR-CP/M Utilities',0,'3B' DB 'VIDTEK',1,'Source for SBC-80, JLS BB',0,'6C' DB 'WORD-80',1,'Word-processing related files',0,'9C' DB 'XEROX',1,'Source for XEROX 820-I',0,'7C' DB 'ZCPR2',1,'ZCPR2 processor for CP/M-80',0,'BC' DB 'ZCPR3',1,'ZCPR3 processor for CP/M-80',0,'CC' DB 0 ;<<== end of table1 table2: DB 'PC-COMM',1,'Modem programs for PC/XT/AT',0,'1D' DB 'PC-GAME',1,'Games for PC/XT/AT',0,'4D' DB 'PC-KERMIT',1,'Columbia U''s Communications Program',0,'3E' DB 'PC-MASM',1,'8086/286 Assembly Language Source',0,'7D' DB 'PC-PROG',1,'General Program Area',0,'8D' DB 'PC-RBBS',1,'Remote system software',0,'6D' DB 'PC-TURBO',1,'Turbo Pascal Files',0,'1E' DB 'PC-UTIL1',1,'Utilities for IBM PC/XT/AT',0,'0D' DB 'PC-UTIL2',1,'More PC/XT/AT Utilities',0,'2D' DB 'PC-WORD',1,'Word processing related files',0,'5D' DB 0 ;<<== end of table2 table3: DB 'MAC',1,'Apple MACINTOSH Area',0,'0F' DB 0 ;<<== end of table3 ; ; -----< end of SECTIONS table>----- ; END pbase ;that's all.