Skip to content

Commit

Permalink
.NET: Add support for enum returns from method invocations
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Apr 12, 2024
1 parent e910464 commit 0514fd4
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 12 deletions.
6 changes: 6 additions & 0 deletions csharp-api/REFrameworkNET/Method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,12 @@ bool Method::HandleInvokeMember_Internal(System::Object^ obj, array<System::Obje
return true;
}

if (returnType->IsEnum()) {
if (auto underlying = returnType->GetUnderlyingType(); underlying != nullptr) {
returnType = underlying; // easy mode
}
}

const auto raw_rt = (reframework::API::TypeDefinition*)returnType;

#define CONCAT_X_C(X, DOT, C) X ## DOT ## C
Expand Down
17 changes: 15 additions & 2 deletions csharp-api/REFrameworkNET/Proxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ public ref class Proxy : public Reflection::DispatchProxy, public IProxy, public

auto targetReturnType = targetMethod->ReturnType;

if (targetReturnType != nullptr) {
if (targetReturnType == nullptr) {
return nullptr;
}

if (!targetReturnType->IsPrimitive && !targetReturnType->IsEnum) {
if (targetReturnType == String::typeid) {
return result;
}
Expand All @@ -161,7 +165,16 @@ public ref class Proxy : public Reflection::DispatchProxy, public IProxy, public
}
}

if (targetMethod->DeclaringType == nullptr || targetReturnType == nullptr) {
if (targetMethod->ReturnType->IsEnum) {
auto underlyingType = targetMethod->ReturnType->GetEnumUnderlyingType();

if (underlyingType != nullptr) {
auto underlyingResult = Convert::ChangeType(result, underlyingType);
return Enum::ToObject(targetMethod->ReturnType, underlyingResult);
}
}

if (targetMethod->DeclaringType == nullptr) {
return result;
}

Expand Down
46 changes: 36 additions & 10 deletions csharp-api/test/Test/Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,46 @@
public class DangerousFunctions {
public static REFrameworkNET.PreHookResult isInsidePreHook(Span<ulong> args) {
//Console.WriteLine("Inside pre hook (From C#) " + args.ToString());
REFrameworkNET.API.LogInfo("isInsidePreHook");
//REFrameworkNET.API.LogInfo("isInsidePreHook");
return REFrameworkNET.PreHookResult.Continue;
}

public static void isInsidePostHook(ref ulong retval) {
Console.WriteLine("Inside post hook (From C#), retval: " + (retval & 1).ToString());
if ((retval & 1) != 0) {
REFrameworkNET.API.LogInfo("Camera is inside");
}
//Console.WriteLine("Inside post hook (From C#), retval: " + (retval & 1).ToString());
}

public static void Entry() {
var mouse = REFrameworkNET.API.GetNativeSingletonT<via.hid.Mouse>();

mouse.set_ShowCursor(false);

var tdb = REFrameworkNET.API.GetTDB();
tdb.GetType(app.CameraManager.REFType.FullName).
GetMethod("isInside")?.
AddHook(false).
AddPre(isInsidePreHook).
AddPost(isInsidePostHook);

tdb.GetType(app.PlayerInputProcessorDetail.REFType.FullName).
GetMethod("processNormalAttack").
AddHook(false).
AddPre((args) => {
var inputProcessor = ManagedObject.ToManagedObject(args[1]).As<app.PlayerInputProcessorDetail>();
var asIObject = inputProcessor as REFrameworkNET.IObject;
ulong flags = args[2];
bool isCombo = (args[4] & 1) != 0;
API.LogInfo("processNormalAttack: " +
inputProcessor.ToString() + " " +
asIObject.GetTypeDefinition()?.GetFullName()?.ToString() + " " +
flags.ToString() + " " +
isCombo.ToString());
return PreHookResult.Continue;
}).
AddPost((ref ulong retval) => {
});

// These via.SceneManager and via.Scene are
// loaded from an external reference assembly
Expand Down Expand Up @@ -59,10 +84,13 @@ public static void Entry() {

var appdomainStatics = tdb.GetType("System.AppDomain").As<_System.AppDomain>();
var appdomain = appdomainStatics.get_CurrentDomain();
dynamic assemblies = appdomain.GetAssemblies();
var assemblies = appdomain.GetAssemblies();

foreach (REFrameworkNET.ManagedObject assemblyRaw in assemblies) {
var assembly = assemblyRaw.As<_System.Reflection.Assembly>();
// TODO: Make this work! get_length, get_item is ugly!
//foreach (REFrameworkNET.ManagedObject assemblyRaw in assemblies) {
for (int i = 0; i < assemblies.get_Length(); i++) {
//var assembly = assemblyRaw.As<_System.Reflection.Assembly>();
var assembly = assemblies.get_Item(i);
REFrameworkNET.API.LogInfo("Assembly: " + assembly.get_Location()?.ToString());
}

Expand All @@ -76,7 +104,9 @@ public static void Entry() {
REFrameworkNET.API.LogInfo("Title: " + title);

var dialog = tdb.GetTypeT<via.os.dialog>();
dialog.open("Hello from C#!");
var dialogError = dialog.open("Hello from C#!");

REFrameworkNET.API.LogInfo("Dialog error: " + dialogError.ToString());

var devUtil = tdb.GetTypeT<via.sound.dev.DevUtil>();
var currentDirectory = System.IO.Directory.GetCurrentDirectory();
Expand All @@ -92,10 +122,6 @@ public static void Entry() {

REFrameworkNET.API.LogInfo("DevUtil: " + devUtilT.GetFullName());
REFrameworkNET.API.LogInfo("Dialog: " + dialogT.GetFullName());

var mouse = REFrameworkNET.API.GetNativeSingletonT<via.hid.Mouse>();

mouse.set_ShowCursor(false);
}

public static void TryEnableFrameGeneration() {
Expand Down

0 comments on commit 0514fd4

Please sign in to comment.