From 38ef24823a51b8a6cadf87b44c4bcc115288ccf8 Mon Sep 17 00:00:00 2001
From: 1fbff5f83b23d39d38b1dfcb4cac8d9b <0a02d0db@opayq.com>
Date: Fri, 18 Oct 2019 18:54:33 +0200
Subject: [PATCH] DM api
---
byond-extools/byond-extools.vcxproj | 7 --
byond-extools/byond-extools.vcxproj.filters | 6 --
byond-extools/dllmain.cpp | 2 +-
byond-extools/src/core/core.cpp | 12 ++-
byond-extools/src/core/proc_management.cpp | 5 +-
byond-extools/src/dm/_extools_api.dm | 103 ++++++++++++++++++++
6 files changed, 117 insertions(+), 18 deletions(-)
create mode 100644 byond-extools/src/dm/_extools_api.dm
diff --git a/byond-extools/byond-extools.vcxproj b/byond-extools/byond-extools.vcxproj
index 1a37f880..7c693b0d 100644
--- a/byond-extools/byond-extools.vcxproj
+++ b/byond-extools/byond-extools.vcxproj
@@ -170,7 +170,6 @@
-
@@ -182,12 +181,6 @@
-
- Create
- Create
- Create
- Create
-
diff --git a/byond-extools/byond-extools.vcxproj.filters b/byond-extools/byond-extools.vcxproj.filters
index 82f75e79..506cb171 100644
--- a/byond-extools/byond-extools.vcxproj.filters
+++ b/byond-extools/byond-extools.vcxproj.filters
@@ -36,9 +36,6 @@
Header Files
-
- Header Files
-
Header Files\core
@@ -68,9 +65,6 @@
Source Files
-
- Source Files
-
Source Files\core
diff --git a/byond-extools/dllmain.cpp b/byond-extools/dllmain.cpp
index f2665971..8847a896 100644
--- a/byond-extools/dllmain.cpp
+++ b/byond-extools/dllmain.cpp
@@ -1,5 +1,5 @@
// dllmain.cpp : Defines the entry point for the DLL application.
-#include "pch.h"
+#include
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
diff --git a/byond-extools/src/core/core.cpp b/byond-extools/src/core/core.cpp
index 2a08df53..12885e71 100644
--- a/byond-extools/src/core/core.cpp
+++ b/byond-extools/src/core/core.cpp
@@ -34,16 +34,24 @@ unsigned int Core::register_opcode(std::string name, opcode_handler handler)
const char* good = "gucci";
const char* bad = "pain";
-extern "C" __declspec(dllexport) const char* initialize(int n_args, const char* args)
+extern "C" __declspec(dllexport) const char* core_initialize(int n_args, const char* args)
{
if (!Core::initialize())
{
+ MessageBoxA(NULL, "Core init failed!", "damn it", NULL);
return bad;
}
if (!Core::hook_em())
{
+ MessageBoxA(NULL, "Hooking failed!", "damn it", NULL);
return bad;
}
- TFFI::initialize();
+ return good;
+}
+
+extern "C" __declspec(dllexport) const char* tffi_initialize(int n_args, const char* args)
+{
+ if (!TFFI::initialize())
+ return bad;
return good;
}
\ No newline at end of file
diff --git a/byond-extools/src/core/proc_management.cpp b/byond-extools/src/core/proc_management.cpp
index d6822b80..556384f1 100644
--- a/byond-extools/src/core/proc_management.cpp
+++ b/byond-extools/src/core/proc_management.cpp
@@ -42,12 +42,12 @@ int Core::Proc::get_local_varcount()
return setup_entry_varcount->local_var_count;
}
-Core::Proc get_proc(std::string name)
+Core::Proc Core::get_proc(std::string name)
{
return procs_by_name[name];
}
-Core::Proc get_proc(unsigned int id)
+Core::Proc Core::get_proc(unsigned int id)
{
return procs_by_id[id];
}
@@ -72,4 +72,5 @@ bool Core::populate_proc_list()
procs_by_name[p.name] = p;
i++;
}
+ return true;
}
\ No newline at end of file
diff --git a/byond-extools/src/dm/_extools_api.dm b/byond-extools/src/dm/_extools_api.dm
new file mode 100644
index 00000000..fec330b8
--- /dev/null
+++ b/byond-extools/src/dm/_extools_api.dm
@@ -0,0 +1,103 @@
+#define EXTOOLS_SUCCESS "gucci"
+#define EXTOOLS_FAILED "pain"
+
+/*
+ Core - Provides necessary functionality for other modules.
+
+ Must be initialized first before initializing any modules!
+
+*/
+
+/proc/extools_initialize()
+ return call("byond-extools.dll", "core_initialize")() == EXTOOLS_SUCCESS
+
+/*
+ TFFI - Threaded FFI
+
+ All DLL calls are automatically threaded off.
+ Black magic is used to suspend (sleep) the currently executing proc, allowing non-blocking FFI.
+
+ You may call a DLL function and sleep until it returns, pass a callback to be called with the result,
+ or call resolve() on the /datum/promise to receive the return value at any time.
+
+ Example:
+
+
+ var/x = call_wait("sample.dll", "do_work", "arg1", "arg2", "arg3")
+
+ - Calls the do_work function from sample.dll with 3 arguments. The proc sleeps until do_work returns.
+
+
+
+ var/datum/promise/P = call_async("sample.dll", "do_work", "arg1")
+ ... do something else ...
+ var/result = P.resolve()
+
+ - Calls do_work with 1 argument. Returns a promise object. Runs some other code before calling P.resolve() to obtain the result.
+
+
+
+ /proc/print_result(result)
+ world << result
+
+ call_cb("sample.dll", "do_work", /proc/print_result, "arg1", "arg2")
+
+ - Calls do_work with 2 arguments. The callback is invoked with the result as the single argument. Execution resumes immediately.
+
+
+*/
+
+/proc/tffi_initialize()
+ call("byond-extools.dll", "tffi_initialize")() == EXTOOLS_SUCCESS
+
+var/fallback_alerted = FALSE
+var/next_promise_id = 0
+
+/datum/promise
+ var/completed = FALSE
+ var/result = ""
+ var/cb = null
+ var/__id = 0
+
+/datum/promise/New()
+ __id = next_promise_id++ //please don't create more than 10^38 promises in a single tick
+
+//This proc's bytecode is overwritten to allow suspending and resuming on demand.
+//None of the code here should run.
+/datum/promise/proc/__internal_resolve(ref, id)
+ if(!fallback_alerted)
+ world << "TFFI: __internal_resolve has not been rewritten, the TFFI DLL was not loaded correctly."
+ world.log << "TFFI: __internal_resolve has not been rewritten, the TFFI DLL was not loaded correctly."
+ fallback_alerted = TRUE
+ while(!completed)
+ sleep(1)
+ //It might be better to just fail and notify the user that something went wrong.
+
+/datum/promise/proc/__resolve_callback()
+ __internal_resolve("\ref[src]", __id)
+ call(cb)(result)
+
+/datum/promise/proc/resolve()
+ __internal_resolve("\ref[src]", __id)
+ return result
+
+/proc/call_async()
+ var/list/arguments = args.Copy()
+ var/datum/promise/P = new
+ arguments.Insert(1, "\ref[P]")
+ call("byond-extools.dll", "call_async")(arglist(arguments))
+ return P
+
+/proc/call_cb()
+ var/list/arguments = args.Copy()
+ var/callback = arguments[3]
+ arguments.Cut(3, 4)
+ var/datum/promise/P = new
+ P.cb = callback
+ arguments.Insert(1, "\ref[P]")
+ call("byond-extools.dll", "call_async")(arglist(arguments))
+ spawn(0)
+ P.__resolve_callback()
+
+/proc/call_wait()
+ return call_async(arglist(args)).resolve()
\ No newline at end of file