u32 GBIMicrocode_DetectVersion( u32 code_base, u32 code_size, u32 data_base, u32 data_size, CustomMicrocodeCallback custom_callback ) { // I think only checking code_base should be enough.. u32 idx = code_base + data_base; // Cheap way to cache ucodes, don't check for strings (too slow!) but check last used ucode entries which is alot faster than string comparison. // This only needed for GBI1/2/SDEX ucodes that use LoadUcode, else we only check when code_base changes, which usually never happens // u32 i; for( i = 0; i < MAX_UCODE_CACHE_ENTRIES; i++ ) { const UcodeInfo &used( gUcodeInfo[ i ] ); // If this returns false, it means this entry is free to use if( used.set == false ) break; if( used.index == idx ) return used.ucode; } // // Try to find the version string in the microcode data. This is faster than calculating a crc of the code // char str[256] = ""; GBIMicrocode_DetectVersionString( data_base, data_size, str, 256 ); // It wasn't the same as the last time around, we'll hash it and check if is a custom ucode. // u32 code_hash = GBIMicrocode_MicrocodeHash( code_base, code_size ); u32 ucode_version = GBI_0; u32 ucode_offset = ~0; for ( u32 i = 0; i < ARRAYSIZE(gMicrocodeData); i++ ) { if ( code_hash == gMicrocodeData[i].hash ) { //DBGConsole_Msg(0, "Ucode has been Detected in Array :[M\"%s\", Ucode %d]", str, gMicrocodeData[ i ].ucode); ucode_version = gMicrocodeData[ i ].ucode; ucode_offset = gMicrocodeData[ i ].offset; } } if( ucode_version != GBI_0 ) { // If this a custom ucode, let's build an array based from ucode_offset custom_callback( ucode_version, ucode_offset ); } else { // // If it wasn't a custom ucode // See if we can identify it by string, if no match was found set default for Fast3D ucode // const char *ucodes[] = { "F3", "L3", "S2DEX" }; char *match = 0; for(u32 j = 0; j<3;j++) { if( (match = strstr(str, ucodes[j])) ) break; } if( match ) { if( strstr(match, "fifo") || strstr(match, "xbus") ) { if( !strncmp(match, "S2DEX", 5) ) ucode_version = GBI_2_S2DEX; else ucode_version = GBI_2; } else { if( !strncmp(match, "S2DEX", 5) ) ucode_version = GBI_1_S2DEX; else ucode_version = GBI_1; } } } // // Retain used ucode info which will be cached // gUcodeInfo[ i ].index = idx; gUcodeInfo[ i ].ucode = ucode_version; gUcodeInfo[ i ].set = true; // DBGConsole_Msg(0,"Detected %s Ucode is: [M Ucode %d, 0x%08x, \"%s\", \"%s\"]",ucode_offset == u32(~0) ? "" :"Custom", ucode_version, code_hash, str, g_ROM.settings.GameName.c_str() ); return ucode_version; }
UcodeInfo GBIMicrocode_DetectVersion( u32 code_base, u32 code_size, u32 data_base, u32 data_size ) { // I think only checking code_base should be enough.. u32 address = code_base + data_base; // Cheap way to cache ucodes, don't check for strings (too slow!) but check last used ucode entries which is alot faster than string comparison. // This only needed for GBI1/2/SDEX ucodes that use LoadUcode, else we only check when code_base changes, which usually never happens // u32 i; for( i = 0; i < MAX_UCODE_CACHE_ENTRIES; i++ ) { // If this returns false, it means this entry is free to use if (gUcodeInfo[i].set == false) break; if (gUcodeInfo[i].address == address) return gUcodeInfo[i]; } // // Try to find the version string in the microcode data. This is faster than calculating a crc of the code // char str[256] = ""; GBIMicrocode_DetectVersionString( data_base, data_size, str, 256 ); // It wasn't the same as the last time around, we'll hash it and check if is a custom ucode. // u32 code_hash = GBIMicrocode_MicrocodeHash( code_base, code_size ); for ( u32 x = 0; x < ARRAYSIZE(gMicrocodeData); x++ ) { if ( code_hash == gMicrocodeData[x].hash ) { //DBGConsole_Msg(0, "Ucode has been Detected in Array :[M\"%s\", Ucode %d]", str, gMicrocodeData[ i ].ucode); GBIMicrocode_SetCustom(gMicrocodeData[x].ucode, gMicrocodeData[x].offset); gUcodeInfo[i].set = true; gUcodeInfo[i].func = gCustomInstruction; gUcodeInfo[i].stride = gMicrocodeData[x].stride; gUcodeInfo[i].address = address; return gUcodeInfo[i]; } } // // If it wasn't a custom ucode // See if we can identify it by string, if no match was found set default for Fast3D ucode // const char *ucodes[] = { "F3", "L3", "S2DEX" }; char *match = 0; for(u32 j = 0; j<3;j++) { if( (match = strstr(str, ucodes[j])) ) break; } u32 ucode_stride; u32 ucode_version; if (!match) { ucode_stride = 10; ucode_version = GBI_0; } else { ucode_stride = 2; if( strstr(match, "fifo") || strstr(match, "xbus") ) { if( !strncmp(match, "S2DEX", 5) ) ucode_version = GBI_2_S2DEX; else ucode_version = GBI_2; } else { if( !strncmp(match, "S2DEX", 5) ) ucode_version = GBI_1_S2DEX; else ucode_version = GBI_1; } } gUcodeInfo[i].set = true; gUcodeInfo[i].func = gNormalInstruction[ucode_version]; gUcodeInfo[i].stride = ucode_stride; gUcodeInfo[i].address = address; // DBGConsole_Msg(0,"Detected %s Ucode is: [M Ucode %d, 0x%08x, \"%s\", \"%s\"]",ucode_offset == u32(~0) ? "" :"Custom", ucode_version, code_hash, str, g_ROM.settings.GameName.c_str() ); return gUcodeInfo[i]; }