summaryrefslogtreecommitdiff
path: root/plugins/ruby/ruby.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ruby/ruby.cpp')
-rw-r--r--plugins/ruby/ruby.cpp123
1 files changed, 106 insertions, 17 deletions
diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp
index 1391faa4..7bd6d13e 100644
--- a/plugins/ruby/ruby.cpp
+++ b/plugins/ruby/ruby.cpp
@@ -4,6 +4,7 @@
#include "Export.h"
#include "PluginManager.h"
#include "VersionInfo.h"
+#include "MemAccess.h"
#include "DataDefs.h"
#include "df/global_objects.h"
@@ -204,8 +205,6 @@ DFhackCExport command_result plugin_onstatechange ( color_ostream &out, state_ch
static command_result df_rubyeval(color_ostream &out, std::vector <std::string> & parameters)
{
- command_result ret;
-
if (parameters.size() == 1 && (parameters[0] == "help" || parameters[0] == "?"))
{
out.print("This command executes an arbitrary ruby statement.\n");
@@ -597,6 +596,45 @@ static VALUE rb_dfmemory_write_float(VALUE self, VALUE addr, VALUE val)
return Qtrue;
}
+// return memory permissions at address (eg "rx", nil if unmapped)
+static VALUE rb_dfmemory_check(VALUE self, VALUE addr)
+{
+ void *ptr = (void*)rb_num2ulong(addr);
+ std::vector<t_memrange> ranges;
+ Core::getInstance().p->getMemRanges(ranges);
+
+ unsigned i = 0;
+ while (i < ranges.size() && ranges[i].end <= ptr)
+ i++;
+
+ if (i >= ranges.size() || ranges[i].start > ptr || !ranges[i].valid)
+ return Qnil;
+
+ std::string perm = "";
+ if (ranges[i].read)
+ perm += "r";
+ if (ranges[i].write)
+ perm += "w";
+ if (ranges[i].execute)
+ perm += "x";
+ if (ranges[i].shared)
+ perm += "s";
+
+ return rb_str_new(perm.c_str(), perm.length());
+}
+
+// memory write (tmp override page permissions, eg patch code)
+static VALUE rb_dfmemory_patch(VALUE self, VALUE addr, VALUE raw)
+{
+ int strlen = FIX2INT(rb_funcall(raw, rb_intern("length"), 0));
+ bool ret;
+
+ ret = Core::getInstance().p->patchMemory((void*)rb_num2ulong(addr),
+ rb_string_value_ptr(&raw), strlen);
+
+ return ret ? Qtrue : Qfalse;
+}
+
// stl::string
static VALUE rb_dfmemory_stlstring_new(VALUE self)
@@ -795,11 +833,54 @@ static VALUE rb_dfmemory_bitarray_set(VALUE self, VALUE addr, VALUE idx, VALUE v
return Qtrue;
}
+// add basic support for std::set<uint32> used for passing keyboard keys to viewscreens
+#include <set>
+static VALUE rb_dfmemory_set_new(VALUE self)
+{
+ std::set<unsigned long> *ptr = new std::set<unsigned long>;
+ return rb_uint2inum((uint32_t)ptr);
+}
+
+static VALUE rb_dfmemory_set_delete(VALUE self, VALUE set)
+{
+ std::set<unsigned long> *ptr = (std::set<unsigned long>*)rb_num2ulong(set);
+ if (ptr)
+ delete ptr;
+ return Qtrue;
+}
+
+static VALUE rb_dfmemory_set_set(VALUE self, VALUE set, VALUE key)
+{
+ std::set<unsigned long> *ptr = (std::set<unsigned long>*)rb_num2ulong(set);
+ ptr->insert(rb_num2ulong(key));
+ return Qtrue;
+}
+
+static VALUE rb_dfmemory_set_isset(VALUE self, VALUE set, VALUE key)
+{
+ std::set<unsigned long> *ptr = (std::set<unsigned long>*)rb_num2ulong(set);
+ return ptr->count(rb_num2ulong(key)) ? Qtrue : Qfalse;
+}
+
+static VALUE rb_dfmemory_set_deletekey(VALUE self, VALUE set, VALUE key)
+{
+ std::set<unsigned long> *ptr = (std::set<unsigned long>*)rb_num2ulong(set);
+ ptr->erase(rb_num2ulong(key));
+ return Qtrue;
+}
+
+static VALUE rb_dfmemory_set_clear(VALUE self, VALUE set)
+{
+ std::set<unsigned long> *ptr = (std::set<unsigned long>*)rb_num2ulong(set);
+ ptr->clear();
+ return Qtrue;
+}
+
/* call an arbitrary object virtual method */
#ifdef WIN32
-__declspec(naked) static int raw_vcall(char **that, unsigned long voff, unsigned long a0,
- unsigned long a1, unsigned long a2, unsigned long a3)
+__declspec(naked) static int raw_vcall(void *that, void *fptr, unsigned long a0,
+ unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5)
{
// __thiscall requires that the callee cleans up the stack
// here we dont know how many arguments it will take, so
@@ -808,6 +889,8 @@ __declspec(naked) static int raw_vcall(char **that, unsigned long voff, unsigned
push ebp
mov ebp, esp
+ push a5
+ push a4
push a3
push a2
push a1
@@ -815,9 +898,7 @@ __declspec(naked) static int raw_vcall(char **that, unsigned long voff, unsigned
mov ecx, that
- mov eax, [ecx]
- add eax, voff
- call [eax]
+ call fptr
mov esp, ebp
pop ebp
@@ -825,25 +906,25 @@ __declspec(naked) static int raw_vcall(char **that, unsigned long voff, unsigned
}
}
#else
-static int raw_vcall(char **that, unsigned long voff, unsigned long a0,
- unsigned long a1, unsigned long a2, unsigned long a3)
+static int raw_vcall(void *that, void *fptr, unsigned long a0,
+ unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5)
{
- int (*fptr)(char **me, int, int, int, int);
- fptr = (decltype(fptr))*(void**)(*that + voff);
- return fptr(that, a0, a1, a2, a3);
+ int (*t_fptr)(void *me, int, int, int, int, int, int);
+ t_fptr = (decltype(t_fptr))fptr;
+ return t_fptr(that, a0, a1, a2, a3, a4, a5);
}
#endif
// call an arbitrary vmethod, convert args/ret to native values for raw_vcall
-static VALUE rb_dfvcall(VALUE self, VALUE cppobj, VALUE cppvoff, VALUE a0, VALUE a1, VALUE a2, VALUE a3)
+static VALUE rb_dfvcall(VALUE self, VALUE cppobj, VALUE fptr, VALUE a0, VALUE a1, VALUE a2, VALUE a3, VALUE a4, VALUE a5)
{
- return rb_int2inum(raw_vcall((char**)rb_num2ulong(cppobj), rb_num2ulong(cppvoff),
+ return rb_int2inum(raw_vcall((void*)rb_num2ulong(cppobj), (void*)rb_num2ulong(fptr),
rb_num2ulong(a0), rb_num2ulong(a1),
- rb_num2ulong(a2), rb_num2ulong(a3)));
+ rb_num2ulong(a2), rb_num2ulong(a3),
+ rb_num2ulong(a4), rb_num2ulong(a5)));
}
-
// define module DFHack and its methods
static void ruby_bind_dfhack(void) {
rb_cDFHack = rb_define_module("DFHack");
@@ -862,7 +943,7 @@ static void ruby_bind_dfhack(void) {
rb_define_singleton_method(rb_cDFHack, "print_err", RUBY_METHOD_FUNC(rb_dfprint_err), 1);
rb_define_singleton_method(rb_cDFHack, "malloc", RUBY_METHOD_FUNC(rb_dfmalloc), 1);
rb_define_singleton_method(rb_cDFHack, "free", RUBY_METHOD_FUNC(rb_dffree), 1);
- rb_define_singleton_method(rb_cDFHack, "vmethod_do_call", RUBY_METHOD_FUNC(rb_dfvcall), 6);
+ rb_define_singleton_method(rb_cDFHack, "vmethod_do_call", RUBY_METHOD_FUNC(rb_dfvcall), 8);
rb_define_singleton_method(rb_cDFHack, "memory_read", RUBY_METHOD_FUNC(rb_dfmemory_read), 2);
rb_define_singleton_method(rb_cDFHack, "memory_read_int8", RUBY_METHOD_FUNC(rb_dfmemory_read_int8), 1);
@@ -875,6 +956,8 @@ static void ruby_bind_dfhack(void) {
rb_define_singleton_method(rb_cDFHack, "memory_write_int16", RUBY_METHOD_FUNC(rb_dfmemory_write_int16), 2);
rb_define_singleton_method(rb_cDFHack, "memory_write_int32", RUBY_METHOD_FUNC(rb_dfmemory_write_int32), 2);
rb_define_singleton_method(rb_cDFHack, "memory_write_float", RUBY_METHOD_FUNC(rb_dfmemory_write_float), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_check", RUBY_METHOD_FUNC(rb_dfmemory_check), 1);
+ rb_define_singleton_method(rb_cDFHack, "memory_patch", RUBY_METHOD_FUNC(rb_dfmemory_patch), 2);
rb_define_singleton_method(rb_cDFHack, "memory_stlstring_new", RUBY_METHOD_FUNC(rb_dfmemory_stlstring_new), 0);
rb_define_singleton_method(rb_cDFHack, "memory_stlstring_delete", RUBY_METHOD_FUNC(rb_dfmemory_stlstring_delete), 1);
@@ -908,4 +991,10 @@ static void ruby_bind_dfhack(void) {
rb_define_singleton_method(rb_cDFHack, "memory_bitarray_resize", RUBY_METHOD_FUNC(rb_dfmemory_bitarray_resize), 2);
rb_define_singleton_method(rb_cDFHack, "memory_bitarray_isset", RUBY_METHOD_FUNC(rb_dfmemory_bitarray_isset), 2);
rb_define_singleton_method(rb_cDFHack, "memory_bitarray_set", RUBY_METHOD_FUNC(rb_dfmemory_bitarray_set), 3);
+ rb_define_singleton_method(rb_cDFHack, "memory_stlset_new", RUBY_METHOD_FUNC(rb_dfmemory_set_new), 0);
+ rb_define_singleton_method(rb_cDFHack, "memory_stlset_delete", RUBY_METHOD_FUNC(rb_dfmemory_set_delete), 1);
+ rb_define_singleton_method(rb_cDFHack, "memory_stlset_set", RUBY_METHOD_FUNC(rb_dfmemory_set_set), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_stlset_isset", RUBY_METHOD_FUNC(rb_dfmemory_set_isset), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_stlset_deletekey", RUBY_METHOD_FUNC(rb_dfmemory_set_deletekey), 2);
+ rb_define_singleton_method(rb_cDFHack, "memory_stlset_clear", RUBY_METHOD_FUNC(rb_dfmemory_set_clear), 1);
}