Skip to content

Commit

Permalink
New runner interface algorithm, refactoring
Browse files Browse the repository at this point in the history
- Refactored GM-related module internals to their respective folders and files
- Added a new way of looking up the runner interface - fixes #68 (both Fields of Mistria and Conscript Demo)
- Fixed Run_Room not being found in new runners due to the background_color builtin being removed
  • Loading branch information
Archie-osu committed Sep 17, 2024
1 parent 660018e commit 5d5ee74
Show file tree
Hide file tree
Showing 24 changed files with 3,254 additions and 2,606 deletions.
17 changes: 14 additions & 3 deletions YYToolkit/YYToolkit.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,20 @@
<ClCompile Include="source\ModuleMain.cpp" />
<ClCompile Include="source\YYTK\Module Interface\Interface.cpp" />
<ClCompile Include="source\YYTK\Module Internals\Console\Console.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM-only.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC-only.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-CodeExecute.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-Objects.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-Rooms.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-RunnerInterfaceNew.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-RunnerInterfaceOld.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM\VM-Arrays.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM\VM-BuiltinVariables.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM\VM-Functions.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM\VM-Rooms.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC\YYC-Functions.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC\YYC-Rooms.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC\YYC-Arrays.cpp" />
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC\YYC-BuiltinVariables.cpp" />
<ClCompile Include="source\YYTK\Module Internals\Hooks\Hooks.cpp" />
<ClCompile Include="source\YYTK\Shared.cpp" />
</ItemGroup>
Expand Down
39 changes: 36 additions & 3 deletions YYToolkit/YYToolkit.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,46 @@
<ClCompile Include="source\YYTK\Shared.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic.cpp">
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM-only.cpp">
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC\YYC-Arrays.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC-only.cpp">
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC\YYC-BuiltinVariables.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC\YYC-Rooms.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\YYC\YYC-Functions.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM\VM-Arrays.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM\VM-BuiltinVariables.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM\VM-Functions.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\VM\VM-Rooms.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-Rooms.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-CodeExecute.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-RunnerInterfaceOld.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-Objects.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
<ClCompile Include="source\YYTK\Module Internals\GameMaker\Generic\Generic-RunnerInterfaceNew.cpp">
<Filter>Zdrojové soubory</Filter>
</ClCompile>
</ItemGroup>
Expand Down
38 changes: 35 additions & 3 deletions YYToolkit/include/Aurie/shared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@
#endif // AURIE_FWK_MAJOR

#ifndef AURIE_FWK_MINOR
#define AURIE_FWK_MINOR 0
#define AURIE_FWK_MINOR 1
#endif // AURIE_FWK_MINOR

#ifndef AURIE_FWK_PATCH
#define AURIE_FWK_PATCH 4
#define AURIE_FWK_PATCH 0
#endif // AURIE_FWK_PATCH


Expand Down Expand Up @@ -112,7 +112,9 @@ namespace Aurie
// An AurieMemoryAllocation object
AURIE_OBJECT_ALLOCATION = 3,
// An AurieHook object
AURIE_OBJECT_HOOK = 4
AURIE_OBJECT_HOOK = 4,
// An AurieBreakpoint object
AURIE_OBJECT_BREAKPOINT = 5,
};

enum AurieModuleOperationType : uint32_t
Expand Down Expand Up @@ -225,6 +227,11 @@ namespace Aurie
IN AurieModuleOperationType OperationType,
OPTIONAL IN OUT AurieOperationInfo* OperationInfo
);

using AurieBreakpointCallback = bool(*)(
IN OUT PVOID ProcessorContext,
IN uint32_t ExceptionCode
);
}

#ifndef AURIE_INCLUDE_PRIVATE
Expand Down Expand Up @@ -444,6 +451,22 @@ namespace Aurie
{
return AURIE_API_CALL(MmpSigscanRegion, RegionBase, RegionSize, Pattern, PatternMask, PatternBase);
}


inline AurieStatus MmpSetBreakpoint(
IN PVOID Rip,
IN AurieBreakpointCallback BreakpointCallback
)
{
return AURIE_API_CALL(MmpSetBreakpoint, Rip, BreakpointCallback);
}

inline AurieStatus MmpUnsetBreakpoint(
IN PVOID Rip
)
{
return AURIE_API_CALL(MmpUnsetBreakpoint, Rip);
}
}

inline AurieStatus MdMapImage(
Expand Down Expand Up @@ -598,6 +621,15 @@ namespace Aurie
{
return AURIE_API_CALL(ObpGetObjectType, Object);
}

inline AurieStatus ObpLookupInterfaceOwnerExport(
IN const char* InterfaceName,
IN const char* ExportName,
OUT PVOID& ExportAddress
)
{
return AURIE_API_CALL(ObpLookupInterfaceOwnerExport, InterfaceName, ExportName, ExportAddress);
}
}

