;
; GRDP
;
; Copyright(c) LADsoft
;
; David Lindauer, camille@bluegrass.net
;
;
; breaks.asm
;
; handle breakpoint setting, resetting, enabling, commands
;
	;MASM MODE
	.model small
	.386

include  eprints.inc 
include  emtrap.inc 
include  einput.inc 
include  ehbreak.inc

	PUBLIC	setbreak, breaks, enableBreaks, disableBreaks
	.data
breaklist dd 16 DUP (?)		; List of breakpoints
breakhold db 16 dup (?)		; List of values where 'int 3' has covered
				; the opcode
breakenum dw	0		; Flags telling which breakpoints are set
	
	.code
;
; Command to set a breakpoint comes here
; INPUT: AX contains break number
;	EBX contains break address
;
setbreak	PROC	
	push	bx		;save break address
	call	defCS		; set default CS reg in DX
	and	ax,0fh		; Set the breakpoint set bit
	bts	[breakenum],ax	;set in breaknum bitmap
	shl	ax,2		;dword index into breaklist
	add	ax,offset breaklist	;plus offset
	xchg	ax,bx		;AX=address,BX=break index
	mov	[bx],ax		;set break offset
	mov	[bx + 2],dx	;and segment in list
	pop	bx		;restore break address
	ret
setbreak	ENDP	
;
; Command to clear a breakpoint comes here
; INPUT: AX has break number to clear in bitmap
;
clearbreak	PROC	
	and	ax,0fh		; Reset the flag bit
	btr	[breakenum],ax	;
	ret
clearbreak	ENDP	
;
; Command to display a breakpoint comes here
; INPUT: AX contains index into breaknum bitmap
;
displaybreak	PROC	
	and	ax,0fh		; just in case (shouldn't happen)
	bt	[breakenum],ax	; see if this one is set
	jnc	short nodisplay	; Quit with no disp if this one not set
	push	ax		; save index
	call	crlf		; new line
	pop	ax		; restore index
	push	ax		; save again
	call	printbyte	; Print breakpoint #
	mov	dl,':'		; Print ':'
	call	PutChar
	call	printspace
	pop	bx		; restore index
	shl	bx,2		; cvt to dword index
	add	bx,offset breaklist	;offset from breaklist
	mov	ax,WORD PTR [bx + 2]	; Print segment
	call	printword	;
	mov	dl,':'		; Print ':'
	call	PutChar
	mov	ax,[bx]		; Print offset
	call	printword      
nodisplay:
	ret
displaybreak	ENDP	
;
; When GO or TRAP or PROCEED commands execute, they call this to
; enable breakpoints
;
enableBreaks	PROC	
	mov	cx,15		; For each breakpoint
eblp:
	bt	[breakenum],cx	; If not set
	jnc	short ebnn	; Don't do anything
	mov	bx,cx
	shl	bx,2
	mov	fs,WORD PTR [bx + breaklist + 2]
	mov	si,word ptr [bx + breaklist]
	mov	al,fs:[si]	; Get the byte at that location
	mov	BYTE PTR fs:[si],0cch	; Put an int 3
	mov	bx,cx
	mov	[bx + breakhold],al	; Save it for restore
ebnn:
	dec	cx		; Next breakpoint
	jns	eblp		;
	call	hdwebreakenable	; set DR7 for hardware breaj
	ret	
enableBreaks	ENDP	
;
; Int 3 or int 1 call this to disable breakpoints and restore the
; values covered by the int 3
;
disableBreaks	PROC	
	mov	cx,15		; For each breakpoint
dblp:
	bt	[breakenum],cx	; If not set
	jnc	short dbnn	; Go nothing
	mov	bx,cx
	mov	al,[bx + breakhold]	;get byte overwritten with CC
	shl	bx,2
	mov	si,word ptr [bx + breaklist]	;find break address in
	mov	fs,WORD PTR [bx + breaklist + 2]	;fs:si
	mov	fs:[si],al	; and put original byte back
dbnn:
	dec	cx
	jns	dblp		; Next breakpoint
	btr	[breakenum],0   ; Reset breakpoint 0 (the automatic breakpoint)
	call	hdwebreakdisable ;turn off breaks in DR7
	ret
disableBreaks	ENDP	
;
; Handle breakpoint-related commands
; INPUT: SI points to input line text
;	
;
breaks	PROC	
	call	WadeSpace	; Wade through spaces
	jz	short showall	; Show all breakpoints
	cmp	al,'d'   	; branch off to hdwe routines
	je	hdwebreakcommand; if necessary
	cmp	al,'-'		; Else check for '-'
	pushf			;
	jne	noinc		;
	inc	si		; Skip to next arg
	call	WadeSpace	;
noinc:
	cmp	al,'*'		;clear everything?
	je	clearall	;do it if so
	call    ReadNumber	; Read break number
	jc	short badbreak2	; Exit if error
	cmp	ax,16		; Make sure in range
	jae	short badbreak2	; Exit if error
	or	ax,ax		; Can't do anything with break #0, it's automatic
	jz	short badbreak2	;
	popf			;
	push	ax		; save break number
	jz	short unmake	; If was '-', clear break
	call	WadeSpace	; Else wade to next arg
	jz	badbreak2	; error if not found
	call	ReadAddress	; Read the bp address
	pop	ax		; restore break number
	jc	short badbreak	; Quit if error
	call	setbreak	; Set breakpoint at this address
	jmp	short breakdone	; Get out
unmake:
	call	WadeSpace	; Wade to end
	pop	ax		; restore break number
	jnz	short badbreak	; If there is more we have an error
	call	clearbreak	; Clear breakpoint
	jmp	short breakdone	; Get out
clearall:
	popf			; ZF if -*, NZ if just * no -
	jnz	short badbreak	; not a clear
	inc	si		; next arg
	call	WadeSpace	; find it
	jnz	short	badbreak	;can't be more on line here
	mov	[breakenum],0	;clear entire bitmap
	jmp	breakdone	;and get out
showall:
	test	[breakenum],0ffffh	;are any breaks set now?
	jnz	doshow		; if so, show them
	PRINT_MESSAGE	<13,10,"No breakpoints enabled">
	clc
	ret

doshow:
	mov	cx,15		; For each breakpoint
salp:
	mov	ax,cx		; Display it if set
	call	displaybreak	;
	loop	salp		; for all possible 16 of them
breakdone:
	clc			; Exit, no errors
	ret
badbreak2:
	pop	ax		;
badbreak:
	stc			; Exit, errors
	ret
breaks	ENDP	
END