Post subject: Calculations in MHS based on emulator memory (real time)
Player (208)
Joined: 7/7/2006
Posts: 798
Location: US
I show my method of accomplishing showing calculations in MHS based on Mupen memory in real time. I have not seen thorough documentation of this method anywhere, though I imagine at least a few people have done it. I learned this largely from the help files and the MHS forums. Does anyone have any better suggestions for doing this in emulators that do not have lua integrated? I know CheatEngine has similar possibilities with lua, but is there thorough documentation of how to do that? Does anyone have a CheatEngine-Dolphin script that essentially does this same thing? A separate question: Has anyone managed to incorporate float big endian data type into MHS searches to allow for practical use with Dolphin? -- MHS Tools -> Script Editor: Code 1: HotKeyBreak.lss This piece of code lets you press a hotkey to execute a function to change a variable to end the loop in the second code.
int Scriptbreak = 1;
//In MHS go to Tools: Hotkeys, define key to press to start the script, parm1 = 24 (not 0x24), parm2, parm3 don't matter.
VOID On_HK_24( DWORD dw1, DWORD dw2 ) 
{
    PrintF( "Scriptbreak was %d", Scriptbreak);
    Scriptbreak = 0;
    PrintF( "Scriptbreak is %d", Scriptbreak);    
}
Code 2: BKVelocityInterp.lss In Banjo Kazooie this uses X and Y speed vectors to calculate overall speed and update in real time. This was fairly complicated to implement due to the need to have a second thread for the program to not crash on a potentially endless while loop. I did a lot of reading of the MHS help file and the forums to come to this method. While the code is not particularly elegant or formal, I tried to comment thoroughly to explain what problems can arise.
//MHS Help File defines these functions.
VOID On_HK_23( DWORD dw1, DWORD dw2 ) {
	//In MHS go to Tools: Hotkeys, define key to press to start the script, parm1 = 23 (not 0x23), parm2, parm3 don't matter.
    Clear(); //Clear Display console
    DWORD dwParm = Random( 90 ); // Create a random parameter. (Left in for demonstration)
    
    if ( StrICmp( GetCurProcessName(), "mupen64-rerecording.exe" ) != 0 )
    //this may need changed for different versions of mupen
    {
		PrintF( "You must be attached to a process named mupen64-rerecording.exe !" );
		return;
	}
    
    // Create the second thread with this parameter.  We write “SecondThread” ourselves.
    HANDLE hThread = CreateThread( "SecondThread", dwParm );
    // It may have failed!
    if ( !hThread ) {
        PrintF( "Creating the second thread failed." );
        return;
    } 
    // It succeeded!
    PrintF( "Second thread created with parameter %u.", dwParm );
    CloseHandle( hThread );
}
 
///////////////////////////////////////////////////////////////////////////////////////////////////////// 
 
//We need this second thread because main will freeze if stuck in a while loop.
DWORD SecondThread( DWORD dwParm ) 
{	
  
   extern FLOAT XPos = { "mupen64-rerecording.exe", 0x867C98};  //Must use base addresses found by right clicking on values.  Process name must match.  
   extern FLOAT YPos = { "mupen64-rerecording.exe", 0x867C9C};  //Height
   extern FLOAT ZPos = { "mupen64-rerecording.exe", 0x867CA0};
   extern FLOAT XVel = { "mupen64-rerecording.exe", 0x867CB8};
   extern FLOAT ZVel = { "mupen64-rerecording.exe", 0x867CC0};
   extern FLOAT YVel = { "mupen64-rerecording.exe", 0x867CEC};  //Height

   float HorizontalSpeed = 0;
   float ThreeDSpeed = 0;

    PrintF( "From Second Thread: %u.", dwParm ); //(Left in for demonstration)
    Scriptbreak = 1;  //Break on hotkey global variable declared in HotkeyBreak Script.
    PrintF( "Scriptbreak = %d", Scriptbreak);

    while(Scriptbreak!=0)
    {
		HorizontalSpeed = Sqrt(XVel*XVel + ZVel*ZVel);
		ThreeDSpeed = Sqrt(XVel*XVel + YVel*YVel + ZVel*ZVel);
    
		PrintF( "2DSpeed: %f \n", HorizontalSpeed);
		PrintF( "3DSpeed: %f \n", ThreeDSpeed);	
        PrintF( "Velocity: X: % -015.4f Y: % -015.4f Z: % -015.4f \n", XVel, YVel, ZVel);	
        PrintF( "Position: X: % -015.4f Y: % -015.4f Z: % -015.4f \n", XPos, YPos, ZPos);

		Sleep(100);
		Clear();
		if ( StrICmp( GetCurProcessName(), "mupen64-rerecording.exe" ) != 0 ) 
		{
			PrintF( "Mupen Closed!" );
			return 0;
		}
	}
}