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
