summaryrefslogtreecommitdiff
path: root/plugins/ruby
diff options
context:
space:
mode:
authorjj2012-08-31 15:51:22 +0200
committerjj2012-08-31 15:51:22 +0200
commit54780cac3f03df28d51cfd4a2c59e0dc5369d391 (patch)
treede0f2cc7f982da7bf1443f5740a9fc526eb1bf67 /plugins/ruby
parente6b2cb73af68eeff346baf02359df325c107bd7a (diff)
downloaddfhack-54780cac3f03df28d51cfd4a2c59e0dc5369d391.tar.gz
dfhack-54780cac3f03df28d51cfd4a2c59e0dc5369d391.tar.bz2
dfhack-54780cac3f03df28d51cfd4a2c59e0dc5369d391.tar.xz
ruby: allow vmethod call with 6 args, use direct fptr
Diffstat (limited to 'plugins/ruby')
-rw-r--r--plugins/ruby/README2
-rw-r--r--plugins/ruby/ruby-autogen-defs.rb12
-rw-r--r--plugins/ruby/ruby.cpp32
3 files changed, 25 insertions, 21 deletions
diff --git a/plugins/ruby/README b/plugins/ruby/README
index c9a84fb3..9246fec8 100644
--- a/plugins/ruby/README
+++ b/plugins/ruby/README
@@ -177,7 +177,7 @@ Symbol. This works for array indexes too.
ex: df.unit_find(:selected).status.labors[:HAUL_FOOD] = true
df.map_tile_at(df.cursor).designation.liquid_type = :Water
-Virtual method calls are supported for C++ objects, with a maximum of 4
+Virtual method calls are supported for C++ objects, with a maximum of 6
arguments. Arguments / return value are interpreted as Compound/Enums as
specified in the vmethod definition in the xmls.
diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb
index 0cee6426..87474679 100644
--- a/plugins/ruby/ruby-autogen-defs.rb
+++ b/plugins/ruby/ruby-autogen-defs.rb
@@ -698,8 +698,8 @@ module DFHack
return if not addr
@_tg._at(addr)._get
end
- alias next= _next=
- alias prev= _prev=
+ alias next= _next=
+ alias prev= _prev=
include Enumerable
def each
@@ -795,8 +795,12 @@ module DFHack
v if v != 0
end
- def self.vmethod_call(obj, voff, a0=0, a1=0, a2=0, a3=0, a4=0)
- vmethod_do_call(obj._memaddr, voff, vmethod_arg(a0), vmethod_arg(a1), vmethod_arg(a2), vmethod_arg(a3))
+ def self.vmethod_call(obj, voff, a0=0, a1=0, a2=0, a3=0, a4=0, a5=0)
+ this = obj._memaddr
+ vt = df.get_vtable_ptr(this)
+ fptr = df.memory_read_int32(vt + voff) & 0xffffffff
+ vmethod_do_call(this, fptr, vmethod_arg(a0), vmethod_arg(a1), vmethod_arg(a2),
+ vmethod_arg(a3), vmethod_arg(a4), vmethod_arg(a5))
end
def self.vmethod_arg(arg)
diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp
index 482714d2..d3b269ff 100644
--- a/plugins/ruby/ruby.cpp
+++ b/plugins/ruby/ruby.cpp
@@ -632,7 +632,7 @@ static VALUE rb_dfmemory_patch(VALUE self, VALUE addr, VALUE raw)
bool ret;
ret = Core::getInstance().p->patchMemory((void*)rb_num2ulong(addr),
- rb_string_value_ptr(&raw), strlen);
+ rb_string_value_ptr(&raw), strlen);
return ret ? Qtrue : Qfalse;
}
@@ -838,8 +838,8 @@ static VALUE rb_dfmemory_bitarray_set(VALUE self, VALUE addr, VALUE idx, VALUE v
/* 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
@@ -848,6 +848,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
@@ -855,9 +857,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
@@ -865,25 +865,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");
@@ -902,7 +902,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);