Skip to content

Commit 957b0e2

Browse files
committed
Improve variable accesses
- Removed extraneous argument in GmpFindRVArrayOffset - Made Stage 2 hooks mandatory - Added support for adding to YYObjectBase structures - TODO: Add method for internal structure access - Add GetVariableSlot method for computing hashes of variable names - This enables easy hashmap lookups (tested to work with InternalGetYYVarRef) - Fixed issues caused by missing StructGetMember runner function - GetInstanceMember interface function now works - EnumInstanceMembers interface function now works - Direct accesses through operator[] or CInstance::at() method now work
1 parent d9958ff commit 957b0e2

File tree

6 files changed

+324
-27
lines changed

6 files changed

+324
-27
lines changed

YYToolkit/source/YYTK/Module Interface/Interface.cpp

Lines changed: 165 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,6 @@ namespace YYTK
373373
{
374374
last_status = YYC::GmpFindRVArrayOffset(
375375
array_equals,
376-
m_RunnerInterface,
377376
&m_RValueArrayOffset
378377
);
379378
}
@@ -606,11 +605,43 @@ namespace YYTK
606605

607606
if (!AurieSuccess(last_status))
608607
{
609-
this->PrintWarning(
608+
this->PrintError(
609+
__FILE__,
610+
__LINE__,
610611
"Failed to initialize stage 2 hooks! (%s)",
611612
AurieStatusToString(last_status)
612613
);
613614

615+
return last_status;
616+
}
617+
618+
last_status = GmpGetYYObjectBaseAdd(
619+
m_RunnerInterface,
620+
&m_AddToYYObjectBase
621+
);
622+
623+
if (!AurieSuccess(last_status))
624+
{
625+
this->PrintWarning(
626+
"Failed to find YYObjectBase::Add! (%s)",
627+
AurieStatusToString(last_status)
628+
);
629+
630+
// return last_status;
631+
}
632+
633+
last_status = GmpGetFindAllocSlotFromName(
634+
m_AddToYYObjectBase,
635+
&m_FindAllocSlot
636+
);
637+
638+
if (!AurieSuccess(last_status))
639+
{
640+
this->PrintWarning(
641+
"Failed to find FindAllocSlot! (%s)",
642+
AurieStatusToString(last_status)
643+
);
644+
614645
// return last_status;
615646
}
616647

@@ -624,6 +655,9 @@ namespace YYTK
624655
CmWriteOutput(CM_GRAY, "- m_RValueArrayOffset at 0x%llx", m_RValueArrayOffset);
625656
CmWriteOutput(CM_GRAY, "- m_GetRoomData at 0x%p", m_GetRoomData);
626657
CmWriteOutput(CM_GRAY, "- m_RunRoom at 0x%p", m_RunRoom);
658+
CmWriteOutput(CM_GRAY, "- m_AddToYYObjectBase at 0x%p", m_AddToYYObjectBase);
659+
CmWriteOutput(CM_GRAY, "- m_FindAllocSlot at 0x%p", m_FindAllocSlot);
660+
627661
CmWriteOutput(
628662
CM_GRAY,
629663
"- RFunction Entry Type: %s",
@@ -980,12 +1014,28 @@ namespace YYTK
9801014
OUT RValue*& Member
9811015
)
9821016
{
983-
if (!m_RunnerInterface.StructGetMember)
984-
return AURIE_MODULE_INTERNAL_ERROR;
985-
9861017
if (Instance.m_Kind != VALUE_OBJECT)
9871018
return AURIE_INVALID_PARAMETER;
9881019

1020+
// If we don't have the interface function, we use a fallback method
1021+
if (!m_RunnerInterface.StructGetMember)
1022+
{
1023+
int32_t variable_hash = 0;
1024+
AurieStatus last_status = AURIE_SUCCESS;
1025+
1026+
last_status = this->GetVariableSlot(
1027+
Instance,
1028+
MemberName,
1029+
variable_hash
1030+
);
1031+
1032+
if (!AurieSuccess(last_status))
1033+
return last_status;
1034+
1035+
Member = &Instance.m_Object->InternalGetYYVarRef(variable_hash);
1036+
return AURIE_SUCCESS;
1037+
}
1038+
9891039
RValue* member_value = m_RunnerInterface.StructGetMember(&Instance, MemberName);
9901040

9911041
if (!member_value)
@@ -1004,33 +1054,109 @@ namespace YYTK
10041054
if (Instance.m_Kind != VALUE_OBJECT)
10051055
return AURIE_INVALID_PARAMETER;
10061056

1057+
// Determine the number of keys in the struct
1058+
// Use a fallback method if StructGetKeys isn't available in the interface
1059+
int instance_variable_count = -1;
10071060
if (!m_RunnerInterface.StructGetKeys)
1008-
return AURIE_MODULE_INTERNAL_ERROR;
1061+
{
1062+
AurieStatus last_status = AURIE_SUCCESS;
1063+
RValue name_count;
10091064

1010-
if (!m_RunnerInterface.StructGetMember)
1011-
return AURIE_MODULE_INTERNAL_ERROR;
1065+
// Ask the engine for the count - this function may not be present
1066+
last_status = CallBuiltinEx(
1067+
name_count,
1068+
"variable_struct_names_count",
1069+
nullptr,
1070+
nullptr,
1071+
{ Instance }
1072+
);
10121073

1013-
int instance_variable_count = m_RunnerInterface.StructGetKeys(
1014-
&Instance,
1015-
nullptr,
1016-
nullptr
1017-
);
1074+
// Bail if the function isn't present
1075+
if (!AurieSuccess(last_status))
1076+
return last_status;
10181077

1019-
assert(instance_variable_count > 0);
1078+
instance_variable_count = static_cast<int>(name_count.AsReal());
1079+
}
1080+
else
1081+
{
1082+
// Query the count by passing nullptr for the keys array
1083+
instance_variable_count = m_RunnerInterface.StructGetKeys(
1084+
&Instance,
1085+
nullptr,
1086+
nullptr
1087+
);
1088+
}
10201089

1021-
// Get the names of all
1090+
assert(instance_variable_count >= 0);
1091+
1092+
// Create a vector with enough space to store all the instance variable names
10221093
std::vector<const char*> instance_variable_names(instance_variable_count);
1023-
m_RunnerInterface.StructGetKeys(
1024-
&Instance,
1025-
instance_variable_names.data(),
1026-
&instance_variable_count
1027-
);
1094+
1095+
// Use a fallback if StructGetKeys isn't available
1096+
if (!m_RunnerInterface.StructGetKeys)
1097+
{
1098+
AurieStatus last_status = AURIE_SUCCESS;
1099+
RValue name_array;
1100+
1101+
// Ask the engine for the count - this function may not be present
1102+
last_status = CallBuiltinEx(
1103+
name_array,
1104+
"variable_struct_get_names",
1105+
nullptr,
1106+
nullptr,
1107+
{ Instance }
1108+
);
1109+
1110+
// Bail if the call failed
1111+
if (!AurieSuccess(last_status))
1112+
return last_status;
1113+
1114+
// Loop through all elements of the array
1115+
for (size_t i = 0; i < name_array.length(); i++)
1116+
{
1117+
// Use array_get to not rely on m_RValueArrayOffset
1118+
RValue name;
1119+
last_status = CallBuiltinEx(
1120+
name,
1121+
"array_get",
1122+
nullptr,
1123+
nullptr,
1124+
{ name_array, static_cast<int64_t>(i) }
1125+
);
1126+
1127+
// If we can't get the name just bail
1128+
if (!AurieSuccess(last_status))
1129+
return last_status;
1130+
1131+
// Assign the name into our vector
1132+
instance_variable_names.at(i) = name.AsString().data();
1133+
}
1134+
}
1135+
else
1136+
{
1137+
m_RunnerInterface.StructGetKeys(
1138+
&Instance,
1139+
instance_variable_names.data(),
1140+
&instance_variable_count
1141+
);
1142+
}
10281143

10291144
for (int i = 0; i < instance_variable_count; i++)
10301145
{
10311146
const char* variable_name = instance_variable_names.at(i);
10321147

1033-
if (EnumFunction(variable_name, m_RunnerInterface.StructGetMember(&Instance, variable_name)))
1148+
RValue* member_variable = nullptr;
1149+
AurieStatus last_status = AURIE_SUCCESS;
1150+
1151+
// Try to fetch the variable
1152+
last_status = GetInstanceMember(Instance, variable_name, member_variable);
1153+
1154+
// If we fail we bail
1155+
if (!AurieSuccess(last_status))
1156+
return last_status;
1157+
1158+
// If EnumFunction returns true, we're good to go
1159+
if (EnumFunction(variable_name, member_variable))
10341160
return AURIE_SUCCESS;
10351161
}
10361162

@@ -1467,4 +1593,22 @@ namespace YYTK
14671593

14681594
return AURIE_NOT_IMPLEMENTED;
14691595
}
1596+
1597+
AurieStatus YYTKInterfaceImpl::GetVariableSlot(
1598+
IN const RValue& Object,
1599+
IN const char* VariableName,
1600+
OUT int32_t& Hash
1601+
)
1602+
{
1603+
// TODO: Use variable_struct_get_hash if possible
1604+
if (!m_FindAllocSlot)
1605+
return AURIE_MODULE_INTERNAL_ERROR;
1606+
1607+
Hash = m_FindAllocSlot(
1608+
Object.m_Object,
1609+
VariableName
1610+
);
1611+
1612+
return AURIE_SUCCESS;
1613+
}
14701614
}

