/* gbasleep.cpp Copyright (C) 2007 By Dan Weiss (Dwedit) Copyright (C) 2008-2009 somebody Copyright (C) 2009 yellow wood goblin This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "gbapatcher.h" #include #include #include "gba_sleep_patch_bin.h" const int ACTIVATION_SIZE=36; const int FAKE_SIZE=512*1024; //search in first 512k const int PATCH_LENGTH=2048; void CGbaPatcher::CommonSleepSearch(void) { //The LDR,=xxxxxxxx ARM instruction: // //Load/Store=1 //Writeback=0 //Byte/Word=0 //Up/Down=either //Pre/Post=? //Immediate Offset=0 //rn = r15 //cond= always //1110 01 0 p u 0 0 1 1111 rrrr oooooooooooo //Instruction Mask: //1111 11 1 0 0 1 1 1 1111 0000 000000000000 //Instruction Bits: //1110 01 0 0 0 0 0 1 1111 0000 000000000000 //The STR rd,[rn] ARM instruction: //Load/Store=0 //Writeback=0 //Byte/Word=0 //Up/Down=? //Pre/Post=? //Immediate Offset=0 //cond= always //1110 01 0 p u 0 0 0 rnrn rdrd 000000000000 //MASK: //1111 11 1 0 0 1 1 1 0000 0000 111111111111 //BITS: //1110 01 0 0 0 0 0 0 0000 0000 000000000000 //THUMB: //LDR rd,=xxxxxxxx //01001rrroooooooo //1111100000000000 //0100100000000000 //STR rd,[rb] //01100 00000 bbb ddd //11111 11111 000 000 //01100 00000 000 000 const u32 ldr_mask=0xFE7F0000; const u32 ldr_bits=0xE41F0000; const u32 str_mask=0xFE700FFF; const u32 str_bits=0xE4000000; const u32 t_ldr_mask=0xF800; const u32 t_ldr_bits=0x4800; const u32 t_str_mask=0xFFC0; const u32 t_str_bits=0x6000; u32 reg_data[16]; //contents of register u32 reg_addr[16]; //address of the data which got written u32 reg_lastwrite[16]; //PC at which the data was written to memset(reg_data,0,sizeof(reg_data)); memset(reg_addr,0,sizeof(reg_addr)); memset(reg_lastwrite,0,sizeof(reg_lastwrite)); SetTrimSize(); if((iTrimSize+PATCH_LENGTH)>iWriter->MaxSize()) return; u32 fake_size=FAKE_SIZE; if(fake_size>iTrimSize) fake_size=iTrimSize; //arm u32 patch_location=iTrimSize; u32 activation_location=patch_location+gba_sleep_patch_bin_size; u32 search_size=fake_size/sizeof(u32); for(u32 ii=0;ii>12)&0x0F); int offset=(word&0xFFF); u32 address=(updown)*offset + pc; u32 memdata=0xDEADBEEF; if(address>=0&&address>16)&0x0F); rd=((word>>12)&0x0F); u32 myaddress=ii*sizeof(u32); bool okay=true &&(reg_data[rn]==0x03007FFC) &&(myaddress-reg_lastwrite[rd]<64) &&(myaddress-reg_lastwrite[rn]<64) &&(reg_lastwrite[rd]!=0) &&(reg_lastwrite[rn]!=0) &&((reg_data[rd]&0xFF000000)==0x03000000) ; if(!okay&®_data[rn]==0x03007FFC) { if(myaddress==0xE0) { okay=true; } } if(myaddress> BX rn Add2(myaddress,0xE12FFF10+rn); //ldr rn,=XXXX >> ldr rn,=activation_jump u32 data_address=reg_addr[rn]; if(data_address>=0&&data_address>8)&0x07); int offset=(word&0xFF); u32 address=offset*4+pc; u32 memdata=0xDEADBEEF; address&=~0x03; if(address>=0&&address>3)&0x07); rd=((word>>0)&0x07); u32 myaddress=ii*sizeof(u16); bool okay=true &&(reg_data[rb]==0x03007FFC) &&(myaddress-reg_lastwrite[rd]<80) &&(myaddress-reg_lastwrite[rb]<64) &&(reg_lastwrite[rd]!=0) &&(reg_lastwrite[rb]!=0) &&((reg_data[rd]&0xFF000000)==0x03000000) ; if(okay) { { //str rd,[rn] >> BX rb Add4(myaddress,0x4700+(rb<<3)); //ldr rn,=XXXX >> ldr rn,=activation_jump u32 data_address=reg_addr[rb]; if(data_address>=0&&data_address=top;ii--) { if(Data8()[ii]!=byte||ii==top) { iTrimSize=ii+4; iTrimSize=iTrimSize+(16-(iTrimSize&15)); if(iTrimSize>alignedSize) iTrimSize=alignedSize; break; } } } void CGbaPatcher::CommonSleepPatch(void) { if(!(iCount2+iCount4)) return; for(u32 ii=0;iiWrite(iPatchInfo2[ii].iOffset,(u8*)&(iPatchInfo2[ii].iValue),sizeof(iPatchInfo2[ii].iValue)); } for(u32 ii=0;iiWrite(iPatchInfo4[ii].iOffset,(u8*)&(iPatchInfo4[ii].iValue),sizeof(iPatchInfo4[ii].iValue)); } iResultSize=iTrimSize; iWriter->Write(iTrimSize,gba_sleep_patch_bin,gba_sleep_patch_bin_size); iResultSize=iTrimSize+gba_sleep_patch_bin_size+ACTIVATION_SIZE*iCount3; for(u32 ii=0;ii>2)); mem[5]=0xE8BD5003; mem[6]=0xE59F0000+(iPatchInfo3[ii].iRb<<12); mem[7]=0xE12FFF10+iPatchInfo3[ii].iRb; mem[8]=iPatchInfo3[ii].iAddress+0x08000000; iWriter->Write(iPatchInfo3[ii].iLocation,(u8*)mem,sizeof(mem)); } }