home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / UTILS / DIRUTL / MENU.MAC < prev    next >
Text File  |  2000-06-30  |  12KB  |  461 lines

  1. title MENU
  2. .z80
  3. aseg
  4. ;
  5. ; Originally published in Creative Computing, December 1979
  6. ; by James J. Frantz who wrote this on May 31, 1979.
  7. ; Converted to Z80 code by Frank J. Wancho, August, 1980, and
  8. ; removed the BASIC dependencies - i.e. .COM files are the only
  9. ; file type examined and displayed.
  10. ;
  11. ; This program is designed to be automatically executed
  12. ; by CP/M immediately after a cold (or warm) boot.  This
  13. ; program then displays the contents of the disk in a
  14. ; menu fashion.  All files of specified type are sorted and
  15. ; displayed alphabetically in four columns.  The user then
  16. ; selects the desired program by its menu number.  The
  17. ; selected program is then run.
  18. ;
  19. PAGE
  20.     org    0100h
  21. ;
  22. ; First, the CP/M "Search" command is used to find the
  23. ; file of the specified type.  The pointer to the File
  24. ; Control Block is put in <DE>, and the command number is
  25. ; put in <C>.  The File Control Block is pre-constructed to
  26. ; the form '????????XXX0'.  The XXX is the specified file
  27. ; 'type', and the '?' force a match to any file name of that
  28. ; file type.
  29. ;
  30. start    equ    $
  31.     ld    sp,stack    ; Set up a stack
  32. again    equ    $
  33.     ld    c,17        ; 'Search First' Comand
  34. ;
  35. ; This next routine sorts the file names as they are found
  36. ; on the disk directory.  A name is read from the disk and
  37. ; its location is found in the directory table by comparing
  38. ; alphabetically.
  39. ;
  40. sortlp    equ    $
  41.     ld    de,srcfcb    ; Point File Control Block
  42.     call    bdos        ; Use CP/M entry point
  43. ;
  44. ; CP/M returns the disk address of the next match in <A>.
  45. ; This is a value between 0 and 64, or -1 if no match was
  46. ; found.  Test for -1 and quit when no more files of the
  47. ; specified file 'type' are found on the disk.  The disk
  48. ; address is converted to a pointer to the file name
  49. ; within the sector by multiplying by 32 and adding the
  50. ; base address of the sector.
  51. ;
  52.     cp    255        ; Test for -1
  53.     jp    z,assign    ; Print empty menu
  54.     rrca            ; This is the same as
  55.     rrca            ; 5 ADD A's
  56.     rrca
  57.     and    60h        ; Mask correct bits
  58.     add    a,80h        ; Add base address (0080h)
  59.     ld    e,a        ; Put pointer in <DE>
  60.     ld    d,0        ; as a 16 bit value
  61.     ld    hl,dirtab    ; Point to start of table of
  62.                 ; sorted names
  63.     inc    de        ; Point past erase field
  64. cmplop    equ    $
  65.     push    de        ; Save pointer to next
  66.                 ; entry from disk directory
  67.     ld    c,8        ; Length of compare
  68.     push    hl        ; Save pointer to table
  69. cmp1    equ    $
  70.     ld    a,(de)        ; Get trial name char
  71.     cp    (hl)        ; Match?
  72.     jr    nz,endcmp    ; If not, try next entry
  73.     inc    hl        ; Advance pointers
  74.     inc    de
  75.     dec    c
  76.     jr    nz,cmp1        ; Keep testing
  77. endcmp    equ    $
  78.     pop    bc        ; Restore table pointer
  79.     jr    c,insnam    ; Directory name goes in
  80.                 ; front of the current table
  81.                 ; if lower (CY=1)
  82.     ld    hl,14        ; Length of table entry
  83.     add    hl,bc        ; <HL> to next table entry
  84.     pop    de        ; Recover trial name point
  85.     jr    cmplop        ; Loop again
  86. ;
  87. ; This next portion makes room in the directory table for
  88. ; the new entry by moving all alphabetically higher names
  89. ; upward in memory.
  90. ;
  91. insnam    equ    $
  92.     ld    hl,filcnt    ; Count the number of files
  93.     inc    (hl)        ; to be displayed
  94.     ld    hl,(eot)    ; Get pointer to table end
  95.     ex    de,hl
  96.     ld    hl,14        ; Distance to move
  97.     add    hl,de        ; <HL> point destination
  98.     ld    (eot),hl    ; Save the new End of Table
  99.     inc    hl
  100.     inc    de
  101. ;
  102. moveup    equ    $
  103.     dec    de
  104.     dec    hl
  105.     ld    a,(de)        ; Get byte to move
  106.     ld    (hl),a        ; Put in new spot
  107.     ld    a,c        ; Test for done
  108.     cp    e        ; <BC>=<DE>?
  109.     jr    nz,moveup
  110.     ld    a,b
  111.     cp    d
  112.     jr    nz,moveup
  113.     pop    hl        ; Recover pointer
  114.     ld    c,8
  115.     call    blkmov        ; Insert name in table
  116. ;
  117. ; The menu number field is inserted in the directory table
  118. ; at this point but the actual menu number will be assigned
  119. ; after all the files are sorted.
  120. ;
  121.     ld    hl,menbuf    ; Point menu number block
  122.     ld    c,6        ; Length of move
  123.     call    blkmov        ; Insert text in table
  124. ;
  125. ; The command number for subsequent searches of the disk
  126. ; directory must be altered to cause CP/M to search from
  127. ; where it left off.
  128. ;
  129.     ld    c,18        ; 'Search Next' command
  130.     jp    sortlp
  131. PAGE
  132. ;
  133. ;
  134. ; This is the second major portion of the program.  At this
  135. ; point, all files have been inserted in the directory table
  136. ; in alphabetical order.  Now the menu numbers are assigned
  137. ; and inserted in the proper place in preparation for
  138. ; display on the terminal.
  139. ;
  140. assign    equ    $
  141.     ld    a,(filcnt)
  142.     ld    b,a        ; Save in <B>
  143.     push    af        ; and on stack
  144.     ld    c,0        ; Initial file number
  145.     ld    hl,dirtab+11    ; Point first file number
  146.     ld    de,13        ; Offset to other numbers
  147. numfil    equ    $
  148.     ld    a,c        ; Put file number in <A>
  149.     add    a,1        ; Increment
  150.     daa            ; Decimal convert
  151.     ld    c,a        ; Resave in <C>
  152.     rrca            ; Get tens digit into
  153.     rrca            ; proper place
  154.     rrca
  155.     rrca
  156.     and    0fh        ; and mask
  157.     jr    z,useblk    ; Suppress leading zero by
  158.     add    a,10h        ; add either 20H (ASCII ' ')
  159. useblk    equ    $
  160.     add    a,' '        ; or 20H + 10H for numeric
  161.     ld    (hl),a        ; Put in text stream
  162.     ld    a,c        ; Get units portion
  163.     and    0fh        ; Mask off tens portion
  164.     add    a,'0'        ; Convert to ASCII
  165.     inc    hl
  166.     ld    (hl),a
  167.     add    hl,de        ; Repeat until all files
  168.     djnz    numfil        ; are sequentially numbered
  169. ;
  170.     pop    af        ; Get FILCNT from stack
  171.     push    af        ; and save again for later
  172. ;
  173. ; This algorithym ensures the columns are as even in length
  174. ; as possible.  Don't worry, it works.
  175. ;
  176.     add    a,nbrcol-1
  177.     ld    b,-1        ; <B> accumulates quotient
  178.                 ; So set to -1 for at least
  179.                 ; one pass thru gives 0
  180. divx    equ    $
  181.     inc    b
  182.     sub    nbrcol        ; Divide (FILCNT+3) by
  183.                 ; four to get OFSET1
  184.     jp    p,divx
  185.     add    a,nbrcol    ; Subtracted once too much
  186.                 ; so add it back in
  187.     ld    hl,ofset1
  188.     ld    (hl),b        ; Insert OFSET1 into table
  189.     inc    hl        ; Point OFSET2 location
  190.     jr    nz,setof2    ; Same as OFSET2 if non-
  191.                 ; zero remainder
  192.     dec    b        ; Else OFSET2=OFSET1-1
  193. setof2    equ    $
  194.     ld    (hl),b        ; Put OFSET2 in table
  195.     inc    hl        ; Point OFFSET for Col. 3
  196.     dec    a        ; Test for remainder of 1
  197.     jr    nz,setof3    ; If remainder <> 1, use
  198.                 ; OFSET3=OFSET2
  199.     dec    b        ; Else OFSET3=OFSET2-1
  200. setof3    equ    $
  201.     ld    (hl),b        ; Offset to Col. 4
  202. ;
  203. ; Now that the offsets for the columns have been determined
  204. ; the actual print out can be made
  205. ;
  206. reprt    equ    $
  207.     pop    af        ; Recover FILCNT
  208. reprt1    equ    $
  209.     push    af        ; Save again for later use
  210.     ld    (filcnt),a    ; Save for counting
  211.     ld    a,scrhgt    ; Set for video display size
  212.     ld    (lincnt),a
  213.     call    clear        ; Clear screen
  214.     ld    de,hdg
  215.     call    print
  216. ;
  217.     ld    hl,dirtab-14    ; Point dummy 0th entry
  218. ;
  219. prtlin    equ    $
  220.     push    hl        ; Save base address
  221.     ld    de,ofset0    ; Point offset table
  222.     ld    a,nbrcol    ; 4 columns per line
  223. prtnam    equ    $
  224.     ld    (colcnt),a    ; Save count of columns
  225.     push    hl        ; Save current name pointer
  226.     push    de        ; Save offset table pointer
  227. ;
  228.     ld    de,trplsp    ; Print 3 blanks
  229.     call    print        ; Use CP/M facility
  230.     pop    de        ; Get offset table pointer
  231.     pop    hl        ; Get name pointer
  232.     ld    a,(de)        ; Get offset value
  233. ;
  234. ; The offset value is the number of file names from the
  235. ; current name pointer to move the print buffer.
  236. ;
  237.     ld    bc,14        ; Each name is 14 long
  238. mult14    equ    $
  239.     add    hl,bc        ; Add 14 for each offset
  240.     dec    a        ; Until offset = 0
  241.     jr    nz,mult14
  242.     push    hl        ; Save new name pointer
  243.     push    de        ; Save offset pointer
  244.     ex    de,hl        ; Point name to print w/<DE>
  245.     call    print        ; Print the file name and
  246.                 ; its menu number
  247. ;
  248. tesfin    equ    $
  249.     ld    hl,filcnt    ; See if done printing
  250.     dec    (hl)        ; by testing count of files
  251.     pop    de        ; Get offset pointer
  252.     pop    hl        ; Get pointer to last name
  253.     jr    z,finish    ; No more to print
  254.     inc    de        ; Advance offset pointer
  255.     ld    a,(colcnt)
  256.     dec    a        ; See if columns left = 0
  257.     jr    nz,prtnam    ; Print another same line
  258.     call    crlf        ; Move to next line
  259.     pop    hl        ; Get base of previous line
  260.     ld    de,14        ; Add offset
  261.     add    hl,de
  262.     jr    prtlin
  263. ;
  264. ; The file names and their menu numbers have been printed.
  265. ; This next loop outputs sufficient linefeeds to put the
  266. ; heading at the top of a 16 line video display (thereby
  267. ; clearing the screen), and puts the request for user
  268. ; selection at the bottom of the screen.
  269. ;
  270. ;
  271. finish    equ    $
  272.     pop    hl        ; Unjunk stack
  273. lfloop    equ    $
  274.     call    crlf
  275.     jp    p,lfloop    ; Omit this line if desired
  276.     ld    de,prompt    ; Point instruction msg
  277.     call    print        ; Again CP/M prints message
  278.     ld    de,inbuf
  279.     ld    a,10        ; Ten characters max
  280.     ld    (de),a
  281.     ld    c,10        ; 'Read Buffer' Command
  282.     call    bdos
  283. ;
  284. ; On return from BDOS line input function, the digits
  285. ; typed by the user are in the buffer at INBUF+2.
  286. ; Convert to binary
  287. ;
  288.     ld    hl,inbuf+1    ; Point character count
  289.     ld    a,(hl)        ; Get it and see if > 2
  290.     cp    3
  291.     jr    nc,reprt    ; Reprint the menu
  292.     ld    c,a        ; Count of digits to <C>
  293.     ld    b,0        ; Zero <B>
  294. ;
  295. getnum    equ    $
  296.     inc    hl        ; Point ASCII digit
  297.     ld    a,(hl)        ; Get it
  298.     call    ascbin        ; Convert to binary
  299.     jr    c,reprt        ; Redisplay on error
  300.     dec    c
  301.     jr    nz,getnum
  302. ;
  303. ; <B> has the menu number.  To be sure this is still a legal menu
  304. ; request, compare with FILCNT (still in stack).
  305. ;
  306.     pop    af        ; Recover file count
  307.     cp    b        ; FILCNT-request number
  308.     jp    c,reprt1    ; Redisplay menu if illegal
  309. ;
  310. ;
  311.     ld    de,14        ; Increment between names
  312.     ld    hl,dirtab-14    ; Point dummy 0th entry
  313. finame    equ    $
  314.     add    hl,de        ; Add offset <B> times
  315.     djnz    finame
  316. ;
  317. ; At this point <HL> points to the selected file name.  Now find
  318. ; the address of CP/M so the proper command name and the selected
  319. ; filename can be put into the command buffer.
  320. ;
  321.     ex    de,hl        ; Save pointer to file name
  322.     ld    hl,(6)        ; Get BDOS entry point
  323.     ld    bc,-ccplen    ; Offset to start of CP/M
  324.     add    hl,bc
  325.     push    hl        ; Save CP/M entry point
  326.                 ; on stack for branch.
  327.     ld    bc,7        ; Offset to command buffer
  328.     add    hl,bc        ; <HL> points place to put
  329.                 ; name of .COM file to be executed.
  330.     ld    a,8        ; Get default length of file name
  331.     ld    (hl),a        ; Store in CCP
  332.     inc    hl
  333.     push    de        ; Save pointer to file name
  334.     ex    de,hl        ; <DE> points command buffer
  335. ;
  336. ; Since the scan pointer is not reset by reentry into CP/M,
  337. ; the scan pointer must be reset by this program.  The scan
  338. ; pointer is stored by CP/M at the end of the command buffer.
  339. ;
  340.     ld    hl,128        ; Offset to end of cmd buff
  341.                 ; where pointer is stored
  342.     add    hl,de        ; <HL> points storage place
  343.     ld    (hl),e        ; Update buffer pointer to
  344.     inc    hl        ; to start of the command
  345.     ld    (hl),d        ; buff so CP/M will read.
  346. ;
  347. ; (The insertion of the BASIC command name goes here.  Removed
  348. ; from original version.)
  349. ;
  350.     pop    hl        ; Point selected file name
  351.     ld    c,8        ; Length of file name
  352.     call    blkmov
  353. ;
  354. ; (The insertion of file type goes here if your version of BASIC
  355. ; requires it.)
  356. ;
  357.     xor    a        ; Need a zero at end
  358.     ld    (de),a        ; of command line
  359. ;
  360. ; The address of CP/M is on the stack, so a simple RETurn
  361. ; will execute CP/M and in turn execute 'filename'.
  362. ;
  363.     ret
  364. ;
  365. ; Subroutines
  366. ;
  367. blkmov    equ    $
  368.     ld    a,(hl)
  369.     ld    (de),a
  370.     inc    de
  371.     inc    hl
  372.     dec    c
  373.     jr    nz,blkmov
  374.     ret
  375. ;
  376. ascbin    equ    $
  377.     sub    '0'        ; Subtract ASCII bias
  378.     cp    9+1        ; Be sure it's numeric
  379.     ccf
  380.     ret    c        ; Set CY=1 if illegal
  381.     ld    d,a        ; Save in <D>
  382.     ld    a,b        ; Get previous result
  383.     rlca            ; Multipy by 2
  384.     rlca            ; then 4
  385.     rlca            ; then 8
  386.     add    a,b        ; then 9
  387.     ret    c        ; out of bounds
  388.     add    a,b        ; Then finally by 10
  389.     ret    c        ; CY=1 always means error
  390.     add    a,d        ; Add in new result
  391.     ld    b,a        ; Save in <B>
  392.     ret
  393. ;
  394. crlf    equ    $
  395.     ld    de,crlfmsg
  396.     call    print
  397.     ld    hl,lincnt
  398.     dec    (hl)
  399.     ret
  400. ;
  401. print    equ    $
  402.     ld    c,9        ; Buffer print command
  403.     call    bdos        ; CP/M prints heading
  404.     ret
  405. ;
  406. clear    equ    $
  407.     ld    de,clrs
  408.     call    print
  409.     ret
  410. ;
  411. crlfmsg    equ    $
  412.     defm    0dh,0ah,'$'
  413. clrs    equ    $
  414.     defm    30,30,'$'    ; Clear Screen
  415. hdg    equ    $
  416.     defm    9,9,9,'     MENU',0dh,0ah,0ah,'$'
  417. ;
  418. prompt    equ    $
  419.     defm    'Enter MENU Number and press RETURN: $'
  420. ;
  421. trplsp    equ    $
  422.     defm    '   $'
  423. ;
  424. menbuf    equ    $
  425.     defm    ' -  0$'
  426. ;
  427. ;
  428. ofset0    equ    $
  429.     defb    1
  430. ofset1    equ    $
  431.     defm    0,0,0
  432. ;
  433. eot    equ    $
  434.     defw    dirtab
  435. ;
  436. filcnt    equ    $
  437.     defb    0
  438. colcnt    equ    $
  439.     defb    4
  440. lincnt    equ    $
  441.     defb    0
  442. ;
  443. srcfcb    equ    $
  444.     defm    0,'????????COM',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  445. ;
  446. dirtab    equ    $
  447.     defb    -1        ; Force first file to be put here
  448. ;
  449. stack    equ    dirtab+64*14+30
  450. ;
  451. inbuf    equ    stack
  452. ;
  453. ; Equates
  454. ;
  455. bdos    equ    5
  456. nbrcol    equ    4
  457. ccplen    equ    3106h-2900h
  458. scrsiz    equ    24
  459. scrhgt    equ    scrsiz-4
  460.     end    start
  461.