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