	.data

MarkBuf		dd	0
MarkBufLen	dw	0
BptBuf		dd	0
BptPtr		dw	0
BptBufEnd	dw	0
BptCount	dw	0
StackPtr	dw	0
StageBeg	dd	0
StageStubSeg	dw	0
StageEnd	dw	0
StagePtr	dw	0
StageEnd2	dw	0
BptAddr		dw	0
BptType		dw	0
MarkOffset	dw	0
BitMask		dw	0
BitCount	dw	0
SpecCode	dw	0
InstrLen	dw	0
NextInstr	dd	0
NextInstr2	dd	0
IntBptSet	dw	0
ScreenSwapped	dw	0

	.code

Dummy1	db	0
Dummy2	db	0

InitAnalyse	proc	near
	mov	BptBuf.segm,ax
	mov	BptBuf.offs,bx
	mov	BptPtr,bx
	mov	BptCount,0
	add	bx,dx
	mov	BptBufEnd,bx
	mov	MarkBuf.offs,di
	mov	MarkBuf.segm,es
	mov	ax,cx
	shl	ax,1
	shl	ax,1
	shl	ax,1
	mov	MarkBufLen,ax
	shr	cx,1
	xor	ax,ax
	rep	stosw
	mov	ScreenSwapped,ax
	mov	Dummy1,al
	ret
InitAnalyse	endp

Analyse	proc	near
	cmp	cx,MarkBufLen
	jbe	@@1
	jmp	@@18
@@1:	mov	StageEnd2,ax
	mov	StageBeg.offs,bx
	mov	StageBeg.segm,es
	mov	StageStubSeg,dx
	add	cx,bx
	mov	StageEnd,cx
	mov	IntBptSet,0
	mov	Dummy2,-1
ContAnalyse	label	near
	mov	ax,BptBufEnd
	mov	StackPtr,ax
@@2:	mov	StagePtr,si
	call	CalcMask
	mov	MarkOffset,bx
	mov	BitMask,dx
	mov	BitCount,cx
@@3:	mov	si,MarkOffset
	mov	es,MarkBuf.segm
	mov	ax,BitMask
	test	ax,es:[si]
	jnz	@@7
	mov	di,StagePtr
	mov	es,StageBeg.segm
	call	disasm
	mov	InstrLen,cx
	mov	NextInstr.offs,di
	mov	NextInstr.segm,es
	mov	SpecCode,ax
	mov	si,MarkOffset
	mov	es,MarkBuf.segm
	mov	ax,BitMask
	mov	dx,BitCount
@@4:	or	es:[si],ax
	shl	ax,1
	dec	dx
	jnz	@@5
	mov	ax,1
	mov	dx,16
	add	si,2
	add	MarkOffset,2
@@5:	loop	@@4
	mov	BitMask,ax
	mov	BitCount,dx
	mov	ax,SpecCode
	cmp	ax,scInt
	je	@@9
	mov	IntBptSet,0
	and	ax,ax
	jnz	@@9
@@6:	mov	ax,InstrLen
	add	StagePtr,ax
	mov	ax,StagePtr
	cmp	ax,StageEnd
	jae	@@7
	jmp	@@3
@@7:	mov	si,StackPtr
	cmp	si,BptBufEnd
	je	@@8
	mov	es,MarkBuf.segm
	mov	si,es:[si]
	add	StackPtr,2
	mov	IntBptSet,0
	jmp	@@2
@@8:	clc
	ret
@@9:	mov	bx,ax
	and	bx,7fh
	shl	bx,1
	jmp	@@Tbl[bx-2]
	.data
@@Tbl	dw	@@Ret,@@Jmp,@@Jcc,@@Call,@@Int,@@DS,@@ES,@@Both
	.code
@@Ret:	mov	al,bpRet
	call	SetBptHere
	jmp	@@6
@@Jmp:	test	ax,scInd
	jz	@@Jcc
@@13:	mov	al,bpICall
	call	SetBptHere
	jmp	@@7
@@14:	cmp	SpecCode,scJcc
	je	@@16
@@15:	mov	si,NextInstr.offs
	jmp	@@2
@@16:	mov	si,NextInstr.offs
	call	CalcMask
	mov	es,MarkBuf.segm
	test	dx,es:[bx]
	jnz	@@17
	mov	bx,MarkOffset
	mov	ax,BitMask
	and	ax,es:[bx]
	jnz	@@15
	sub	StackPtr,2
	mov	di,StackPtr
	cmp	di,BptPtr
	jb	@@18
	mov	ax,NextInstr.offs
	stosw
@@17:	jmp	@@6
@@18:	call	RemoveBpts
	stc
	ret
@@Jcc:	mov	ax,NextInstr.segm
	cmp	ax,StageBeg.segm
	jne	@@20
	mov	ax,StageStubSeg
	mov	NextInstr.segm,ax
	mov	ax,NextInstr.offs
	cmp	ax,StageBeg.offs
	jb	@@20
	cmp	ax,StageEnd
	jb	@@14
