;Software License Agreement (BSD License)
;
;Copyright (c) 1997-2008, David Lindauer, (LADSoft).
;All rights reserved.
;
;Redistribution and use of this software in source and binary forms, with or without modification, are
;permitted provided that the following conditions are met:
;
;* Redistributions of source code must retain the above
;  copyright notice, this list of conditions and the
;  following disclaimer.
;
;* Redistributions in binary form must reproduce the above
;  copyright notice, this list of conditions and the
;  following disclaimer in the documentation and/or other
;  materials provided with the distribution.
;
;* Neither the name of LADSoft nor the names of its
;  contributors may be used to endorse or promote products
;  derived from this software without specific prior
;  written permission of LADSoft.
;
;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
;WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
;PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
;ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
;LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
;INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
;TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
;ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	;MASM MODE
	.386
	.model use32 small

include  prints.ase 
include  mtrap.ase 
include  input.ase 

	PUBLIC	SetBreak, breaks, EnableBreaks, DisableBreaks, enableOneBreak
	extrn hdwebreakcommand : PROC, hdwebreakenable : PROC
	extrn hdwebreakdisable : PROC

	.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
;
SetBreak	PROC	
	and	eax,0fh		; Set the breakpoint set bit
	bts	[breakenum],ax	;
	mov	[eax*4+breaklist],ebx	;
	ret
SetBreak	ENDP	
;
; Command to clear a breakpoint comes here
;
clearbreak	PROC	
	and	ax,0fh		; Reset the flag bit
	btr	[breakenum],ax	;
	ret
clearbreak	ENDP	
;
; Command to display a breakpoint comes here
;
displaybreak	PROC	
	and	eax,0fh		; See if set
	bt	[breakenum],ax	;
	jnc	short nodisplay	; Quit with no disp if no breakpoint set
	push	eax		; CR/LF
	call	crlf
	pop	eax		;
	push	eax		;
	call	PrintByte	; Print breakpoint #
	mov	dl,':'		; Print ':'
	call	PutChar
	call	PrintSpace
	pop	ebx		;
	mov	eax,DWORD PTR [ebx*4+breaklist]	; Print segment
	call	PrintDword	;
nodisplay:
	ret
displaybreak	ENDP	
enableOneBreak PROC
	mov	esi,dword ptr [ecx*4 + breaklist]
	mov	al,[esi]	; Get the byte at that location
	mov	BYTE PTR [esi],0cch	; Put an int 3
	mov	[ecx + breakhold],al	; Save it for restore
	ret
enableOneBreak ENDP
;
; When GO or TRAP or PROCEED commands execute, they call this to
; enable breakpoints
;
EnableBreaks	PROC	
	mov	ecx,15		; For each breakpoint
eblp:
	bt	[breakenum],cx	; If not set
	jnc	short ebnn	; Don't do anything
	call	enableOneBreak;
ebnn:
	dec	ecx		; Next breakpoint
	jns	eblp		;
	mov	eax,ecx		;
	call	hdwebreakenable
	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	ecx,15		; For each breakpoint
dblp:
	bt	[breakenum],cx	; If not set
	jnc	short dbnn	; Go nothing
	mov	al,[ecx + breakhold]
	
	mov	esi,[ecx*4 + breaklist]	;
	mov	[esi],al	;
dbnn:
	dec	ecx
	jns	dblp		; Next breakpoint
	btr	[breakenum],0   ; Reset breakpoint 0 (the automatic breakpoint)
	call	hdwebreakdisable
	ret
DisableBreaks	ENDP	
;
; Handle breakpoint-related commands
;
breaks	PROC	
	call	WadeSpace	; Wade through spaces
	jz	showall	; Show all breakpoints
	cmp	al,'d'
	jz	hdwebreakcommand
	cmp	al,'-'		; Else check for '-'
	pushfd			;
	jnz	noinc		;
	inc	esi		; Skip to next arg
	call	WadeSpace	;
noinc:
	cmp	al,'*'
	jz	clearall
	call    ReadNumber	; Read break number
	jc	badbreak2	; Exit if error
	cmp	eax,16		; Make sure in range
	jnc	badbreak2	; Exit if error
	or	eax,eax		; Can't do anything with break #0, it's automatic
	jz	badbreak2	;
	popfd			;
	push	eax		;
	jz	short unmake	; If was '-', clear break
	call	WadeSpace	; Else wade to next arg
	jz	badbreak2
	call	ReadAddress	; Read the bp address
	pop	eax		;
	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	eax		;
	jnz	short badbreak	; If there is more we have an error
	call	clearbreak	; Clear breakpoint
	jmp	short breakdone	; Get out
clearall:
	popf
	jnz	short badbreak
	inc	esi
	call	WadeSpace
	jnz	short	badbreak
	mov	[breakenum],0
	jmp	breakdone
showall:
	test	[breakenum],0ffffh
	jnz	doshow
	Msg	<13,10,"No breakpoints enabled">
	clc
	ret

doshow:
	mov	ecx,15		; For each breakpoint
salp:
	mov	eax,ecx		; Display it if set
	call	displaybreak	;
	loop	salp		;
breakdone:
	clc			; Exit, no errors
	ret
badbreak2:
	pop	eax		;
badbreak:
	stc			; Exit, errors
	ret
breaks	ENDP	
END
