diff options
Diffstat (limited to '')
-rw-r--r-- | src/codehandler.cpp | 439 | ||||
-rw-r--r-- | src/codehandler.s | 368 |
2 files changed, 807 insertions, 0 deletions
diff --git a/src/codehandler.cpp b/src/codehandler.cpp new file mode 100644 index 0000000..b1d67d2 --- /dev/null +++ b/src/codehandler.cpp @@ -0,0 +1,439 @@ +#include <common.h> + +u8 frozen_value = 0; +u32 regbuffer[72] = {0}; +u32 dwordbuffer[2] = {0}; +u32 bpbuffer[4] = {0}; +u8 cmd; + +/*FIXME + * u32 register_to_match = 0; + * u32 register_value = 0; + * u32 bplist[40] = {0}; + */ + +#define PACKET_SIZE 0xF800 + +extern "C" void writebranch(u32 source, u32 destination); +extern "C" void bphandler(); + +// return true if remainder +bool _packetdivide(u32 memrange, u32 size, u32* full, u32* remainder) { + *full = memrange / size; + *remainder = memrange % size; + return (*remainder) ? true : false; +} + +u32 checkexisend(u32 EXI_command) { + //OSReport("checkexisend(0x%08x);\n", EXI_command); + *(u32*)0xCD006814 = 0xD0; + *(u32*)0xCD006824 = EXI_command; + *(u32*)0xCD006820 = 0x19; + + u32 exi_chan1cr = 1; + while((exi_chan1cr)&1) { + exi_chan1cr = *(u32*)0xCD006820; + exi_chan1cr &= 1; + } + + *(u32*)0xCD006814 = exi_chan1cr; + return *(u32*)0xCD006824; +} + +struct exidata { + unsigned bits0to3 : 4; + unsigned bit4 : 1; + unsigned bit5 : 1; + unsigned bit6 : 1; + unsigned bit7 : 1; + unsigned data : 8; + unsigned bottom : 16; +}; + +bool exichecktx() { + *(u32*)0xCD006814 = 0xD0; + *(u32*)0xCD006824 = 0xC0000000; + *(u32*)0xCD006820 = 0x09; + + u32 exi_chan1cr = 1; + while((exi_chan1cr)&1) { + exi_chan1cr = *(u32*)0xCD006820; + exi_chan1cr &= 1; + } + + *(u32*)0xCD006814 = exi_chan1cr; + u32 ret = *(u32*)0xCD006824; + struct exidata* dat = (exidata*)&ret; + return (dat->bit5) ? true : false; +} + +bool exireceivebyte(u8* byte) { + //OSReport("exireceivebyte()\n"); + u32 ret = checkexisend(0xA0000000); + struct exidata * dat = (exidata*)&ret; + *byte = dat->data; + return (dat->bit4) ? true : false; +} + +bool exicheckreceive() { + bool ret = false; + while(!ret) { + u32 foo = checkexisend(0xD0000000); + struct exidata* dat = (exidata*)&foo; + ret = dat->bit5; + } + return ret; +} + +void exireceivebuffer(u32 counter, u8* buffer) { + for(u32 ii=0; ii<counter; ii++) { + u8 byte; + bool ret = false; + while(!ret) { + exicheckreceive(); + exicheckreceive(); + ret = exireceivebyte(&byte); + } + buffer[ii] = byte; + } +} + +bool exisendbyte(u8 byte) { + u32 sendbyte = byte << 20; + sendbyte |= 0xB0000000; + + u32 ret = checkexisend(sendbyte); + struct exidata* dat = (exidata*)&ret; + return (dat->bit5) ? true : false; +} + +void exisendbuffer(u32 counter, u8* buffer) { + bool ret = false; + for(u32 ii=0; ii<counter; ii++) { + while(!ret) { + ret = exichecktx(); + } + ret = false; + while(!ret) { + ret = exisendbyte( buffer[ii] ); + } + //OSReport("Sent byte from buffer\n"); + } +} + +void versionnumber() { + // send 0x80 for wii + exisendbyte(0x80); +} + +void pausestatus() { + exisendbyte(frozen_value); +} + +void freezegame() { + frozen_value = 1; + //OSReport("frozen_value: %d\n", frozen_value); +} + +void unfreezegame() { + frozen_value = 0; + //OSReport("frozen_value: %d\n", frozen_value); +} + +u8 get_frozenvalue() { + return frozen_value; +} + +void writedword() { + exireceivebuffer(8, (u8*)dwordbuffer); + + u32 location = dwordbuffer[0]; + u32 value = dwordbuffer[1]; + *(u32*)location = value; + + asm("dcbf 0, %0; sync; icbi 0, %0; isync" : : "b"(location)); +} + +void writeword() { + exireceivebuffer(8, (u8*)dwordbuffer); + + u32 location = dwordbuffer[0]; + u32 value = dwordbuffer[1]; + *(u16*)location = (u16)value; + + asm("dcbf 0, %0; sync; icbi 0, %0; isync" : : "b"(location)); +} + +void writebyte() { + exireceivebuffer(8, (u8*)dwordbuffer); + + u32 location = dwordbuffer[0]; + u32 value = dwordbuffer[1]; + *(u8*)location = (u8)value; + + asm("dcbf 0, %0; sync; icbi 0, %0; isync" : : "b"(location)); +} + +//FIXME removed upload +/* +void upbpdata() { + exisendbyte(0xAA); + upload(regbuffer, 40*4); +} +*/ + +void getbpdata() { + exisendbuffer(72*4, (u8*)regbuffer); +} + +//returns false if we need to go to resume and not finish +bool breakpoints(u8 type) { + //FIXME + u32 _bphandler = (u32)bphandler; + writebranch(0x80000300, _bphandler); + writebranch(0x80000D00, _bphandler); + writebranch(0x80001300, _bphandler); + + bpbuffer[0] = 0; //clears inst bp + bpbuffer[1] = 0; //clears data bp + bpbuffer[2] = 0; //clears alignment + + u32 SRR1 = regbuffer[6]; // SRR1 + + if(frozen_value != 2) { // not on breakpoint + bpbuffer[3] = 0; // clear broken on address + }else if(type == 0x44) { // step + bpbuffer[3] = frozen_value; // set broken on address to frozen_value + if(frozen_value == 2) { + regbuffer[6] = SRR1 | 0x400; + unfreezegame(); + //FIXME need to go to resume and not finish + return false; + } + } + + //cmpwi cr6,r29,0x10 # 0x10=instruction, 0x09/0x89=data + //cmpwi cr5,r29,0x44 # 0x44=step + + regbuffer[6] = SRR1 & 0xffffbfff; + if(type != 0x44) { + u32 value1, value2; + exireceivebuffer(4, (u8*)&value1); + if(type == 0x10) { + bpbuffer[0] = value1; // instbp = value1; + }else{ + bpbuffer[1] = value1; // databp = value1; + } + + if(type == 0x89) { + exireceivebuffer(4, (u8*)&value2); + bpbuffer[2] = value2; + } + + u32 IABR = bpbuffer[0]; // IABR = instbp + u32 DABR = bpbuffer[1]; // DABR = databp + asm("mtspr 1010, %0; mtspr 1013, %1" : : "b"(IABR), "b"(DABR)); + } + return true; +} + +void cancelbreakpoints() { + u32 x = 0; + asm("mtspr 1013, %0; mtspr 1010, %0" : "=r"(x) : ); + + // clears bit 21 of SRR1 + regbuffer[6] = regbuffer[6] & 0xfffffbff; +} + +void readmem() { + exisendbyte(0xAA); + + exireceivebuffer(8, (u8*)dwordbuffer); + + u32 start_location = dwordbuffer[0]; + u32 end_location = dwordbuffer[1]; + u32 memrange = end_location - start_location; + + u32 full, remainder; + bool ret = _packetdivide(memrange, PACKET_SIZE, &full, &remainder); + + u32 location = start_location; + while(full) { + exisendbuffer(PACKET_SIZE, (u8*)location); + + bool ret2 = false; + bool ret3 = false; + u8 byte; + while(!ret3) { + while(!ret2) { + exicheckreceive(); + exicheckreceive(); + ret2 = exireceivebyte(&byte); + } + + if(byte == 0xCC) { + goto done_readmem; + }else if(byte == 0xBB) { + ret3 = true; + }else if(byte == 0xAA) { + location += PACKET_SIZE; + full--; + ret3 = true; + } + } + } + while(remainder) { + exisendbuffer(remainder, (u8*)location); + + //OSReport("Buffer sent\n"); + bool ret2 = false; + bool ret3 = false; + u8 byte; + while(!ret3) { + while(!ret2) { + exicheckreceive(); + exicheckreceive(); + ret2 = exireceivebyte(&byte); + } + + if(byte == 0xCC) { + goto done_readmem; + }else if(byte == 0xBB) { + ret3 = true; + }else if(byte == 0xAA) { + location += remainder; + remainder = 0; + ret3 = true; + } + } + } +done_readmem: + asm("nop"); +} + +bool command_handler() { + cmd = 0; + bool ret = exireceivebyte(&cmd); + if(!ret) + return true; + + switch(cmd) { + case 0x1: + writebyte(); + break; + case 0x2: + writeword(); + break; + case 0x3: + writedword(); + break; + case 0x4: + readmem(); + break; + case 0x6: + freezegame(); + break; + case 0x7: + unfreezegame(); + break; + case 0x8: // resume + return false; + break; + case 0x9: + return breakpoints(cmd); + break; + case 0x10: + return breakpoints(cmd); + break; + case 0x2F: // NOT IMPLEMENTED + break; + case 0x30: + getbpdata(); + break; + case 0x38: + cancelbreakpoints(); + break; + case 0x40: // NOT IMPLEMENTED + break; + case 0x41: // NOT IMPLEMENTED + break; + case 0x44: + return breakpoints(cmd); + break; + case 0x50: + pausestatus(); + break; + case 0x60: // NOT IMPLEMENTED + break; + case 0x89: + return breakpoints(cmd); + break; + case 0x99: + versionnumber(); + break; + default: + break; + }; + return true; +} + +//FIXME +bool handle_bps() { + return false; +} + +#if 0 // DEFAULT IABR BPHANDLER + bpregs[0x0C] = r3 + bpregs[0x10] = r4 + bpregs[0x14] = r5 + bpregs[0x80] = CR + bpregs[0x84] = LR + bpregs[0x88] = CTR + bpregs[0x8C] = XER + bpregs[0x198] = SRR0 + bpregs[0x19C] = SRR1 + 80000300 7C9043A6 mtsprg 0,r4 + 80000304 808000C0 lwz r4,0xC0(r0) + 80000308 9064000C stw r3,0xC(r4) + 8000030c 7C7042A6 mfsprg r3,0 + 80000310 90640010 stw r3,0x10(r4) + 80000314 90A40014 stw r5,0x14(r4) + 80000318 A06401A2 lhz r3,0x1A2(r4) + 8000031c 60630002 ori r3,r3,2 + 80000320 B06401A2 sth r3,0x1A2(r4) + 80000324 7C600026 mfcr r3 + 80000328 90640080 stw r3,0x80(r4) + 8000032c 7C6802A6 mflr r3 + 80000330 90640084 stw r3,0x84(r4) + 80000334 7C6902A6 mfctr r3 + 80000338 90640088 stw r3,0x88(r4) + 8000033c 7C6102A6 mfxer r3 + 80000340 9064008C stw r3,0x8C(r4) + 80000344 7C7A02A6 mfsrr0 r3 + 80000348 90640198 stw r3,0x198(r4) + 8000034c 7C7B02A6 mfsrr1 r3 + 80000350 9064019C stw r3,0x19C(r4) + 80000354 7C651B78 mr r5,r3 + 80000358 60000000 nop + 8000035c 7C6000A6 mfmsr r3 + 80000360 60630030 ori r3,r3,0x30 + 80000364 7C7B03A6 mtsrr1 r3 + 80000368 38600002 li r3,2 + 8000036c 808000D4 lwz r4,0xD4(r0) + 80000370 54A507BD rlwinm. r5,r5,0,30,30 + 80000374 40820014 bne- 0x80000388 + 80000378 3CA0801B lis r5,0x801B + 8000037c 38A5B0F0 subi r5,r5,20240 #0x801AB0F0 + 80000380 7CBA03A6 mtsrr0 r5 + 80000384 4C000064 rfi + 80000388 546515BA rlwinm r5,r3,2,22,29 + 8000038c 80A53000 lwz r5,0x3000(r5) + 80000390 7CBA03A6 mtsrr0 r5 + 80000394 4C000064 rfi + 80000398 60A5E040 ori r5,r5,0xE040 + 8000039c 54A500BE rlwinm r5,r5,0,2,31 + 800003a0 546315BA rlwinm r3,r3,2,22,29 + 800003a4 7CA3282E lwzx r5,r3,r5 + 800003a8 7CBA03A6 mtsrr0 r5 + 800003ac 4C000064 rfi +#endif diff --git a/src/codehandler.s b/src/codehandler.s new file mode 100644 index 0000000..bf9ce13 --- /dev/null +++ b/src/codehandler.s @@ -0,0 +1,368 @@ +.text
+
+#ifndef __MWERKS__
+.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
+
+.extern frozen_value
+.extern regbuffer
+.extern bpbuffer
+.extern command_handler__Fv
+.extern get_frozenvalue__Fv
+.extern exisendbyte__FUc
+
+.extern OSReport
+
+.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
+
+_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
+
+_check_frozen:
+ lis r18, frozen_value@h
+ ori r18, r18, frozen_value@l
+ lwz r0, 0x0(r18)
+ cmpwi r0, 2
+ bne frozen
+#TESTING FOR EXECUTION
+ lis r3, stringer@h
+ ori r3, r3, stringer@l
+ bl OSReport
+
+
+frozen:
+ bl command_handler__Fv
+ cmpwi r3, 0
+ beq resumegame
+ b finish
+
+#******************************************************************
+# subroutine: bphandler
+# Data/Instruction address breakpoint handler, save context and return
+#******************************************************************
+.global bphandler
+bphandler:
+ mtsprg 0, r3
+ lis r3, regbuffer@h
+ ori r3, r3, regbuffer@l
+ stmw r4, 0x2C(r3) # Store r4 - r31
+
+ stw r0, 0x1C(r3) # Store r0
+ stw r1, 0x20(r3) # Store r1
+ stw r2, 0x24(r3) # Store r2
+ mr r4, r3
+ mfsprg r3, 0
+ stw r3, 0x28(r4) # Store r3
+
+ mfsrr1 r3
+ rlwinm r3, r3,0,22,20 # clear trace
+ stw r3, 0x18(r4) # Store SRR1
+ rlwinm r3, r3,0,24,15
+ ori r3, r3,0x2000
+# rlwinm r3, r3,0,17,15 # clear hw interrupt
+ mtsrr1 r3 # restore srr1 with hw interrupt & trace cleared
+
+ mfsrr0 r3
+ stw r3, 0x14(r4) # Store SRR0
+
+ 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
+
+ lis r3, break@h
+ ori r3, r3, break@l
+ mtsrr0 r3
+ rfi
+
+break:
+ li r3, 0
+ mtspr 1010, r3 # Clear IABR
+ mtspr 1013, r3 # Clear DABR
+
+#BACKUP FPR
+ lis r4, regbuffer@h
+ ori r4, r4, regbuffer@l
+ stfs f0, 0xA0(r4)
+ stfs f1, 0xA4(r4)
+ stfs f2, 0xA8(r4)
+ stfs f3, 0xAC(r4)
+ stfs f4, 0xB0(r4)
+ stfs f5, 0xB4(r4)
+ stfs f6, 0xB8(r4)
+ stfs f7, 0xBC(r4)
+ stfs f8, 0xC0(r4)
+ stfs f9, 0xC4(r4)
+ stfs f10, 0xC8(r4)
+ stfs f11, 0xCC(r4)
+ stfs f12, 0xD0(r4)
+ stfs f13, 0xD4(r4)
+ stfs f14, 0xD8(r4)
+ stfs f15, 0xDC(r4)
+ stfs f16, 0xE0(r4)
+ stfs f17, 0xE4(r4)
+ stfs f18, 0xE8(r4)
+ stfs f19, 0xEC(r4)
+ stfs f20, 0xF0(r4)
+ stfs f21, 0xF4(r4)
+ stfs f22, 0xF8(r4)
+ stfs f23, 0xFC(r4)
+ stfs f24, 0x100(r4)
+ stfs f25, 0x104(r4)
+ stfs f26, 0x108(r4)
+ stfs f27, 0x10C(r4)
+ stfs f28, 0x110(r4)
+ stfs f29, 0x114(r4)
+ stfs f30, 0x118(r4)
+ stfs f31, 0x11C(r4)
+
+#TESTING FOR EXECUTION
+# lis r3, stringer@h
+# ori r3, r3, stringer@l
+# bl OSReport
+
+# r4=regbuffer, r=bpbuffer
+# r16=instBp, r17=dataBp, r19=lastBp
+
+#HANDLE MORE STUFF
+ lis r5, bpbuffer@h
+ ori r5, r5, bpbuffer@l
+
+ lwz r16, 0x0(r5) # inst bp
+ lwz r17, 0x4(r5) # data bp
+ lwz r19, 0xC(r5) # last break address
+
+ cmpwi r19, 0
+ beq _redobp # last break was 0. redo bp
+
+ cmpwi r19, 2
+ bne addr_1
+ lwz r9, 0x14(r4) # SRR0
+ addi r9, r19, 3
+ stw r9, 0x0(r5) # inst bp
+ stw r9, 0xC(r5) # last broken on address
+ b _executebp
+
+addr_1:
+ cmpw r16, r19
+ beq _step
+
+ cmpw r17, r19
+ beq _step
+
+ add r9, r16, r17
+ stw r9, 0xC(r5) # counter for alignment
+
+
+_alignementcheck:
+ lwz r16, 0x8(r5) # bp alignment check
+ cmpwi r16, 0
+ beq _executebp # no alignement = normal break
+
+ lwz r3, 0x10(r4) # DAR
+ 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, 0x8(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, 0xC(r5) # we set last broken on address to 0
+ lwz r9, 0x18(r4)
+ ori r9, r9, 0x400
+ stw r9, 0x18(r4) # SRR1 |= 0x400
+ 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, 0xC(r5) # we set last broken on address to 1
+ b _skipbp # and we don't break
+
+_executebp:
+# lis r1, temp_stack@h
+# ori r1, r1, temp_stack@l # setup temp stack
+ lis r4, frozen_value@h
+ ori r4, r4, frozen_value@l
+ li r5, 2
+ stw r5, 0x0(r4) # Freeze once returned to let user know there is a breakpoint hit
+
+ li r3, 0x11
+ bl exisendbyte__FUc # 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
+
+
+#******************************************************************
+# Finish
+# Check if the gecko has been paused. if no return to game
+#******************************************************************
+
+finish:
+ bl get_frozenvalue__Fv
+ cmpwi r3, 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
+
+ mtmsr 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
+#******************************************************************
+.global writebranch
+writebranch:
+ subf r6, r3, r4 # subtract r3 from r4 and place in r17
+ lis r5, 0x4800 # 0x48000000
+ rlwimi r5,r6,0,6,29
+ stw r5, 0(r3) # result in r3
+
+ dcbf r0, r3 # data cache block flush
+ sync
+ icbi r0, r3
+ isync
+
+ blr # return
+
+#==================================================================
+
+frozenvalue: #frozen value, then LR
+.long 0,0
+command:
+.byte 0,0,0,0
+
+.align 4
+.long 0
+stringer:
+.ascii "I found a codez 1\n"
+stringer2:
+.ascii "I found a codez 2\n"
+stringer3:
+.ascii "I found a codez 3\n"
+.end
+
|