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