ruby: set everything up

develop
jj 2012-04-12 19:12:46 +02:00
parent ac0d878b69
commit f503bf36f4
2 changed files with 360 additions and 225 deletions

@ -77,36 +77,65 @@ class Number < MemStruct
@_bits = bits @_bits = bits
@_signed = signed @_signed = signed
end 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 end
class Float < MemStruct 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 end
class BitField < Number class BitField < MemStruct
attr_accessor :_shift, :_len attr_accessor :_shift, :_len
def initialize(shift, len) def initialize(shift, len)
@_shift = shift @_shift = shift
@_len = len @_len = len
super(32, false) end
def _mask
(1 << @_len) - 1
end end
def _get(whole=false) def _get
v = super() v = DFHack.memory_read_int32(@_memaddr) >> @_shift
return v if whole
v = (v >> @_shift) % (1 << @_len)
if @_len == 1 if @_len == 1
v == 0 ? false : true ((v & 1) == 0) ? false : true
else else
v v & _mask
end end
end end
def _set(v) def _set(v)
if @_len == 1 if @_len == 1
# allow 'bit = 0'
v = (v && v != 0 ? 1 : 0) v = (v && v != 0 ? 1 : 0)
end end
v = ((v % (1 << @_len)) << @_shift) v = (v & _mask) << @_shift
ori = _get(true) ori = DFHack.memory_read_int32(@_memaddr) & 0xffffffff
super(ori - (ori & (-1 % (1 << @_len)) << @_shift) + v) DFHack.memory_write_int32(@_memaddr, ori - (ori & ((-1 & _mask) << @_shift)) + v)
end end
end end
@ -116,6 +145,30 @@ class Pointer < MemStruct
@_tglen = tglen @_tglen = tglen
@_tg = tg @_tg = tg
end 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 end
class StaticArray < MemStruct class StaticArray < MemStruct
attr_accessor :_tglen, :_length, :_tg attr_accessor :_tglen, :_length, :_tg
@ -124,21 +177,21 @@ class StaticArray < MemStruct
@_length = length @_length = length
@_tg = tg @_tg = tg
end 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 length _length
alias size _length alias size _length
def _tgat(i) def _tgat(i)
tg._at(@_memaddr + i*@_tglen) @_tg._at(@_memaddr + i*@_tglen) if i >= 0 and i < @_length
end end
def [](i) def [](i)
if (i > 0) or (@_length and i < @_length) i += @_length if i < 0
tgat(i)._get tgat(i)._get
end end
end
def []=(i, v) def []=(i, v)
if (i > 0) or (@_length and i < @_length) i += @_length if i < 0
tgat(i)._set tgat(i)._set(v)
end
end end
end end
class StaticString < MemStruct class StaticString < MemStruct
@ -146,6 +199,12 @@ class StaticString < MemStruct
def initialize(length) def initialize(length)
@_length = length @_length = length
end end
def _get
DFHack.memory_read(@_memaddr, @_length)
end
def _set(v)
DFHack.memory_write(@_memaddr, v[0, @_length])
end
end end
class StlVector < MemStruct class StlVector < MemStruct
@ -154,10 +213,87 @@ class StlVector < MemStruct
@_tglen = tglen @_tglen = tglen
@_tg = tg @_tg = tg
end 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 end
class StlString < MemStruct class StlString < MemStruct
def _get
DFHack.memory_read_stlstring(@_memaddr)
end
def _set(v)
DFHack.memory_write_stlstring(@_memaddr, v)
end
end end
class StlBitVector < MemStruct class StlBitVector < MemStruct
# TODO
end end
class StlDeque < MemStruct class StlDeque < MemStruct
attr_accessor :_tglen, :_tg attr_accessor :_tglen, :_tg
@ -168,6 +304,7 @@ class StlDeque < MemStruct
end end
class DfFlagarray < MemStruct class DfFlagarray < MemStruct
# TODO
end end
class DfArray < MemStruct class DfArray < MemStruct
attr_accessor :_tglen, :_tg attr_accessor :_tglen, :_tg
@ -175,6 +312,8 @@ class DfArray < MemStruct
@_tglen = tglen @_tglen = tglen
@_tg = tg @_tg = tg
end end
# TODO
end end
class DfLinkedList < MemStruct class DfLinkedList < MemStruct
attr_accessor :_tg attr_accessor :_tg

