home *** CD-ROM | disk | FTP | other *** search
- ; MENU PROGRAM
- ; FOR
- ; MACHINE LANGUAGE OR BASIC PROGRAMS
- ;
- ; BY
- ; JAMES J. FRANTZ
- ; MAY 31, 1979
- ;
- ;
- ORG 0100H
- ;
- ;
- BASIC$PROG EQU 0 ;SET TO 0 FOR MACHINE
- ;
- LXI SP,STACK$AREA ;SET UP A STACK
- 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
- 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
- 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:
- 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
- ;
- 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 ;
- 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
- LXI D,DOUBL$SPACE ;PRINT 2 BLANKS
- 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 NO.
- ;
- 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
- JP LF$LOOP ;OMIT THIS LINE IF DESIRED
- LXI D,PROMPT ;POINT INSTRUCTION MESSAGE
- MVI C,9
- CALL BDOS
- LXI D,INPUT$BUFF
- MVI A,10 ;10 CHRS MAX
- STAX D
- MVI C,10 ;'READ BUFFER' COMMAND
- CALL BDOS
- ;
- ;
- ;
- LXI H,INPUT$BUFF+1 ;POINT TO CHR 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 NO.
- JC REPRINT1 ;REDISPLAY MENU IF ILLEGAL
- ;
- LXI D,14 ;INC BETWEEN NAMES
- LXI H,DIR$TABLE-14 ;POINT DUMMY 0TH ENTRY
- ;
- FIND$NAME:
- DAD D ;ADD OFFSET B TIMES
- DCR B
- JNZ FIND$NAME
- ;
- ;
- XCHG ;SAVE POINTER TO FILE NAME
- LHLD 6 ;GET BDOS ENTRY POINT
- LXI B,-CCP$LEN ;OFFSET TO START OF CM/M
- DAD B
- PUSH H ;SAVE CP/M ENTRY POINT
- ;ON STACK FOR BRANCH
- LXI B,8 ;OFFSET TO COMMAND BUFFER
- DAD B ;(HL) POINTS PLACE TO PUT
- ;NAME OF .COM FILE TO BE
- ;EXECUTED
- PUSH D ;SAVE POINTER TO FILE NAME
- XCHG ;(DE) POINTS COMMAND BUDFER
- ;
- ;
- ;
- LXI H,128 ;OFFSET TO END OF CMD BUFF
- ;WHERE POINTER IS STORED
- DAD D ;(HL) POIN TS STORAGE PLACE
- MOV M,E ;UPDATE BUFFER POINTER TO
- INX H ;THE START OF THE COMMAND
- MOV M,D ;BUFF SO CP/M WILL READ
- ;
- IF BASIC$PROG
- ;
- LXI H,COMMAND$NAME ;POINT COMMAND NAME
- MVI C,LEN$CMD$NAME ;LENGHT OF COMMAND NAME
- CALL BLOCK$MOVE
- ;
- ENDIF
- ;
- POP H ;POINT SELECTED FILE NAME
- MVI C,8 ;LENGTH OF FILE NAME
- CALL BLOCK$MOVE
- ;
- ;
- IF BASIC$PROG
- ;
- LXI H, SPEC$TYPE
- MVI C,4
- CALL BLOCK$MOVE
- ;
- ENDIF
- ;
- XRA A ;NEEDS A 0 AT END
- STAX D ;OF COMMAND LINE
- ;
- RET
- ;
- ;
- ;SUBROUTINES
- ;
- 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
- ;
- ;
- CRLFMSG DB 0DH,0AH,'$'
- ;
- HEADING DB 0AH,9,9,9,' MENU',0DH,0AH,0AH,'$'
- ;
- IF BASIC$PROG
- ;
- COMMAND$NAME:
- DB 'BASIC '
- ;
- LEN$CMD$NAME EQU $-COMMAND$NAME
- ;
- SPEC$TYPE:
- DB '.BAS'
- ;
- ENDIF
- ;
- PROMPT:
- DB 'ENTER MENU NUMBER & PRESS RETURN''$'
- ;
- DOUBL$SPACE:
- DB ' $'
- ;
- MENU$BUFF:
- DB ' - 0$'
- ;
- 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
- ;
- IF BASIC$PROG
- ;
- SRCH$FCB:
- DB 0,'????????BAS',0
- ;
- ENDIF
- ;
- SRCH$FCB:
- DB 0,'????????COM',0
- ;
-
- ;
- DIR$TABLE:
- DB 255
- ;
- STACK$AREA EQU 200*14 + 30
- ;
- INPUT$BUFF EQU STACK$AREA
- ;
- ;
- ; EQUATES:
- ;
- BDOS EQU 5
- NBR$COL EQU 4
- CCP$LEN EQU 3C06H-3400H
- SCREEN$SIZE EQU 24
- SCREEN$HGT EQU 80
- ;
- ;
- ;
- ;
-
- END
-