home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / p / sbasics.lbr / DRIVER.BZS / DRIVER.BAS
Encoding:
BASIC Source File  |  1993-10-25  |  11.4 KB  |  427 lines

  1. comment
  2.     Program:    DRIVER
  3.     Version:    1.0  
  4.         Date:        30 May 83
  5.     Purpose:    Display a menu of COM files and execute selected
  6.             program.
  7.     Writer:         Bryan Ashby
  8.             850 Pine Avenue, Pacific Grove, CA 93950.          
  9.     Copyright:    None.  This program is deposited in the public domain
  10.             in the hope that it may be improved.
  11.  
  12.     Program Structure:
  13.                 DRIVER
  14.                                    |
  15.           _________________________|________________
  16.           |        |                 |               |
  17.       SET_DISK   MENU          SELECT         RUN
  18.                    |             |    |           | |
  19.              |   POINTER_BACK   |  PARAMETERS |
  20.              |              |            ADD_CHAR
  21.              |          POINTER_FORWARD
  22.              |
  23.      ______________|__________________________________
  24.      |           |       |         |                  |
  25. READ_SECTOR    MATCH   SKEW   DISPLAY_LABEL   DIRECTORY_ENTRY
  26.  
  27. end
  28. $page
  29. rem ---------------------------------------
  30. rem Set addresses of BIOS entry points.
  31. rem See CP/M Alteration Guide, Section 6.
  32. rem ---------------------------------------
  33. var    SELDSK      ; Select disk
  34.     SETTRK        ; Set track
  35.     SETSEC        ; Set sector
  36.     SETDMA        ; Set Disk Memory Access buffer
  37.     B_READ        ; Read sector
  38.     SECTRAN        ; Logical-to-physical sector translate
  39.         = integer
  40. based    WBOOT     = integer
  41. base      WBOOT at 1
  42. SELDSK    = WBOOT + 24
  43. SETTRK    = WBOOT + 27
  44. SETSEC    = WBOOT + 30
  45. SETDMA    = WBOOT + 33
  46. B_READ    = WBOOT + 36
  47. SECTRAN    = WBOOT + 36
  48.  
  49. rem -------------
  50. rem CPU registers
  51. rem -------------
  52. var    HL,DE,BC,A_PSW    = integer
  53. based     BIOS_RETURN    = byte
  54. location var HL = A_PSW
  55. base BIOS_RETURN at HL + 1
  56.  
  57. rem ----------------------------------------------
  58. rem Disk Memory Access (DMA) buffer for sector I/O
  59. rem ----------------------------------------------
  60. dim byte    SECTOR(128)
  61. var         LOC_SECTOR = integer
  62. location array    LOC_SECTOR = SECTOR
  63.  
  64. dim byte COMMANDS(20,10)
  65. $constant     TOPLINE = 5
  66. $constant     BOTTOMLINE = 19 
  67. $constant     COL1    = 18
  68. $constant     COL2    = 52
  69. $constant    ETERNITY = 0
  70. $page
  71. var     BYTE    = byte    ; Input character
  72. var    I,J,K        ; Work variables
  73.     FCB_LOC        ; Location of File Control Block
  74.     DIR_SECTORS    ; Number of sectors occupied by directory
  75.        COUNT            ; Number of COM files
  76.     LEFTCOUNT    ; Number of files in left column
  77.     X,Y         ; Location of cursor
  78.         = integer
  79. based    FIRST_DIR_TRACK    ;
  80.     SKEW_TABLE_ADDRESS ;
  81.     SECTORS_PER_TRACK  = integer
  82. dim base byte FILENAME(8)    
  83.  
  84. $constant TBUFF = 80H
  85. based BUFFLEN   = byte
  86. base  BUFFLEN   at TBUFF
  87. dim base char COMBUFF(30)
  88. locate COMBUFF at TBUFF + 1
  89. dim base byte COMARRAY(30)
  90. var     COMMAND = string:14  
  91. $page
  92.  
  93. Procedure SET_DISK ( DISK = char )
  94. rem ==========================================================
  95. rem Select the disk in the DISK drive and set the DMA.
  96. rem ==========================================================
  97. var    DISKNUM        ;
  98.     DPH_ADDRESS    = integer    ; Address of Disk Parameter Header
  99. based    DPB              = integer    ; Disk Parameter Block
  100. based   DIR_BLOCKS    = integer
  101.  
  102. DISKNUM = DISK - 'A'
  103.  
  104. call (SELDSK, DPH_ADDRESS, DE, DISKNUM, A_PSW)
  105.  
  106.    base SKEW_TABLE_ADDRESS at DPH_ADDRESS
  107.    base DPB           at DPH_ADDRESS + 10
  108.    base SECTORS_PER_TRACK  at DPB
  109.    base DIR_BLOCKS       at DPB + 7
  110.    base FIRST_DIR_TRACK       at DPB + 13
  111.    DIR_SECTORS    = (DIR_BLOCKS+1) / 4
  112.    BC = LOC_SECTOR + 1
  113.  
  114. call (SETDMA, HL, DE, BC, A_PSW)
  115.  
  116. end
  117. $page
  118.  
  119. Function SKEW (SECTR = integer) = integer
  120. rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  121. rem Return the physical sector number coresponding to the logical sector SECTR
  122. rem Uses the BIOS routine SECTRAN and the translate table address which was set
  123. rem in SET_DISK.
  124. rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  125. if SKEW_TABLE_ADDRESS <> 0 \
  126.     then begin
  127.         BC = SECTR - 1
  128.         call (SECTRAN, HL, SKEW_TABLE_ADDRESS, BC, A_PSW)
  129.          end
  130.     else HL = SECTR - 1
  131. end = HL
  132.  
  133. Procedure READ_SECTOR (TRACK, SEC = integer)
  134. rem =================================================
  135. rem Read sector SEC of track TRACK into SECTOR array.
  136. rem =================================================
  137. for K = 1 to 128
  138.     SECTOR[K] = 0
  139. next K
  140. call (SETTRK, HL, DE, TRACK, A_PSW)
  141. call (SETSEC, HL, DE, SEC,   A_PSW)
  142. call (B_READ, HL, DE, BC,    A_PSW)
  143. SECTOR[0] = BIOS_RETURN
  144. end
  145.  
  146. Procedure GOTOXY (XX,YY = integer)
  147. rem ================================ 
  148. rem Move cursor to column XX, line YY.
  149. rem 1,1 is top left.
  150. rem ================================
  151. print chr(27); '='; chr(YY+31); chr(XX+31);
  152. end
  153.  
  154. Procedure DISPLAY (XX,YY = integer; IT = string)
  155. rem ==================
  156. rem Display IT at XX,YY.
  157. rem ==================
  158. GOTOXY XX,YY
  159. print IT;
  160. end
  161. $page
  162. Procedure DISPLAY_LABEL (DISK=byte)
  163. rem ==========================================
  164. rem Display the disk 'label'.
  165. rem The label is a filename starting with '-'.
  166. rem ==========================================
  167. var L = integer
  168. dim base byte TYPE(3)    
  169. DISPLAY X-6, 3, "Disk ";
  170. print DISK; " is:             ";
  171. GOTOXY X+5, 3
  172. for L = 1 to 8
  173.     if FILENAME[L] = ' ' \
  174.     then L = 8
  175.     else print FILENAME[L];
  176. next L
  177. print '.';
  178. locate TYPE at FCB_LOC + 9
  179. for L = 1 to 3
  180.     print TYPE[L];
  181. next L
  182. end
  183.  
  184. Function MATCH (ADDRESS=integer; TARGET=string:8) = byte
  185. rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  186. rem See whether the characters starting at ADDRESS match the TARGET string.
  187. rem ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  188. dim base byte ARRAY(8)
  189. var RESULT = byte
  190. var INDEX  = integer
  191. locate ARRAY at ADDRESS
  192. RESULT = 't'
  193. INDEX = 0
  194. repeat
  195.     begin
  196.     INDEX = INDEX + 1
  197.     if ARRAY[INDEX] <> mid(TARGET,INDEX,1) then RESULT = 'f'
  198.     end
  199. until RESULT = 'f' or INDEX = len(TARGET)
  200. end = RESULT
  201. $page
  202. Procedure DIRECTORY_ENTRY (DISK = byte)
  203. rem ============================================================= 
  204. rem Read an entry from the directory on DISK.
  205. rem If its a COM file, display it and save it in the COMMANDS table.
  206. rem =============================================================
  207. based    EXTENT  = byte
  208. base    EXTENT  at FCB_LOC + 13
  209. if EXTENT = 0 \
  210.     then begin
  211.         if FILENAME[1] = '-' then DISPLAY_LABEL DISK
  212.             if MATCH(FCB_LOC+9,"COM") \
  213.         then if MATCH(FCB_LOC+1,"DRIVER") = 'f' \
  214.             then begin
  215.                 GOTOXY X, Y
  216.                 print DISK; ": ";
  217.                 COUNT = COUNT + 1
  218.                 COMMANDS[COUNT,1] = DISK
  219.                 COMMANDS[COUNT,2] = ':'
  220.                 for K = 1 to 8
  221.                     print FILENAME[K];
  222.                     COMMANDS[COUNT,K+2] = FILENAME[K]
  223.                 next K
  224.                 Y = Y + 1
  225.                 if Y > BOTTOMLINE \
  226.                     then begin
  227.                         Y = TOPLINE
  228.                         X  = COL2
  229.                      end
  230.                  end
  231.      end
  232. end
  233. $page
  234. Procedure MENU ( DISK = byte )
  235. rem ============================================================= 
  236. rem Read the directory of the DISK, and construct the menu.
  237. rem Display each COM file name and save it in the COMMANDS table.
  238. rem The first byte is ASCII 229 (E5H) if entry is unused.
  239. rem =============================================================
  240. var    TRACK    ;
  241.     SEC    ;
  242.     COUNTX    = integer
  243. based   USED    = byte
  244. COUNTX  = COUNT
  245. TRACK    = FIRST_DIR_TRACK
  246. SEC    = 0
  247. for I = 1 to DIR_SECTORS
  248.     SEC = SEC + 1
  249.     if SEC > SECTORS_PER_TRACK \
  250.     then begin
  251.         TRACK = TRACK + 1
  252.         SEC   = 1
  253.          end
  254.     READ_SECTOR TRACK, SKEW(SEC)
  255.     for FCB_LOC = LOC_SECTOR to LOC_SECTOR+96 step 32
  256.     base USED at FCB_LOC
  257.     locate FILENAME at FCB_LOC + 1
  258.     if USED = chr(229) \
  259.         then if FILENAME[1] = chr(229) \
  260.             then I = DIR_SECTORS    rem: No more dirctory entries.
  261.             else I = I            rem: Dummy statement
  262.         else DIRECTORY_ENTRY DISK
  263.     next FCB_LOC
  264. next I                
  265. if COUNT = COUNTX \
  266.     then begin
  267.         if DISK = 'A' then X = COL1
  268.               else X = COL2
  269.         DISPLAY X,TOPLINE, "(No COM files) "
  270.      end
  271. end
  272. $page
  273. procedure POINTER_BACK
  274. rem ======================================================================
  275. rem Move the pointer back;  if at the top, move to the bottom.
  276. rem Called from SELECT in response to an up-arrow, left-arrow, "<" or ",".
  277. rem ======================================================================
  278. if I = 1 \
  279.     then begin
  280.         I = COUNT
  281.         if LEFTCOUNT = COUNT \
  282.         then Y = TOPLINE + COUNT - 1
  283.         else begin
  284.             Y = TOPLINE + COUNT - LEFTCOUNT - 1
  285.             X  = COL2 - 5
  286.              end
  287.      end
  288.     else begin
  289.         I = I - 1
  290.         if Y = TOPLINE \
  291.         then begin
  292.             Y = TOPLINE + LEFTCOUNT - 1
  293.             X  = COL1 - 5
  294.              end
  295.         else Y = Y - 1
  296.     end
  297. end
  298.  
  299. procedure POINTER_FORWARD
  300. rem ======================================================================
  301. rem Move the pointer forward;  if at the bottom, move to the top.
  302. rem ======================================================================
  303. if I = COUNT \
  304.     then begin
  305.         I    = 1
  306.         Y = TOPLINE
  307.         X  = COL1 - 5
  308.      end
  309.     else begin
  310.         I = I + 1
  311.         if I = LEFTCOUNT + 1 \
  312.             then begin
  313.                 Y = TOPLINE
  314.                 X  = COL2 - 5
  315.              end
  316.         else Y = Y + 1
  317.      end
  318. end
  319. $page
  320. procedure PROMPT (MESSAGE=string)
  321. rem ==================================================================
  322. rem Display a message on the prompt line.  Clear the rest of the line.
  323. rem ==================================================================
  324. var COL,LINE = integer
  325. COL = len(MESSAGE) + 1
  326. LINE = BOTTOMLINE + 2
  327. DISPLAY   1, LINE, MESSAGE
  328. DISPLAY COL, LINE, space$(80-COL)
  329. GOTOXY  COL+1, LINE
  330. end
  331.  
  332.  
  333. procedure SELECT
  334. rem =========================================
  335. rem Select a program from the table.
  336. rem I is sequence number of selected program.
  337. rem =========================================
  338. PROMPT "X selects program;  any other key moves pointer."
  339. Y = TOPLINE
  340. X = COL1 - 5
  341. I = 1
  342. repeat
  343.    begin
  344.     DISPLAY X, Y, "X-->" 
  345.     GOTOXY  X, Y
  346.     input3 BYTE
  347.     if BYTE <> 'X' and BYTE <> 'x' \
  348.         then begin
  349.              DISPLAY X, Y, "    " 
  350.             if BYTE = 8 or BYTE = 11 or BYTE = ',' or BYTE = '<' \
  351.             then POINTER_BACK
  352.             else POINTER_FORWARD
  353.          end
  354.    end
  355. until BYTE = 'X' or BYTE = 'x'
  356. end
  357. $page
  358. procedure RUN
  359. rem ----------------------------------------------------------------------
  360. rem Display the selected program name and execute it.
  361. rem ----------------------------------------------------------------------
  362. var NOMORE = byte
  363. X = 1
  364. Y = BOTTOMLINE + 3
  365. GOTOXY  X, Y
  366. COMMAND = space$(14)
  367. NOMORE = 'f'
  368. repeat
  369.     begin
  370.     if X > 2 then mid(COMMAND,X-2,1) = COMMANDS[I,X]
  371.     if X = 2 then print '>';
  372.          else print COMMANDS[I,X];
  373.     X = X + 1
  374.     if X = 11 \
  375.         then NOMORE = 't'
  376.         else if COMMANDS[I,X] = ' ' then NOMORE = 't'
  377.     end
  378. until NOMORE
  379. print ' ';
  380. if X = 11 \
  381.     then mid(COMMAND,X-1,4) = ".COM"
  382.     else mid(COMMAND,X-2,4) = ".COM"
  383.  
  384. SET_DISK COMMANDS[I,1]        rem: Select drive A or B
  385.  
  386. execute COMMAND            rem: Exit DRIVER.  It is assumed that DRIVER
  387.                 rem: has been linked into CP/M by the Auto-load
  388.                 rem: feature, so it will be reinvoked on the
  389.                 rem: next warm boot.
  390. end
  391. $page
  392. print chr(26); 
  393. DISPLAY 29,1, "~~~  D R I V E R  ~~~"
  394.  
  395. Y    = TOPLINE
  396. X    = COL1
  397. COUNT     = 0
  398. SET_DISK 'A'
  399.  
  400. MENU 'A'
  401.  
  402. if X = COL1 then LEFTCOUNT = COUNT
  403.         else LEFTCOUNT = BOTTOMLINE - TOPLINE + 1
  404. PROMPT "Drive B too ?  (y/n)  "
  405. input3 BYTE
  406. if BYTE = 'Y' or BYTE = 'y' \
  407.     then begin
  408.         SET_DISK 'B'
  409.         if X = COL1 then Y = TOPLINE
  410.         X = COL2
  411.         MENU 'B'
  412.      end
  413.  
  414. if COUNT > 0 \
  415.     then repeat
  416.          begin
  417.         SELECT
  418.         RUN
  419.          end
  420.      until ETERNITY
  421.     else begin
  422.          PROMPT "Please put another disk in A or B, then press any key."
  423.          input3 BYTE
  424.      end
  425.  
  426. end
  427.