home *** CD-ROM | disk | FTP | other *** search
- ;
- ; MENU.ASM Version 2.0 as of April 26, 1981
- ;
- ; Original Program by: James J. Frantz, May 31, 1979
- ;
- ; Menu Program Selection for '.BAS', '.INT' or '.COM' Files
- ;
- ;
- ; Modified from original by: Kelly Smith
- ;
- ; Version 2.0 contains the following modifications:
- ;
- ; (1) Made CP/M 2.X compatible; previous version would
- ; "clobber" the '$' string delimiter in filename and
- ; would display filenames and garbage memory 'ad
- ; nauseum'.
- ;
- ; (2) Added equates for either MBASIC or CBASIC assembly
- ; function, and corresponding 'heading'.
- ;
- ; Note: You must have MBASIC.COM on the currently
- ; logged diskette if 'mbasic$program' equate is
- ; true, and it will expect files of type '.BAS'.
- ; If 'cbasic$program' equate is true, you must
- ; have CRUN.COM on the currently logged
- ; diskette, and it will expect files of type
- ; '.INT'. If neither is equated to true, '.COM'
- ; filetypes are assumed.
- ;
- ; (3) Added command option to select drive for user
- ; requested MENU. (i.e., MENU B:<cr>). If corresponding
- ; filetype is not found for assembled MENU type (.BAS,
- ; .INT or .COM), MENU will display "+++ File Not Found
- ; +++" and return to the default drive.
- ;
- ; (4) Added "Disk Drive - X:" to heading display, where 'X'
- ; is the selected drive.
- ;
- ; (5) Added conditional assembly switches for 'upper'
- ; (uppercase only terminals), 'stdcpm' (standard CP/M),
- ; 'altcpm' (alternate CP/M).
- ;
- ; (6) Added conditional assembly switch for 'no$sys$files',
- ; to inhibit display of CP/M 2.X 'SYS' files. Handy, if
- ; running a Remote CP/M System and you don't want to let
- ; the whole world know whats 'hidden'...
- ;
- ; (7) Stripped MSB "tag bit" for files set-up for Remote
- ; CP/M Systems as "not for distribution". Files would
- ; not be sorted in proper order for display without
- ; this...this will also work for MP/M system
- ; configuration where "tag bit" must be 'Bit 6' (NOT Bit
- ; 7)...Bit 7 used as "tag" in MP/M environment fouls up
- ; the 'Control-S' start/stop video scroll function, so
- ; some users are switching to Bit 6 as "tag"...
- ;
- ; (8) Fixed bug when MENU is set for BASIC file (either
- ; MBASIC or CBASIC) and is in B: (or greater drive) and
- ; attempting to load the MBASIC (or CRUN) and THEN the
- ; '.BAS' (or '.INT') file...now looks on same diskette
- ; that MENU is on.
- ;
- ; (9) Added 'widecrt' equate for two CRT terminal display
- ; formats. Set the equate 'widecrt' to true if your CRT
- ; terminal can display 80 columns by 24 rows. If
- ; 'widecrt' is false, the default display is 64 columns
- ; by 16 rows.
- ;
- ; As supplied, MENU.ASM is set-up for the following system
- ; configuration and display format:
- ;
- ; Lowercase terminal display: upper = false
- ;
- ; 80 column by 24 row display: widecrt = true
- ;
- ; Standard CP/M: stdcpm = true
- ; altcpm = false
- ;
- ; Display '.COM' Menu: mbasic$program = false
- ; cbasic$program = false
- ;
- ; No display of 'SYS' files: no$sys$files = true
- ;
- ;
- ;
- ; A Generalized Suggestions for Using MENU
- ;
- ; If you have kids that love to play games on your system,
- ; this is perhaps the most 'protective' way to keep there
- ; "busy little hands" out of the CP/M operating
- ; system...Just set the little BAST..errr, pardon me...set
- ; your "prodigy child" up with a GAMES diskette that
- ; AUTOLOAD's the MENU program, and never ever again will you
- ; hear "Gee Dad, I tried ERA *.* and now nuthi'n works...".
- ;
- ;
- ;
- true equ -1 ; define true
- false equ not true; define false
- ;
- mbasic$program equ false ; true = .BAS
- cbasic$program equ false ; true = .INT
- ;
- ; Note: Only one may be true, and
- ; both false = .COM
- ;
- no$sys$files equ true ; true = no SYS display, false = SYS display
- ;
- upper equ false ; true if uppercase only terminal
- widecrt equ true ; true if 80 column/24 row terminal
- ;
- stdcpm equ true ; true if standard CP/M (base address 0000h)
- altcpm equ false ; true if alternate CP/M (base address 4200h)
- ;
- if stdcpm ; if standard CP/M...
- base equ 0000h ; base for standard CP/M system
- endif ; end if...
- ;
- if altcpm ; if alternate CP/M...
- base equ 4200h ; base for H8 or TRS-80 CP/M system
- endif ; end if...
- ;
- bdos equ base+5 ; CP/M BDOS entry address for function call
- tfcb equ base+5ch; transient file control block base address
- ;
- nbr$col equ 4 ; number of columns to display
-
- if widecrt ; if 80 column/24 row crt terminal...
- screen$size equ 24 ; terminal has 24 lines/screen display
- screen$hgt equ 80 ; terminal has 80 rows/screen display
- endif ; end if...
-
- if not widecrt ; if 64 column/16 row crt terminal...
- screen$size equ 16 ; terminal has 16 lines/screen display
- screen$hgt equ 64 ; terminal has 64 rows/screen display
- endif ; end if...
- ;
- ccp$len equ 3c06h-3400h ; calculate CCP length
- ;
- bel equ 007h ; (^g) bell - human attention required
- lf equ 00ah ; (^j) line feed
- cr equ 00dh ; (^m) carriage return
-
- org base+100h
-
- start: lxi sp,stack$area ; set up a stack
- lda tfcb ; get drive specification
- ora a ; was drive explicity requested?
- jnz drive$request ; if yes, skip interrogate disk request
- mvi c,25 ; 'interrogate disk' function
- call bdos ; find out which disk we're on...
- inr a ; make A: = 1
- ;
- drive$request:
- ;
- adi 'A'-1 ; make it ASCII
- sta driveid ; save the ASCII drive identification
- sbi '@' ; make it HEX
- sta srch$fcb ; set selection for requested or default drive
- mvi c,17 ; 'search first' command
- ;
- sort$loop:
- ;
- lxi d,srch$fcb ; point file control block
- call bdos ; use CP/M entry point
- ora a ; test for -1
- jm assign$menu$nbr ; print empty
- jz kludge ; do not set file found, if zero
- sta file$found ; set file found flag
- kludge: rrc ; this is the same as
- rrc ; 5 "add a's"
- rrc
- ani 60h ; mask correct bits
- adi 80h ; add base address (0080h)
- mov e,a ; put pointer in (de)
- mvi d,0 ; as 16 bit value
- lxi h,dirtable ; point start of table of
- ; sorted names
- inx d ; point past erase field
- ;
- compare$loop:
- ;
- push d ; save pointer to next
- ; entry from disk directory
- mvi c,8 ; length of compare
- push h ; save pointer to table
- ;
- compare1:
- ;
- ldax d ; get trial name char
- ani 7fh ; mask-off high bit 'cause may be
- ; "tagged" as 'not for distribution' for RCPM's
- cmp m ; match?
- jnz end$compare ; if not, try next entry
- inx h ; advance pointers
- inx d
- dcr c ; one less char to compare
- jnz compare1 ; keep testing
- ;
- end$compare:
- ;
- pop b ; restore table pointer
- jc insert$name ; directory name goes in
- ; front of current table
- ; entry if lower (cy = 1)
- lxi h,14 ; length of table entry
- dad b ; (hl) to next table entry
- pop d ; recover trailer name point
- jmp compare$loop ; loop again
- ;
- insert$name:
- ;
- if no$sys$files ; if no SYStem files to be displayed...
- push b ; save pointer to table entry
- push d ; save pointer to file name
- xchg
- lxi d,9 ; add bias for "SYS" flag character
- dad d
- mov a,m ; get character
- ani 80h ; mask for "SYS" flag
- pop d ; adjust stack, in case we take the next jump
- pop b ; ...or we really need the pointers
- jnz abort ; abort this filename, if "SYS"
- endif ; end if...
-
- ldax d ; get first byte of filename
- ani 7fh ; mask-off high bit 'cause may be
- ; "tagged" as 'not for distribution' for RCPM's
- stax d ; and save back, so proper file sort display
- lxi h,file$count ; count the number of files
- inr m ; to be displayed
- lhld end$of$table ; get pointer to table
- xchg
- lxi h,14 ; distance to move
- dad d ; (hl) point destination
- shld end$of$table ; save the new end of table
- inx h
- inx d
- ;
- move$up:
- ;
- dcx d
- dcx h
- ldax d ; get byte to move
- mov m,a ; put in new spot
- mov a,c ; test for done
- cmp e ; (bc) = (de)?
- jnz move$up
- mov a,b
- cmp d
- jnz move$up
- pop h ; recover pointer
- mvi c,8
- call block$move ; insert name in table
- lxi h,menu$buff ; point menu number block
- mvi c,6 ; length of movek
- call block$move ; insert text in table
- abort: mvi c,18 ; 'search next' command
- jmp sort$loop
- ;
- assign$menu$nbr:
- ;
- lda file$count
- mov b,a ; save in (b)
- push psw ; and on stack
- mvi c,0 ; initial file number
- lxi h,dirtable+11 ; point first file number
- lxi d,13 ; offset to other numbers
- ;
- number$files:
- ;
- mov a,c ; put file number in (a)
- adi 1 ; increment
- daa ; decimal convert
- mov c,a ; resave in (c)
- rrc ; get tens digit into
- rrc ; proper place
- rrc ;
- rrc
- ani 0fh ; add mask
- jz use$blank ; supress leading zero by
- adi 10h ; add either 20h (ASCII ' ')
- ;
- use$blank:
- ;
- adi ' ' ; or 20h + 10h for numeral
- mov m,a ; put in text stream
- mov a,c ; get units portion
- ani 0fh ; mask off tens portion
- adi '0' ; convert to ASCII
- inx h
- mov m,a
- dad d ; repeat until all files
- dcr b ; are sequentially numbered
- jnz number$files
- pop psw ; get file$count from stack
- push psw ; and save again for later
- adi nbr$col-1
- mvi b,255 ; (b) accumulates quotient
- ; so set to -1 for at least
- ; 1 pass thru gives 0
- ;
- divx:
- ;
- inr b
- sui nbr$col ; divide (file$count+3) by
- ; fout to get offset1
- jp divx
- adi nbr$col ; substracted once too much
- ; so add it back on
- lxi h,offset1
- mov m,b ; insert offset1 into table
- inx h ; point offset2 location
- jnz setoffset2 ; same as offset1 if non-
- ; zero remainder
- dcr b ; else offset2 = offset1-1
- ;
- setoffset2:
- ;
- mov m,b ; put offset2 in table
- inx h ; point offset for col 3
- dcr a ; test for remainder of 1
- jnz setoffset3 ; if remainder <> 1, use
- ; offset3 = offset2-1
- dcr b ; else offset3 = offset2-1y
- ;
- setoffset3:
- ;
- mov m,b ; else offset to column 4
- ;
- reprint:
- ;
- pop psw ; recover file count
- ;
- reprint1:
- ;
- push psw ; save again for later use
- sta file$count ; save for counting
- mvi a,screen$hgt ; set for video display size
- sta line$count
- lda file$found ; get file$found flag
- ora a ; and set psw flags
- jz exit ; if zero, no files of this type found
- lxi d,heading
- mvi c,9 ; buffer printer command
- call bdos ; CP/M prints heading
- lxi h,dir$table-14 ; point dummy 0th entry
- ;
- print$line:
- ;
- push h ; save base address
- lxi d,offset0 ; point offset table
- mvi a,nbr$col ; 4 column per line
- ;
- print$name:
- ;
- sta column$cnt ; save count of columns
- push h ; save current name pointer
- push d ; save offset table pointer
-
- if widecrt ; if 80 column/24 row crt terminal...
- lxi d,doubl$space ; print 2 spaces
- mvi c,9 ; 'print buffer' command
- call bdos ; use CP/M
- endif ; end if...
-
- lxi d,doubl$space ; print 2 spaces
- mvi c,9 ; 'print buffer' command
- call bdos ; use CP/M
- pop d ; get offset table pointer
- pop h ; get name pointer
- ldax d ; get offset value
- lxi b,14 ; each name is 14 long
- ;
- mult$14:
- ;
- dad b ; add 14 for each offset
- dcr a ; until offset = 0
- jnz mult$14
- push h ; save new name pointer
- push d ; save offset pointer
- xchg ; pointer name to print w/(de)
- mvi c,9 ; print buffer
- call bdos ; print file name
- ; and it's menu number
- ;
- test$finish:
- ;
- lxi h,file$count ; see if done printing
- dcr m ; by testing count of files
- pop d ; get offset pointer
- pop h ; get pointer to last name
- jz finish ; no more to print
- inx d ; advance offset pointer
- lda column$cnt
- dcr a ; see if column left = 0
- jnz print$name ; print another save line
- call crlf
- pop h ; get base of previous line
- lxi d,14 ; add offset
- dad d
- jmp print$line
- ;
- finish:
- ;
- pop h ; unjunk stack
- ;
- lf$loop:
- ;
- call crlf
- lxi d,prompt ; point instruction message
- mvi c,9
- call bdos
- lxi d,input$buff
- mvi a,10 ; 10 characters maximum
- stax d
- mvi c,10 ; 'read buffer' command
- call bdos
- lxi h,input$buff+1 ; point to character counter
- mov a,m ; get it and see if >2
- cpi 3
- jnc reprint ; reprint the menu
- mov c,a ; count of digits to (c)
- mvi b,0
- ;
- get$menu$nbr:
- ;
- inx h ; point ASCII digit
- mov a,m ; get it
- call ascii$convert ; convert to binary
- jc reprint ; re-display on error
- dcr c
- jnz get$menu$nbr
- pop psw ; recover file counter
- cmp b ; file count - request number
- jc reprint1 ; redisplay menu if illegal
- lxi d,14 ; increment between names
- lxi h,dir$table-14 ; point dummy 0th entry
- ;
- find$name:
- ;
- dad d ; add offset b times
- dcr b
- jnz find$name
- push d ; found filename, tidy-up screen...
- push h
- lxi d,crlfmsg
- mvi c,9
- call bdos
- pop h
- pop d
- xchg ; save pointer to file name
- lhld base+6 ; get bdos entry point
- lxi b,-ccp$len ; offset to start of CP/M
- dad b
- push h ; save CP/M entry point
- ; on stack for branch
- lxi b,8 ; offset to command buffer "autoload"
- dad b ; (hl) points place to put name of
- ; .BAS, .INT, or .COM file to be
- ; executed
- push d ; save pointer to file name
- xchg ; (de) points to command buffer
- lxi h,128 ; offset to end of command buffer
- ; where pointer is stored
- dad d ; (hl) points to storage place
- mov m,e ; update buffer pointer to
- inx h ; the start of the command
- mov m,d ; buffer so CP/M will read
- lda driveid ; get selected drive identification
- stax d ; store at start of command buffer
- inx d ; bump for ':' delimeter position
- mvi a,':' ; make delimeter
- stax d ; and store it...
- inx d ; bump for destination pointer to filename
-
- if mbasic$program or cbasic$program ; if BASIC program...
- lxi h,command$name ; point command name
- mvi c,len$cmd$name ; length of command name
- call block$move
- lda driveid ; get selected drive identification
- stax d ; store at start of command buffer
- inx d ; bump for ':' delimeter position
- mvi a,':' ; make delimeter
- stax d ; and store it...
- inx d ; bump for destination pointer to filename
- endif ; end if...
-
- pop h ; point selected file name
- mvi c,8 ; length of file name
- call block$move
-
- if mbasic$program or cbasic$program ; if BASIC program...
- lxi h, spec$type
- mvi c,4
- call block$move
- endif ; end if...
-
- xra a ; needs a 0 at end
- stax d ; of command line
- ret
- ;
- block$move:
- ;
- mov a,m
- stax d
- inx d
- inx h
- dcr c
- jnz block$move
- ret
- ;
- ascii$convert:
- ;
- sui '0' ; subtract ASCII bias
- cpi 9+1 ; be sure it's numeric
- cmc
- rc
- mov d,a
- mov a,b
- rlc
- rlc
- rlc
- add b
- rc
- add b
- rc
- add d
- mov b,a
- ret
- ;
- crlf:
- ;
- lxi d,crlfmsg
- mvi c,9
- call bdos
- lxi h,line$count
- dcr m
- ret
- ;
- exit: lxi d,nofile ; indicate no files present
- mvi c,9
- call bdos
- jmp base ; and exit to CP/M via "warm boot"
- ;
- if upper ; if uppercase only terminal...
- nofile: db cr,lf,lf,'+++ FILE NOT FOUND! +++',cr,lf,'$'
- endif
-
- if not upper ; if not uppercase only terminal...
- nofile: db cr,lf,lf,'+++ File Not Found! +++',cr,lf,'$'
- endif
-
- crlfmsg: db cr,lf,'$'
- ;
- heading: db cr,lf,lf
- if widecrt and mbasic$program
- db ' '
- endif
-
- if not widecrt and mbasic$program
- db ' '
- endif
-
- if upper and mbasic$program
- db 'MICROSOFT COMPATIBLE BASIC FILE MENU'
- endif
-
- if not upper and mbasic$program
- db 'Microsoft Compatible BASIC File Menu'
- endif
-
- if widecrt and cbasic$program
- db ' '
- endif
-
- if not widecrt and cbasic$program
- db ' '
- endif
-
- if upper and cbasic$program
- db 'COMPILER SYSTEMS COMPATIBLE BASIC FILE MENU'
- endif
-
- if not upper and cbasic$program
- db 'Compiler Systems Compatible BASIC File Menu'
- endif
-
- if widecrt and not mbasic$program and not cbasic$program
- db ' '
- endif
-
- if not widecrt and not mbasic$program and not cbasic$program
- db ' '
- endif
-
- if upper and not mbasic$program and not cbasic$program
- db 'CP/M COMMAND FILE MENU'
- endif
-
- if not upper and not mbasic$program and not cbasic$program
- db 'CP/M Command File Menu'
- endif
-
- db cr,lf
-
- if widecrt ; if 80 column/24 row crt terminal...
- db ' '
- endif ; end if...
-
- if not widecrt ; if 64 column/16 row crt terminal
- db ' '
- endif ; end if...
-
- if upper ; if uppercase only terminal...
- db 'DISK DRIVE - '
- endif ; end if...
-
- if not upper ; if not uppercase only terminal
- db 'Disk Drive - '
- endif ; end if...
-
- driveid:ds 1 ; current logged ASCII drive identification
-
- db ':',cr,lf,lf,'$'
-
- if upper ; if uppercase only terminal
- prompt: db cr,lf,bel,' ENTER MENU NUMBER, AND PRESS RETURN: $'
- endif ; end if...
-
- if not upper ; if not uppercase only terminal...
- prompt: db cr,lf,bel,' Enter menu number, and press return: $'
- endif ; end if...
-
- if mbasic$program ; if MBASIC program...
- command$name: db 'MBASIC ' ; Microsoft BASIC
- ;
- len$cmd$name equ $-command$name
- ;
- spec$type: db '.BAS'
- endif ; end if...
-
- if cbasic$program ; if CBASIC program...
- command$name: db 'CRUN ' ; Compiler Systems BASIC
- ;
- len$cmd$name equ $-command$name
- ;
- spec$type: db '.INT'
- endif ; end if...
-
- doubl$space: db ' $'
- ;
- menu$buff: db ' - 00$'
- ;
- offset0: db 1
- ;
- offset1: db 0,0,0
- ;
- end$of$table: dw dirtable
- ;
- file$count: db 0
- ;
- column$cnt: db 4
- ;
- line$count: db 0
- ;
- file$found: db 0 ; file found flag
-
- if mbasic$program ; if MBASIC program...
- srch$fcb: db 0,'????????BAS',0,0,0,0
- endif ; end if...
-
- if cbasic$program ; if CBASIC program...
- srch$fcb: db 0,'????????INT',0,0,0,0
- endif ; end if...
-
- if not mbasic$program and not cbasic$program ; if not BASIC program...
- srch$fcb: db 0,'????????COM',0,0,0,0
- endif ; end if...
-
- dir$table: db 255
- ;
- stack$area equ 200*14 + 30
- ;
- input$buff equ stack$area
- ;
- end start
-