home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol007 / menu.asm < prev    next >
Assembly Source File  |  1984-04-29  |  8KB  |  427 lines

  1. ;            MENU PROGRAM
  2. ;               FOR
  3. ;        MACHINE LANGUAGE OR BASIC PROGRAMS
  4. ;
  5. ;               BY
  6. ;            JAMES J. FRANTZ
  7. ;              MAY 31, 1979    
  8. ;
  9. ;
  10.     ORG    0100H
  11. ;
  12. ;
  13. BASIC$PROG    EQU    0        ;SET TO 0 FOR MACHINE
  14. ;
  15.     LXI    SP,STACK$AREA        ;SET UP A STACK
  16.     MVI    C,17            ;'SEARCH FIRST' COMMAND
  17. ;
  18. SORT$LOOP:
  19.     LXI    D,SRCH$FCB        ;POINT FILE CONTROL BLOCK
  20.     CALL    BDOS            ;USE CP/M ENTRY POINT
  21. ;
  22. ;
  23.     ORA    A            ;TEST FOR -1
  24.     JM    ASSIGN$MENU$NBR        ;PRINT EMPTY
  25.     RRC                ;THIS IS THE SAME AS
  26.     RRC                ;5 "ADD A'S"
  27.     RRC
  28.     ANI    60H             ;MASK CORRECT BITS
  29.     ADI    80H            ;ADD BASE ADDRESS(0080H)
  30.     MOV    E,A            ;PUT POINTER IN (DE)
  31.     MVI    D,0            ;AS 16 BIT VALUE
  32.     LXI    H,DIRTABLE        ;POINT START OF TABLE OF
  33.                     ;SORTED NAMES
  34.     INX    D            ;POINT PAST ERASE FIELD
  35. ;
  36. COMPARE$LOOP:
  37. ;
  38.     PUSH    D            ;SAVE POINTER TO NEXT
  39.                     ;ENTRY FROM DISK DIRECTORY
  40.     MVI    C,8            ;LENGTH OF COMPARE
  41.     PUSH    H            ;SAVE POINTER TO TABLE
  42. ;
  43. COMPARE1:
  44.     LDAX    D            ;GET TRIAL NAME CHAR
  45.     CMP    M            ;MATCH?
  46.     JNZ    END$COMPARE        ;IF NOT, TRY NEXT ENTRY
  47.     INX    H            ;ADVANCE POINTERS
  48.     INX    D                
  49.     DCR    C            ;ONE LESS CHAR TO COMPARE    
  50.     JNZ    COMPARE1        ;KEEP TESTING    
  51. END$COMPARE:    
  52.     POP    B            ;RESTORE TABLE POINTER
  53.     JC    INSERT$NAME        ;DIRECTORY NAME GOES IN    
  54.                     ;FRONT OF CURRENT TABLE
  55.                     ;ENTRY IF LOWER(CY=1)
  56.     LXI    H,14            ;LENGTH OF TABLE ENTRY
  57.     DAD    B            ;(HL) TO NEXT TABLE ENTRY
  58.     POP    D            ;RECOVER TRAILER NAME POINT
  59.     JMP    COMPARE$LOOP        ;LOOP AGAIN
  60. ;    
  61. ;
  62. INSERT$NAME:
  63.     LXI    H,FILE$COUNT        ;COUNT THE NUMBER OF FILES
  64.     INR    M            ;TO BE DISPLAYED
  65.     LHLD    END$OF$TABLE        ;GET POINTER TO TABLE
  66.     XCHG
  67.     LXI    H,14            ;DISTANCE TO MOVE
  68.     DAD    D            ;(HL) POINT DESTINATION
  69.     SHLD    END$OF$TABLE        ;SAVE THE NEW END OF TABLE
  70.     INX    H
  71.     INX    D
  72. MOVE$UP:
  73.     DCX    D
  74.     DCX    H
  75.     LDAX    D            ;GET BYTE TO MOVE
  76.     MOV    M,A            ;PUT IN NEW SPOT
  77.     MOV    A,C            ;TEST FOR DONE
  78.     CMP    E            ;(BC)=(DE)?
  79.     JNZ    MOVE$UP
  80.     MOV    A,B
  81.     CMP    D
  82.     JNZ    MOVE$UP
  83.     POP    H            ;RECOVER POINTER
  84.     MVI    C,8
  85.     CALL    BLOCK$MOVE        ;INSERT NAME IN TABLE
  86. ;
  87.     LXI    H,MENU$BUFF        ;POINT MENU NUMBER BLOCK
  88.     MVI    C,6            ;LENGTH OF MOVEK
  89.     CALL    BLOCK$MOVE        ;INSERT TEXT IN TABLE
  90. ;
  91.     MVI    C,18            ;'SEARCH NEXT' COMMAND
  92.     JMP    SORT$LOOP
  93. ;
  94. ASSIGN$MENU$NBR:
  95.     LDA    FILE$COUNT
  96.     MOV    B,A            ;SAVE IN (B)
  97.     PUSH    PSW            ;AND ON STACK
  98.     MVI    C,0            ;INITIAL FILE NUMBER
  99.     LXI    H,DIRTABLE+11        ;POINT FIRST FILE NUMBER
  100.     LXI    D,13            ;OFFSET TO OTHER NUMBERS
  101. ;
  102. NUMBER$FILES:
  103.     MOV    A,C            ;PUT FILE NUMBER IN (A)
  104.     ADI    1            ;INCREMENT
  105.     DAA                ;DECIMAL CONVERT
  106.     MOV    C,A            ;RESAVE    IN (C)
  107.     RRC                ;GET TENS DIGIT INTO
  108.     RRC                ;PROPER PLACE
  109.     RRC                ;
  110.     RRC
  111.     ANI    0FH            ;ADD MASK
  112.     JZ    USE$BLANK        ;SUPRESS LEADING ZERO BY
  113.     ADI    10H            ;ADD EITHER 20H(ASCII ' ')
  114. USE$BLANK:
  115.     ADI    ' '            ;OR 20H + 10H FOR NUMERAL
  116.     MOV    M,A            ;PUT IN TEXT STREAM
  117.     MOV    A,C            ;GET UNITS PORTION
  118.     ANI    0FH            ;MASK OFF TENS PORTION
  119.     ADI    '0'            ;CONVERT TO ASCII
  120.     INX    H            
  121.     MOV    M,A
  122.     DAD    D            ;REPEAT UNTIL ALL FILES
  123.     DCR    B            ;ARE SEQUENTIALLY NUMBERED
  124.     JNZ    NUMBER$FILES
  125. ;    
  126.     POP    PSW            ;GET FILE$COUNT FROM STACK
  127.     PUSH    PSW            ;AND SAVE AGAIN FOR LATER
  128. ;
  129. ;
  130.     ADI    NBR$COL-1
  131.     MVI    B,255            ;(B) ACCUMULATES QUOTIENT
  132.                     ;SO SET TO -1 FOR AT LEAST
  133.                     ;1 PASS THRU GIVES 0
  134. ;
  135. DIVX:
  136.     INR    B            ;
  137.     SUI    NBR$COL            ;DIVIDE (FILE$COUNT+3)BY
  138.                     ;FOUT TO GET OFFSET1
  139. ;
  140.     JP    DIVX
  141.     ADI    NBR$COL            ;SUBSTRACTED ONCE TOO MUCH
  142.                     ;SO ADD IT BACK ON
  143.     LXI    H,OFFSET1        
  144.     MOV    M,B            ;INSERT OFFSET1 INTO TABLE
  145.     INX    H            ;POINT OFFSET2 LOCATION
  146.     JNZ    SETOFFSET2        ;SAME AS OFFSET1 IF NON-
  147.                     ;ZERO REMAINDER
  148.     DCR    B            ;ELSE OFFSET2=OFFSET1-1
  149. ;:
  150. SETOFFSET2:
  151.     MOV    M,B            ;PUT OFFSET2 IN TABLE
  152.     INX    H            ;POINT OFFSET    FOR COL 3
  153.     DCR    A            ;TEST FOR REMAINDER OF 1
  154.     JNZ    SETOFFSET3        ;IF REMAINDER <> 1, USE
  155.                     ;OFFSET3=OFFSET2-1
  156.     DCR    B            ;ELSE OFFSET3=OFFSET2-1Y
  157. ;
  158. SETOFFSET3:
  159.     MOV    M,B            ;ELSE OFFSET TO COLUMN 4
  160. ;    
  161. ;    
  162. REPRINT:
  163.     POP    PSW            ;RECOVER FILE COUNT
  164. ;
  165. REPRINT1:    
  166.     PUSH    PSW            ;SAVE AGAIN FOR LATER USE
  167.     STA    FILE$COUNT        ;SAVE FOR COUNTING    
  168.     MVI    A,SCREEN$HGT        ;SET FOR VIDEO DISPLAY SIZE
  169.     STA    LINE$COUNT        ;
  170.     LXI    D,HEADING
  171.     MVI    C,9            ;BUFFER PRINTER COMMAND
  172.     CALL    BDOS            ;CP/M PRINTS HEADING
  173. ;    
  174.     LXI    H,DIR$TABLE - 14    ;POINT DUMMY 0TH ENTRY
  175. ;    
  176. PRINT$LINE:
  177.     PUSH    H            ;SAVE BASE ADDRESS
  178.     LXI    D,OFFSET0        ;POINT OFFSET TABLE
  179.     MVI    A,NBR$COL        ;4 COLUMN PER LINE
  180. ;
  181. PRINT$NAME:
  182.     STA    COLUMN$CNT        ;SAVE COUNT OF COLUMNS
  183.     PUSH    H            ;SAVE CURRENT NAME POINTER
  184.     PUSH    D            ;SAVE OFFSET TABLE POINTER
  185.     LXI    D,DOUBL$SPACE        ;PRINT 2 BLANKS
  186.     MVI    C,9            ;'PRINT BUFFER' COMMAND
  187.     CALL    BDOS            ;USE CP/M 
  188.     POP    D            ;GET OFFSET TABLE POINTER
  189.     POP    H            ;GET NAME POINTER
  190.     LDAX    D            ;GET OFFSET VALUE
  191. ;
  192.     LXI    B,14            ;EACH NAME IS 14 LONG
  193. ;
  194. MULT$14:
  195.     DAD    B            ;ADD 14 FOR EACH OFFSET
  196.     DCR    A            ;UNTIL OFFSET = 0
  197.     JNZ    MULT$14
  198.     PUSH    H            ;SAVE NEW NAME POINTER
  199.     PUSH    D            ;SAVE OFFSET POINTER
  200.     XCHG                ;POINTER NAME TO PRINT W/(DE)
  201.     MVI    C,9            ;PRINT BUFFER
  202.     CALL    BDOS            ;PRINT FILE NAME
  203.                     ;AND IT'S MENU NO.
  204. ;
  205. TEST$FINISH:
  206.     LXI    H,FILE$COUNT        ;SEE IF DONE PRINTING
  207.     DCR    M            ;BY TESTING COUNT OF FILES
  208.     POP    D            ;GET OFFSET POINTER
  209.     POP    H            ;GET POINTER TO LAST NAME
  210.     JZ    FINISH            ;NO MORE TO PRINT
  211.     INX    D            ;ADVANCE OFFSET POINTER
  212.     LDA    COLUMN$CNT
  213.     DCR    A            ;SEE IF COLUMN LEFT = 0
  214.     JNZ    PRINT$NAME        ;PRINT ANOTHER SAVE LINE 
  215.     CALL    CRLF            
  216.     POP    H            ;GET BASE OF PREVIOUS LINE
  217.     LXI    D,14            ;ADD OFFSET
  218.     DAD    D    
  219.     JMP    PRINT$LINE
  220. ;
  221. ;
  222. ;
  223. FINISH:
  224.     POP    H            ;UNJUNK STACK
  225. ;
  226. LF$LOOP:
  227.     CALL    CRLF
  228.     JP    LF$LOOP            ;OMIT THIS LINE IF DESIRED
  229.     LXI    D,PROMPT        ;POINT INSTRUCTION MESSAGE
  230.     MVI    C,9            
  231.     CALL    BDOS
  232.     LXI    D,INPUT$BUFF
  233.     MVI    A,10            ;10 CHRS MAX
  234.     STAX    D
  235.     MVI    C,10            ;'READ BUFFER' COMMAND
  236.     CALL    BDOS
  237. ;
  238. ;
  239. ;
  240.     LXI    H,INPUT$BUFF+1        ;POINT TO CHR COUNTER
  241.     MOV    A,M            ;GET IT AND SEE IF >2 
  242.     CPI    3
  243.     JNC    REPRINT            ;REPRINT THE MENU
  244.     MOV    C,A            ;COUNT OF DIGITS TO (C)
  245.     MVI    B,0
  246. ;
  247. GET$MENU$NBR:
  248.     INX    H            ;POINT ASCII DIGIT
  249.     MOV    A,M            ;GET IT
  250.     CALL    ASCII$CONVERT        ;CONVERT TO BINARY
  251.     JC    REPRINT            ;RE-DISPLAY ON ERROR
  252.     DCR    C        
  253.     JNZ    GET$MENU$NBR
  254. ;
  255. ;
  256.     POP    PSW            ;RECOVER FILE COUNTER
  257.     CMP    B            ;FILE$ COUNT- REQUEST NO.
  258.     JC    REPRINT1        ;REDISPLAY MENU IF ILLEGAL
  259. ;
  260.     LXI    D,14            ;INC BETWEEN NAMES
  261.     LXI    H,DIR$TABLE-14        ;POINT DUMMY 0TH ENTRY
  262. ;
  263. FIND$NAME:
  264.     DAD    D            ;ADD OFFSET B TIMES
  265.     DCR    B            
  266.     JNZ    FIND$NAME
  267. ;
  268. ;
  269.     XCHG                ;SAVE POINTER TO FILE NAME
  270.     LHLD    6            ;GET BDOS ENTRY POINT
  271.     LXI    B,-CCP$LEN        ;OFFSET TO START OF CM/M
  272.     DAD    B
  273.     PUSH    H            ;SAVE CP/M ENTRY POINT
  274.                     ;ON STACK FOR BRANCH
  275.     LXI    B,8            ;OFFSET TO COMMAND BUFFER
  276.     DAD    B            ;(HL) POINTS PLACE TO PUT 
  277.                     ;NAME OF .COM FILE TO BE
  278.                     ;EXECUTED
  279.     PUSH    D            ;SAVE POINTER TO FILE NAME
  280.     XCHG                ;(DE) POINTS COMMAND BUDFER
  281. ;
  282. ;
  283. ;
  284.     LXI    H,128            ;OFFSET TO END OF CMD BUFF
  285.                     ;WHERE POINTER IS STORED
  286.     DAD    D            ;(HL) POIN TS STORAGE PLACE
  287.     MOV    M,E            ;UPDATE BUFFER POINTER TO
  288.     INX    H            ;THE START OF THE COMMAND
  289.     MOV    M,D            ;BUFF SO CP/M WILL READ
  290. ;    
  291.     IF    BASIC$PROG
  292. ;
  293.     LXI    H,COMMAND$NAME        ;POINT COMMAND NAME
  294.     MVI    C,LEN$CMD$NAME        ;LENGHT OF COMMAND NAME
  295.     CALL    BLOCK$MOVE
  296. ;
  297.     ENDIF
  298. ;
  299.     POP    H            ;POINT SELECTED FILE NAME
  300.     MVI    C,8            ;LENGTH OF FILE NAME
  301.     CALL    BLOCK$MOVE
  302. ;
  303. ;
  304.     IF    BASIC$PROG
  305. ;
  306.     LXI    H, SPEC$TYPE
  307.     MVI    C,4
  308.     CALL    BLOCK$MOVE 
  309. ;
  310.     ENDIF
  311. ;
  312.     XRA    A            ;NEEDS A 0 AT END
  313.     STAX    D            ;OF COMMAND LINE
  314. ;
  315.     RET
  316. ;
  317. ;
  318. ;SUBROUTINES
  319. ;
  320. BLOCK$MOVE:
  321.     MOV    A,M
  322.     STAX    D
  323.     INX    D
  324.     INX    H
  325.     DCR    C
  326.     JNZ    BLOCK$MOVE
  327.     RET
  328. ;
  329. ASCII$CONVERT:
  330.     SUI    '0'            ;SUBTRACT ASCII BIAS
  331.     CPI    9+1            ;BE SURE IT'S NUMERIC
  332.     CMC
  333.     RC
  334.     MOV    D,A
  335.     MOV    A,B
  336.     RLC
  337.     RLC
  338.     RLC
  339.     ADD    B
  340.     RC
  341.     ADD    B
  342.     RC
  343.     ADD    D
  344.     MOV    B,A
  345.     RET
  346. ;
  347. CRLF:
  348.     LXI    D,CRLFMSG
  349.     MVI    C,9
  350.     CALL    BDOS
  351.     LXI    H,LINE$COUNT
  352.     DCR    M
  353.     RET
  354. ;
  355. ;
  356. CRLFMSG    DB    0DH,0AH,'$'
  357. ;
  358. HEADING    DB    0AH,9,9,9,'    MENU',0DH,0AH,0AH,'$'
  359. ;
  360.     IF    BASIC$PROG
  361. ;
  362. COMMAND$NAME:
  363.     DB    'BASIC '
  364. ;
  365. LEN$CMD$NAME    EQU    $-COMMAND$NAME
  366. ;
  367. SPEC$TYPE:
  368.     DB    '.BAS'
  369. ;
  370.     ENDIF
  371. ;
  372. PROMPT:
  373.     DB    'ENTER MENU NUMBER & PRESS RETURN''$'
  374. ;
  375. DOUBL$SPACE:
  376.     DB    ' $'
  377. ;
  378. MENU$BUFF:
  379.     DB    ' - 0$'
  380. ;
  381. OFFSET0    DB    1
  382. OFFSET1    DB    0,0,0
  383. ;
  384. END$OF$TABLE:
  385.     DW    DIRTABLE
  386. ;
  387. FILE$COUNT:
  388.     DB    0
  389. COLUMN$CNT:
  390.     DB    4
  391. LINE$COUNT:
  392.     DB    0
  393. ;
  394.     IF    BASIC$PROG
  395. ;
  396. SRCH$FCB:
  397.     DB    0,'????????BAS',0
  398. ;
  399.     ENDIF
  400. ;
  401. SRCH$FCB:
  402.     DB    0,'????????COM',0
  403. ;
  404.  
  405. ;
  406. DIR$TABLE:
  407.     DB    255
  408. ;
  409. STACK$AREA    EQU    200*14 + 30
  410. ;
  411. INPUT$BUFF    EQU    STACK$AREA
  412. ;
  413. ;
  414. ;    EQUATES:
  415. ;
  416. BDOS    EQU    5
  417. NBR$COL    EQU    4
  418. CCP$LEN    EQU    3C06H-3400H
  419. SCREEN$SIZE    EQU    24
  420. SCREEN$HGT    EQU    80
  421. ;
  422. ;
  423. ;
  424. ;
  425.  
  426.     END
  427.