YYToolkit/source/YYTK/Module Interface/Interface.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ namespace YYTK
5656
// Needed for RValue array access
5757
// RValue* actual_array = (RValue**)(RValue.m_Pointer)[this_value / sizeof(RValue*)];
5858
int64_t m_RValueArrayOffset = 0;
59+
60+
// Used to add or set a named value in a YYObjectBase structure.
61+
PFN_YYObjectBaseAdd m_AddToYYObjectBase = nullptr;
62+
63+
// Used to turn a name into a hash to use in lookups in the internal hashmap.
64+
// While accessible through variable_struct_get_hash in newer runners,
65+
// some don't have the function.
66+
// In case the name isn't in the hashmap, the function allocates a new slot for it,
67+
// effectively creating the variable inside the object.
68+
PFN_FindAllocSlot m_FindAllocSlot = nullptr;
5969
public:
6070
// Stores plugin callbacks
6171
std::vector<ModuleCallbackDescriptor> m_RegisteredCallbacks;
@@ -266,6 +276,12 @@ namespace YYTK
266276
IN const RValue& Object,
267277
IN std::function<void(CInstance* Self, CInstance* Other)> Method
268278
) override final;
279+
280+
virtual Aurie::AurieStatus GetVariableSlot(
281+
IN const RValue& Object,
282+
IN const char* VariableName,
283+
OUT int32_t& Hash
284+
) override final;
269285
};
270286

271287
inline YYTKInterfaceImpl g_ModuleInterface;

0 commit comments

Comments
 (0)