Skip to content
This repository has been archived by the owner on Jan 1, 2025. It is now read-only.

Commit

Permalink
Bug Bash 5/24 (#36)
Browse files Browse the repository at this point in the history
* stamp

* stamp

* TPS support

* big commit
  • Loading branch information
Matt-Hurd authored May 25, 2019
1 parent 92746be commit 49977d9
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 138 deletions.
65 changes: 41 additions & 24 deletions src/BL2-SDK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace BL2SDK
UObject *engine = nullptr;
CHookManager *HookManager = nullptr;
bool injectedCallNext = false;
bool CallPostEdit = true;

CPythonInterface *Python;

Expand Down Expand Up @@ -318,6 +319,11 @@ namespace BL2SDK
}
};

void KeepAlive(UObject *obj) {
for (UObject *outer = obj; outer; outer = outer->Outer)
outer->ObjectFlags.A |= 0x4000;
}

UObject *ConstructObject(UClass* Class, UObject* Outer, FName Name, unsigned int SetFlags, unsigned int InternalSetFlags, UObject* Template, FOutputDevice *Error, void* InstanceGraph, int bAssumeTemplateIsArchetype)
{
if (!Error) {
Expand Down Expand Up @@ -345,28 +351,39 @@ namespace BL2SDK
return HookManager->Remove(funcName, hookName);
}

UObject *LoadTexture(char *Filename, char *TextureName) {
UTexture2D *NewTexture = (UTexture2D *)UObject::Find("Texture2D", std::string("Transient.") + TextureName);
if (NewTexture)
return NewTexture;
int x, y, n;
unsigned char *data = stbi_load(Filename, &x, &y, &n, 4);
if (!data)
throw std::exception("Unable to parse image file");
NewTexture = (UTexture2D *)ConstructObject(UObject::FindClass("Texture2D"), GetEngine()->Outer, FName(TextureName), 0x83, 0, nullptr, nullptr, nullptr, false);
if (!NewTexture)
return nullptr;
NewTexture->ObjectFlags.A |= 0x4000;
NewTexture->SizeX = x;
NewTexture->OriginalSizeX = x;
NewTexture->SizeY = y;
NewTexture->OriginalSizeY = y;
NewTexture->Format = 2;
NewTexture->Mips.Data.Dummy = (int)data;
NewTexture->Mips.ArrayMax = 1;
NewTexture->Mips.ArrayNum = 1;
NewTexture->ResidentMips = 1;
NewTexture->RequestedMips = 1;
return (UObject *)NewTexture;
}
//UObject *LoadTexture(char *Filename, char *TextureName) {
// UTexture2D *NewTexture = (UTexture2D *)UObject::Find("Texture2D", std::string("Transient.") + TextureName);
// if (NewTexture)
// return NewTexture;
// int x, y, n;
// unsigned char *data = stbi_load(Filename, &x, &y, &n, 4);
// if (!data)
// throw std::exception("Unable to parse image file");
// NewTexture = (UTexture2D *)ConstructObject(UObject::FindClass("Texture2D"), GetEngine()->Outer, FName(TextureName), 0x83, 0, nullptr, nullptr, nullptr, false);
// UTexture2D *DefaultTexture = (UTexture2D *)UObject::Find("Texture2D", "Engine.Default__Texture2D ");
// if (!NewTexture)
// return nullptr;
// NewTexture->ObjectFlags.A |= 0x4000;
// NewTexture->SizeX = x;
// NewTexture->OriginalSizeX = x;
// NewTexture->SizeY = y;
// NewTexture->OriginalSizeY = y;
// NewTexture->Format = 2;
// FTexture2DMipMap *MipsData = (FTexture2DMipMap *)calloc(1, sizeof(FTexture2DMipMap));
// MipsData->SizeX = x;
// MipsData->SizeY = y;
// memcpy(&MipsData->Data, &DefaultTexture->Mips.Data[0]->Data, sizeof(FUntypedBulkData_Mirror));
// MipsData->Data.bShouldFreeOnEmpty = 0;
// MipsData->Data.BulkData.Dummy = (int)data;
// NewTexture->Mips.Data = (FTexture2DMipMap **)malloc(sizeof(FTexture2DMipMap *));
// NewTexture->Mips.Data[0] = MipsData;
// NewTexture->Mips.Count = 1;
// NewTexture->Mips.Max = 1;
// NewTexture->ResidentMips = 1;
// FPropertyChangedEvent ChangeEvent {};
// ChangeEvent.Property = (UProperty *)UObject::Find("BoolProperty", "Engine.Texture.SRGB");
// ChangeEvent.ChangeType = 1;
// NewTexture->PostEditChangeProperty(&ChangeEvent);
// return (UObject *)NewTexture;
//}
}
162 changes: 82 additions & 80 deletions src/BL2SDK/Core_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,99 +115,96 @@ pybind11::object FHelper::GetProperty(UProperty *prop) {
return py::none();
}

