diff options
| author | Stephen Simpson <megazig@gmail.com> | 2011-10-10 22:16:35 -0500 | 
|---|---|---|
| committer | Stephen Simpson <megazig@gmail.com> | 2011-10-10 22:16:35 -0500 | 
| commit | 1bf7f8a471746eef9badf5f37031da6f8d88e9a2 (patch) | |
| tree | 03e4e62a435d88e5fd8d9dda2d9cc848e5a16af1 /src | |
| parent | a61758720db96f59e0fb82aab9f326d37e186a11 (diff) | |
| download | kamek-1bf7f8a471746eef9badf5f37031da6f8d88e9a2.tar.gz kamek-1bf7f8a471746eef9badf5f37031da6f8d88e9a2.zip | |
added ability to link in .o files
tweeked MountainGoombas Launch state for always arcing up
added two more goomba types to the Launch state
added in codehandler. bp not working, but rest seems functional
Diffstat (limited to '')
| -rw-r--r-- | src/bossMegaGoomba.cpp | 141 | ||||
| -rw-r--r-- | src/codehandler.o | bin | 0 -> 5772 bytes | |||
| -rwxr-xr-x | src/codehandler.real.s | 821 | 
3 files changed, 931 insertions, 31 deletions
| diff --git a/src/bossMegaGoomba.cpp b/src/bossMegaGoomba.cpp index 65bbdb2..e6c2b0b 100644 --- a/src/bossMegaGoomba.cpp +++ b/src/bossMegaGoomba.cpp @@ -14,7 +14,6 @@ class daMegaGoomba_c : public dEn_c {  	m3d::mdl_c bodyModel;  	float timer; -	nw4r::ut::Rect Bounding;  	float dying;  	HermiteKey keysX[0x10]; @@ -25,6 +24,35 @@ class daMegaGoomba_c : public dEn_c {  //	unsigned int Zkey_count;  	char life; + +	//TODO use these for MegaGecko testing of params +	u32 marker1_start; +	nw4r::ut::Rect Bounding; +	u32 marker1_end; +	u32 marker2_start; +	int pickedChoice; +	u32 marker2_end; +	u32 marker3_start; +	float XSpeed; +	u32 marker3_end; +	u32 marker4_start; +	float JumpHeight; +	u32 marker4_end; +	u32 marker5_start; +	float JumpDist; +	u32 marker5_end; +	u32 marker6_start; +	float JumpTime; +	u32 marker6_end; +	u32 marker7_start; +	int playIt; +	u32 marker7_end; +	u32 marker8_start; +	int toPlay; +	u32 marker8_end; +	u32 marker9_start; +	u32 marker9_end; +  	bool takeHit(char count);  	void dieFall_Execute(); @@ -192,18 +220,45 @@ int daMegaGoomba_c::onCreate() {  	this->aPhysics.initWithStruct(this, &HitMeBaby);  	this->aPhysics.addToList(); -	pos.y -= 20.0; +	pos.y -= 16.0;  	pos.z = 3000.0;  	rot.x = rot.y = rot.z = speed.x = dying = 0.0;  	direction = 0;  	life = 3;  	//TODO 1) allow setting bounding rect with settings  	//TODO 2) don't use bounding rect. use wall/floor/ceiling detection -	Bounding.left = pos.x - 350.0; +	Bounding.left = pos.x - 212.0;  	Bounding.top = pos.y + 500.0; -	Bounding.right = pos.x + 350.0; +	Bounding.right = pos.x + 212.0;  	Bounding.bottom = pos.y; +	//TODO for tests +	this->marker1_start = 0xaabbcc11; +	this->marker1_end = 0xaabbff11; +	this->marker2_start = 0xaabbcc12; +	this->marker2_end = 0xaabbff12; +	this->marker3_start = 0xaabbcc13; +	this->marker3_end = 0xaabbff13; +	this->marker4_start = 0xaabbcc14; +	this->marker4_end = 0xaabbff14; +	this->marker5_start = 0xaabbcc15; +	this->marker5_end = 0xaabbff15; +	this->marker6_start = 0xaabbcc16; +	this->marker6_end = 0xaabbff16; +	this->marker7_start = 0xaabbcc17; +	this->marker7_end = 0xaabbff17; +	this->marker8_start = 0xaabbcc18; +	this->marker8_end = 0xaabbff18; +	this->marker9_start = 0xaabbcc19; +	this->marker9_end = 0xaabbff19; +	this->pickedChoice = -1; +	this->XSpeed = 2.0;		// GOOD FOR FINAL SPEED? +	this->JumpHeight = 48.0; +	this->JumpDist = 64.0; +	this->JumpTime = 50.0; +	this->playIt = 0; +	this->toPlay = 0; +  	OSReport("Setting MegaGoomba's State\n");  	doStateChange(&StateID_Grow); @@ -241,21 +296,23 @@ int daMegaGoomba_c::onDraw() {  void daMegaGoomba_c::updateModelMatrices() {  	// Bounds checking  	// TODO possibly change to a state change -	if(this->pos.x < this->Bounding.left) { -		this->direction = !this->direction; -		this->speed.x = -this->speed.x; -		this->pos.x = this->Bounding.left; -	} else if (this->pos.x > this->Bounding.right) { -		this->direction = !this->direction; -		this->speed.x = -this->speed.x; -		this->pos.x = this->Bounding.right; -	} -	if(this->pos.y < this->Bounding.bottom) { -		this->speed.y = 0.0; -		this->pos.y = this->Bounding.bottom; -	} else if (this->pos.y > this->Bounding.top) { -		this->speed.y = 0.0; -		this->pos.y = this->Bounding.bottom; +	if(this->life > 0) { +		if(this->pos.x < this->Bounding.left) { +			this->direction = !this->direction; +			this->speed.x = -this->speed.x; +			this->pos.x = this->Bounding.left; +		} else if (this->pos.x > this->Bounding.right) { +			this->direction = !this->direction; +			this->speed.x = -this->speed.x; +			this->pos.x = this->Bounding.right; +		} +		if(this->pos.y < this->Bounding.bottom) { +			this->speed.y = 0.0; +			this->pos.y = this->Bounding.bottom; +		} else if (this->pos.y > this->Bounding.top) { +			this->speed.y = 0.0; +			this->pos.y = this->Bounding.bottom; +		}  	}  	// This won't work with wrap because I'm lazy. @@ -345,22 +402,34 @@ void daMegaGoomba_c::executeState_Launch() {  		this->rot.y = sin(this->timer * 3.14 / 5) * 4000;  		dStageActor_c *spawner = NULL; -		// 120ticks /  40numbers * 2cases  = 6avg kuribo -		int randChoice = GenerateRandomNumber(40); +		// 120ticks /  80numbers * 4cases  = 6avg kuribo +		int randChoice = GenerateRandomNumber(80);  		int randChoiceX = GenerateRandomNumber(12); -		int randChoiceY = GenerateRandomNumber(12); +		int randChoiceY = GenerateRandomNumber(7);  		switch(randChoice) {  			case 0:  			case 1:  				spawner = CreateActor(EN_KURIBO, 0, this->pos, 0, 0);  				spawner->speed.x = randChoiceX - 6.0; -				spawner->speed.y = randChoiceY * 1.0; +				spawner->speed.y = randChoiceY + 3.0;  				spawner->scale = (Vec){1.0, 1.0, 1.0};  				break;  			case 2:  				spawner = CreateActor(EN_BEANS_KURIBO, 0, this->pos, 0, 0); -				spawner->speed.x = randChoiceX - 12.0; -				spawner->speed.y = randChoiceY * 1.0; +				spawner->speed.x = randChoiceX - 6.0; +				spawner->speed.y = randChoiceY + 3.0; +				spawner->scale = (Vec){1.0, 1.0, 1.0}; +				break; +			case 3: +				spawner = CreateActor(EN_PATA_KURIBO, 0, this->pos, 0, 0); +				spawner->speed.x = randChoiceX - 6.0; +				spawner->speed.y = randChoiceY + 3.0; +				spawner->scale = (Vec){1.0, 1.0, 1.0}; +				break; +			case 4: +				spawner = CreateActor(EN_MAME_KURIBO, 0, this->pos, 0, 0); +				spawner->speed.x = randChoiceX - 6.0; +				spawner->speed.y = randChoiceY + 3.0;  				spawner->scale = (Vec){1.0, 1.0, 1.0};  				break;  			default: @@ -380,9 +449,9 @@ void daMegaGoomba_c::beginState_Jump() {  	this->timer = 1.0;  	//Variables for choosing a curve -	float jump_height = 36.0; -	float delta = (this->direction) ? -24.0 : 24.0; -	float fullTime = 90.0; +	float jump_height = this->JumpHeight; +	float delta = (this->direction) ? -JumpDist : JumpDist; +	float fullTime = this->JumpTime;  	//Key count  	Xkey_count = 2;  	Ykey_count = 3; @@ -404,7 +473,7 @@ void daMegaGoomba_c::executeState_Jump() {  	this->pos.x = GetHermiteCurveValue(this->timer, this->keysX, Xkey_count);  	this->pos.y = GetHermiteCurveValue(this->timer, this->keysY, Ykey_count); -	float TimerMax = 91.0; +	float TimerMax = JumpTime + 1.0;  	if (this->timer > TimerMax) {  		doStateChange(&StateID_Walk);  	} @@ -423,14 +492,24 @@ void daMegaGoomba_c::beginState_Walk() {  }  void daMegaGoomba_c::executeState_Walk() {  -	float delta = (this->direction) ? -0.5 : 0.5; +	float delta = (this->direction) ? -this->XSpeed : this->XSpeed;  	this->pos.x += delta;  	int Choice;  	float TimerMax = 150.0;  	if (this->timer > TimerMax) { -		Choice = GenerateRandomNumber(4); +		if(this->pickedChoice != -1) { +			Choice = this->pickedChoice; +			/* +			if(this->playIt = 1) { +				playSound(this->toPlay); +				this->playIt = 0; +			} +			*/ +		} else { +			Choice = GenerateRandomNumber(4); +		}  		switch(Choice) {  			case 0:  				doStateChange(&StateID_Jump); diff --git a/src/codehandler.o b/src/codehandler.oBinary files differ new file mode 100644 index 0000000..d14757e --- /dev/null +++ b/src/codehandler.o diff --git a/src/codehandler.real.s b/src/codehandler.real.s new file mode 100755 index 0000000..37d7df5 --- /dev/null +++ b/src/codehandler.real.s @@ -0,0 +1,821 @@ +# 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
 +
 +.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
 +	 
 +.globl _start
 +
 +gameid:
 +.long	0,0
 +cheatdata:
 +.long	frozenvalue
 +.space 39*4
 +
 +_start:
 +	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	r25
 +	ori	r26,r25,0x2000		#enable floating point ?
 +	andi.	r26,r26,0xF9FF
 +	mtmsr	r26
 +
 +	stfd	f2,152(r1)		# stores f2
 +	stfd	f3,160(r1)		# stores f3
 +
 +    lis r20, 0xCC00
 +    lhz r28, 0x4010(r20)
 +    ori r21, r28, 0xFF
 +    sth r21, 0x4010(r20) # disable MP3 memory protection
 +
 +_check_state:
 +	lis r31, state@h
 +	ori r31, r31, state@l
 +	lwz r31, 0(r31)
 +	cmpwi r31, 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
 +	lis r31, state@h
 +	ori r31, r31, state@l
 +	stw r5, 0(r31)			# set state to 1 (exception handling linked)
 +
 +_setvalues:
 +	li	r21,0
 +	li	r22,0x19
 +	li	r23,0xD0
 +	lis	r24,0xCD00
 +
 +	lis r18, frozenvalue@h
 +	ori	r18, r18, frozenvalue@l	# read buffer just store in lowmem
 +	lwz	r0,172(r1)				# loads lr
 +	stw	r0,4(r18)				# stores lr
 +    stw r21, 0x643C(r24)		# exi speed up
 +
 +frozen:
 +	bl	exireceivebyte
 +	beq	finish			# r3 returns 1 or 0, one for byte received ok
 +
 +checkcommand:
 +
 +	cmpwi	   r29, 0x04		# checks lf 8/1/32 bits write command
 +	bge	   _nextcommand
 +	cmpwi      r29, 0x01
 +	blt	   finish
 +	b	  writedword		#write value to address
 +_nextcommand:
 +	beq	readmem
 +	cmpwi	r29, 0x06
 +	beq	freezegame
 +	cmpwi	r29, 0x07
 +	beq	unfreezegame
 +	cmpwi	r29, 0x08
 +	beq	resumegame
 +	cmpwi	r29, 0x09
 +	beq	breakpoints		#ibp
 +	cmpwi	r29, 0x10
 +	beq	breakpoints		#dbp
 +	cmpwi	r29, 0x2F
 +	beq	upbpdata
 +	cmpwi	r29, 0x30
 +	beq	getbpdata
 +	cmpwi	r29, 0x38
 +	beq	cancelbreakpoints
 +	cmpwi	r29, 0x41
 +	beq	uploadcode
 +	cmpwi	     r29, 0x44
 +	beq	breakpoints #step
 +	cmpwi	r29, 0x50
 +	beq	pausestatus
 +	cmpwi	r29, 0x89
 +	beq	breakpoints #aligned dbp
 +	cmpwi	r29, 0x99
 +	beq	versionnumber
 +	b	finish
 +
 +#******************************************************************
 +#                        subroutine: getpausestatus:
 +#                one  running, two  paused, three  on a breakpoint
 +#******************************************************************
 +
 +pausestatus:
 +	lwz	r3,0(18)
 +	bl	exisendbyte
 +	b	finish
 +
 +
 +#******************************************************************
 +#                        subroutine: freezegame:
 +#                Write a 1 to a memory location to freeze
 +#******************************************************************
 +
 +freezegame:
 +	li	r4, 1
 +	stw	r4, 0(r18)
 +	b	finish
 +
 +#******************************************************************
 +#                        subroutine: unfreezegame:
 +#                Write a 0 to a memory location to unfreeze
 +#******************************************************************
 +
 +unfreezegame:
 +	stw	r21, 0(r18)
 +	b	resumegame
 +
 +#******************************************************************
 +#                        subroutine: upload bp data:
 +#                receive the dp databuffer from the PC
 +#******************************************************************
 +
 +upbpdata:
 +	bl	exisendbyteAA
 +
 +	li	r16, 40*4				# 42 "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,r29,0x10		# 0x10=instruction, 0x09/0x89=data
 +	cmpwi	cr5,r29,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	r21,0(r12)		# clears inst bp
 +	stw	r21,4(r12)		# clears data bp
 +	stw	r21,8(r12)		# clears alignement
 +
 +	lis r4, regbuffer@h
 +	ori	r4, r4, regbuffer@l
 +	lwz	r9,0x18(r4)
 +
 +	lwz	r3,0(r18)
 +	cmpwi	r3,2		# checks if the gecko is on a breakpoint
 +	bne	+12
 +	beq	cr5,+12
 +	b	bp
 +	li	r3,0
 +	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)
 +	b	unfreezegame
 +
 +bp:
 +	rlwinm	r9,r9,0,22,20
 +	stw	r9,0x18(r4)
 +	beq	cr5,finish
 +	beq	cr6,+8
 +	addi r12,r12,4			# if databp r12=r12+4
 +
 +	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
 +	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
 +	lwz	r9,0x14(r4)
 +	addi	r9,r19,3
 +	stw	r9,0(r5)			# inst bp
 +	stw	r9,12(r5)			# counter for alignment
 +	b	_executebp
 +
 +	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
 +	lis r4, frozenvalue@h
 +	ori	r4, r4, frozenvalue@l	# Freeze once returned to let user know there is a breakpoint hit
 +	stw	r5, 0(r4)
 +
 +	li	r3, 0x11
 +	bl	exisendbyte		# tell the PC a bp has happened (send 0x11)
 +
 +	bl	_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,r29,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 r27, rem@h
 +	ori	r27, r27, 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(r27)		# 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	r30
 +	lis	r3, 0xA000		# EXI read command
 +
 +	bl checkexisend
 +
 +	andis.	r3, r16, 0x800
 +	rlwinm	r29,r16,16,24,31
 +	mtlr	r30
 +	blr
 +
 +#******************************************************************
 +#                        subroutine: checkexisend:
 +#  
 +#******************************************************************
 +
 +checkexisend:
 +
 +	stw	r23, 0x6814(r24)		# 32mhz Port B
 +	stw	r3, 0x6824(r24)
 +	stw	r22, 0x6820(r24)	  # 0xCC006820 (Channel 1 Control Register)
 +
 +exicheckreceivewait:		
 + 	lwz	r5, 0x6820(r24)
 +	andi.	r5, r5, 1
 +	bne	exicheckreceivewait	# while((exi_chan1cr)&1);
 +
 +	lwz	r16, 0x6824(r24)
 +	stw	r5, 0x6814(r24)
 +
 +	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	r29, 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:
 +	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	r30
 +	slwi	r3, r3, 20			# (sendbyte<<20);
 +	oris	r3, r3, 0xB000		# 0xB0000000 | (OR)
 +	li	r22,0x19
 +	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
 +
 +#******************************************************************
 +#                        subroutine: exicheckrecieve:
 +#         Return 1(r3) lf byte receive, 0(r3) lf no byte
 +#******************************************************************
 +
 +exicheckreceive:
 +	mflr	r30
 +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	r30
 +	blr
 +
 +#******************************************************************
 +#                Readmem: (reads a memory range back to PC)
 +#                r3 byte to send, returns 1 lf sent, 0 lf 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 r27, rem@h
 +	ori	r27, r27, rem@l		# place holder for remainder bytes
 +	
 +	ori	r17, r21, 0xF800		# 64K packet
 +	sub	r16, r5, r12		# memrange = (*endlocation - *startlocation)
 +
 +	bl	_packetdivide
 +
 +nextsendpacket:
 +	bgt	transfer		#compares r11 and 0
 +	lwz	r17, 0(r27)		# 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	r29, 0xCC		# cancel code
 +	beq	finish
 +	cmpwi	r29, 0xBB		# retry code
 +	beq	transfer
 +	cmpwi	r29, 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, r21		# clear the DABR
 +	mtspr	1010, r21		# 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)
 +	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(r18)
 +	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 r28,0x4010(r20) # restore memory protection value
 +
 +	lfd	f2,152(r1)		# loads f2
 +	lfd	f3,160(r1)		# loads f3
 +
 +	mfmsr	r25
 +
 +	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
 +#******************************************************************
 +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(r27)		# 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
 +
 +regbuffer:
 +.space 72*4
 +
 +state:
 +.long 0			# 0=none 1=linked 2=???
 +
 +.align 3
 +
 +codelist:
 +.space 2*4
 +.end
 +
 +
 | 