@@20:	push	NextInstr ds
	lea	ax,NextInstr2
	push	ax
	call	FindSrcLine
	or	ax,dx
	jz	@@13
	mov	al,bpStop
	les	di,NextInstr
	call	SetBpt
	cmp	SpecCode,scJcc
	je	@@24
	jmp	@@7
@@Int:	cmp	IntBptSet,0
	jne	@@22
	mov	IntBptSet,1
	mov	al,bpInt
	call	SetBptHere
@@22:	jmp	@@6
@@Call:	cmp	Action,acTraceInto
	jne	@@29
	test	ax,scInd
	jz	@@25
	mov	al,bpIJmp
	call	SetBptHere
@@24:	jmp	@@6
@@25:	les	di,NextInstr
	cmp	word ptr es:[0],3fcdh
	jne	@@27
	mov	ax,es:[di+1]
	cmp	byte ptr es:[di],0eah
	je	@@26
	mov	ax,es:[di+2]
@@26:	mov	NextInstr.offs,ax
@@27:	mov	ax,NextInstr.segm
	cmp	ax,StageBeg.segm
	jne	@@28
	mov	ax,StageStubSeg
	mov	NextInstr.segm,ax
@@28:	push	NextInstr ds
	lea	ax,NextInstr2
	push	ax
	call	FindSrcLine
	or	ax,dx
	jz	@@29
	mov	al,bpStop
	les	di,NextInstr2
	call	SetBpt
	jmp	@@6
@@29:	mov	al,bpCall
	call	SetBptHere
	jmp	@@6
@@DS:	mov	al,bpDS
	call	SetBptHere
	jmp	@@6
@@ES:	mov	al,bpES
	call	SetBptHere
	jmp	@@6
@@Both:	mov	al,bpBoth
	call	SetBptHere
	jmp	@@6
Analyse	endp

	.data
Masks	dw	0001h,16
	dw	0002h,15
	dw	0004h,14
	dw	0008h,13
	dw	0010h,12
	dw	0020h,11
	dw	0040h,10
	dw	0080h,9
	dw	0100h,8
	dw	0200h,7
	dw	0400h,6
	dw	0800h,5
	dw	1000h,4
	dw	2000h,3
	dw	4000h,2
	dw	8000h,1
	.code

CalcMask	proc	near
	sub	si,StageBeg.offs
	mov	bx,si
	mov	cl,4
	shr	bx,cl
	shl	bx,1
	add	bx,MarkBuf.offs
	and	si,0fh
	shl	si,1
	shl	si,1
	mov	dx,Masks[si]
	mov	cx,Masks[si+2]
	ret
CalcMask	endp

GetRealSeg	proc	near
	cmp	word ptr es:[0],3fcdh
	jne	@@1
	cmp	word ptr es:[10h],0
	je	@@2
	mov	es,es:[10h]
@@1:	clc
	ret
@@2:	stc
	ret
GetRealSeg	endp

SetBptHere	proc	near
	mov	di,StagePtr
	mov	es,StageBeg.segm
SetBpt	label	near
	call	BptOnAddr
	jz	@@2
	mov	bx,BptPtr
	lea	dx,[bx+size DBpt]
	cmp	dx,StackPtr
	ja	@@3
	push	ds
	mov	ds,BptBuf.segm
	mov	[bx].Adr.Offs,di
	mov	[bx].Adr.Segm,es
	mov	[bx].Typ,al
	call	GetRealSeg
	jc	@@1
	mov	al,es:[di]
	mov	[bx].OldB,al
	mov	byte ptr es:[di],0cch
@@1:	pop	ds
	add	BptPtr,size DBpt
	inc	BptCount
@@2:	ret
@@3:	call	RemoveBpts
	call	RemoveUserBpts
	jmp	StkOv
SetBptHere	endp

RemoveBpts	proc	near
	mov	cx,BptCount
	jcxz	@@3
	push	ds
	lds	si,BptBuf
@@1:	les	di,[si].Adr
	call	GetRealSeg
	jc	@@2
	cmp	byte ptr es:[di],0cch
	jne	@@2
	mov	al,[si].OldB
	mov	es:[di],al
@@2:	add	si,size DBpt
	loop	@@1
	pop	ds
	mov	ax,BptBuf.offs
	mov	BptPtr,ax
	mov	BptCount,0
@@3:	ret
RemoveBpts	endp

BptOnAddr	proc	near
	push	es ds
	mov	dx,es
	mov	cx,BptCount
	jcxz	@@3
	lds	si,BptBuf
@@1:	cmp	di,[si].Adr.Offs
	jne	@@2
	cmp	dx,[si].Adr.Segm
	je	@@7
@@2:	add	si,size DBpt
	loop	@@1
@@3:	pop	ds
	push	ds
	mov	cx,UserBptCount
	jcxz	@@6
	lds	si,UserBptBuf
@@4:	cmp	[si].Typ,0
	je	@@5
	cmp	di,[si].Adr.Offs
	jne	@@5
	cmp	dx,[si].Adr.Segm
	je	@@7
@@5:	add	si,size DBpt
	loop	@@4
@@6:	or	cl,1
@@7:	pop	ds es
	ret
BptOnAddr	endp