bool FHelper::SetProperty(class UStructProperty *prop, py::object val) {
void FHelper::SetProperty(class UStructProperty *prop, py::object val) {
if (py::isinstance<py::tuple>(val))
{
py::tuple tup = (py::tuple)val;

unsigned int currentIndex = 0;
for (UProperty* Child = (UProperty *)prop->GetStruct()->Children; Child; Child = (UProperty *)Child->Next)
currentIndex++;

if (tup.size() > currentIndex) {
throw std::exception(Util::Format("FHelper::SetProperty: Not all tuple values converted for struct!\n").c_str());
}

currentIndex = 0;
for (UProperty* Child = (UProperty *)prop->GetStruct()->Children; Child; Child = (UProperty *)Child->Next) {
Logging::LogD("Child = %s, %d\n", Child->GetFullName().c_str(), Child->Offset_Internal);
if (currentIndex < tup.size())
((FHelper *)(((char *)this) + prop->Offset_Internal))->SetProperty(Child, tup[currentIndex++]);
}
if (tup.size() > currentIndex) {
Logging::LogF("Not all tuple values converted for struct!\n");
return false;
}
return true;
}
else if (py::isinstance<FStruct>(val)) {
Logging::LogD("FSTRUCT OMG\n");
}
return false;
else
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected tuple!\n").c_str());
}

bool FHelper::SetProperty(class UStrProperty *prop, py::object val) {
void FHelper::SetProperty(class UStrProperty *prop, py::object val) {
if (!py::isinstance<py::str>(val))
return false;
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected string!\n").c_str());
memcpy(((char *)this) + prop->Offset_Internal, &FString(val.cast<std::string>().c_str()), sizeof(FString));
return true;
}

bool FHelper::SetProperty(class UObjectProperty *prop, py::object val) {
if (!py::isinstance<UObject>(val))
return false;
void FHelper::SetProperty(class UObjectProperty *prop, py::object val) {
if (!py::isinstance<UObject>(val) && !py::isinstance<py::none>(val))
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected UObject!\n").c_str());
((UObject **)(((char *)this) + prop->Offset_Internal))[0] = val.cast<UObject *>();
return true;
}

bool FHelper::SetProperty(class UComponentProperty *prop, py::object val) {
if (!py::isinstance<UComponent>(val))
return false;
void FHelper::SetProperty(class UComponentProperty *prop, py::object val) {
if (!py::isinstance<UComponent>(val) && !py::isinstance<py::none>(val))
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected UComponent!\n").c_str());
((UComponent **)(((char *)this) + prop->Offset_Internal))[0] = val.cast<UComponent *>();
return true;
}

bool FHelper::SetProperty(class UClassProperty *prop, py::object val) {
if (!py::isinstance<UClass>(val))
return false;
void FHelper::SetProperty(class UClassProperty *prop, py::object val) {
if (!py::isinstance<UClass>(val) && !py::isinstance<py::none>(val))
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected UClass!\n").c_str());
((UClass **)(((char *)this) + prop->Offset_Internal))[0] = val.cast<UClass *>();
return true;
}

bool FHelper::SetProperty(class UNameProperty *prop, py::object val) {
void FHelper::SetProperty(class UNameProperty *prop, py::object val) {
if (!py::isinstance<py::str>(val))
return false;
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected string!\n").c_str());
memcpy(((char *)this) + prop->Offset_Internal, &FName(val.cast<std::string>().c_str()), sizeof(FName));
return true;
}

bool FHelper::SetProperty(class UInterfaceProperty *prop, py::object val) {
if (!py::isinstance<UInterface>(val))
return false;
((UInterface **)(((char *)this) + prop->Offset_Internal))[0] = val.cast<UInterface *>();
return true;
void FHelper::SetProperty(class UInterfaceProperty *prop, py::object val) {
if (!py::isinstance<UObject>(val) && !py::isinstance<py::none>(val))
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected UObject!\n").c_str());
if (py::isinstance<py::none>(val))
((FScriptInterface *)(((char *)this) + prop->Offset_Internal))[0] = FScriptInterface{0, 0};
else {
UObject *ObjVal = val.cast<UObject *>();
FScriptInterface interf = ObjVal->QueryInterface(prop->GetInterfaceClass());
((FScriptInterface *)(((char *)this) + prop->Offset_Internal))[0] = interf;
}
}

bool FHelper::SetProperty(class UDelegateProperty *prop, py::object val) {
void FHelper::SetProperty(class UDelegateProperty *prop, py::object val) {
if (!py::isinstance<FScriptDelegate>(val))
return false;
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected FScriptDelegate!\n").c_str());
memcpy(((char *)this) + prop->Offset_Internal, &FScriptDelegate(val.cast<FScriptDelegate>()), sizeof(FScriptDelegate));
return true;
}

bool FHelper::SetProperty(class UFloatProperty *prop, py::object val) {
void FHelper::SetProperty(class UFloatProperty *prop, py::object val) {
Logging::LogD("Set %f\n", val.cast<float>());
((float *)(((char *)this) + prop->Offset_Internal))[0] = val.cast<float>();
return true;
}

bool FHelper::SetProperty(class UIntProperty *prop, py::object val) {
void FHelper::SetProperty(class UIntProperty *prop, py::object val) {
if (!py::isinstance<py::int_>(val))
return false;
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected int!\n").c_str());
((int *)(((char *)this) + prop->Offset_Internal))[0] = val.cast<int>();
return true;
}

bool FHelper::SetProperty(class UByteProperty *prop, py::object val) {
if (!py::isinstance<int>(val) && val.cast<int>() <= 255)
return false;
void FHelper::SetProperty(class UByteProperty *prop, py::object val) {
if (!py::isinstance<py::int_>(val))
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected (char!\n").c_str());
(((char *)this) + prop->Offset_Internal)[0] = (char)val.cast<int>();
return true;
}

bool FHelper::SetProperty(class UBoolProperty *prop, py::object val) {
void FHelper::SetProperty(class UBoolProperty *prop, py::object val) {
try {
Logging::LogD("SetBoolProperty %d, mask: 0x%x, base: 0x%x, offset: 0x%x\n", val.cast<bool>(), prop->GetMask(), this, prop->Offset_Internal);
if (val.cast<bool>())
Expand All @@ -216,60 +213,59 @@ bool FHelper::SetProperty(class UBoolProperty *prop, py::object val) {
((unsigned int *)(((char *)this) + prop->Offset_Internal))[0] &= ~prop->GetMask();
}
catch (std::exception e) {
Logging::LogF(e.what());
throw std::exception(Util::Format("FHelper::SetProperty: %s\n", e.what()).c_str());
}
return true;
}

bool FHelper::SetProperty(class UArrayProperty *prop, py::object val) {
void FHelper::SetProperty(class UArrayProperty *prop, py::object val) {
if (!py::isinstance<py::sequence>(val))
return false;
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected list!\n").c_str());
auto s = py::reinterpret_borrow<py::sequence>(val);
Logging::LogD("A\n");
char *Data = (char *)((tMalloc)BL2SDK::pGMalloc[0]->VfTable[1])(BL2SDK::pGMalloc[0], prop->GetInner()->ElementSize * s.size(), 8);
Logging::LogD("C %d %d %p %p %d %p\n", prop->GetInner()->ElementSize, prop->Offset_Internal, this, Data, s.size(), (TArray<void *> *)(((char *)this) + prop->Offset_Internal));
memset(Data, 0, prop->GetInner()->ElementSize * s.size());
((TArray<void *> *)(((char *)this) + prop->Offset_Internal))->Data = (void **)Data;
((TArray<void *> *)(((char *)this) + prop->Offset_Internal))->Count = s.size();
((TArray<void *> *)(((char *)this) + prop->Offset_Internal))->Max = s.size();
if (s.size() > ((TArray<void *> *)(((char *)this) + prop->Offset_Internal))->Count) {
char *Data = (char *)((tMalloc)BL2SDK::pGMalloc[0]->VfTable[1])(BL2SDK::pGMalloc[0], prop->GetInner()->ElementSize * s.size(), 8);
memset(Data, 0, prop->GetInner()->ElementSize * s.size());
((TArray<char> *)(((char *)this) + prop->Offset_Internal))->Data = Data;
((TArray<char> *)(((char *)this) + prop->Offset_Internal))->Max = s.size();
}
((TArray<char> *)(((char *)this) + prop->Offset_Internal))->Count = s.size();
char *Data = ((TArray<char> *)(((char *)this) + prop->Offset_Internal))->Data;
int x = 0;
for (auto it : val) {
Logging::LogD("%x\n", (Data + prop->GetInner()->ElementSize * x));
((FHelper *)(Data + prop->GetInner()->ElementSize * x++))->SetProperty(prop->GetInner(), py::reinterpret_borrow<py::object>(it));
}
return true;
}

bool FHelper::SetProperty(class UProperty *prop, py::object val) {
void FHelper::SetProperty(class UProperty *prop, py::object val) {
Logging::LogD("FHelper::SetProperty Called with '%s'\n", prop->GetFullName().c_str());
bool ret = false;
if (!strcmp(prop->Class->GetName().c_str(), "StructProperty"))
return SetProperty((UStructProperty *)prop, val);
SetProperty((UStructProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "StrProperty"))
return SetProperty((UStrProperty *)prop, val);
SetProperty((UStrProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "ObjectProperty"))
return SetProperty((UObjectProperty *)prop, val);
SetProperty((UObjectProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "ComponentProperty"))
return SetProperty((UComponentProperty *)prop, val);
SetProperty((UComponentProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "ClassProperty"))
return SetProperty((UClassProperty *)prop, val);
SetProperty((UClassProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "NameProperty"))
return SetProperty((UNameProperty *)prop, val);
SetProperty((UNameProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "IntProperty"))
return SetProperty((UIntProperty *)prop, val);
SetProperty((UIntProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "InterfaceProperty"))
return SetProperty((UInterfaceProperty *)prop, val);
SetProperty((UInterfaceProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "FloatProperty"))
return SetProperty((UFloatProperty *)prop, val);
SetProperty((UFloatProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "DelegateProperty"))
return SetProperty((UDelegateProperty *)prop, val);
SetProperty((UDelegateProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "ByteProperty"))
return SetProperty((UByteProperty *)prop, val);
SetProperty((UByteProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "BoolProperty"))
return SetProperty((UBoolProperty *)prop, val);
SetProperty((UBoolProperty *)prop, val);
else if (!strcmp(prop->Class->GetName().c_str(), "ArrayProperty"))
return SetProperty((UArrayProperty *)prop, val);
throw std::exception(Util::Format("FHelper::SetProperty got unexpected property type '%s'", prop->GetFullName().c_str()).c_str());
return false;
SetProperty((UArrayProperty *)prop, val);
else
throw std::exception(Util::Format("FHelper::SetProperty got unexpected property type '%s'", prop->GetFullName().c_str()).c_str());
}

TArray< UObject* >* UObject::GObjects()
Expand Down Expand Up @@ -429,15 +425,21 @@ pybind11::object UObject::GetProperty(std::string PropName) {
return pybind11::none();
}

bool UObject::SetProperty(std::string& PropName, py::object val) {
void UObject::SetProperty(std::string& PropName, py::object val) {
class UObject *obj = this->Class->FindChildByName(FName(PropName));
if (!obj)
return false;
return;
auto prop = reinterpret_cast<UProperty *>(obj);
if (!strcmp(obj->Class->GetName().c_str(), "Function"))
return ((FHelper *)((char *)this))->SetProperty((UObjectProperty *)prop, val);
((FHelper *)((char *)this))->SetProperty((UObjectProperty *)prop, val);
else
return ((FHelper *)((char *)this))->SetProperty(prop, val);
((FHelper *)((char *)this))->SetProperty(prop, val);
if (BL2SDK::CallPostEdit) {
FPropertyChangedEvent ChangeEvent{};
ChangeEvent.Property = prop;
ChangeEvent.ChangeType = 1;
PostEditChangeProperty(&ChangeEvent);
}
}


Expand Down Expand Up @@ -3865,7 +3867,7 @@ FScriptInterface UObject::QueryInterface(class UClass* InterfaceClass)
{
static auto fn = (UFunction *)UObject::Find("Function", "Core.Object.QueryInterface");

UObject_QueryInterface_Params params;
struct UObject_QueryInterface_Params params;
params.InterfaceClass = InterfaceClass;

auto flags = fn->FunctionFlags;
Expand Down
2 changes: 0 additions & 2 deletions src/BL2SDK/GFxUI_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ class UAkEvent* UGFxManager::LookupSound(const struct FName& UIEvent)
return params.ReturnValue;
}


// Function GFxUI.GFxManager.ShowDialog
// (Event, Public)
// Parameters:
Expand All @@ -232,7 +231,6 @@ FScriptInterface UGFxManager::ShowDialog(class APlayerController* PC)
return params.ReturnValue;
}


// Function GFxUI.GFxManager.Init
// (Defined, Event, Public)
// Parameters:
Expand Down
4 changes: 3 additions & 1 deletion src/CPythonInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ PYBIND11_EMBEDDED_MODULE(bl2sdk, m)

m.def("Log", [](std::string in) { Logging::LogPy(in.c_str()); });
m.def("LoadPackage", &BL2SDK::LoadPackage, py::arg("filename"), py::arg("flags") = 0, py::arg("force") = false);
m.def("KeepAlive", &BL2SDK::KeepAlive);
m.def("FindObject", [](char *ClassName, char *ObjectFullName) { return UObject::Find(ClassName, ObjectFullName); }, py::return_value_policy::reference);
m.def("FindObject", [](UClass *Class, char *ObjectFullName) { return UObject::Find(Class, ObjectFullName); }, py::return_value_policy::reference);
m.def("LoadObject", [](char *ClassName, char *ObjectFullName) { return UObject::Load(ClassName, ObjectFullName); }, py::return_value_policy::reference);
m.def("LoadObject", [](UClass *Class, char *ObjectFullName) { return UObject::Load(Class, ObjectFullName); }, py::return_value_policy::reference);
m.def("LoadTexture", &BL2SDK::LoadTexture, py::return_value_policy::reference);
//m.def("LoadTexture", &BL2SDK::LoadTexture, py::return_value_policy::reference);
m.def("SetLoggingLevel", &Logging::SetLoggingLevel);
m.def("ConstructObject", &BL2SDK::ConstructObject, "Construct Objects", py::arg("Class"), py::arg("Outer") = BL2SDK::GetEngine()->Outer, py::arg("Name") = FName(), py::arg("SetFlags") = 0x1, py::arg("InternalSetFlags") = 0x00, py::arg("Template") = (UObject*)nullptr, py::arg("Error") = (FOutputDevice *)nullptr, py::arg("InstanceGraph") = (void*)nullptr, py::arg("bAssumeTemplateIsArchetype") = (int)0, py::return_value_policy::reference);
m.def("ConstructObject", [](char *ClassName, UObject* Outer, FName Name, unsigned int SetFlags, unsigned int InternalSetFlags, UObject* Template, FOutputDevice *Error, void* InstanceGraph, int bAssumeTemplateIsArchetype) {
Expand All @@ -90,6 +91,7 @@ PYBIND11_EMBEDDED_MODULE(bl2sdk, m)
m.def("RemoveHook", [](const std::string& funcName, const std::string& hookName) { BL2SDK::RemoveHook(funcName, hookName); });
m.def("DoInjectedCallNext", &BL2SDK::doInjectedCallNext);
m.def("LogAllCalls", &BL2SDK::LogAllCalls);
m.def("CallPostEdit", [](bool NewValue) { BL2SDK::CallPostEdit = NewValue; });
}

void AddToConsoleLog(UConsole *console, FString input) {
Expand Down
Loading

0 comments on commit 49977d9

Please sign in to comment.