/*
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));
}
}