diff --git a/source/arm11/cheat.c b/source/arm11/cheat.c index 3f964dd..0c12bea 100644 --- a/source/arm11/cheat.c +++ b/source/arm11/cheat.c @@ -336,44 +336,71 @@ static int cht_calc_needsize( int mode, int numirq ) static CodeLocation rom_fit_newsize( CodeLocation rom, int realend, int totalsize, u32 szrom, u32 *newsize ) { u32 size = realend + totalsize; - if( size > SIZE_32M ) + + // get the biggest space that all bytes is 0 + CodeLocation found=NULL, current=NULL; + int szfound=0, szcurrent=0; + int reallen = INSTR_LEN( realend ); + instruction_t freeinstr = 0; // 0/0xffffffff will be free + +#define START_FREE_BLOCK(n) {\ + current = rom+i;\ + freeinstr = n;\ + } +#define END_FREE_BLOCK {\ + if( szcurrent > szfound )\ + {\ + found = current;\ + szfound = szcurrent;\ + }\ + current = NULL;\ + szcurrent = 0;\ + } + + for( int i=0; i < reallen; ++i ) { - // get the biggest space that all bytes is 0 - CodeLocation found=NULL, current=NULL; - int szfound=0, szcurrent=0; - int reallen = INSTR_LEN( realend ); - for( int i=0; i < reallen; ++i ) + if( rom[i] == 0 ) { - if( rom[i] == 0 ) + if( szcurrent == 0 ) { - if( szcurrent == 0 ) current = rom+i; - szcurrent += INSTR_SIZE; + START_FREE_BLOCK(0); } - else if( szcurrent > 0 ) + else { - if( szcurrent > szfound ) - { - found = current; - szfound = szcurrent; - } - current = NULL; - szcurrent = 0; + if( freeinstr == 0 )// same block + szcurrent += INSTR_SIZE; + else END_FREE_BLOCK; + } + } + else if( rom[i] == 0xffffffff ) + { + if( szcurrent == 0xffffffff ) + { + START_FREE_BLOCK(0xffffffff); + } + else + { + if( freeinstr == 0xffffffff ) + szcurrent += INSTR_SIZE; + else END_FREE_BLOCK; } } - // the zero-filled space is big enough, 3 is a guess value - if( szfound > totalsize * 3 ) - { - return found + FIT_SPACE_RESERVED; - } - else return NULL; + else if( szcurrent > 0 ) END_FREE_BLOCK; } - else if( nextPow2(size) != nextPow2(szrom) ) + + // the zero-filled space is big enough, 3 is a guess value + if( szfound > totalsize * 3 ) { - // 似乎没什么要动的 - *newsize = size + INSTR_SIZE; // reserve a word for padding - return rom + INSTR_LEN( realend ); + return found + FIT_SPACE_RESERVED; } + // cannot find a good block + if( size > SIZE_32M ) return NULL; + + // grow cart volumn + else if( szrom < size || nextPow2(size) != nextPow2(szrom) ) + *newsize = size + INSTR_SIZE; + return rom + INSTR_LEN( realend ); }