PassBpt	proc	near
	mov	si,BptAddr
	mov	es,BptBuf.Segm
	les	di,es:[si].Adr
	call	GetRealSeg
	jc	@@1
	cmp	byte ptr es:[di],0cch
	jne	@@1
	mov	al,[si].OldB
	mov	es:[di],al
	call	OneStep
	mov	si,BptAddr
	mov	es,BptBuf.Segm
	les	di,[si].Adr
	mov	al,es:[di]
	mov	[si].OldB,al
	mov	byte ptr es:[di],0cch
@@1:	ret
PassBpt	endp

	.data
BptSeg	dw	0
	.code
ProcessBpt	proc	near
	mov	cx,BptCount
	jcxz	@@3
	mov	di,BptBuf.Offs
	mov	es,BptBuf.Segm
	mov	ax,Rg.rIP
	mov	dx,Rg.rCS
@@1:	scasw
	je	@@4
@@2:	add	di,size DBpt-2
	loop	@@1
@@3:	stc
	ret
@@4:	push	es
	mov	es,es:[di-2].Adr.Segm
	call	GetRealSeg
	mov	bx,es
	pop	es
	jc	@@2
	cmp	dx,bx
	jne	@@2
	mov	ax,es:[di-2].Adr.Segm
	mov	BptSeg,ax
	sub	di,2
	mov	BptAddr,di
	mov	al,es:[di].Typ
	cbw
	mov	BptType,ax
	mov	bx,ax
	cmp	al,bpIJmp
	je	@@6
	cmp	al,bpICall
	je	@@6
	push	ds es
	les	si,es:[di].Adr
	call	GetRealSeg
	push	es
	pop	ds
	pop	es
	jc	@@5
	cmp	byte ptr [si],0cch
	jne	@@5
	mov	al,es:[di].OldB
	mov	[si],al
@@5:	pop	ds
@@6:	shl	bx,1
	jmp	@@Tbl[bx]
	.data
@@Tbl	dw	@@DS,@@ES,@@Both,@@Call,@@Call,@@Ret,@@Stop,@@IJmp,@@ICall
	.code
@@ICall:call	PassBpt
	mov	si,Rg.rCS
	cmp	si,StageBeg.Segm
	jne	@@Stop
	mov	si,Rg.rIP
	cmp	si,StageBeg.Offs
	jb	@@Stop
	cmp	si,StageEnd
	jae	@@Stop
	call	CalcMask
	mov	es,MarkBuf.segm
	test	dx,es:[bx]
	jnz	@@9
	mov	si,Rg.rIP
	call	ContAnalyse
@@9:	xor	al,al
	ret
@@IJmp:	call	PassBpt
	jmp	short @@Stop
@@Ret:	mov	OvrBptFlag,1
	call	OneStep
	mov	OvrBptFlag,0
	cmp	Action,acStepOver
	jne	@@Stop
	mov	Action,acTraceInto
@@Stop:	push	BptSeg Rg.rIP ds
	lea	ax,NextInstr2
	push	ax
	call	FindSrcLine
	cmp	BptType,bpIJmp
	jne	@@13
	mov	bx,ax
	or	bx,dx
	jz	@@Call
@@13:	push	ax dx
	call	RemoveBpts
	pop	dx ax
	mov	bx,ax
	or	bx,dx
	jnz	@@14
	call	ScreenSwap
	xor	ax,ax
	xor	dx,dx
@@14:	ret
@@DS:	mov	ax,Rg.rDS
@@16:	push	ax
	mov	di,BptAddr
	push	ds
	mov	ds,BptBuf.Segm
	les	si,[di].Adr
	call	GetRealSeg
	cmp	byte ptr es:[si],0cch
	jne	@@17
	mov	al,[di].OldB
	mov	es:[si],al
@@17:	pop	ds ax
	cmp	ax,50h
	jb	@@Call
	cmp	ax,0a000h
	jb	@@18
	cmp	ax,0c000h
	jb	@@Call
@@18:	xor	al,al
	ret
@@Both:	mov	ax,Rg.rDS
	cmp	ax,0a000h
	jae	@@16
	cmp	ax,50h
	jb	@@16
@@ES:	mov	ax,Rg.rES
	jmp	@@16
@@Call:	cmp	ScreenSwapped,0
	jne	@@24
	call	ScreenSwap
	mov	ScreenSwapped,1
	mov	cx,BptCount
	push	ds
	lds	si,BptBuf
@@22:	cmp	[si].Typ,bpInt
	ja	@@23
	les	di,[si].Adr
	cmp	byte ptr es:[di],0cch
	jne	@@23
	mov	al,[si].OldB
	mov	es:[di],al
@@23:	add	si,size DBpt
	loop	@@22
	pop	ds
@@24:	xor	al,al
	ret
ProcessBpt	endp

DisableBpts	proc	near
	mov	cx,BptCount
	jcxz	@@3
	push	ds
	lds	si,BptBuf
@@1:	les	di,[si].Adr
	cmp	byte ptr es:[di],0cch
	jne	@@2
	mov	al,[si].OldB
	mov	es:[di],al
@@2:	add	si,size DBpt
	loop	@@1
	pop	ds
@@3:	ret
DisableBpts	endp
