home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug033.arc
/
MENU.ASM
< prev
next >
Wrap
Assembly Source File
|
1979-12-31
|
10KB
|
510 lines
; MENU PROGRAM
; FOR
; MACHINE LANGUAGE OR BASIC PROGRAMS
;
; BY
; JAMES J. FRANTZ
; MAY 31, 1979
;
;Modified by Jim Woolley, FOG Disk Librarian, 11/82
;
;Calling syntax:
;
; MENU menu of .COM files on default drive
; MENU d: menu of .COM files on drive d:
;
; BMENU menu of .BAS (MBASIC) files on default drive
; MBASIC.COM assumed to be on default drive, also
; BMENU d: menu of .BAS (MBASIC) files on drive d:
; MBASIC.COM assumed to be on default drive
; BMENU d1: d2: menu of .BAS (MBASIC) files on drive d1:
; MBASIC.COM found on drive d2:
;
; CMENU menu of .INT (CBASIC) files on default drive
; CRUN2.COM assumed to be on default drive, also
; CMENU d: menu of .INT (CBASIC) files on drive d:
; CRUN2.COM assumed to be on default drive
; CMENU d1: d2: menu of .INT (CBASIC) files on drive d1:
; CRUN2.COM found on drive d2:
;
;CORRECTIONS BY K. COYE SEPT 11, 1982
;
;1. SEARCH.FCB WAS TOO SHORT CAUSING OVERWRITE OF DIR$TABLE
;2. MENU$BUF WAS 5 CHARS LONG INSTEAD OF THE REQUIRED 6
;
ORG 0100H
;
;
true equ 1
false equ 0
com$prog equ true ;for .COM files
cbas$prog equ false ;for CBASIC files
MBAS$PROG EQU false ;for MBASIC files
;
LXI SP,STACK$AREA ;SET UP A STACK
lda def$fcb
sta menu$drive
;
if mbas$prog or cbas$prog
lda def$fcb+16
sta bas$drive
endif
;
lxi d,def$fcb+1
lxi h,srch$fcb
mvi c,srch$fcb$len
call block$move
MVI C,17 ;'SEARCH FIRST' COMMAND
;
SORT$LOOP:
LXI D,def$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 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
ora a
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 ;COLUMN PER LINE
;
PRINT$NAME:
STA COLUMN$CNT ;SAVE COUNT OF COLUMNS
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.
LXI D,DOUBL$SPACE ;PRINT 2 BLANKS
MVI C,9 ;'PRINT BUFFER' COMMAND
CALL BDOS ;USE CP/M
;
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
lda line$count
dcr a
jnz test$fin$2
lxi d,more$msg
mvi c,9
call bdos
mvi c,1 ;console input
call bdos
cpi 'y'
jz test$fin$2
cpi 'Y'
jnz finish
test$fin$2:
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
CALL CRLF
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 1 ;GET BDOS ENTRY POINT
mvi l,0
LXI B,-CCP$LEN ;OFFSET TO START OF ccp
DAD B
PUSH H ;SAVE ccp 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,cmd$buf$len ;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 mbas$prog or cbas$prog
lda bas$drive
call drive$sub
endif
;
IF MBAS$PROG
LXI H,mbcom$name ;POINT COMMAND NAME
MVI C,mbcom$len ;LENGHT OF COMMAND NAME
CALL BLOCK$MOVE
ENDIF
;
if cbas$prog
lxi h,cbcom$name
mvi c,cbcom$len
call block$move
endif
;
lda menu$drive ;drive for menu selection
call drive$sub
;
POP H ;POINT SELECTED FILE NAME
MVI C,8 ;LENGTH OF FILE NAME
CALL BLOCK$MOVE
;
;
XRA A ;NEEDS A 0 AT END
STAX D ;OF COMMAND LINE
lda 4 ;select default drive
mov c,a
;
RET
;
;
;SUBROUTINES
;
BLOCK$MOVE:
MOV A,M
STAX D
INX D
INX H
DCR C
JNZ BLOCK$MOVE
RET
;
drive$sub:
ora a
jz end$drive$sub
adi 'A'-1 ;make ASCII
xchg ;make H point to command buffer
mov m,a
inx h
mvi m,':'
inx h
xchg
end$drive$sub:
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,'$'
;
more$msg:
db 0dh,0ah,'More (Y/N)? $'
;
HEADING DB 0AH,'MENU:',0DH,0AH,0AH,'$'
;
IF MBAS$PROG
mbcom$name:
DB 'MBASIC '
mbcom$len: EQU $-mbcom$name
ENDIF
;
if cbas$prog
cbcom$name:
db 'CRUN2 '
cbcom$len: equ $-cbcom$name
endif
;
PROMPT:
DB 'ENTER MENU NUMBER & PRESS RETURN: $'
;
DOUBL$SPACE:
DB ' $' ;REALLY 4 SPACES
;
MENU$BUFF:
DB ' - 00$'
;
OFFSET0 DB 1
OFFSET1 DB 0,0,0
;
END$OF$TABLE:
DW DIRTABLE
;
FILE$COUNT:
DB 0
COLUMN$CNT:
DB 0
LINE$COUNT:
DB 0
;
def$fcb equ 5ch
menu$drive:
ds 1
;
IF MBAS$PROG
bas$drive:
ds 1
SRCH$FCB:
DB '????????BAS',0
ENDIF
;
if cbas$prog
bas$drive:
ds 1
srch$fcb:
db '????????INT',0
endif
;
if com$prog
SRCH$FCB:
DB '????????COM',0
endif
;
srch$fcb$len: equ $-srch$fcb
;
DIR$TABLE:
DB 255
;
STACK$AREA EQU 200*14 + 30
;
INPUT$BUFF EQU STACK$AREA
;
;
; EQUATES:
;
BDOS EQU 5
NBR$COL EQU 3
CCP$LEN EQU 0e00h+0800h
SCREEN$HGT: EQU 20
cmd$buf$len: equ 128
;
END