inline AurieStatus PpQueryImageArchitecture(
Expand Down
98 changes: 77 additions & 21 deletions YYToolkit/source/YYTK/Module Interface/Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,22 +301,49 @@ namespace YYTK

if (!m_FirstInitComplete)
{
// Create the runner interface event
m_RunnerInterfacePopulatedEvent = CreateEventA(
nullptr,
FALSE,
FALSE,
nullptr
);

// Get the runner interface by reading assembly
last_status = GmpGetRunnerInterface(
m_RunnerInterface
);

// If we didn't get that, there's no chance in hell we're doing anything with the runner
// If we didn't get that, there's no chance in hell we're doing anything with the runner...
// Until v3.4, where a new method is introduced!
if (!AurieSuccess(last_status))
{
this->PrintError(
__FILE__,
__LINE__,
"Failed to find runner interface! (%s)",
AurieStatusToString(last_status)
PVOID rip = nullptr;
last_status = GmpBreakpointInterfaceCreation(
&rip,
GmpHandleInterfaceCreationBP
);

return last_status;
if (!AurieSuccess(last_status) || !rip)
{
this->PrintError(
__FILE__,
__LINE__,
"Failed to find runner interface! (%s)",
AurieStatusToString(last_status)
);

return last_status;
}
else
{
m_IsUsingVeh = true;
this->Print(
CM_LIGHTAQUA,
"Game code analysis finished. Breakpoint set on RIP 0x%p.",
rip
);
}
}

last_status = Hooks::HkPreinitialize();
Expand All @@ -341,6 +368,22 @@ namespace YYTK

if (!m_SecondInitComplete)
{
// If we're using VEH, we have to wait until the runner interface is populated
// by the exception handler.
// We do this by using the event, which is signaled by the exception handler.
if (m_IsUsingVeh)
{
this->Print(
CM_LIGHTAQUA,
"Please wait while the game creates a runner interface."
);

WaitForSingleObject(
m_RunnerInterfacePopulatedEvent,
INFINITE
);
}

// Now we have to figure out if the runner is YYC or VM
// We can either do that by calling "code_is_compiled",
// or by checking if the YYC-only version of GmpFindFunctionsArray succeeds.
Expand Down Expand Up @@ -563,44 +606,54 @@ namespace YYTK
}

// Find the Run_Room pointer
size_t background_color_index = 0;
size_t builtin_variable_index = 0;
last_status = GetBuiltinVariableIndex(
"background_color",
background_color_index
builtin_variable_index
);

if (!AurieSuccess(last_status))
{
this->PrintError(
__FILE__,
__LINE__,
"Failed to find background_color built-in variable! (%s)",
AurieStatusToString(last_status)
// We failed to get background_color (it seems to not exist in Fields of Mistria 2024.6 for example)
last_status = GetBuiltinVariableIndex(
"room_width",
builtin_variable_index
);

return last_status;
// If even room_width fails, we bail.
if (!AurieSuccess(last_status))
{
this->PrintError(
__FILE__,
__LINE__,
"Failed to find built-in variables (background_color & room_width)! (%s)",
AurieStatusToString(last_status)
);

return last_status;
}
}

RVariableRoutine* background_color_entry = nullptr;
RVariableRoutine* builtin_variable_information = nullptr;
last_status = GetBuiltinVariableInformation(
background_color_index,
background_color_entry
builtin_variable_index,
builtin_variable_information
);

if (!AurieSuccess(last_status))
{
this->PrintError(
__FILE__,
__LINE__,
"Failed to get background_color built-in variable information! (%s)",
"Failed to get built-in variable information! (%s)",
AurieStatusToString(last_status)
);

return last_status;
}

last_status = GmpFindCurrentRoomData(
background_color_entry->m_SetVariable,
builtin_variable_information->m_SetVariable,
&m_RunRoom
);

Expand Down Expand Up @@ -746,7 +799,7 @@ namespace YYTK
CmWriteOutput(CM_GRAY, "- m_RunRoom at 0x%p", m_RunRoom);
CmWriteOutput(CM_GRAY, "- m_AddToYYObjectBase at 0x%p", m_AddToYYObjectBase);
CmWriteOutput(CM_GRAY, "- m_FindAllocSlot at 0x%p", m_FindAllocSlot);

CmWriteOutput(
CM_GRAY,
"- RFunction Entry Type: %s",
Expand All @@ -768,6 +821,9 @@ namespace YYTK

void YYTKInterfaceImpl::Destroy()
{
if (m_RunnerInterfacePopulatedEvent)
CloseHandle(m_RunnerInterfacePopulatedEvent);

Hooks::HkUninitialize(
m_WindowHandle
);
Expand Down
11 changes: 11 additions & 0 deletions YYToolkit/source/YYTK/Module Interface/Interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ namespace YYTK
YYRunnerInterface m_RunnerInterface = {};

bool m_IsYYCRunner = false;

// Set to true if VEH is used to get the runner interface.
// If it is, the runner interface is unavailable during stage 1 init.
bool m_IsUsingVeh = false;

// A handle to an event which is signaled by the vectored exception handler.
// Once signaled, the runner interface has been populated with values.
HANDLE m_RunnerInterfacePopulatedEvent = nullptr;

// The instruction pointer of the Extension_PrePrepare breakpoint.
PVOID m_ExceptionRIP = nullptr;
private:

// A pointer to the functions array in memory
Expand Down
Loading

0 comments on commit 5d5ee74

Please sign in to comment.