diff options
Diffstat (limited to 'plugins/ruby/ruby.cpp')
| -rw-r--r-- | plugins/ruby/ruby.cpp | 123 |
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); } |
