diff options
Diffstat (limited to '')
| -rw-r--r-- | codehandler.yaml | 4 | ||||
| -rwxr-xr-x | src/codehandler.S | 878 | 
2 files changed, 880 insertions, 2 deletions
| diff --git a/codehandler.yaml b/codehandler.yaml index cfbeb9e..377d80b 100644 --- a/codehandler.yaml +++ b/codehandler.yaml @@ -1,8 +1,8 @@ -source_files: [../src/codehandler.o] +source_files: [../src/codehandler.S]  hooks:    - name: CodeHandlerHook      type: branch_insn      branch_type: b      src_addr_pal: 0x801bdf78 -    target_func: '_start' +    target_func: '_codehandler_start' diff --git a/src/codehandler.S b/src/codehandler.S new file mode 100755 index 0000000..da62466 --- /dev/null +++ b/src/codehandler.S @@ -0,0 +1,878 @@ +# initial setup
 +# * add exception handling for all cases
 +# many breakpoints handling
 +# * add breakpoint list with addresses
 +# * add breakpoint list with original values
 +# allow PPC side searches
 +# * u32 with number of matches
 +# * list of addresses that match
 +# breakpoint conditions
 +# * address == foo
 +# *		&&
 +# * r* == bar
 +# * r* != bar
 +# * r* > bar
 +# * r* < bar
 +
 +.text
 +
 +#if 0
 +.set r0,0;   .set r1,1;   .set r2,2;   .set r3,3;   .set r4,4
 +.set r5,5;   .set r6,6;   .set r7,7;   .set r8,8;   .set r9,9
 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
 +.set r30,30; .set r31,31; .set f0,0;   .set f2,2;   .set f3,3
 +#endif
 +
 +.set FROZENVAL, 18;
 +.set CCOO, 20;
 +.set ZEROVAL, 21;
 +.set CRCHECK, 22;
 +.set EXIPORT, 23;
 +.set CDOO, 24;
 +.set MSR, 25;
 +.set NEWMSR, 26;
 +.set REMAINDER, 27;
 +.set MP3PROT, 28;
 +.set RECVBYTE, 29;
 +.set TEMPLR, 30;
 +.set STATE, 31;
 +
 +.globl _codehandler_start
 +
 +gameid:
 +.long	0,0
 +cheatdata:
 +.long	frozenvalue
 +.space 39*4
 +
 +.extern OSReport
 +_codehandler_start:
 +#if 0
 +	lis r3, debug_string@h
 +	ori r3, r3, debug_string@l
 +	bl OSReport
 +debug_string:
 +.string "Codehandler called\n"
 +#endif
 +	stwu	r1,-168(r1)		# stores sp
 +	stw		r0,8(r1)		# stores r0
 +
 +	mflr	r0
 +	stw		r0,172(r1)		# stores lr
 +
 +	mfcr	r0
 +	stw		r0,12(r1)		# stores cr
 +
 +	mfctr	r0
 +	stw		r0,16(r1)		# stores ctr
 +
 +	mfxer	r0
 +	stw		r0,20(r1)		# stores xer
 +
 +	stmw	r3,24(r1)		# saves r3-r31
 +
 +	mfmsr	MSR
 +	ori		NEWMSR,MSR,0x2000	#enable floating point ?
 +	andi.	NEWMSR,NEWMSR,0xF9FF
 +	mtmsr	NEWMSR
 +
 +	stfd	f2,152(r1)		# stores f2
 +	stfd	f3,160(r1)		# stores f3
 +
 +	lis		CCOO, 0xCC00
 +	lhz		MP3PROT, 0x4010(CCOO)
 +	ori		r21, MP3PROT, 0xFF
 +	sth		r21, 0x4010(CCOO) # disable MP3 memory protection
 +
 +_check_state:
 +	lis		STATE, state@h
 +	ori		STATE, STATE, state@l
 +	lwz		r5, 0(STATE)
 +	cmpwi	r5, 0
 +	bne- _setvalues
 +
 +_init_exceptions:
 +	# 4,3,5,17 are trampled
 +	lis		r4,bphandler@h
 +	ori		r4,r4,bphandler@l
 +	lis		r3,0x8000
 +	ori		r3,r3,0x300			# bprw  0x80000300
 +	bl  writebranch
 +
 +	addi	r3,r3,0xA00			# trace 0x80000D00
 +	bl	writebranch
 +
 +	addi	r3,r3,0x600			# bpx   0x80001300
 +	bl	writebranch
 +
 +	li		r5, 1
 +	stw		r5, 0(STATE)		# set state to 1 (exception handling linked)
 +
 +_setvalues:
 +	li		ZEROVAL,0
 +	li		CRCHECK,0x19
 +	li		EXIPORT,0xD0
 +	lis		CDOO,0xCD00
 +
 +	lis		FROZENVAL, frozenvalue@h
 +	ori		FROZENVAL, FROZENVAL, frozenvalue@l	# read buffer just store in lowmem
 +	lwz		r0,172(r1)				# loads lr
 +	#stw	r0,4(r18)				# stores lr
 +	stw		r0,4(FROZENVAL)			# stores lr
 +	stw		ZEROVAL, 0x643C(CDOO)	# exi speed up
 +
 +frozen:
 +	bl	exireceivebyte
 +	beq	finish					# r3 returns 1 or 0, one for byte received ok
 +
 +checkcommand:
 +	cmpwi	RECVBYTE, 0x04		# checks if 8/16/32 bits write command
 +	bge _nextcommand
 +	cmpwi	RECVBYTE, 0x01
 +	blt finish
 +	b   writedword				#write value to address
 +_nextcommand:
 +	beq	readmem
 +	cmpwi	RECVBYTE, 0x06
 +	beq	freezegame
 +	cmpwi	RECVBYTE, 0x07
 +	beq	unfreezegame
 +	cmpwi	RECVBYTE, 0x08
 +	beq	resumegame
 +	cmpwi	RECVBYTE, 0x09
 +	beq	breakpoints		#ibp
 +	cmpwi	RECVBYTE, 0x10
 +	beq	breakpoints		#dbp
 +	cmpwi	RECVBYTE, 0x2F
 +	beq	upbpdata
 +	cmpwi	RECVBYTE, 0x30
 +	beq	getbpdata
 +	cmpwi	RECVBYTE, 0x38
 +	beq	cancelbreakpoints
 +	cmpwi	RECVBYTE, 0x41
 +	beq	uploadcode
 +	cmpwi	RECVBYTE, 0x44
 +	beq	breakpoints #step
 +	cmpwi	RECVBYTE, 0x50
 +	beq	pausestatus
 +	cmpwi	RECVBYTE, 0x89
 +	beq	breakpoints #aligned dbp
 +	cmpwi	RECVBYTE, 0x99
 +	beq	versionnumber
 +	b	finish
 +
 +#******************************************************************
 +#						subroutine: getpausestatus:
 +#				zero  running, one  paused, two  on a breakpoint
 +#******************************************************************
 +
 +pausestatus:
 +	lwz		r3,0(FROZENVAL)
 +	bl  exisendbyte
 +	b   finish
 +
 +
 +#******************************************************************
 +#						subroutine: freezegame:
 +#				Write a 1 to a memory location to freeze
 +#******************************************************************
 +
 +freezegame:
 +	li		r4, 1
 +	stw		r4, 0(FROZENVAL)
 +	b   finish
 +
 +#******************************************************************
 +#						subroutine: unfreezegame:
 +#				Write a 0 to a memory location to unfreeze
 +#******************************************************************
 +
 +unfreezegame:
 +	stw		ZEROVAL, 0(FROZENVAL)
 +	b   resumegame
 +
 +#******************************************************************
 +#						subroutine: upload bp data:
 +#				receive the dp databuffer from the PC
 +#******************************************************************
 +
 +upbpdata:
 +	bl  exisendbyteAA
 +
 +	li		r16, 40*4				# 40 "registers rN" * 4
 +	lis		r12, regbuffer@h
 +	ori		r12, r12, regbuffer@l
 +	b   upload
 +
 +#******************************************************************
 +#						subroutine: getbp data:
 +#				send the dp databuffer to the PC
 +#******************************************************************
 +
 +getbpdata:
 +	li		r3, 72*4				# register buffer
 +	lis		r12, regbuffer@h
 +	ori		r12, r12, regbuffer@l
 +	bl  exisendbuffer			# send it, less than a packet
 +	b   finish
 +
 +
 +#******************************************************************
 +#						subroutine: breakpoints:
 +#				handles data/instruction address breakpoints
 +#******************************************************************
 +
 +breakpoints:
 +
 +	cmpwi	cr6,RECVBYTE,0x10		# 0x10=instruction, 0x09/0x89=data
 +	cmpwi	cr5,RECVBYTE,0x44		# 0x44=step
 +
 +	lis r4, bphandler@h
 +	ori	r4,r4,bphandler@l	#used for writebranch (=source address)
 +
 +	lis	r3,0x8000
 +	ori	r3,r3,0x300			# bprw  0x80000300
 +	bl	writebranch
 +
 +	addi r3,r3,0xA00		# trace 0x80000D00
 +	bl	writebranch
 +
 +	addi r3,r3,0x600		# bpx   0x80001300
 +	bl	writebranch
 +
 +	lis r12, bpbuffer@h
 +	ori	r12, r12, bpbuffer@l	# read buffer just store in lowmem
 +
 +	stw	ZEROVAL,0(r12)		# clears inst bp
 +	stw	ZEROVAL,4(r12)		# clears data bp
 +	stw	ZEROVAL,8(r12)		# clears alignement
 +
 +	lis r4, regbuffer@h
 +	ori	r4, r4, regbuffer@l
 +	lwz	r9,0x18(r4)			# srr1
 +
 +	lwz	r3,0(FROZENVAL)
 +	cmpwi	r3,2		# checks if the gecko is on a breakpoint
 +	;bne	+12
 +	;beq	cr5,+12
 +	bne p12
 +	beq cr5, p12_2
 +	b	bp
 +p12:
 +	li	r3,0
 +p12_2:
 +	stw	r3,12(r12)			# if not, clears the previous "broken on" address
 +	bne	bp
 +
 +	bne	cr5,bp
 +	ori	r9,r9,0x400
 +	stw	r9,0x18(r4)			# srr1 |= 0x400			# set SE (single step)
 +	b	unfreezegame
 +
 +bp:
 +	rlwinm	r9,r9,0,22,20
 +	stw	r9,0x18(r4)			# srr1 &= 0xfffffbff	# clear SE (single step)
 +	beq	cr5,finish
 +	;beq	cr6,+8
 +	beq cr6, p8
 +	addi r12,r12,4			# if databp r12=r12+4
 +
 +p8:
 +	li	r3, 4				# 4 bytes
 +	bl	exireceivebuffer
 +
 +	ble	cr6,noalignement	# if not aligned data bp (0x89)
 +
 +	addi	r12,r12,4
 +
 +	li	r3, 4				# 4 bytes
 +	bl	exireceivebuffer
 +
 +noalignement:
 +	lis r4, bpbuffer@h
 +	ori	r4, r4, bpbuffer@l	# read buffer just store in lowmem
 +
 +	lwz	r3, 0(r4)			# inst bp
 +	lwz	r4, 4(r4)			# data bp
 +	mtspr	1010, r3		# set IABR
 +	mtspr	1013, r4		# set DABR
 +	b	finish
 +
 +#******************************************************************
 +#						subroutine: bphandler
 +#	Data/Instruction address breakpoint handler, save context and return
 +#******************************************************************
 +
 +#FIXME
 +bphandler:
 +	mtsprg	2,r1			# sprg2 = r1
 +	lis r1, regbuffer@h
 +	ori r1, r1, regbuffer@l
 +	mtsprg	3,r3			# sprg3 = r3
 +	mfsrr1	r3				# r3=srr1
 +	rlwinm	r3,r3,0,22,20		# clear trace
 +	xoris	r1, r1, 0x8000		# ensure physical address
 +	stw r3, 0x18(r1)
 +	rlwinm	r3,r3,0,24,15
 +	ori	r3,r3,0x2000
 +	mfsrr0	r1				# r1=srr0
 +
 +#	rlwinm	r3,r3,0,17,15		# clear hw interrupt
 +	mtsrr1	r3			# restore srr1 with hw interrupt & trace cleared
 +
 +	lis	r3,break@h
 +	ori	r3,r3,break@l
 +	mtsrr0	r3
 +	rfi
 +
 +break:
 +	lis	r3, regbuffer@h
 +	ori	r3, r3, regbuffer@l
 +	stw	r1,0x14(r3)		#stores srr0
 +
 +	mr	r1,r3
 +	mfsprg	r3,3
 +	stmw	r2,0x24(r1)		#saves r2-r31
 +	mr	r4,r1
 +	mfsprg	r1,2
 +
 +	stw	r0,0x1C(r4)
 +	stw	r1,0x20(r4)
 +
 +	mflr	r3
 +	stw	r3, 0x9C(r4)		# Store LR
 +
 +	mfcr	r3
 +	stw	r3, 0x0(r4)		# Store CR
 +
 +	mfxer	r3
 +	stw	r3, 0x4(r4)		# Store XER
 +
 +	mfctr	r3
 +	stw	r3, 0x8(r4)		# Store CTR
 +
 +	mfdsisr	r3
 +	stw	r3, 0xC(r4)		# Store DSISR
 +
 +	mfdar	r3
 +	stw	r3, 0x10(r4)	# Store DAR
 +
 +	li	r9,0
 +	mtspr	1010,r9		# Clear IABR
 +	mtspr	1013,r9		# Clear DABR
 +
 +	lis r5,floatstore@h
 +	ori r5,r5,floatstore@l # Set r5 to instruction address
 +	lis r31,0xD004
 +	ori r31,r31,0x00A0 # Set r31 to 'stfs f0,0xA0(r4)' (==0xD00400A0)
 +floatloop:
 +	stw r31,0(r5)
 +	dcbst r0,r5
 +	sync
 +	icbi r0,r5
 +	isync
 +floatstore:
 +	stfs	f0,0xA0(r4)
 +	addi r31,r31,4			# Advance instruction offset
 +	addis r31,r31,0x20		# Advance instruction register
 +	rlwinm. r16,r31,0,5,5	# Check for register > 31
 +	beq floatloop
 +
 +skip_floating_point:
 +
 +	lis r5, bpbuffer@h
 +	ori	r5,r5,bpbuffer@l
 +
 +	lwz	r16,0(r5)			# inst bp
 +	lwz	r17,4(r5)			# data bp
 +	lwz	r19,12(r5)			# counter for alignment
 +
 +	cmpwi	r19,0
 +	beq	_redobp
 +
 +	cmpwi	r19,2
 +	;bne	+24
 +	bne p24
 +	lwz	r9,0x14(r4)
 +	addi	r9,r19,3
 +	stw	r9,0(r5)			# inst bp
 +	stw	r9,12(r5)			# counter for alignment
 +	b	_executebp
 +
 +p24:
 +	cmpw	r16,r19
 +	beq	_step
 +
 +	cmpw	r17,r19
 +	beq	_step
 +
 +	add	r9,r16,r17
 +	stw	r9,12(r5)		# counter for alignment
 +
 +
 +_alignementcheck:
 +	lwz	r16,8(r5)		# bp alignment check
 +	cmpwi	r16,0
 +	beq	_executebp		# no alignement = normal break
 +
 +	lwz	r3,0x10(r4)
 +	cmpw	r16,r3		# we check if address = aligned address
 +	bne	_step			# if no, we need to set a bp on the next instruction
 +
 +	li	r16,0
 +	stw	r16,8(r5)		# if we are on the good address we clear the aligned bp check
 +	b	_executebp		# and we break
 +
 +_step:
 +	li	r17,0
 +	stw	r17,12(r5)		# counter for alignment
 +	lwz	r9,0x18(r4)
 +	ori	r9,r9,0x400
 +	stw	r9,0x18(r4)
 +	b	_skipbp			#and we don't break right now
 +
 +_redobp:
 +	mtspr	1010,r16		# we set back the instbp with the original value
 +	mtspr	1013,r17		# we set back the databp with the original value
 +	li	r9,1
 +	stw	r9,12(r5)			# counter for alignment
 +	b	_skipbp				# and we don't break
 +
 +_executebp:
 +	li	r5, 2
 +	;TODO check FROZENVAL vs r4 in other
 +	lis FROZENVAL, frozenvalue@h
 +	ori	FROZENVAL, FROZENVAL, frozenvalue@l	# Freeze once returned to let user know there is a breakpoint hit
 +	stw	r5, 0(FROZENVAL)
 +
 +# NOT NEEDED BY MEGAZIG
 +#	li	r3, 0x11
 +#	bl	exisendbyte		# tell the PC a bp has happened (send 0x11)
 +#
 +	nop
 +	nop
 +
 +	bl	_codehandler_start			# bl mainloop, so you can set up a new breakpoint.
 +
 +_skipbp:
 +	mfmsr	r1
 +	rlwinm	r1,r1,0,31,29
 +	rlwinm	r1,r1,0,17,15
 +	mtmsr	r1			# we disable the interrupt so nothing interfers with the restore
 +
 +	lis r1, regbuffer@h
 +	ori	r1, r1, regbuffer@l
 +
 +	lwz	r3,0x0(r1)
 +	mtcr	r3			# restores CR
 +	lwz	r3,0x14(r1)
 +	mtsrr0	r3			# restores SRR0
 +	lwz	r3,0x18(r1)
 +	mtsrr1	r3			# restores SRR1
 +	lwz	r3,0x9C(r1)
 +	mtlr	r3			# restores LR
 +
 +	lmw	r2,0x24(r1)		# restores r2-r31
 +
 +	lwz	r0,0x1C(r1)		# restores r0
 +	lwz	r1,0x20(r1)		# restores r1
 +
 +	rfi				# back to the game
 +
 +#******************************************************************
 +#						subroutine: write dword:
 +#				Write a long word value to memory sent from PC
 +#******************************************************************
 +
 +writedword:
 +	cmpwi	cr5,RECVBYTE,2
 +	li	r3, 8			# 8 bytes (location 4 / Value 4)
 +
 +	lis r12, dwordbuffer@h
 +	ori	r12, r12, dwordbuffer@l	# buffer
 +	bl	exireceivebuffer
 +
 +	lwz	r5, 0(r12)
 +	lwz	r3, 4(r12)		# read the value
 +	stb	r3, 0(r5)		# write to location
 +	blt	cr5,skipp
 +	sth	r3, 0(r5)		# write to location
 +	beq	cr5,skipp
 +	stw	r3, 0(r5)		# write to location
 +skipp:
 +	dcbf	r0, r5		# data cache block flush
 +	sync
 +	icbi	r0, r5
 +	isync
 +	b	finish
 +
 +#******************************************************************
 +#						subroutine: Upload :
 +#						Fill memory with value
 +#******************************************************************
 +
 +uploadcode:
 +	bl	exisendbyteAA
 +
 +	li	r3, 8			# 8 bytes
 +	lis r12, dwordbuffer@h
 +	ori	r12, r12, dwordbuffer@l	# buffer
 +
 +	bl	exireceivebuffer
 +
 +	lwz	r16, 4(r12)
 +	lwz	r12, 0(r12)
 +
 +upload:
 +	lis REMAINDER, rem@h
 +	ori	REMAINDER, REMAINDER, rem@l		# Remainder of bytes upload code
 +	li	r17,0xF80
 +	bl	_packetdivide
 +	beq	douploadremainder
 +
 +nextrecpacket:
 +	mr	r3,r17
 +	bl	exireceivebuffer	# r12 start = start of buffer
 +
 +uploadwait:
 +	bl	exisendbyteAA
 +	beq	uploadwait
 +	add	r12,r12,r14
 +
 +	subic.	r11, r11, 1		# decrease loop counter
 +	bgt	nextrecpacket
 +
 +douploadremainder:			# send the remainder bytes
 +	lwz	r3, 0(REMAINDER)	# remainder
 +	cmpwi	r3,0
 +	beq	finishupload
 +	bl	exireceivebuffer
 +finishupload:
 +	dcbf	r0, r12		# data cache block flush
 +	sync
 +	icbi	r0, r12		# instruction cache block flush
 +	isync
 +	b	finish
 +
 +#******************************************************************
 +#			subroutine: exireceivebyte:
 +#		 Return 1(r3) if byte receive, 0(r3) if no byte
 +#		 Command byte is stored at 0x800027ff
 +#******************************************************************
 +
 +exireceivebyte:
 +	mflr	TEMPLR
 +	lis	r3, 0xA000		# EXI read command
 +
 +	bl checkexisend
 +
 +	andis.	r3, r16, 0x800
 +	rlwinm	RECVBYTE,r16,16,24,31
 +	mtlr	TEMPLR
 +	blr
 +
 +#******************************************************************
 +#						subroutine: checkexisend:
 +#
 +#******************************************************************
 +
 +checkexisend:
 +
 +	stw	EXIPORT, 0x6814(CDOO)		# 32mhz Port B
 +	stw	r3, 0x6824(CDOO)
 +	stw	CRCHECK, 0x6820(CDOO)	  # 0xCC006820 (Channel 1 Control Register)
 +
 +exicheckreceivewait:
 + 	lwz	r5, 0x6820(CDOO)
 +	andi.	r5, r5, 1
 +	bne	exicheckreceivewait	# while((exi_chan1cr)&1);
 +
 +	lwz	r16, 0x6824(CDOO)
 +	stw	r5, 0x6814(CDOO)
 +
 +	blr
 +
 +#******************************************************************
 +#						subroutine: exireceivebuffer:
 +#  r3 byte counter, r12 points to buffer, r3 gets copied as gets destroyed
 +#******************************************************************
 +
 +exireceivebuffer:
 +	mflr	r10			# save link register
 +	mtctr	r3			# counter
 +	li	r14,0
 +
 +bufferloop:
 +	bl	exicheckreceive
 +	bl	exicheckreceive
 +	bl	exireceivebyte
 +	beq	bufferloop		# r3 returns 1 or 0, one for byte received ok
 +
 +	stbx	RECVBYTE, r14,r12		# store byte into buffer
 +
 +	addi	r14, r14, 1		# increase buffer by 1
 +	bdnz	bufferloop
 +
 +	mtlr	r10			# retore link register
 +	blr					# return to command check
 +
 +#******************************************************************
 +#						exisendbuffer:
 +#  r3 byte counter, r12 points to buffer, r3 gets copied as gets destroyed
 +#******************************************************************
 +
 +exisendbuffer:
 +	mflr	r10			# save link register
 +	mtctr	r3			# r3->counter
 +	li	r14,0
 +
 +sendloop:
 +	bl  exichecktx
 +	beq sendloop
 +	lbzx	r3, r12,r14
 +	bl	exisendbyte
 +	beq	sendloop
 +
 +	addi	r14, r14, 1		# increase buffer
 +	bdnz	sendloop
 +	mtlr	r10			# restore link register
 +	blr
 +
 +#******************************************************************
 +#						exisendbyte:12345678
 +#  r3 byte to send, returns 1 if sent, 0 if fail (!!! called by breakpoint)
 +#******************************************************************
 +exisendbyteAA:
 +	li	r3,0xAA
 +
 +exisendbyte:					# r3, send value
 +	mflr	TEMPLR
 +	slwi	r3, r3, 20			# (sendbyte<<20);
 +	oris	r3, r3, 0xB000		# 0xB0000000 | (OR)
 +	#TODO why am I missing?
 +	li	r22,0x19			# already done in _setvals
 +	li	r23,0xD0			# already done in _setvals
 +	lis	r24,0xCD00			# already done in _setvals
 +
 +	bl checkexisend
 +
 +	extrwi.  r3, r16, 1,5		# returns either 0 or 1, one for byte received ok
 +	mtlr	TEMPLR
 +	blr
 +
 +#******************************************************************
 +#						subroutine: exicheckrecieve:
 +#		 Return 1(r3) if byte receive, 0(r3) if no byte
 +#******************************************************************
 +
 +exicheckreceive:
 +	mflr	TEMPLR
 +exicheckreceive2:
 +	lis	r3, 0xD000		# EXI check status command
 +
 +	bl checkexisend
 +
 +	rlwinm.	r3,r16,6,31,31		# returns either 0 or 1 for r3
 +
 +	beq	 exicheckreceive2
 +	mtlr	TEMPLR
 +	blr
 +
 +#******************************************************************
 +#				subroutine: exichecktx:
 +#		Return 1 if ok to send, 0 if not
 +#******************************************************************
 +exichecktx:
 +	mflr	r30
 +	lis r3, 0xC000
 +	; TODO yet I'm here
 +	li  r22, 0x09
 +	li  r23, 0xD0
 +	lis r24, 0xCD00
 +
 +	bl checkexisend
 +
 +	extrwi. r3, r16, 1,5		# returns either 0 or 1, one for byte received ok
 +	mtlr	r30
 +	blr
 +
 +#******************************************************************
 +#				Readmem: (reads a memory range back to PC)
 +#				r3 byte to send, returns 1 if sent, 0 if fail
 +#******************************************************************
 +
 +readmem:
 +	bl	exisendbyteAA
 +
 +	li	r3, 8						# 8 bytes
 +	lis r12, dwordbuffer@h
 +	ori	r12, r12, dwordbuffer@l		# buffer
 +
 +	bl	exireceivebuffer
 +
 +	lwz	r5, 4(r12)
 +	lwz	r12, 0(r12)
 +
 +	lis REMAINDER, rem@h
 +	ori	REMAINDER, REMAINDER, rem@l	# place holder for remainder bytes
 +
 +	ori	r17, ZEROVAL, 0xF800		# 64K packet
 +	sub	r16, r5, r12				# memrange = (*endlocation - *startlocation)
 +
 +	bl	_packetdivide
 +
 +nextsendpacket:
 +	bgt	transfer			#compares r11 and 0
 +	lwz	r17, 0(REMAINDER)	# remainder
 +	cmpwi	r17,0
 +	beq	finish
 +transfer:
 +	mr	r3,r17				# number of bytes
 +	bl	exisendbuffer
 +
 +bytewait1:
 +	bl	exicheckreceive
 +	bl	exicheckreceive
 +	bl	exireceivebyte
 +	beq	bytewait1			# r3 returns 1 or 0, one for byte received ok
 +	cmpwi	RECVBYTE, 0xCC	# cancel code
 +	beq	finish
 +	cmpwi	RECVBYTE, 0xBB	# retry code
 +	beq	transfer
 +	cmpwi	RECVBYTE, 0xAA
 +	bne	bytewait1
 +	add	r12,r12,r14
 +	subic.	r11, r11, 1		# decrease loop counter
 +	blt	finish
 +	b	nextsendpacket
 +
 +#******************************************************************
 +#				Cancel Breakpoints
 +#				Clears instruction and data and step breakpoints
 +#******************************************************************
 +
 +cancelbreakpoints:
 +	mtspr	1013, ZEROVAL		# clear the DABR
 +	mtspr	1010, ZEROVAL		# clear the IABR
 +	lis		r4, regbuffer@h
 +	ori		r4, r4, regbuffer@l
 +	lwz		r9,0x18(r4)
 +	rlwinm	r9,r9,0,22,20
 +	stw		r9,0x18(r4)			# srr1 &= ~(1<<12)	# clear SE bit
 +	b finish
 +
 +#******************************************************************
 +#					subroutine: version number
 +#				Sends back the current gecko version number.
 +#******************************************************************
 +
 +versionnumber:
 +	li	r3, 0x80		# 0x80 = Wii, 0x81 = NGC
 +	bl	exisendbyte
 +	#b	finish
 +
 +#******************************************************************
 +#				Finish
 +#		Check if the gecko has been paused. if no return to game
 +#******************************************************************
 +
 +finish:
 +	lwz	r4, 0(FROZENVAL)
 +	cmpwi	r4, 0		# check to see if we have frozen the game
 +	bne	frozen			# loop around if we have
 +						# (changed to return for the bp)
 +
 +resumegame:
 +
 +	sth MP3PROT,0x4010(CCOO) # restore memory protection value
 +
 +	lfd	f2,152(r1)		# loads f2
 +	lfd	f3,160(r1)		# loads f3
 +
 +	mtmsr	MSR
 +
 +	lwz	r0,172(r1)
 +	mtlr	r0			# restores lr
 +
 +	lwz	r0,12(r1)
 +	mtcr	r0			# restores cr
 +
 +	lwz	r0,16(r1)
 +	mtctr	r0			# restores ctr
 +
 +	lwz	r0,20(r1)
 +	mtxer	r0			# restores xer
 +
 +	lmw	r3,24(r1)		# restores r3-r31
 +
 +	lwz	r0,8(r1)		# loads r0
 +
 +	addi	r1,r1,168
 +
 +	isync
 +
 +	blr					# return back to game
 +
 +#******************************************************************
 +#						Write branch
 +#	r3 - source (our mastercode location)
 +#	r4 - destination (lowmem area 0x80001800 address which will branch to
 +#	volatile: r17, r5
 +#******************************************************************
 +writebranch:
 +
 +	subf	r17, r3, r4		# subtract r3 from r4 and place in r17
 +	lis	r5, 0x4800			# 0x48000000
 +	rlwimi	r5,r17,0,6,29
 +	stw	r5, 0(r3)			# result in r3
 +
 +	dcbf	r0, r3			# data cache block flush
 +	sync
 +	icbi	r0, r3
 +	isync
 +
 +	blr						# return
 +
 +
 +
 +#******************************************************************
 +#						Packet Divide
 +#  Used by the down/up routines to calculate the number of packet to send
 +#******************************************************************
 +
 +_packetdivide:
 +	divw.	r11, r16, r17		# fullpackets = memrange / 0xF80 (r11 is full packets)
 +	mullw	r10, r11, r17
 +	subf	r10, r10, r16		# r10 holds remainder byte counter
 +	stw	r10, 0(REMAINDER)		# store remainder
 +	blr
 +
 +#==================================================================
 +
 +frozenvalue:	#frozen value, then LR
 +.long	0,0
 +dwordbuffer:
 +.long	0,0
 +rem:
 +.long	0
 +bpbuffer:
 +.long 0		#inst address to bp on
 +.long 0		#data address to bp on
 +.long 0		#alignement check
 +.long 0		#counter for alignement / previous broken on address
 +
 +regbuffer:
 +.space 72*4
 +
 +state:
 +.long 0			# 0=none 1=linked 2=???
 +
 +.align 4
 +
 +codelist:
 +.space 2*4
 +.end
 +
 | 
