Example #1
0
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;
}
Example #2
0
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];
}