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;
}
}
}