# 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