summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/bossMegaGoomba.cpp141
-rw-r--r--src/codehandler.obin0 -> 5772 bytes
-rwxr-xr-xsrc/codehandler.real.s821
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.o
new file mode 100644
index 0000000..d14757e
--- /dev/null
+++ b/src/codehandler.o
Binary files differ
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
+
+