
; -----------------= breakpoint subroutine =----------------
; don't know how well subs will work but we can see
; so how is this going to work? I'm thinking that 
; I'll first find the end of the instruction at 
; the breakpoint addr and put an SWI there, too. Then, when
; the first SWI happens, you can continue and when the 
; second SWI happens you can replace the first :)
; ----------------------------------------------------------
***
;break_sub: "m_breakp.asm"
;	called from command line "> break [+][-][<addr>]"
;	it adds a breakpoint at the certain address or subtracts the breakpoint
;	at that particular address
;	Reg Input:
;		None
;	Reg Output:
;		None
***

break_sub:
	jsr		skip_wspace		; skips whitespace. in "util.asm"
	ldaa		0,y			; loads first character from the character buffer
	iny					; increments the char buff pointer

	cmpa		#'+'			; checks to see if it is a plus, which means add a breakpoint
	beq		jsr_bkpt_add		; if it is, do stuff with add
	cmpa		#'-'			; checks to see if it is a minus, which means subtract a breakpoint
	beq		jsr_bkpt_sub		; if it is, do stuff with sub
	
	jsr		print_bkpt_sub		; if its neither, print the breakpoint table
	rts					;

jsr_bkpt_sub:
	jsr		bkpt_sub		; do stuff with removing a breakpoint
	rts					; returns
jsr_bkpt_add:
	jsr		bkpt_add		; do stuff with adding a breakpoint
	rts					; returns
bs_error:
	ldy		#error_msg		; if error is found, load an error message
	jsr		print_string		; and print the string. see "serial.asm"
	rts					; then return


						; bkpt_add -- routine to add breakpoints
bkpt_add:
	jsr		parse_address		; get the addr where we want this SWI	
						; returns in X
	cmpb		#$ff			; if $ff is in B, that means there was an error
	beq		ba_error		; return with error code

	pshx					; save the breakpoint address


						; x=address in the breakpoint table
						; a=offset to another breakpoint table
						; used to store the old data before the swi
						; replaced it
	jsr		bp_get_empty		; returns addr in X, offset in A
	cmpa		#$ff			; no empties?
	beq		ba_no_empty		; print the error message
	
	puly					; Y=bkpt addr
	sty		0,x			; put it into the table

	ldx		#bkpt_tbl_code		; loads the breakpoint table code. see "main.asm"
*						* tab again
	psha					; moves the offset from
	pulb					; B to A
	abx					; adds A to X
	ldaa		0,y			; get the code from the address,
	staa		0,x			; save it on the other table
*						* he could do staa   a, x  instead of adding a to x.

	ldaa		#$3f			; $3f is an swi instruction code. loads into A
	staa		0,y			; put the SWI there replacing the address
	
	rts					; and return, breakpoints have been added

ba_no_empty:
	ldy		#bkpt_err
	jsr		print_string
ba_error:
	ldab		#$ff	
	rts


						; bpge_get_empty -- finds an empty bkpt table entry
						; in: nothing
						; out: X -- addr of first empty bkpt table entry
						; out: A -- offset of that entry in the table (bkpt number)
						;      A -- $ff on error (no empty entry)
bp_get_empty:
	ldx		#bkpt_table		; loads address of the breakpoint table
	clra					; clears A
bpge_loop1:
	psha					; stores A
	ldd		0,x			; get this entry
	beq		bpge_empty		; its empty!
	inx					; increment twice, because address are two bytes
	inx					;
	pula					; bring back A
	inca					; increment A(offset)
	cmpa		#$05			; five entries
	beq		bpge_no_empty		; no empty entry
	bra		bpge_loop1		; otherwise continue
bpge_no_empty:
	ldaa		#$ff			; loads error code
	rts					; returns to stack
bpge_empty:
	pula					; pull A(the offset)
	rts					; returns with X being address of empty spot

***
;bkpt_sub: "m_breakp.asm"
;	routine to remove a breakpoint. Called by break_sub
;	Reg Input:
;		Y = command buffer addr
;	Reg Output:
;		None
***

						; bkpt_sub -- routine to remove breakpoints
bkpt_sub:
	jsr		parse_address		; returns in X, address that was parsed
	cmpb		#$ff			; if there was an error
	beq		ba_error		; return with error message

						; we need to search the bkpt table for this addr
	xgdx					; put the addr in D
	jsr		sh_search_addr		; returns offset in A, addr in X. see "swi.asm"

*						* does he really need to put all of those 0s?
	cpx		#$0000			; if not found, X=0000
	beq		bsub_not_a_bkpt		; on error

	psha					; save state of A(offse)
	pshx					; and save state of X(address)

	ldaa		bkpt_state		; state of the bkpt system
	cmpa		#$00			; if $00, then we're not "between" SWIs
	beq		bsub_not_between	; so then go to that section of code

						; when we're here, we need to not only 
						; change the bkpt table, we need to
						; replace the "second" SWI with the code 
						; thats supposed to be there!
	ldx		bkpt_addr2		; addr of the second SWI
	ldaa		bkpt_code		; and the code to go there
	staa		0,x			; restore the code
	clra					; clears A
	staa		bkpt_state		; clear the state so it doesn't do strange things


						; all we need to do here is replace the "first" SWI with the code
						; thats supposed to be there and remove that bkpt from the table
bsub_not_between:				; remember to zero it out!
	pulx					; addr of this bkpt in the table
	pulb					; offset in the table
	pshx					; save that addr again
	
	ldy		0,x			; get the addr of this bkpt
	ldx		#bkpt_tbl_code		; load table that stores old data
	abx					; add offset to it
	ldaa		0,x			; get old byte
	staa		0,y			; restore the code
	
	pulx					; get back the address
	ldd		#$0000			; load D with zero
	std		0,x			; zero that entry in the bkpt table
	rts					; return

bsub_not_a_bkpt:
	rts					; return

	
