home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug060.arc
/
CPM#005.LBR
/
MKWAIT20.ASM
< prev
next >
Wrap
Assembly Source File
|
1979-12-31
|
34KB
|
1,962 lines
xVersion equ '2'
yVersion equ '0'
;**** MKWAIT Version x.y ****
;
;Copyright (c) Peter C. Cole July, 1985 Duncanville, TX
;All commercial rights reserved.
;Released for free distribution only. Not to be sold.
;**** Version Changes ****
;
;1.0 - Released 7-27-85
;
;1.1 - Added feature to allow pushing any key to continue, not just <RETURN>.
; Added flashing "READ NOTE:".
; Added feature to terminate SUBMIT files.
; Changed method on how CP/M command lines terminated.
;
;2.0 - Added feature to "Check Line Above". (8-10-85)
;
PAGE
;**** Assembly Definations ****
NL: equ 0A0Dh ;new line
CPage: equ 5A1Bh ;clear page
MsgEnd: equ 0 ;message end flag
Bdos: equ 5 ;Bdos address
Stack1: equ 4000h ;Location of MKWAIT and FileName stack
Temp: equ Stack1+2 ;Location to store temp string for editing
Existing: equ 4800h ;Location to store existing FileName program
MaxChar: equ 255 ;Maximum number of characters allowed in message
;Also change number in message string EE2.
Exit: equ 0 ;Where to jmp to return to CP/M
CurPos: equ 0FD53h ;Adr to find present position of cursor in Video Bank
org 100h
;**** Start Program ****
Start: jmp Start1
;Set stack
Start1: lxi sp,Stack1
;Set output delimiter
mvi c,110
mvi d,0
mvi e,MsgEnd
call Bdos
;Set Bdos error mode to "return and display error"
mvi c,45
mvi e,0FEh
call Bdos
;Set number of read/write sectors to 8 (1k)
mvi c,44
mvi e,8
call Bdos
PAGE
;**** Begin Message ****
BeginMsg: lxi d,BM2
call Type
jmp BM10
èBM2: dw CPage
db '****************************** MKWAIT Version '
db xVersion,'.',yVersion,' ******************************'
db 'Copyright (c) 1985 by Peter C. Cole'
dw NL
db 'Duncanville, Texas.'
dw NL
db 'All commercial rights reserved.'
dw NL
db 'Released for free distribution only. Not to be sold.'
dw NL
db '****************************************'
db '****************************************'
dw NL
db 'MKWAIT will create or edit a "Wait File" ' ;41
db 'on the disk drive of your choice.' ;33
dw NL
db 'MKWAIT will only run on the Osborne ' ;36
db 'Executive. ' ;11
dw NL,NL
db MsgEnd
;**** Subroutine Type ****
;DE must already be loaded
Type: mvi c,9
call Bdos
ret
PAGE
;**** Main Menu ****
Begin: call HomeIt
BM10: lxi d,BM11
call Type
jmp BM12
BM11: db 'Please select:'
dw NL
db ' A,B,etc - Read this disk drive for an existing '
db MsgEnd
BM12: call FileName
lxi d,BM13
call Type
jmp BM14
BM13: db ' file.'
dw NL
db ' X - Exit to CP/M. Also can use ^C'
dw NL
db ' 1 - Create a new '
db MsgEnd
BM14: call FileName
lxi d,BM15è call Type
jmp BM17
BM15: db ' message.'
dw NL
db ' 2 - Change to a different file name.'
dw NL
db ' 3 - Create or Change "Check Line Above". '
db 'It is now '
db MsgEnd
BM17: lda SkipFlag
ana a
jz BM30 ;jmp if disabled
call BM18
jmp BM40
BM18: lxi h,LinesUp
lxi d,LineData
jmp BM20
PAGE
;**** Subroutine BM20 ****
;HL=where to find LinesUp
;DE=where to find LineData
BM20: push d
push h
lxi d,BM21
call Type
jmp BM23
BM21: db '"activated".'
dw NL
db ' It will look '
db MsgEnd
BM22: ds 1 ;to hold units digit below
BM23: pop h ;Displays number of lines up
mov a,m
adi 0 ;daa doesn't seem to work on its own
daa
mov b,a
ani 0F0h
mov a,b
jz BM24
ani 0Fh ;show two digits
ori 30h
sta BM22
mvi e,'1'
mvi c,2
call Bdos
lda BM22
mov e,a
mvi c,2
call Bdos
jmp BM25
BM24: ani 0Fh ;shows one digit
ori 30h
mov e,a
mvi c,2
call Bdos
BM25: lxi d,BM26
call Type
jmp BM27
BM26: db ' lines up for: '
db MsgEnd
BM27: pop d ;LineData
call Type
ret
PAGE
BM30: lxi d,BM31
call Type
jmp BM40
BM31: db '"disabled".'
db MsgEnd
BM40: lxi d,BM41
call Type
jmp BM42
BM41: dw NL
db ' W - Create a new '
db MsgEnd
BM42: call FileName
lxi d,BM43
call Type
jmp BM44
BM43: db ' file on a "to be selected" disk drive.'
dw NL
db ' <RETURN> - Edit the below message (if any).'
dw NL,NL
db MsgEnd
BM44: lxi d,String
call Type
lxi d,BM45
call Type
jmp Wait
BM45: dw NL
db MsgEnd
PAGE
;**** Subroutine FileName ****
;Displays active file name
FileName: lxi d,FN1
call Type
ret
FN1: db 'WAIT',0,0,0,0 ;allow for max. of 8 characters
db MsgEnd
;**** Subroutine Create ****
;Creates a fresh FCB
Create: lxi h,FcbRun
lxi d,FcbNew
mvi b,FcbEnd-FcbNew
Create1: ldax d
mov m,a
inx h
inx d
dcr b
jnz Create1
ret
;**** Subroutine HomeIt ****
;Homes cursor to just under Header and clears to end of page.
HomeIt: lxi d,Clear
call Type
ret
Clear: db 1Bh,3Dh ;move cursor
db 27h,20h ;to just under header
db 1Bh,59h ;clear from cursor to endè db MsgEnd
;**** Subroutine ClearBuf ****
ClearBuf: lxi h,Buffer
lxi b,EndBuffer-Buffer
ClearB1: mvi m,0
inx h
dcx b
mov a,c
ora b
jnz ClearB1
ret
**** Subroutine ClearLD ****
ClearLD: lxi h,LineData0
lxi b,EndData-LineData0
jmp ClearB1
PAGE
;**** Wait for key ****
Wait: mvi c,6
mvi e,0FDh
call Bdos
cpi 3 ;test if ^C
jz Exit
cpi 0Dh ;<RETURN>
jz ReEdit
cpi '1'
jz New
cpi '2'
jz Diff
cpi '3'
jz CLA ;"Check Line Above"
ani 5Fh ;convert if small to cap.
cpi 'X' ;test if X
jz Exit
cpi 'W'
jz Write
cpi 'A' ;is it less than 'A'?
jc Wait ;jmp if yes (not A to P)
cpi 'Q' ;is it less than 'Q'?
jc ExistFile ;jmp if yes
jmp Wait ;sorry, not A to P.
PAGE
;**** Work on "Check Line Above" ****
;Clear Screen
CLA: call HomeIt
;Start screen message
lxi d,CLA2
call Type
jmp CLA4
CLA2: db '"Check Line Above" is now '
db MsgEnd
;Is SkipFlag disabled?
CLA4: lda SkipFlag
ana a
jz CLA30 ;jmp if disabled
call BM18
;Cont screen message
lxi d,CLA6
call Type
jmp CLA7
CLA6: dw NL,NL
db 'Please push:'
dw NL
db ' <ESC> - Return to Main Menu with conditions as '
db 'shown above.'
dw NL
db ' D - Disable "Check Line Above" and return to '
db 'Main Menu.'
dw NL
db ' E - Edit "Check Line Above" message.'
dw NL
db ' S - Set number of lines to look up.'
dw NL,NL
db MsgEnd
PAGE
;Wait for key
CLA7: mvi c,6
mvi e,0FDh
call Bdos
cpi 1Bh ;<ESC>
jz Begin
cpi 'D'
jz CLA10
cpi 'd'
jz CLA10
cpi 'E'
jz CLA20
cpi 'e'
jz CLA20
cpi 'S'
jz CLA15
cpi 's'
jz CLA15
jmp CLA7 ;Sorry none of the above
;Clear "Skip Flag"
CLA10: mvi a,0
sta SkipFlag
jmp Begin
;Set number of lines to look above
CLA15: call HomeIt
lxi d,CLA16
call Type
jmp CLA17
CLA16: db 'Please select the number of lines to look up. '
db 'For Example:'
dw NL,NL
db '----------'
dw NL
db 'XXXX'
dw NL,NL
db 'A>WAIT'
dw NL
db '----------'
dw NL,NL,NL
db 'XXXX is 2 lines up. Select 0 to 9.'
dw NL,NL
db MsgEnd
CLA17: mvi c,6
mvi e,0FDh
call Bdos
ani 0Fh
sta LinesUp
jmp CLA
PAGE
;Edit CLA
;Move message to new location
CLA20: lxi h,Temp
lxi d,LineData0
ldax d ;Load max char
mov m,a
inx h
inx d
ldax d ;load char returned
mov m,a
inx h
inx d
CLA21: ldax d
mov m,a
inx h
inx d
ana a
jnz CLA21
;Edit message string
CLA22: call HomeIt
lxi d,CLA23
call Type
lxi h,Temp
mvi m,31
xchg
call LineEdit
cpi 0
jz CLA25
cpi 1
jz CLA
cpi 2
jz BadWait
jmp CLA
CLA23: db 'Enter up to 31 characters for the '
db '"Enter Line Above" message.'
db MsgEnd
;Load new message line to LineData
CLA25: call ClearLD
lxi h,LineData0
lxi d,Temp
call LB0
jmp CLA
PAGE
CLA30: lxi d,CLA31
call Type
jmp CLA34
CLA31: db '"disabled".'
dw NL,NL
db 'Please push:'
dw NL
db ' <ESC> - Return to Main Menu without any changes.'
dw NL
db ' A - Activate "Check Line Above".'
dw NL,NL
db MsgEnd
;Which key pushed?
CLA34: mvi c,6
mvi e,0FDh
call Bdos
cpi 1Bh ;<ESC>
jz Begin
cpi 'A'
jz CLA35
cpi 'a'
jz CLA35
jmp CLA34 ;Sorry none of the above
;Set SkipFlag
CLA35: mvi a,0FFh
sta SkipFlag
jmp CLA
PAGE
;**** Open Existing File ****
;Convert to drive code and store
ExistFile: ani 1Fh
sta FcbNew
;Create FcbRun
call Create
;Clear screen
call HomeIt
;Open Existing File
mvi c,15
lxi d,FcbRun
call Bdos
è;Test if file opened
ana a
jz FileExists ;jmp if file opened with no problem
mov a,h
cpi 0
jnz BadWait
;File not found. Give message.
lxi d,NoFileMsg
call Type
jmp BadWait
NoFileMsg: dw NL,NL
db 'File not found.'
dw NL
db MsgEnd
;Test Existing file
FileExists: call TestFile
jnz BadWait
;MKWAIT file - give message
lxi d,MSmsg1
call Type
jmp MS2
MSmsg1: dw NL,NL
db 'Do you want to use this file? (Y/N) '
db MsgEnd
PAGE
;Wait for Answer
MS2: mvi c,6
mvi e,0FDh
call Bdos
cpi 'Y'
jz LoadCLA
cpi 'y'
jz LoadCLA
jmp Begin
;Edit existing message string
ExistEdit: call HomeIt
lxi d,EE2
call Type
lxi h,Existing+Buffer-Data
mvi m,MaxChar ;only allow max number of char
xchg
call LineEdit
cpi 0
jz LoadCLA
cpi 1
jz Begin
cpi 2
jz BadWait
jmp Begin
EE2: db 'Enter up to 255 characters. Messages will '
db 'automatically go to the next line'
dw NL
db 'after every 80 characters. Therefore, '
db 'you may want to use spaces to finish'
dw NL
db 'a line in the right place.'
db MsgEnd
;Load "Check Line Above" data
LoadCLA: call ClearLD
lxi h,SkipFlag
lxi d, Existing+SkipFlag-Data
mvi b,EndCLA-SkipFlag
LdCLA1: ldax d
mov m,a
inx h
inx d
dcr b
jnz LdCLA1
lxi h,LineData0
lxi d,Existing+LineData0-Data
call LB0
PAGE
;Load from MKWAIT file to "Buffer"
LoadBuffer: call ClearBuf
lxi h,Buffer
lxi d,Existing+Buffer-Data
call LB0
jmp Begin
LB0: ldax d ;load max char
mov m,a
inx h
inx d
ldax d ;load char returned
mov m,a
inx h
inx d
LB1: ldax d ;load data
mov m,a
inx h
inx d
ana a ;is it end flag?
jnz LB1 ;jmp if no
ret
;**** Routine New ****
;Create a string with no data
New: lxi h,Temp
mvi m,MaxChar
inx h
mvi m,0
inx h
mvi m,0
jmp ReEdit2
;**** Routine BadWait ****
;Will wait for any key (sends message) and then jmp to Begin
BadWait: lxi d,BadOpen1
call Type
mvi e,0FDh ;wait for key
mvi c,6
call Bdos
jmp Begin
BadOpen1: dw NL,NL
db 'Push <RETURN> to continue.'
dw NLè db MsgEnd
PAGE
;**** Routine ReEdit ****
;Move Buffer to new location
ReEdit: lxi h,Temp
lxi d,Buffer
ldax d ;Load max char
mov m,a
inx h
inx d
ldax d ;load char returned
mov m,a
inx h
inx d
ReEdit1: ldax d
mov m,a
inx h
inx d
ana a
jnz ReEdit1
;Edit message string
ReEdit2: call HomeIt
lxi d,EE2
call Type
lxi h,Temp
mvi m,MaxChar
xchg
call LineEdit
cpi 0
jz ReEdit5
cpi 1
jz Begin
cpi 2
jz BadWait
jmp Begin
;Load new message line to Buffer
ReEdit5: call ClearBuf
lxi h,Buffer
lxi d,Temp
call LB0
jmp Begin
PAGE
;**** Subroutine TestFile ****
;Test existing file found on disk
;If MKWAIT file then return with Zero Flag set
;Send message
TestFile:
call FileName
lxi d,FEmsg
call Type
jmp FEmsgOut
FEmsg: db ' exists on the selected drive.'
dw NL
db MsgEnd
FEmsgOut: db 0
;Clear area for existing FileName so that old end message destroyed.
lxi h,Existing
lxi b,400h ;more than enough
ClearArea: mvi m,0
inx h
dcx b
mov a,b
ora c
jnz ClearArea
;Load existing file
mvi c,26 ;set DMA address
lxi d,Existing
call Bdos
mvi c,15 ;open existing file
lxi d,FcbRun
call Bdosè
mvi c,20 ;read sequential
lxi d,FcbRun
call Bdos
;Test if embedded "MKWAIT end message" is present
lxi h,Existing+400h-(+EndS9-EndS8)
lxi d,EndS8
mvi b,EndS9-EndS8
Test: ldax d
cmp m
jnz NotFile ;jmp if embedded message not MKWAIT's
inx h !inx d
dcr b
jnz Test
PAGE
;This is a MKWAIT file - Send message
lxi d,MF1
call Type
jmp MF2
MF1: dw NL
db 'This file was created by MKWAIT '
db MsgEnd
MF2: lxi d,Existing+EndS7-Data ;Send Version number
call Type
lxi d,MF11
call Type
jmp MF12
MF11: dw NL,NL
db ' "Check Line Above" is now '
db MsgEnd
MF12: lda Existing+SkipFlag-Data
ana a
jz MF20 ;jmp if disabled
call MF15
jmp MF23
MF15: lxi h,Existing+LinesUp-Data
lxi d,Existing+LineData-Data
jmp BM20
MF20: lxi d,BM31
call Type
MF23: lxi d,MF24
call Type
jmp MF25
MF24: dw NL,NL
db 'The file',39,'s message line is:'
dw NL
db MsgEnd
MF25: lxi d,Existing+String-Data ;Send String message
call Type
xra a ;set zero flag
ret
èPAGE
;Not a MKWAIT file - Send message
NotFile: lxi d,NMmsg
call Type
mvi a,1 ;clear zero flag
ana a
ret
NMmsg: db 'This file was not made by MKWAIT. '
dw NL
db MsgEnd
PAGE
;**** Write File to Disk ****
;Ask which drive to select
Write: call HomeIt
lxi d,Write2
call Type
jmp Write3
Write2: db 'Which drive do you want to write '
db MsgEnd
Write3: call FileName
lxi d,Write5
call Type
jmp Write6
Write5: db ' to?'
dw NL
db 'Select A,B,etc. or <ESC> to return to main menu.'
dw NL
db MsgEnd
;Wait for key
Write6: mvi c,6
mvi e,0FDh
call Bdos
cpi 1Bh ;ESC
jz Begin
ani 5Fh ;convert from small to cap.
cpi 'A' ;is it less than 'A'?
jc Write6 ;jmp if yes
cpi 'Q' ;is it less than 'Q'
jc Write10 ;jmp if yes
jmp Write6 ;sorry, not A to P
;Convert to drive code and store
Write10: sta Write17 ;store drive letter
ani 1Fh
sta FcbNew
;Create FcbRun
call Create
PAGE
;Clear screen
Write11: call HomeIt
;Open New File
mvi c,22
lxi d,FcbRun
call Bdos
è;Test if file opened
ana a
jz Write40 ;jmp if file opened with no problem
mov a,h
cpi 8h
jz Write15
cpi 0
jnz BadWait
;No directory space available
lxi d,Write12
call Type
jmp BadWait
Write12: dw NL,NL
db 'No directory space available.'
dw NL
db MsgEnd
;Ask if file to be overwritten?
Write15: call HomeIt
call FileName
lxi d,Write16
call Type
jmp Write20
Write16: db ' already exists on drive '
Write17: db 'A: '
dw NL
db 'Do you wish to overwrite this file with your new '
db '"wait" file? (Y/N) '
db MsgEnd
PAGE
;Wait for Erase Answer
Write20: mvi c,6
mvi e,0FDh
call Bdos
cpi 'Y'
jz Write22
cpi 'y'
jz Write22
jmp Begin
;Erase fileèWrite22: mvi c,19
lxi d,FcbRun
call Bdos
ana a ;test if erased
jz Write11 ;jmp if erased
mov a,h ;test if R/O
cpi 3
jz Write30 ;jmp if R/O
jmp BadWait
;Ask About Read/Only
Write30: lxi d,Write31
call Type
jmp Write32
Write31: dw NL,NL
db 'The file is Read/Only. Overwrite? (Y/N) '
db MsgEnd
;Wait for answer
Write32: mvi c,6
mvi e,0FDh
call Bdos
cpi 'Y'
jz Write35
cpi 'y'
jz Write35
jmp Begin
;Erase Read/Only
Write35:lda FcbRun+9 ;set FCB to R/Wè ani 7Fh
sta FcbRun+9
mvi c,30 ;now set file on disk to R/W
lxi d,FcbRun
call Bdos
jmp Write22
PAGE
;**** Load End Flags into Data ****
;Get next address after String
Write40: mvi b,0 ;load number of char to bc
lda Buffer+1
mov c,a
lxi h,String ;load string start adr
dad b ;offset
;add end flag of 0h
mvi m,0
inx h
;**** Write Data to Disk ****
mvi c,26 ;set DMA address
lxi d,Data
call Bdos
mvi c,21 ;write data
lxi d,FcbRun
call Bdos
mvi c,16 ;close file
lxi d,FcbRun
call Bdos
jmp Begin
**** FCB "to be run" location ***
FcbRun: ds 1
db 'WAIT COM'
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
**** FCB "to be read" location ****
FcbNew: ds 1
db 'WAIT COM'
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
FcbEnd: ds 1
PAGE
**** Program Data Assembly Area ****
;Below is the program of the WAIT file. It always starts at 100h.
Data:
OffSet: equ Data-100h
;Set Stack
lxi sp,Stack1
;Set Output Delimiter to 0h.
mvi c,110
mvi e,0h
call Bdos
;Jmp one line down so cursor is always in far left column
mvi c,9
lxi d,DataNL-Offset
call Bdos
;Is SkipFlag set?
lda SkipFlag-Offset
ana a
jnz TestLine-Offset
;Skip another line on screen and send flashing message
Data0: mvi c,9
lxi d,Data1-OffSet
call Bdos
jmp Data2-OffSet
Data1: dw NL
db 27,94 ;start flash
db 'READ NOTE:'
db 27,113 ;stop flash
db 7 ;Beep
DataNL: dw NL
db 0
;Send message
Data2: mvi c,9
lxi d,String-OffSet
call Bdos
;Send waiting message
mvi c,9
lxi d,Data4-OffSet
call Bdos
jmp Data5-OffSet
Data4: dw NL,NL
db 'Push <RETURN> to continue or '
db '<ESC> to terminate command string.'
dw NL
db 0
PAGE
;Wait for key
Data5: mvi c,6
mvi e,0FDh
call Bdos
cpi 1Bh ;ESC
jz Data7-OffSet
jmp 0 ;jmp to cp/m
;Return to CP/M without finishing any command lines
;Find and remove any SUBMIT RSX's
Data7: mvi c,60
lxi d,Data8-OffSet
call Bdos ;will return code of FFh if none found.
inr a
jnz Data7-OffSet
jmp Data10-OffSet
;RSX PB Address
Data8: db 81h ;Code to SUBMIT to terminate
db 0
;Find and remove any command RSX.
;Test if another command
Data10: mvi c,49
lxi d,Data15-OffSet ;Get High adr of next command
call Bdos
ana a ;test if 0h
jz 0 ;jmp if no next command
;Set command RSX "remove flag"
mov h,a
mvi l,0Eh
mvi m,0FFh
;Set next command address to 0000h
Data11: mvi c,49
lxi d,Data16-OffSet
call Bdos
jmp 0
;SCB PB Address for Data10
Data15: db 16h ;Offset to High adr of next command
db 0 ;Get operation
;SCB PB Address for Data11
Data16: db 15h ;Offset to adr of next command
db 0FEh ;Set word
dw 0000h ;The word value
PAGE
;Activate Video Bank
TestLine: in 0
sta LineBank-Offset
ori 40h
out 0
;Get present position of cursor
lhld CurPos
;Go up so many lines
lda LinesUp-Offset
adi 2 ;go up at least 2 lines
mov b,a
TL1: mov a,l
cpi 80h
jz TL4-Offset ;jmp if Low = 80h
mvi l,80h ;Set Low to 80h
dcr h ;Decrement High
TL2: dcr b
jnz TL1-Offset ;jmp if not last line
jmp TL10-Offset
TL4: mvi l,0 ;Set Low to 00h
jmp TL2-Offset
;Does data match?
TL10: lxi d,LineData-Offset
TL12: ldax d
ana a ;is it end flag?
jz TL16-Offset ;jmp if end flag
cmp m
jnz TL14-Offset ;jmp if no match
inx h
inx d
jmp TL12-Offset
;Restore banks and show WAIT message
TL14: lda LineBank-Offset
out 0
jmp Data0-Offset
;Restore banks and return to CP/M
TL16: lda LineBank-Offset
out 0
jmp Exit
PAGE
;Skip space to 027Eh (allows extra program space if needed)
ds 27Eh-100h-($-Data)
;Development Area for Message.
;Message will be from 280h to 37Fh (up to 255 char's).
Buffer: ds 2 ;2 bytes for number of characters in message ;027Eh
String: db 0 ;Start of string of characters in message. ;0280h
ds 0380h-100h-($-Data) ;skip space to 0380h
EndBuffer: ;This label used by ClearBuf:
;Storage for data bytes and words ;0380h
SkipFlag: db 0 ;Will test screen if this flag not zero
LineBank: ds 1 ;Temp storage of bank
LinesUp: db 0 ;Number of lines above CP/M command line
;skip space to 038Eh
EndCLA: ds 38Eh-100h-($-Data)
;Storage for "Check Line Above" message (up to 31 characters) ;038Eh
LineData0: ds 2 ;2 bytes for number of characters in message ;0390h
LineData: db 0
ds 3B0h-100h-($-Data) ;skip space to 03B0h
EndData: ;This label used by ClearLD:
;skip space to 04D2h (allows extra program or data space if needed) ;03B0h
ds 4D2h-100h-($-Data)
;Version number
EndS7: db 'Ver. ',xVersion,'.',yVersion,0,0,0 ;04D2h
;Recognition message
EndS8: db 'This WAIT.COM was created by MKWAIT' ;04DDh
EndS9: db 0 ;0500h
PAGE
;**** Routine Diff ****
;Change to a different file name
;Send message
Diff: call HomeIt
lxi d,Diff1
call Type
jmp Diff2
Diff1: db 'What is the new file name to be?'
dw NL
db 'Enter up to an 8 character file name.'
dw NL
db MsgEnd
;Setup NewName
Diff2: lxi h,NewName
mvi m,8 ;8 characters max
inx h
inx h
mvi m,0 ;no data to start
jmp Diff4
NewName: ds 15
;Get file name
Diff4: lxi d,NewName
call LineEdit
cpi 0
jz Diff10
cpi 1
jz Begin
cpi 2
jz BadWait
jmp Begin
PAGE
;Test if no data
Diff10: lda NewName+1
ana a
jz Begin ;Forget it if no data
;Convert small letters to caps
lxi h,NewName+2
Diff11: mov a,m
ana a
jz Diff13
cpi 'a'
jc Diff12 ;jmp if less than 'a'
cpi 'z'+1
jnc Diff12 ;jmp if greater than 'z'
sui 20h ;convert
mov m,a
Diff12: inx h
jmp Diff11
;Fill FcbRun file name with blanks
Diff13: mvi b,8
mvi a,' '
lxi h,FcbRun+1
Diff15: mov m,a
inx h
dcr b
jnz Diff15
;Move new file name to FcbRun
lxi h,NewName+2
lxi d,FcbRun+1
Diff17: mov a,m
ana a
jz Diff20
stax d
inx h
inx d
jmp Diff17
PAGE
;Fill FcbNew file name with blanks
Diff20: mvi b,8
mvi a,' '
lxi h,FcbNew+1
Diff21: mov m,a
inx h
dcr b
jnz Diff21
;Move new file name to FcbNew
lxi h,NewName+2
lxi d,FcbNew+1
Diff23: mov a,m
ana a
jz Diff25
stax d
inx h
inx d
jmp Diff23
;Fill FN1 file name with 0's
Diff25: mvi b,8
mvi a,0
lxi h,FN1
Diff27: mov m,a
inx h
dcr b
jnz Diff27
;Move new file name to FN1
lxi h,NewName+2
lxi d,FN1
Diff30: mov a,m
ana a
jz Diff33
stax d
inx h
inx d
jmp Diff30
;That's it. Lets go home.
Diff33: jmp Begin
PAGE
;**** Subroutine LineEdit ****
;
;DE = Start address of string to edit (set by user)
; 1st byte = maximum number of characters (set by user)
; Does not include end flag of 0.
; 2nd byte = total number of characters returned (set by LineEdit)
; Does not include end flag of 0.
; 3rd byte = zero if string has no data (set by user)
; 3rd byte = not zero if string has data (string must end with 0)
;
;Preload "WhichRow" with the row number to be used for the displayed line.
; 00h = 1st row (Top row of screen)
; 01h = 2nd row
; etc
; 17h = 24th row (Bottom row of screen)
;
;CP/M cursor is moved to far left so LineEdit can remove it.
;LineEdit Cursor will start at far left.
;Cursor will be inverse, blinking, full intensity.
;Non-cursor characters will be black background, full intensity.
;
;Nonprintable characters will not be allowed in string.
;
;MsgEnd must be 0h.
;
;Returns with accumulator set to:
; 0 - good edit. (2nd byte equals 0 to maximum characters in string)
; 1 - edit not wanted (ESC pushed)
; 2 - problem opening line (one line message given)
;
;"String" is location of data .
;"Line" is location of video ram.
;
LineMax: db MaxChar ;maximum number of characters allowed (max = 255)
;1st byte can be equal to or less than LineMax
WhichRow: db 17h ;row that line editor will use
StringStart: ds 2 ;start address of string to edit
StringBegin: ds 2 ;First char of string
String1st: ds 2 ;Address of char in string that is 1st char in line
StringCursor: ds 2 ;cursor location in string
LineBegin: ds 2 ;start address of line
LineCursor: ds 2 ;cursor location in line
PAGE
;Store start address of string
LineEdit: xchg
shld StringStart
;Make CP/M cursor start location same as LineEdit location
lda WhichRow
ani 24
sta CursorY
;Send Edit header
lxi d,Edit1
call Type
jmp Edit3
Edit1: dw NL,NL
db 'Use these keys for editing:'
dw NL,NL
db ' ^A - Go to far left.'
dw NL
db ' ^F - Go to far right.'
dw NL
db ' ^G or down arrow - delete character.'
dw NL
db ' ^- or ^left arrow - delete character on left.'
dw NL
db ' Use left and right arrow keys to move cursor.'
dw NL
db ' Only printable characters allowed.'
dw NL
db ' Push <ESC> to exit without new edit.'
dw NL
db ' Push <RETURN> when finished.'
db 1Bh,3Dh ;position cursor
CursorY db 0+32
CursorX db 0+32
db MsgEnd
PAGE
;Create video bank start address
Edit3: ora a ;clear carry
lda WhichRow ;get row number
lxi h,0C000h ;preload hl for video bank address
rar ;get LSB of WhichRow for MSB of reg l
mov b,a ;store LSB's for reg h
mov a,l ;move LSB of WhichRow into MSB of reg l
rar
mov l,a
mov a,b ;get LSB's for reg h
ora h ;move MSB's of WhichRow into LSB's of reg h
mov h,a ;
shld LineBegin ;store line start address
PAGE
;Test if max desired ok
Edit5: lhld StringStart
mov c,m ;load max char's
inx h
mvi m,0 ;set to 0 char returned for now
inx h
lda LineMax ;load max allowed
cmp c ;test if equal to or less than
jz Edit8 ;ok (equal)
jnc Edit8 ;ok (less than)
;Max desired not ok - send message
lxi d,Edit6
call Type
mvi a,2
ret
Edit6: db 'Maximum characters desired is more than that allowed.'
db MsgEnd
;Test if any nonprintable char found
Edit8:
mvi b,0 ;to keep track of number of char
lda LineMax ;to test if max exceeded
inr a ;account for end flag
mov c,a
Edit9: mov a,m
ana a
jz Edit20 ;jmp if end flag of 0 found
cpi ' '
jc Edit11 ;jmp if control char
cpi 7Fh
jnc Edit11 ;jmp if equal to or greater than 7Fh
inr b
dcr c
jz Edit16 ;jmp if max exceeded
inx h
jmp Edit9
;nonprintable char found
Edit11: lxi d,Edit12
call Type
mvi a,2
ret
Edit12: db 'Sorry, this string has a nonprintable character.'
db MsgEnd
PAGE
;number of char's exceed limit
Edit16: lxi d,Edit17
call Type
mvi a,2
ret
Edit17: db 'Sorry, this string is too long.'
db MsgEnd
;does string given exceed its own limit?
Edit20: lhld StringStart
mov a,m
cmp b
jnc Edit25 ;jmp if ok
;string given exceeds its own limit
lxi d,Edit22
call Type
mvi a,2
ret
Edit22: db 'Sorry, this string exceeds its own maximum limit.'
db MsgEnd
;Load number of char's found
Edit25: lhld StringStart
inx h
mov m,b
;display line
lhld StringStart ;preload start address of string
inx h
inx h
shld StringBegin
shld String1st
shld StringCursor
lhld LineBegin ;preload start address of line
shld LineCursor
shld OldCursor
call Display
jmp Edit
PAGE
;** Subroutine Display **
OldCursor: ds 2
Bank: ds 1
;Turn on Video Bank
Display: in 0
sta Bank
ori 40h
out 0
;Turn off old cursor
lhld OldCursor
mov a,m
ani 01111111b ;turn off reverse video
mov m,a
mov a,h ;go to DXXX address
adi 10h
mov h,a
mov a,m
ani 11011111b ;turn off blink
mov m,a
;Load new line data until end flag
lhld String1st
xchg
lhld LineBegin
mvi b,80
Display1: ldax d
ana a ;test if 0 end flag
jz Display2 ;jmp if yes
mov m,a
inx h
inx d
dcr b
jnz Display1
;Finish with blanks
Display2: mvi a,' '
Display3: mov m,a
inx h
dcr b
jnz Display3
PAGE
;Turn on new cursor and store location as OldCursor
lhld LineCursor
shld OldCursor
mov a,m
ori 10000000b ;turn on inverse video
mov m,a
mov a,h ;go to DXXX address
adi 10h
mov h,a
mov a,m
ori 00100000b ;turn on blink
mov m,a
;Turn off Video Bank
lda Bank
out 0
ret
PAGE
;Wait for edit key
Edit: mvi c,6
mvi e,0FDh
call Bdos
cpi 1Bh ;ESC
jz ExitEdit
cpi 01h ;^A (CP/M to left edge)
jz LeftEdge
cpi 06h ;^F (CP/M to right edge)
jz RightEdge
cpi 07h ;^G (CP/M and WS delete character)
jz DeleteChar
cpi 0Ah ;^J (CP/M Arrow down)
jz DeleteChar
cpi 18h ;^X (WS Arrow down)
jz DeleteChar
cpi 1Fh ;^_ (WS delete character on left - also ^ arrow left)
jz DeleteLeft
cpi 7Fh ;DEL
jz DeleteLeft
cpi 04h ;^D (WS arrow right)
jz Right
cpi 0Ch ;^L (CP/M arrow right)
jz Right
cpi 13h ;^S (WS arrow left)
jz Left
cpi 08h ;^H (CP/M arrow left)
jz Left
cpi 0Dh ;^M (Carriage Return)
jz DoneEdit
cpi ' '
jc Edit ;jmp if control char
cpi 80h
jnc Edit ;jmp if equal to or greater than 80h
jmp EnterChar
;Return from Edit with flag of abandon edit
ExitEdit: mvi a,1
ret
;Return from Edit with flag of good new edit
DoneEdit: mvi a,0
ret
PAGE
;**** Routine Right ****
;move cursor right
;can String move right?
Right: lhld StringCursor
mov a,m
ana a
jz Edit ;jmp if no
;move String right
inx h
shld StringCursor
;can Line move right?
lhld LineCursor
mov a,l
cpi 4Fh
jz RightMove ;jmp if no
cpi 0CFh
jz RightMove ;jmp if no
;move Line right
inx h
shld LineCursor
;display new line
RightOut: call Display
jmp Edit
;move String right
RightMove: lhld String1st
inx h
shld String1st
jmp RightOut
PAGE
;**** Routine Left ****
;moves cursor left
;Can String move left?
Left: lhld StringBegin
xchg
lhld StringCursor
mov a,d
cmp h
jnz Left1 ;jmp if yes
mov a,e
cmp l
jnz Left1 ;jmp if yes
jmp Edit ;jmp if no
;Move String left
Left1 dcx h
shld StringCursor
;Can Line move left?
lhld LineCursor
mov a,l
cpi 0h
jz LeftMove ;jmp if no
cpi 80h
jz LeftMove ;jmp if no
;move Line left
dcx h
shld LineCursor
;display new line
LeftOut: call Display
jmp Edit
;move String left
LeftMove: lhld String1st
dcx h
shld String1st
jmp LeftOut
PAGE
;**** Routine RightEdge ****
;Moves cursor to far right edge
;Can String move right?
RightEdge: lhld LineCursor ;for top
push h
lhld String1st ;for de
xchg
lhld StringCursor ;for hl
mov a,m
cpi 0h
jz REout ;jmp if no
;Move StringCursor and LineCursor right
;Can LineCursor move right
RE1: xthl
mov a,l
cpi 4Fh
jz RE5 ;jmp if no
cpi 0CFh
jz RE5 ;jmp if no
;move LineCursor right
inx h
RE2: xthl
;move StringCursor right
inx h
;can String move right
mov a,m
cpi 0h
jnz RE1 ;jmp if yes
;load new values
RE3: shld StringCursor
xchg
shld String1st
pop h
shld LineCursor
;display new line
call Display
jmp Edit
PAGE
;Move StringCursor and String1st right
;Return LineCursor
RE5: xthl
;move StringCursor and String1st right
RE6: inx h
inx d
;can String move right
mov a,m
cpi 0h
jnz RE6 ;jmp if yes
jmp RE3
REout: pop h
jmp Edit
PAGE
;**** Routine LeftEdge ****
;Moves cursor to far left edge
;Can String move left?
LeftEdge:
lhld StringBegin ;for bc
mov b,h
mov c,l
lhld StringCursor
mov a,b
cmp h
jnz LE0 ;jmp if yes
mov a,c
cmp l
jnz LE0 ;jmp if yes
jmp Edit ;jmp if no
LE0: lhld LineCursor ;for top
push h
lhld String1st ;for de
xchg
lhld StringCursor ;for hl
;Move StringCursor and LineCursor left
;Can LineCursor move left
LE1: xthl
mov a,l
cpi 0h
jz LE5 ;jmp if no
cpi 80h
jz LE5 ;jmp if no
;move LineCursor left
dcx h
LE2: xthl
;move StringCursor left
dcx h
;can String move left
mov a,b
cmp h
jnz LE1 ;jmp if yes
mov a,c
cmp l
jnz LE1 ;jmp if yes
PAGE
;load new values
LE3: shld StringCursor
xchg
shld String1st
pop h
shld LineCursor
;display new line
call Display
jmp Edit
;Move StringCursor and String1st left
;Return LineCursor
LE5: xthl
;move StringCursor and String1st left
LE6: dcx h
dcx d
;can String move left
mov a,b
cmp h
jnz LE6 ;jmp if yes
mov a,c
cmp l
jnz LE6 ;jmp if yes
jmp LE3 ;jmp if no
PAGE
;**** Routine DeleteChar ****
;Deletes character cursor is on
;Is StringCursor at end?
DeleteChar:
lhld StringCursor
mov a,m
dcx h
ana a
jz Edit ;jmp if yes
;Delete data at cursor
DelChar1: inx h
inx h
mov a,m
dcx h
mov m,a
ana a ;is it last char
jnz DelChar1 ;jmp if no
;Decrement char count
lhld StringStart
inx h
mov a,m
dcr a
mov m,a
;Display new line
call Display
jmp Edit
PAGE
;**** Routine DeleteLeft ****
;Delete character on left of cursor
;Is StringCursor at end?
DeleteLeft:
lhld StringBegin
xchg
lhld StringCursor
mov a,d
cmp h
jnz DelLeft1 ;jmp if no
mov a,e
cmp l
jnz DelLeft1 ;jmp if no
jmp Edit ;jmp if yes
;Is LineCursor at end?
DelLeft1:
lhld LineCursor
mov a,l
cpi 0h
jz Edit ;jmp if yes
cpi 80h
jz Edit ;jmp if yes
;Decrement LineCursor position
dcx h
shld LineCursor
;Decrement StringCursor position
lhld StringCursor
dcx h
shld StringCursor
;Delete data at left of cursor
dcx h
DelLeft2: inx h
inx h
mov a,m
dcx h
mov m,a
ana a ;is it last char
jnz DelLeft2 ;jmp if no
;Decrement char count
lhld StringStart
inx h
mov a,m
dcr a
mov m,a
;Display new line
call Display
jmp Edit
PAGE
;**** Routine EnterChar ****
;Enter character at cursor position.
;Cursor and all to right moves right.
;Store character
EnterChar:
mov c,a ;char stored in c
;Is String full?
lhld StringStart
mov a,m
inx h
cmp m
jnz Char1 ;jmp if no
;Send bell
mvi c,2
mvi e,7h
call Bdos
jmp Edit
;Increment String count
Char1: mov a,m
inr a
mov m,a
;Increment StringCursor
lhld StringCursor
inx h
shld StringCursor
dcx h
;Move in new data
Char2: mov a,m ;get data for next
mov m,c ;write data
mov c,a ;set up for next
inx h
ana a ;is it last
jnz Char2 ;jmp if no
mov m,c ;write end flag
PAGE
;Can LineCursor move right?
lhld LineCursor
mov a,l
cpi 4Fh
jz Char5 ;jmp if no
cpi 0CFh
jz Char5 ;jmp if no
;move LineCursor right
inx h
shld LineCursor
;Display line
Char4: call Display
jmp Edit
;Increment String1st
Char5: lhld String1st
inx h
shld String1st
jmp Char4
end 100h