@ -12,14 +12,16 @@
#include <ruby.h> #include <ruby.h>
using std::string;
using std::vector;
using namespace DFHack; using namespace DFHack;
// DFHack stuff
static void df_rubythread(void*); static void df_rubythread(void*);
static command_result df_rubyload(color_ostream &out, vector <string> & parameters); static command_result df_rubyload(color_ostream &out, std::vector <std::string> & parameters);
static command_result df_rubyeval(color_ostream &out, vector <string> & parameters); static command_result df_rubyeval(color_ostream &out, std::vector <std::string> & parameters);
static void ruby_bind_dfhack(void); static void ruby_bind_dfhack(void);
// inter-thread communication stuff // inter-thread communication stuff
@ -39,7 +41,6 @@ static command_result r_result;
static tthread::thread *r_thread; static tthread::thread *r_thread;
static int onupdate_active; static int onupdate_active;
// dfhack interface
DFHACK_PLUGIN("ruby") DFHACK_PLUGIN("ruby")
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
@ -122,7 +123,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
return ret; return ret;
} }
static command_result df_rubyload(color_ostream &out, vector <string> & parameters) static command_result df_rubyload(color_ostream &out, std::vector <std::string> & parameters)
{ {
command_result ret; command_result ret;
@ -154,7 +155,7 @@ static command_result df_rubyload(color_ostream &out, vector <string> & paramete
return ret; return ret;
} }
static command_result df_rubyeval(color_ostream &out, vector <string> & parameters) static command_result df_rubyeval(color_ostream &out, std::vector <std::string> & parameters)
{ {
command_result ret; command_result ret;
@ -195,6 +196,8 @@ static command_result df_rubyeval(color_ostream &out, vector <string> & paramete
// ruby stuff
// ruby thread code // ruby thread code
static void dump_rb_error(void) 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_cDFHack;
static VALUE rb_c_WrapData;
// DFHack methods // DFHack module ruby methods, binds specific dfhack methods
// enable/disable calls to DFHack.onupdate() // enable/disable calls to DFHack.onupdate()
static VALUE rb_dfonupdateactive(VALUE self) static VALUE rb_dfonupdateactive(VALUE self)
{ {
@ -308,16 +311,33 @@ static VALUE rb_dfsuspend(VALUE self)
return Qtrue; return Qtrue;
} }
/* // returns the delta to apply to dfhack xml addrs wrt actual memory addresses
static VALUE rb_dfgetversion(VALUE self) // 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) static VALUE rb_dfprint_str(VALUE self, VALUE s)
{ {
// TODO color_ostream proxy yadda yadda
//getcore().con.print("%s", rb_string_value_ptr(&s)); //getcore().con.print("%s", rb_string_value_ptr(&s));
Core::printerr("%s", rb_string_value_ptr(&s)); Core::printerr("%s", rb_string_value_ptr(&s));
return Qnil; return Qnil;
@ -329,22 +349,30 @@ static VALUE rb_dfprint_err(VALUE self, VALUE s)
return Qnil; return Qnil;
} }
// raw memory access /* TODO needs main dfhack support
// WARNING: may cause game crash ! double-check your addresses ! this needs a custom DFHack::Plugin subclass to pass the cmdname to invoke(), to match the ruby callback
static VALUE rb_dfmemread(VALUE self, VALUE addr, VALUE len) // 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 ... rb_raise(rb_eRuntimeError, "not implemented");
int strlen = FIX2INT(rb_funcall(raw, rb_intern("length"), 0)); }
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) static VALUE rb_dfmalloc(VALUE self, VALUE len)
{ {
@ -357,214 +385,170 @@ static VALUE rb_dffree(VALUE self, VALUE ptr)
return Qtrue; return Qtrue;
} }
// raw c++ wrappers
// return the nth element of a vector // memory reading (buffer)
static VALUE rb_dfvectorat(VALUE self, VALUE vect_addr, VALUE idx) static VALUE rb_dfmemory_read(VALUE self, VALUE addr, VALUE len)
{ {
vector<uint32_t> *v = (vector<uint32_t>*)rb_num2ulong(vect_addr); return rb_str_new((char*)rb_num2ulong(addr), rb_num2ulong(len));
return rb_uint2inum(v->at(FIX2INT(idx)));
} }
static VALUE rb_dfmemory_read_stlstring(VALUE self, VALUE addr)
// return a c++ string as a ruby string (nul-terminated)
static VALUE rb_dfreadstring(VALUE self, VALUE str_addr)
{ {
string *s = (string*)rb_num2ulong(str_addr); std::string *s = (std::string*)rb_num2ulong(addr);
return rb_str_new2(s->c_str()); return rb_str_new(s->c_str(), s->length());
} }
// memory reading (integers/floats)
static VALUE rb_dfmemory_read_int8(VALUE self, VALUE addr)
/* 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)
{ {
commands.push_back(PluginCommand(rb_string_value_ptr(&name), return rb_int2inum(*(char*)rb_num2ulong(addr));
rb_string_value_ptr(&descr),
df_rubycustom));
return Qtrue;
} }
*/ static VALUE rb_dfmemory_read_int16(VALUE self, VALUE addr)
static VALUE rb_dfregister(VALUE self, VALUE name, VALUE descr)
{ {
rb_raise(rb_eRuntimeError, "not implemented"); return rb_int2inum(*(short*)rb_num2ulong(addr));
} }
static VALUE rb_dfmemory_read_int32(VALUE self, VALUE addr)
// return the address of the struct in DF memory (for raw memread/write)
static VALUE rb_memaddr(VALUE self)
{ {
void *data; return rb_int2inum(*(int*)rb_num2ulong(addr));
Data_Get_Struct(self, void, data);
return rb_uint2inum((uint32_t)data);
} }
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 memcpy((void*)rb_num2ulong(addr), rb_string_value_ptr(&raw), strlen);
// begin generated T_cursor binding
static VALUE rb_c_T_cursor;
static VALUE rb_m_T_cursor_x(VALUE self) { return Qtrue;
struct df::global::T_cursor *var;
Data_Get_Struct(self, struct df::global::T_cursor, var);
return rb_uint2inum(var->x);
} }
static VALUE rb_m_T_cursor_x_set(VALUE self, VALUE val) { static VALUE rb_dfmemory_write_stlstring(VALUE self, VALUE addr, VALUE val)
struct df::global::T_cursor *var; {
Data_Get_Struct(self, struct df::global::T_cursor, var); std::string *s = (std::string*)rb_num2ulong(addr);
var->x = rb_num2ulong(val); int strlen = FIX2INT(rb_funcall(val, rb_intern("length"), 0));
s->assign(rb_string_value_ptr(&val), strlen);
return Qtrue; return Qtrue;
} }
static VALUE rb_m_T_cursor_y(VALUE self) { // memory writing (integers/floats)
struct df::global::T_cursor *var; static VALUE rb_dfmemory_write_int8(VALUE self, VALUE addr, VALUE val)
Data_Get_Struct(self, struct df::global::T_cursor, var); {
return rb_uint2inum(var->y); *(char*)rb_num2ulong(addr) = rb_num2ulong(val);
}
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);
return Qtrue; return Qtrue;
} }
static VALUE rb_dfmemory_write_int16(VALUE self, VALUE addr, VALUE val)
static VALUE rb_m_T_cursor_z(VALUE self) { {
struct df::global::T_cursor *var; *(short*)rb_num2ulong(addr) = rb_num2ulong(val);
Data_Get_Struct(self, struct df::global::T_cursor, var); return Qtrue;
return rb_uint2inum(var->z);
} }
static VALUE rb_m_T_cursor_z_set(VALUE self, VALUE val) { static VALUE rb_dfmemory_write_int32(VALUE self, VALUE addr, VALUE val)
struct df::global::T_cursor *var; {
Data_Get_Struct(self, struct df::global::T_cursor, var); *(int*)rb_num2ulong(addr) = rb_num2ulong(val);
var->z = rb_num2ulong(val);
return Qtrue; return Qtrue;
} }
// link methods to the class static VALUE rb_dfmemory_write_float(VALUE self, VALUE addr, VALUE val)
static void ruby_bind_T_cursor(void) { {
// create a class, child of WrapData, in module DFHack *(float*)rb_num2ulong(addr) = rb_num2dbl(val);
rb_c_T_cursor = rb_define_class_under(rb_cDFHack, "T_cursor", rb_c_WrapData); return Qtrue;
// 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);
} }
// create an instance of T_cursor from global::cursor // vector access
// this method is linked to DFHack.cursor in ruby_bind_dfhack() // vector<uint8>
static VALUE rb_global_cursor(VALUE self) { static VALUE rb_dfmemory_vec8_length(VALUE self, VALUE addr)
return Data_Wrap_Struct(rb_c_T_cursor, 0, 0, df::global::cursor); {
std::vector<uint8_t> *v = (std::vector<uint8_t>*)rb_num2ulong(addr);
return rb_uint2inum(v->size());
} }
static VALUE rb_dfmemory_vec8_at(VALUE self, VALUE addr, VALUE idx)
{
// begin generated unit binding std::vector<uint8_t> *v = (std::vector<uint8_t>*)rb_num2ulong(addr);
static VALUE rb_c_unit; return rb_uint2inum(v->at(FIX2INT(idx)));
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_m_unit_id_set(VALUE self, VALUE val) { static VALUE rb_dfmemory_vec8_set(VALUE self, VALUE addr, VALUE idx, VALUE val)
struct df::unit *var; {
Data_Get_Struct(self, struct df::unit, var); std::vector<uint8_t> *v = (std::vector<uint8_t>*)rb_num2ulong(addr);
var->id = rb_num2ulong(val); v->at(FIX2INT(idx)) = rb_num2ulong(val);
return Qtrue; return Qtrue;
} }
static VALUE rb_dfmemory_vec8_insert(VALUE self, VALUE addr, VALUE idx, VALUE val)
static void ruby_bind_unit(void) { {
// ruby class name must begin with uppercase std::vector<uint8_t> *v = (std::vector<uint8_t>*)rb_num2ulong(addr);
rb_c_unit = rb_define_class_under(rb_cDFHack, "Unit", rb_c_WrapData); v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val));
return Qtrue;
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_delete(VALUE self, VALUE addr, VALUE idx)
{
// begin generated world binding std::vector<uint8_t> *v = (std::vector<uint8_t>*)rb_num2ulong(addr);
static VALUE rb_c_world; v->erase(v->begin()+FIX2INT(idx));
static VALUE rb_c_world_T_units; return Qtrue;
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 ; i<var->all.size() ; ++i)
rb_ary_push(ret, Data_Wrap_Struct(rb_c_unit, 0, 0, var->all[i]));
return ret;
} }
static VALUE rb_m_world_units(VALUE self) { // vector<uint16>
struct df::world *var; static VALUE rb_dfmemory_vec16_length(VALUE self, VALUE addr)
Data_Get_Struct(self, struct df::world, var); {
return Data_Wrap_Struct(rb_c_world_T_units, 0, 0, &var->units); std::vector<uint16_t> *v = (std::vector<uint16_t>*)rb_num2ulong(addr);
return rb_uint2inum(v->size());
} }
static VALUE rb_dfmemory_vec16_at(VALUE self, VALUE addr, VALUE idx)
static void ruby_bind_world(void) { {
rb_c_world = rb_define_class_under(rb_cDFHack, "World", rb_c_WrapData); std::vector<uint16_t> *v = (std::vector<uint16_t>*)rb_num2ulong(addr);
rb_c_world_T_units = rb_define_class_under(rb_c_world, "T_units", rb_c_WrapData); return rb_uint2inum(v->at(FIX2INT(idx)));
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_set(VALUE self, VALUE addr, VALUE idx, VALUE val)
static VALUE rb_global_world(VALUE self) { {
return Data_Wrap_Struct(rb_c_world, 0, 0, df::global::world); std::vector<uint16_t> *v = (std::vector<uint16_t>*)rb_num2ulong(addr);
v->at(FIX2INT(idx)) = rb_num2ulong(val);
return Qtrue;
} }
static VALUE rb_dfmemory_vec16_insert(VALUE self, VALUE addr, VALUE idx, VALUE val)
/*
static VALUE rb_dfcreatures(VALUE self)
{ {
OffsetGroup *ogc = getcore().vinfo->getGroup("Creatures"); std::vector<uint16_t> *v = (std::vector<uint16_t>*)rb_num2ulong(addr);
vector <df_creature*> *v = (vector<df_creature*>*)ogc->getAddress("vector"); v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val));
return Qtrue;
VALUE ret = rb_ary_new();
for (unsigned i=0 ; i<v->size() ; ++i)
rb_ary_push(ret, Data_Wrap_Struct(rb_cCreature, 0, 0, v->at(i)));
return ret;
} }
static VALUE rb_dfmemory_vec16_delete(VALUE self, VALUE addr, VALUE idx)
static VALUE rb_getlaborname(VALUE self, VALUE idx)
{ {
return rb_str_new2(getcore().vinfo->getLabor(FIX2INT(idx)).c_str()); std::vector<uint16_t> *v = (std::vector<uint16_t>*)rb_num2ulong(addr);
v->erase(v->begin()+FIX2INT(idx));
return Qtrue;
} }
static VALUE rb_getskillname(VALUE self, VALUE idx) // vector<uint32>
static VALUE rb_dfmemory_vec32_length(VALUE self, VALUE addr)
{ {
return rb_str_new2(getcore().vinfo->getSkill(FIX2INT(idx)).c_str()); std::vector<uint32_t> *v = (std::vector<uint32_t>*)rb_num2ulong(addr);
return rb_uint2inum(v->size());
} }
static VALUE rb_dfmemory_vec32_at(VALUE self, VALUE addr, VALUE idx)
static VALUE rb_mapblock(VALUE self, VALUE x, VALUE y, VALUE z)
{ {
Maps *map; std::vector<uint32_t> *v = (std::vector<uint32_t>*)rb_num2ulong(addr);
Data_Get_Struct(self, Maps, map); return rb_uint2inum(v->at(FIX2INT(idx)));
df_block *block; }
static VALUE rb_dfmemory_vec32_set(VALUE self, VALUE addr, VALUE idx, VALUE val)
block = map->getBlock(FIX2INT(x)/16, FIX2INT(y)/16, FIX2INT(z)); {
if (!block) std::vector<uint32_t> *v = (std::vector<uint32_t>*)rb_num2ulong(addr);
return Qnil; v->at(FIX2INT(idx)) = rb_num2ulong(val);
return Qtrue;
return Data_Wrap_Struct(rb_cMapBlock, 0, 0, block); }
static VALUE rb_dfmemory_vec32_insert(VALUE self, VALUE addr, VALUE idx, VALUE val)
{
std::vector<uint32_t> *v = (std::vector<uint32_t>*)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<uint32_t> *v = (std::vector<uint32_t>*)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, "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, "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, "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, "register_dfcommand", RUBY_METHOD_FUNC(rb_dfregister), 2);
//rb_define_singleton_method(rb_cDFHack, "version", RUBY_METHOD_FUNC(rb_dfgetversion), 0);
rb_define_singleton_method(rb_cDFHack, "print_str", RUBY_METHOD_FUNC(rb_dfprint_str), 1); 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, "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, "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, "free", RUBY_METHOD_FUNC(rb_dffree), 1);
rb_define_singleton_method(rb_cDFHack, "vectorat", RUBY_METHOD_FUNC(rb_dfvectorat), 2); rb_define_const(rb_cDFHack, "REBASE_DELTA", rb_dfrebase_delta());
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); 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);
// accessors for dfhack globals rb_define_singleton_method(rb_cDFHack, "memory_read_int8", RUBY_METHOD_FUNC(rb_dfmemory_read_int8), 1);
rb_define_singleton_method(rb_cDFHack, "cursor", RUBY_METHOD_FUNC(rb_global_cursor), 0); rb_define_singleton_method(rb_cDFHack, "memory_read_int16", RUBY_METHOD_FUNC(rb_dfmemory_read_int16), 1);
rb_define_singleton_method(rb_cDFHack, "world", RUBY_METHOD_FUNC(rb_global_world), 0); 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);
// parent class for all wrapped objects
rb_c_WrapData = rb_define_class_under(rb_cDFHack, "WrapData", rb_cObject); rb_define_singleton_method(rb_cDFHack, "memory_write", RUBY_METHOD_FUNC(rb_dfmemory_write), 2);
rb_define_method(rb_c_WrapData, "memaddr", RUBY_METHOD_FUNC(rb_memaddr), 0); 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);
// call generated bindings rb_define_singleton_method(rb_cDFHack, "memory_write_int16", RUBY_METHOD_FUNC(rb_dfmemory_write_int16), 2);
ruby_bind_T_cursor(); rb_define_singleton_method(rb_cDFHack, "memory_write_int32", RUBY_METHOD_FUNC(rb_dfmemory_write_int32), 2);
ruby_bind_unit(); rb_define_singleton_method(rb_cDFHack, "memory_write_float", RUBY_METHOD_FUNC(rb_dfmemory_write_float), 2);
ruby_bind_world();
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 // load the default ruby-level definitions
int state=0; int state=0;