diff --git a/plugins/ruby/ruby-memstruct.rb b/plugins/ruby/ruby-memstruct.rb index f4afe8761..6ef3873cf 100644 --- a/plugins/ruby/ruby-memstruct.rb +++ b/plugins/ruby/ruby-memstruct.rb @@ -77,36 +77,65 @@ class Number < MemStruct @_bits = bits @_signed = signed end + + def _get + v = case @_bits + when 32; DFHack.memory_read_int32(@_memaddr) + when 16; DFHack.memory_read_int16(@_memaddr) + when 8; DFHack.memory_read_int8( @_memaddr) + when 64;(DFHack.memory_read_int32(@_memaddr) & 0xffffffff) + (DFHack.memory_read_int32(@_memaddr+4) << 32) + end + v &= (1 << @_bits) - 1 if not @_signed + v + end + + def _set(v) + case @_bits + when 32; DFHack.memory_write_int32(@_memaddr, v) + when 16; DFHack.memory_write_int16(@_memaddr, v) + when 8; DFHack.memory_write_int8( @_memaddr, v) + when 64; DFHack.memory_write_int32(@_memaddr, v & 0xffffffff) ; DFHack.memory_write_int32(@memaddr+4, v>>32) + end + end end class Float < MemStruct + # _get/_set defined in ruby.cpp + def _get + DFHack.memory_read_float(@_memaddr) + end + + def _set(v) + DFHack.memory_write_float(@_memaddr, v) + end end -class BitField < Number +class BitField < MemStruct attr_accessor :_shift, :_len def initialize(shift, len) @_shift = shift @_len = len - super(32, false) + end + def _mask + (1 << @_len) - 1 end - def _get(whole=false) - v = super() - return v if whole - v = (v >> @_shift) % (1 << @_len) + def _get + v = DFHack.memory_read_int32(@_memaddr) >> @_shift if @_len == 1 - v == 0 ? false : true + ((v & 1) == 0) ? false : true else - v + v & _mask end end def _set(v) if @_len == 1 + # allow 'bit = 0' v = (v && v != 0 ? 1 : 0) end - v = ((v % (1 << @_len)) << @_shift) + v = (v & _mask) << @_shift - ori = _get(true) - super(ori - (ori & (-1 % (1 << @_len)) << @_shift) + v) + ori = DFHack.memory_read_int32(@_memaddr) & 0xffffffff + DFHack.memory_write_int32(@_memaddr, ori - (ori & ((-1 & _mask) << @_shift)) + v) end end @@ -116,6 +145,30 @@ class Pointer < MemStruct @_tglen = tglen @_tg = tg end + + def _getp + DFHack.memory_read_int32(@_memaddr) & 0xffffffff + end + def _setp(v) + DFHack.memory_write_int32(@_memaddr, v) + end + + # _getp/_setp defined in ruby.cpp, access the pointer value + def _get + addr = _getp + return if addr == 0 # XXX are there pointers with -1 as 'empty' value ? + @_tg._at(addr)._get + end + def _set(v) + addr = _getp + raise 'null pointer' if addr == 0 # TODO malloc ? + @_tg._at(addr)._set(v) + end + + # the pointer is invisible, forward all methods to the pointed object + def method_missing(*a) + _get.send(*a) + end end class StaticArray < MemStruct attr_accessor :_tglen, :_length, :_tg @@ -124,21 +177,21 @@ class StaticArray < MemStruct @_length = length @_tg = tg end - def _set(a) ; a.each_with_index { |v, i| self[i] = v } ; end + def _set(a) + a.each_with_index { |v, i| self[i] = v } + end alias length _length alias size _length def _tgat(i) - tg._at(@_memaddr + i*@_tglen) + @_tg._at(@_memaddr + i*@_tglen) if i >= 0 and i < @_length end def [](i) - if (i > 0) or (@_length and i < @_length) - tgat(i)._get - end + i += @_length if i < 0 + tgat(i)._get end def []=(i, v) - if (i > 0) or (@_length and i < @_length) - tgat(i)._set - end + i += @_length if i < 0 + tgat(i)._set(v) end end class StaticString < MemStruct @@ -146,6 +199,12 @@ class StaticString < MemStruct def initialize(length) @_length = length end + def _get + DFHack.memory_read(@_memaddr, @_length) + end + def _set(v) + DFHack.memory_write(@_memaddr, v[0, @_length]) + end end class StlVector < MemStruct @@ -154,10 +213,87 @@ class StlVector < MemStruct @_tglen = tglen @_tg = tg end + + def length + case @_tglen + when 1; DFHack.memory_vector8_length(@_memaddr) + when 2; DFHack.memory_vector16_length(@_memaddr) + else DFHack.memory_vector32_length(@_memaddr) + end + end + alias size length + + def value_at(idx) + case @_tglen + when 1; DFHack.memory_vector8_at(@_memaddr, idx) + when 2; DFHack.memory_vector16_at(@_memaddr, idx) + else DFHack.memory_vector32_at(@_memaddr, idx) + end + end + def insert_at(idx, val) + case @_tglen + when 1; DFHack.memory_vector8_insert(@_memaddr, idx, val) + when 2; DFHack.memory_vector16_insert(@_memaddr, idx, val) + else DFHack.memory_vector32_insert(@_memaddr, idx, val) + end + end + def delete_at(idx) + case @_tglen + when 1; DFHack.memory_vector8_delete(@_memaddr, idx) + when 2; DFHack.memory_vector16_delete(@_memaddr, idx) + else DFHack.memory_vector32_delete(@_memaddr, idx) + end + end + + def _set(v) + delete_at(length-1) while length > v.length # match lengthes + v.each_with_index { |e, i| self[i] = e } # patch entries + end + + def clear + delete_at(length-1) while length > 0 + end + def [](idx) + idx += length if idx < 0 + @_tg._at(value_at(idx)) if idx >= 0 and idx < length + end + def []=(idx, v) + idx += length if idx < 0 + if idx >= length + insert_at(idx, v) + elsif idx < 0 + raise 'invalid idx' + else + set_value_at(idx, v) + end + end + def <<(v) + insert_at(length, v) + self + end + def pop + l = length + if l > 0 + v = self[l-1] + delete_at(l-1) + end + v + end + def to_a + (0...length).map { |i| self[i] } + end end class StlString < MemStruct + def _get + DFHack.memory_read_stlstring(@_memaddr) + end + + def _set(v) + DFHack.memory_write_stlstring(@_memaddr, v) + end end class StlBitVector < MemStruct + # TODO end class StlDeque < MemStruct attr_accessor :_tglen, :_tg @@ -168,6 +304,7 @@ class StlDeque < MemStruct end class DfFlagarray < MemStruct + # TODO end class DfArray < MemStruct attr_accessor :_tglen, :_tg @@ -175,6 +312,8 @@ class DfArray < MemStruct @_tglen = tglen @_tg = tg end + + # TODO end class DfLinkedList < MemStruct attr_accessor :_tg diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp index 74755424f..7230b0d91 100644 --- a/plugins/ruby/ruby.cpp +++ b/plugins/ruby/ruby.cpp @@ -12,14 +12,16 @@ #include -using std::string; -using std::vector; using namespace DFHack; + +// DFHack stuff + + static void df_rubythread(void*); -static command_result df_rubyload(color_ostream &out, vector & parameters); -static command_result df_rubyeval(color_ostream &out, vector & parameters); +static command_result df_rubyload(color_ostream &out, std::vector & parameters); +static command_result df_rubyeval(color_ostream &out, std::vector & parameters); static void ruby_bind_dfhack(void); // inter-thread communication stuff @@ -39,7 +41,6 @@ static command_result r_result; static tthread::thread *r_thread; static int onupdate_active; -// dfhack interface DFHACK_PLUGIN("ruby") DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) @@ -122,7 +123,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) return ret; } -static command_result df_rubyload(color_ostream &out, vector & parameters) +static command_result df_rubyload(color_ostream &out, std::vector & parameters) { command_result ret; @@ -154,7 +155,7 @@ static command_result df_rubyload(color_ostream &out, vector & paramete return ret; } -static command_result df_rubyeval(color_ostream &out, vector & parameters) +static command_result df_rubyeval(color_ostream &out, std::vector & parameters) { command_result ret; @@ -195,6 +196,8 @@ static command_result df_rubyeval(color_ostream &out, vector & paramete +// ruby stuff + // ruby thread code static void dump_rb_error(void) { @@ -275,12 +278,12 @@ static void df_rubythread(void *p) -// ruby classes +// main DFHack ruby module static VALUE rb_cDFHack; -static VALUE rb_c_WrapData; -// DFHack methods +// DFHack module ruby methods, binds specific dfhack methods + // enable/disable calls to DFHack.onupdate() static VALUE rb_dfonupdateactive(VALUE self) { @@ -308,16 +311,33 @@ static VALUE rb_dfsuspend(VALUE self) return Qtrue; } -/* -static VALUE rb_dfgetversion(VALUE self) +// returns the delta to apply to dfhack xml addrs wrt actual memory addresses +// usage: real_addr = addr_from_xml + this_delta; +static VALUE rb_dfrebase_delta(void) { - return rb_str_new2(getcore().vinfo->getVersion().c_str()); + uint32_t expected_base_address; + uint32_t actual_base_address = 0; +#ifdef WIN32 + expected_base_address = 0x00400000; + actual_base_address = (uint32_t)GetModuleHandle(0); +#else + expected_base_address = 0x08048000; + FILE *f = fopen("/proc/self/maps", "r"); + char line[256]; + while (fgets(line, sizeof(line), f)) { + if (strstr(line, "libs/Dwarf_Fortress")) { + actual_base_address = strtoul(line, 0, 16); + break; + } + } +#endif + + return rb_int2inum(actual_base_address - expected_base_address); } -*/ -// TODO color_ostream proxy yadda yadda static VALUE rb_dfprint_str(VALUE self, VALUE s) { + // TODO color_ostream proxy yadda yadda //getcore().con.print("%s", rb_string_value_ptr(&s)); Core::printerr("%s", rb_string_value_ptr(&s)); return Qnil; @@ -329,22 +349,30 @@ static VALUE rb_dfprint_err(VALUE self, VALUE s) return Qnil; } -// raw memory access -// WARNING: may cause game crash ! double-check your addresses ! -static VALUE rb_dfmemread(VALUE self, VALUE addr, VALUE len) +/* TODO needs main dfhack support + this needs a custom DFHack::Plugin subclass to pass the cmdname to invoke(), to match the ruby callback +// register a ruby method as dfhack console command +// usage: DFHack.register("moo", "this commands prints moo on the console") { DFHack.puts "moo !" } +static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr) { - return rb_str_new((char*)rb_num2ulong(addr), rb_num2ulong(len)); -} + commands.push_back(PluginCommand(rb_string_value_ptr(&name), + rb_string_value_ptr(&descr), + df_rubycustom)); -static VALUE rb_dfmemwrite(VALUE self, VALUE addr, VALUE raw) + return Qtrue; +} +*/ +static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr) { - // no stable api for raw.length between rb1.8/rb1.9 ... - int strlen = FIX2INT(rb_funcall(raw, rb_intern("length"), 0)); + rb_raise(rb_eRuntimeError, "not implemented"); +} - memcpy((void*)rb_num2ulong(addr), rb_string_value_ptr(&raw), strlen); - return Qtrue; -} + + +// raw memory access +// used by the ruby class definitions +// WARNING: may cause game crash ! double-check your addresses ! static VALUE rb_dfmalloc(VALUE self, VALUE len) { @@ -357,214 +385,170 @@ static VALUE rb_dffree(VALUE self, VALUE ptr) return Qtrue; } -// raw c++ wrappers -// return the nth element of a vector -static VALUE rb_dfvectorat(VALUE self, VALUE vect_addr, VALUE idx) + +// memory reading (buffer) +static VALUE rb_dfmemory_read(VALUE self, VALUE addr, VALUE len) { - vector *v = (vector*)rb_num2ulong(vect_addr); - return rb_uint2inum(v->at(FIX2INT(idx))); + return rb_str_new((char*)rb_num2ulong(addr), rb_num2ulong(len)); } - -// return a c++ string as a ruby string (nul-terminated) -static VALUE rb_dfreadstring(VALUE self, VALUE str_addr) +static VALUE rb_dfmemory_read_stlstring(VALUE self, VALUE addr) { - string *s = (string*)rb_num2ulong(str_addr); - return rb_str_new2(s->c_str()); + std::string *s = (std::string*)rb_num2ulong(addr); + return rb_str_new(s->c_str(), s->length()); } - - - -/* XXX this needs a custom DFHack::Plugin subclass to pass the cmdname to invoke(), to match the ruby callback -// register a ruby method as dfhack console command -// usage: DFHack.register("moo", "this commands prints moo on the console") { DFHack.puts "moo !" } -static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr) +// memory reading (integers/floats) +static VALUE rb_dfmemory_read_int8(VALUE self, VALUE addr) { - commands.push_back(PluginCommand(rb_string_value_ptr(&name), - rb_string_value_ptr(&descr), - df_rubycustom)); - - return Qtrue; + return rb_int2inum(*(char*)rb_num2ulong(addr)); } -*/ -static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr) +static VALUE rb_dfmemory_read_int16(VALUE self, VALUE addr) { - rb_raise(rb_eRuntimeError, "not implemented"); + return rb_int2inum(*(short*)rb_num2ulong(addr)); } - - -// return the address of the struct in DF memory (for raw memread/write) -static VALUE rb_memaddr(VALUE self) +static VALUE rb_dfmemory_read_int32(VALUE self, VALUE addr) { - void *data; - Data_Get_Struct(self, void, data); - - return rb_uint2inum((uint32_t)data); + return rb_int2inum(*(int*)rb_num2ulong(addr)); } +static VALUE rb_dfmemory_read_float(VALUE self, VALUE addr) +{ + return rb_float_new(*(float*)rb_num2ulong(addr)); +} +// memory writing (buffer) +static VALUE rb_dfmemory_write(VALUE self, VALUE addr, VALUE raw) +{ + // no stable api for raw.length between rb1.8/rb1.9 ... + int strlen = FIX2INT(rb_funcall(raw, rb_intern("length"), 0)); -// BEGIN GENERATED SECTION - -// begin generated T_cursor binding -static VALUE rb_c_T_cursor; + memcpy((void*)rb_num2ulong(addr), rb_string_value_ptr(&raw), strlen); -static VALUE rb_m_T_cursor_x(VALUE self) { - struct df::global::T_cursor *var; - Data_Get_Struct(self, struct df::global::T_cursor, var); - return rb_uint2inum(var->x); + return Qtrue; } -static VALUE rb_m_T_cursor_x_set(VALUE self, VALUE val) { - struct df::global::T_cursor *var; - Data_Get_Struct(self, struct df::global::T_cursor, var); - var->x = rb_num2ulong(val); +static VALUE rb_dfmemory_write_stlstring(VALUE self, VALUE addr, VALUE val) +{ + std::string *s = (std::string*)rb_num2ulong(addr); + int strlen = FIX2INT(rb_funcall(val, rb_intern("length"), 0)); + s->assign(rb_string_value_ptr(&val), strlen); return Qtrue; } -static VALUE rb_m_T_cursor_y(VALUE self) { - struct df::global::T_cursor *var; - Data_Get_Struct(self, struct df::global::T_cursor, var); - return rb_uint2inum(var->y); -} -static VALUE rb_m_T_cursor_y_set(VALUE self, VALUE val) { - struct df::global::T_cursor *var; - Data_Get_Struct(self, struct df::global::T_cursor, var); - var->y = rb_num2ulong(val); +// memory writing (integers/floats) +static VALUE rb_dfmemory_write_int8(VALUE self, VALUE addr, VALUE val) +{ + *(char*)rb_num2ulong(addr) = rb_num2ulong(val); return Qtrue; } - -static VALUE rb_m_T_cursor_z(VALUE self) { - struct df::global::T_cursor *var; - Data_Get_Struct(self, struct df::global::T_cursor, var); - return rb_uint2inum(var->z); +static VALUE rb_dfmemory_write_int16(VALUE self, VALUE addr, VALUE val) +{ + *(short*)rb_num2ulong(addr) = rb_num2ulong(val); + return Qtrue; } -static VALUE rb_m_T_cursor_z_set(VALUE self, VALUE val) { - struct df::global::T_cursor *var; - Data_Get_Struct(self, struct df::global::T_cursor, var); - var->z = rb_num2ulong(val); +static VALUE rb_dfmemory_write_int32(VALUE self, VALUE addr, VALUE val) +{ + *(int*)rb_num2ulong(addr) = rb_num2ulong(val); return Qtrue; } -// link methods to the class -static void ruby_bind_T_cursor(void) { - // create a class, child of WrapData, in module DFHack - rb_c_T_cursor = rb_define_class_under(rb_cDFHack, "T_cursor", rb_c_WrapData); - - // reader for 'x' (0 = no arg) - rb_define_method(rb_c_T_cursor, "x", RUBY_METHOD_FUNC(rb_m_T_cursor_x), 0); - // writer for 'x' (1 arg) - rb_define_method(rb_c_T_cursor, "x=", RUBY_METHOD_FUNC(rb_m_T_cursor_x_set), 1); - rb_define_method(rb_c_T_cursor, "y", RUBY_METHOD_FUNC(rb_m_T_cursor_y), 0); - rb_define_method(rb_c_T_cursor, "y=", RUBY_METHOD_FUNC(rb_m_T_cursor_y_set), 1); - rb_define_method(rb_c_T_cursor, "z", RUBY_METHOD_FUNC(rb_m_T_cursor_z), 0); - rb_define_method(rb_c_T_cursor, "z=", RUBY_METHOD_FUNC(rb_m_T_cursor_z_set), 1); +static VALUE rb_dfmemory_write_float(VALUE self, VALUE addr, VALUE val) +{ + *(float*)rb_num2ulong(addr) = rb_num2dbl(val); + return Qtrue; } -// create an instance of T_cursor from global::cursor -// this method is linked to DFHack.cursor in ruby_bind_dfhack() -static VALUE rb_global_cursor(VALUE self) { - return Data_Wrap_Struct(rb_c_T_cursor, 0, 0, df::global::cursor); +// vector access +// vector +static VALUE rb_dfmemory_vec8_length(VALUE self, VALUE addr) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + return rb_uint2inum(v->size()); } - - -// begin generated unit binding -static VALUE rb_c_unit; - -static VALUE rb_m_unit_id(VALUE self) { - struct df::unit *var; - Data_Get_Struct(self, struct df::unit, var); - - return rb_uint2inum(var->id); +static VALUE rb_dfmemory_vec8_at(VALUE self, VALUE addr, VALUE idx) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + return rb_uint2inum(v->at(FIX2INT(idx))); } -static VALUE rb_m_unit_id_set(VALUE self, VALUE val) { - struct df::unit *var; - Data_Get_Struct(self, struct df::unit, var); - var->id = rb_num2ulong(val); +static VALUE rb_dfmemory_vec8_set(VALUE self, VALUE addr, VALUE idx, VALUE val) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->at(FIX2INT(idx)) = rb_num2ulong(val); return Qtrue; } - -static void ruby_bind_unit(void) { - // ruby class name must begin with uppercase - rb_c_unit = rb_define_class_under(rb_cDFHack, "Unit", rb_c_WrapData); - - rb_define_method(rb_c_unit, "id", RUBY_METHOD_FUNC(rb_m_unit_id), 0); - rb_define_method(rb_c_unit, "id=", RUBY_METHOD_FUNC(rb_m_unit_id_set), 1); +static VALUE rb_dfmemory_vec8_insert(VALUE self, VALUE addr, VALUE idx, VALUE val) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val)); + return Qtrue; } - - -// begin generated world binding -static VALUE rb_c_world; -static VALUE rb_c_world_T_units; - -static VALUE rb_m_world_T_units_all(VALUE self) { - struct df::world::T_units *var; - Data_Get_Struct(self, struct df::world::T_units, var); - - // read a vector - VALUE ret = rb_ary_new(); - for (unsigned i=0 ; iall.size() ; ++i) - rb_ary_push(ret, Data_Wrap_Struct(rb_c_unit, 0, 0, var->all[i])); - - return ret; +static VALUE rb_dfmemory_vec8_delete(VALUE self, VALUE addr, VALUE idx) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->erase(v->begin()+FIX2INT(idx)); + return Qtrue; } -static VALUE rb_m_world_units(VALUE self) { - struct df::world *var; - Data_Get_Struct(self, struct df::world, var); - return Data_Wrap_Struct(rb_c_world_T_units, 0, 0, &var->units); +// vector +static VALUE rb_dfmemory_vec16_length(VALUE self, VALUE addr) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + return rb_uint2inum(v->size()); } - -static void ruby_bind_world(void) { - rb_c_world = rb_define_class_under(rb_cDFHack, "World", rb_c_WrapData); - rb_c_world_T_units = rb_define_class_under(rb_c_world, "T_units", rb_c_WrapData); - - rb_define_method(rb_c_world, "units", RUBY_METHOD_FUNC(rb_m_world_units), 0); - rb_define_method(rb_c_world_T_units, "all", RUBY_METHOD_FUNC(rb_m_world_T_units_all), 0); +static VALUE rb_dfmemory_vec16_at(VALUE self, VALUE addr, VALUE idx) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + return rb_uint2inum(v->at(FIX2INT(idx))); } - -static VALUE rb_global_world(VALUE self) { - return Data_Wrap_Struct(rb_c_world, 0, 0, df::global::world); +static VALUE rb_dfmemory_vec16_set(VALUE self, VALUE addr, VALUE idx, VALUE val) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->at(FIX2INT(idx)) = rb_num2ulong(val); + return Qtrue; } - -/* -static VALUE rb_dfcreatures(VALUE self) +static VALUE rb_dfmemory_vec16_insert(VALUE self, VALUE addr, VALUE idx, VALUE val) { - OffsetGroup *ogc = getcore().vinfo->getGroup("Creatures"); - vector *v = (vector*)ogc->getAddress("vector"); - - VALUE ret = rb_ary_new(); - for (unsigned i=0 ; isize() ; ++i) - rb_ary_push(ret, Data_Wrap_Struct(rb_cCreature, 0, 0, v->at(i))); - - return ret; + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val)); + return Qtrue; } - -static VALUE rb_getlaborname(VALUE self, VALUE idx) +static VALUE rb_dfmemory_vec16_delete(VALUE self, VALUE addr, VALUE idx) { - return rb_str_new2(getcore().vinfo->getLabor(FIX2INT(idx)).c_str()); + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->erase(v->begin()+FIX2INT(idx)); + return Qtrue; } -static VALUE rb_getskillname(VALUE self, VALUE idx) +// vector +static VALUE rb_dfmemory_vec32_length(VALUE self, VALUE addr) { - return rb_str_new2(getcore().vinfo->getSkill(FIX2INT(idx)).c_str()); + std::vector *v = (std::vector*)rb_num2ulong(addr); + return rb_uint2inum(v->size()); } - -static VALUE rb_mapblock(VALUE self, VALUE x, VALUE y, VALUE z) +static VALUE rb_dfmemory_vec32_at(VALUE self, VALUE addr, VALUE idx) { - Maps *map; - Data_Get_Struct(self, Maps, map); - df_block *block; - - block = map->getBlock(FIX2INT(x)/16, FIX2INT(y)/16, FIX2INT(z)); - if (!block) - return Qnil; - - return Data_Wrap_Struct(rb_cMapBlock, 0, 0, block); + std::vector *v = (std::vector*)rb_num2ulong(addr); + return rb_uint2inum(v->at(FIX2INT(idx))); +} +static VALUE rb_dfmemory_vec32_set(VALUE self, VALUE addr, VALUE idx, VALUE val) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->at(FIX2INT(idx)) = rb_num2ulong(val); + return Qtrue; +} +static VALUE rb_dfmemory_vec32_insert(VALUE self, VALUE addr, VALUE idx, VALUE val) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val)); + return Qtrue; +} +static VALUE rb_dfmemory_vec32_delete(VALUE self, VALUE addr, VALUE idx) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->erase(v->begin()+FIX2INT(idx)); + return Qtrue; } -*/ - @@ -577,30 +561,42 @@ static void ruby_bind_dfhack(void) { rb_define_singleton_method(rb_cDFHack, "onupdate_active=", RUBY_METHOD_FUNC(rb_dfonupdateactiveset), 1); rb_define_singleton_method(rb_cDFHack, "resume", RUBY_METHOD_FUNC(rb_dfresume), 0); rb_define_singleton_method(rb_cDFHack, "do_suspend", RUBY_METHOD_FUNC(rb_dfsuspend), 0); - rb_define_singleton_method(rb_cDFHack, "resume", RUBY_METHOD_FUNC(rb_dfresume), 0); - //rb_define_singleton_method(rb_cDFHack, "version", RUBY_METHOD_FUNC(rb_dfgetversion), 0); + rb_define_singleton_method(rb_cDFHack, "register_dfcommand", RUBY_METHOD_FUNC(rb_dfregister), 2); rb_define_singleton_method(rb_cDFHack, "print_str", RUBY_METHOD_FUNC(rb_dfprint_str), 1); rb_define_singleton_method(rb_cDFHack, "print_err", RUBY_METHOD_FUNC(rb_dfprint_err), 1); - rb_define_singleton_method(rb_cDFHack, "memread", RUBY_METHOD_FUNC(rb_dfmemread), 2); - rb_define_singleton_method(rb_cDFHack, "memwrite", RUBY_METHOD_FUNC(rb_dfmemwrite), 2); 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, "vectorat", RUBY_METHOD_FUNC(rb_dfvectorat), 2); - rb_define_singleton_method(rb_cDFHack, "readstring", RUBY_METHOD_FUNC(rb_dfreadstring), 1); - rb_define_singleton_method(rb_cDFHack, "register_dfcommand", RUBY_METHOD_FUNC(rb_dfregister), 2); - - // accessors for dfhack globals - rb_define_singleton_method(rb_cDFHack, "cursor", RUBY_METHOD_FUNC(rb_global_cursor), 0); - rb_define_singleton_method(rb_cDFHack, "world", RUBY_METHOD_FUNC(rb_global_world), 0); - - // parent class for all wrapped objects - rb_c_WrapData = rb_define_class_under(rb_cDFHack, "WrapData", rb_cObject); - rb_define_method(rb_c_WrapData, "memaddr", RUBY_METHOD_FUNC(rb_memaddr), 0); - - // call generated bindings - ruby_bind_T_cursor(); - ruby_bind_unit(); - ruby_bind_world(); + rb_define_const(rb_cDFHack, "REBASE_DELTA", rb_dfrebase_delta()); + + rb_define_singleton_method(rb_cDFHack, "memory_read", RUBY_METHOD_FUNC(rb_dfmemory_read), 2); + rb_define_singleton_method(rb_cDFHack, "memory_read_stlstring", RUBY_METHOD_FUNC(rb_dfmemory_read_stlstring), 1); + rb_define_singleton_method(rb_cDFHack, "memory_read_int8", RUBY_METHOD_FUNC(rb_dfmemory_read_int8), 1); + rb_define_singleton_method(rb_cDFHack, "memory_read_int16", RUBY_METHOD_FUNC(rb_dfmemory_read_int16), 1); + rb_define_singleton_method(rb_cDFHack, "memory_read_int32", RUBY_METHOD_FUNC(rb_dfmemory_read_int32), 1); + rb_define_singleton_method(rb_cDFHack, "memory_read_float", RUBY_METHOD_FUNC(rb_dfmemory_read_float), 1); + + rb_define_singleton_method(rb_cDFHack, "memory_write", RUBY_METHOD_FUNC(rb_dfmemory_write), 2); + rb_define_singleton_method(rb_cDFHack, "memory_write_stlstring", RUBY_METHOD_FUNC(rb_dfmemory_write_stlstring), 2); + rb_define_singleton_method(rb_cDFHack, "memory_write_int8", RUBY_METHOD_FUNC(rb_dfmemory_write_int8), 2); + 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_vector8_length", RUBY_METHOD_FUNC(rb_dfmemory_vec8_length), 1); + rb_define_singleton_method(rb_cDFHack, "memory_vector8_at", RUBY_METHOD_FUNC(rb_dfmemory_vec8_at), 2); + rb_define_singleton_method(rb_cDFHack, "memory_vector8_set", RUBY_METHOD_FUNC(rb_dfmemory_vec8_set), 3); + rb_define_singleton_method(rb_cDFHack, "memory_vector8_insert", RUBY_METHOD_FUNC(rb_dfmemory_vec8_insert), 3); + rb_define_singleton_method(rb_cDFHack, "memory_vector8_delete", RUBY_METHOD_FUNC(rb_dfmemory_vec8_delete), 2); + rb_define_singleton_method(rb_cDFHack, "memory_vector16_length", RUBY_METHOD_FUNC(rb_dfmemory_vec16_length), 1); + rb_define_singleton_method(rb_cDFHack, "memory_vector16_at", RUBY_METHOD_FUNC(rb_dfmemory_vec16_at), 2); + rb_define_singleton_method(rb_cDFHack, "memory_vector16_set", RUBY_METHOD_FUNC(rb_dfmemory_vec16_set), 3); + rb_define_singleton_method(rb_cDFHack, "memory_vector16_insert", RUBY_METHOD_FUNC(rb_dfmemory_vec16_insert), 3); + rb_define_singleton_method(rb_cDFHack, "memory_vector16_delete", RUBY_METHOD_FUNC(rb_dfmemory_vec16_delete), 2); + rb_define_singleton_method(rb_cDFHack, "memory_vector32_length", RUBY_METHOD_FUNC(rb_dfmemory_vec32_length), 1); + rb_define_singleton_method(rb_cDFHack, "memory_vector32_at", RUBY_METHOD_FUNC(rb_dfmemory_vec32_at), 2); + rb_define_singleton_method(rb_cDFHack, "memory_vector32_set", RUBY_METHOD_FUNC(rb_dfmemory_vec32_set), 3); + rb_define_singleton_method(rb_cDFHack, "memory_vector32_insert", RUBY_METHOD_FUNC(rb_dfmemory_vec32_insert), 3); + rb_define_singleton_method(rb_cDFHack, "memory_vector32_delete", RUBY_METHOD_FUNC(rb_dfmemory_vec32_delete), 2); // load the default ruby-level definitions int state=0;