|
|
@ -1,11 +1,11 @@
|
|
|
|
module DFHack
|
|
|
|
module DFHack
|
|
|
|
module MemHack
|
|
|
|
module MemHack
|
|
|
|
|
|
|
|
INSPECT_SIZE_LIMIT=1024
|
|
|
|
class MemStruct
|
|
|
|
class MemStruct
|
|
|
|
attr_accessor :_memaddr
|
|
|
|
attr_accessor :_memaddr
|
|
|
|
def _at(addr) ; d = dup ; d._memaddr = addr ; d ; end
|
|
|
|
def _at(addr) ; d = dup ; d._memaddr = addr ; d ; end
|
|
|
|
def _get ; self ; end
|
|
|
|
def _get ; self ; end
|
|
|
|
def _cpp_init ; end
|
|
|
|
def _cpp_init ; end
|
|
|
|
def inspect ; _get.inspect ; end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
class Compound < MemStruct
|
|
|
|
class Compound < MemStruct
|
|
|
@ -121,7 +121,7 @@ class Compound < MemStruct
|
|
|
|
out = "#<#{cn}"
|
|
|
|
out = "#<#{cn}"
|
|
|
|
_fields_ancestors.each { |n, o, s|
|
|
|
|
_fields_ancestors.each { |n, o, s|
|
|
|
|
out << ' ' if out.length != 0 and out[-1, 1] != ' '
|
|
|
|
out << ' ' if out.length != 0 and out[-1, 1] != ' '
|
|
|
|
if out.length > 1024
|
|
|
|
if out.length > INSPECT_SIZE_LIMIT
|
|
|
|
out << '...'
|
|
|
|
out << '...'
|
|
|
|
break
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -132,6 +132,8 @@ class Compound < MemStruct
|
|
|
|
def inspect_field(n, o, s)
|
|
|
|
def inspect_field(n, o, s)
|
|
|
|
if s.kind_of?(BitField) and s._len == 1
|
|
|
|
if s.kind_of?(BitField) and s._len == 1
|
|
|
|
send(n) ? n.to_s : ''
|
|
|
|
send(n) ? n.to_s : ''
|
|
|
|
|
|
|
|
elsif s.kind_of?(Pointer)
|
|
|
|
|
|
|
|
s._at(@_memaddr+o).inspect
|
|
|
|
elsif n == :_whole
|
|
|
|
elsif n == :_whole
|
|
|
|
"_whole=0x#{_whole.to_s(16)}"
|
|
|
|
"_whole=0x#{_whole.to_s(16)}"
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -237,7 +239,7 @@ class Pointer < MemStruct
|
|
|
|
DFHack.memory_read_int32(@_memaddr) & 0xffffffff
|
|
|
|
DFHack.memory_read_int32(@_memaddr) & 0xffffffff
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def _getv
|
|
|
|
def _get
|
|
|
|
addr = _getp
|
|
|
|
addr = _getp
|
|
|
|
return if addr == 0
|
|
|
|
return if addr == 0
|
|
|
|
@_tg._at(addr)._get
|
|
|
|
@_tg._at(addr)._get
|
|
|
@ -246,30 +248,25 @@ class Pointer < MemStruct
|
|
|
|
# XXX shaky...
|
|
|
|
# XXX shaky...
|
|
|
|
def _set(v)
|
|
|
|
def _set(v)
|
|
|
|
if v.kind_of?(Pointer)
|
|
|
|
if v.kind_of?(Pointer)
|
|
|
|
DFHack.memory_write_int32(@_memaddr, v._getv)
|
|
|
|
DFHack.memory_write_int32(@_memaddr, v._getp)
|
|
|
|
elsif v.kind_of?(MemStruct)
|
|
|
|
elsif v.kind_of?(MemStruct)
|
|
|
|
DFHack.memory_write_int32(@_memaddr, v._memaddr)
|
|
|
|
DFHack.memory_write_int32(@_memaddr, v._memaddr)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
_getv._set(v)
|
|
|
|
_get._set(v)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# these ruby Object methods should be forwarded to the ptr
|
|
|
|
|
|
|
|
undef id
|
|
|
|
|
|
|
|
undef type
|
|
|
|
|
|
|
|
def method_missing(*a)
|
|
|
|
|
|
|
|
_getv.send(*a)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
def respond_to?(q)
|
|
|
|
|
|
|
|
_getv.respond_to?(q)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def inspect
|
|
|
|
def inspect
|
|
|
|
|
|
|
|
ptr = _getp
|
|
|
|
|
|
|
|
if ptr == 0
|
|
|
|
|
|
|
|
'NULL'
|
|
|
|
|
|
|
|
else
|
|
|
|
cn = (@_tg ? @_tg.class.name.sub(/^DFHack::/, '') : '')
|
|
|
|
cn = (@_tg ? @_tg.class.name.sub(/^DFHack::/, '') : '')
|
|
|
|
cn = @_tg._glob if cn == 'MemHack::Global'
|
|
|
|
cn = @_tg._glob if cn == 'MemHack::Global'
|
|
|
|
"#<Pointer #{cn} #{'0x%X' % _getp}>"
|
|
|
|
"#<Pointer #{cn} #{'0x%X' % _getp}>"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
class PointerAry < MemStruct
|
|
|
|
class PointerAry < MemStruct
|
|
|
|
attr_accessor :_tglen, :_tg
|
|
|
|
attr_accessor :_tglen, :_tg
|
|
|
|
def initialize(tglen, tg)
|
|
|
|
def initialize(tglen, tg)
|
|
|
@ -304,6 +301,25 @@ module IndexEnum
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Enumerable
|
|
|
|
|
|
|
|
include ::Enumerable
|
|
|
|
|
|
|
|
def each ; (0...length).each { |i| yield self[i] } ; end
|
|
|
|
|
|
|
|
def inspect
|
|
|
|
|
|
|
|
enum = DFHack.const_get(_indexenum)::ENUM if _indexenum
|
|
|
|
|
|
|
|
out = '['
|
|
|
|
|
|
|
|
each { |i|
|
|
|
|
|
|
|
|
out << ', ' if out.length > 1
|
|
|
|
|
|
|
|
if out.length > INSPECT_SIZE_LIMIT
|
|
|
|
|
|
|
|
out << '...'
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
out << "#{enum[i]}=" if enum
|
|
|
|
|
|
|
|
out << i.inspect
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
out << ']'
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
def flatten ; map { |e| e.respond_to?(:flatten) ? e.flatten : e }.flatten ; end
|
|
|
|
|
|
|
|
end
|
|
|
|
class StaticArray < MemStruct
|
|
|
|
class StaticArray < MemStruct
|
|
|
|
include IndexEnum
|
|
|
|
include IndexEnum
|
|
|
|
attr_accessor :_tglen, :_length, :_indexenum, :_tg
|
|
|
|
attr_accessor :_tglen, :_length, :_indexenum, :_tg
|
|
|
@ -336,16 +352,6 @@ class StaticArray < MemStruct
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
include Enumerable
|
|
|
|
include Enumerable
|
|
|
|
def each ; (0...length).each { |i| yield self[i] } ; end
|
|
|
|
|
|
|
|
def inspect
|
|
|
|
|
|
|
|
if _indexenum
|
|
|
|
|
|
|
|
e = DFHack.const_get(_indexenum)::ENUM
|
|
|
|
|
|
|
|
'[' + (0...length).map { |i| "#{e[i]}=#{self[i].inspect}" }.join(' ') + ']'
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
to_a.inspect
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
def flatten ; map { |e| e.respond_to?(:flatten) ? e.flatten : e }.flatten ; end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
class StaticString < MemStruct
|
|
|
|
class StaticString < MemStruct
|
|
|
|
attr_accessor :_length
|
|
|
|
attr_accessor :_length
|
|
|
@ -420,14 +426,6 @@ class StlVector32 < MemStruct
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
include Enumerable
|
|
|
|
include Enumerable
|
|
|
|
def each ; (0...length).each { |i| yield self[i] } ; end
|
|
|
|
|
|
|
|
def inspect
|
|
|
|
|
|
|
|
if _tg and _tg.kind_of?(Pointer)
|
|
|
|
|
|
|
|
length > 0 ? "[#{length}*#{self[0].inspect}]" : '[]'
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
to_a.inspect
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
# do a binary search in an ordered vector for a specific target attribute
|
|
|
|
# do a binary search in an ordered vector for a specific target attribute
|
|
|
|
# ex: world.history.figures.binsearch(unit.hist_figure_id)
|
|
|
|
# ex: world.history.figures.binsearch(unit.hist_figure_id)
|
|
|
|
def binsearch(target, field=:id)
|
|
|
|
def binsearch(target, field=:id)
|
|
|
@ -555,15 +553,6 @@ class DfFlagarray < MemStruct
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
include Enumerable
|
|
|
|
include Enumerable
|
|
|
|
def each ; (0...length).each { |i| yield self[i] } ; end
|
|
|
|
|
|
|
|
def inspect
|
|
|
|
|
|
|
|
if _indexenum
|
|
|
|
|
|
|
|
e = DFHack.const_get(_indexenum)::ENUM
|
|
|
|
|
|
|
|
'[' + (0...length).map { |i| if self[i] ; e[i] || i ; end }.compact.join(' ') + ']'
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
to_a.inspect
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
class DfArray < Compound
|
|
|
|
class DfArray < Compound
|
|
|
|
attr_accessor :_tglen, :_tg
|
|
|
|
attr_accessor :_tglen, :_tg
|
|
|
@ -594,8 +583,6 @@ class DfArray < Compound
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
include Enumerable
|
|
|
|
include Enumerable
|
|
|
|
def each ; (0...length).each { |i| yield self[i] } ; end
|
|
|
|
|
|
|
|
def inspect ; to_a.inspect ; end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
class DfLinkedList < Compound
|
|
|
|
class DfLinkedList < Compound
|
|
|
|
attr_accessor :_tg
|
|
|
|
attr_accessor :_tg
|
|
|
@ -608,27 +595,32 @@ class DfLinkedList < Compound
|
|
|
|
field(:_next, 8) { number 32, false }
|
|
|
|
field(:_next, 8) { number 32, false }
|
|
|
|
|
|
|
|
|
|
|
|
def item
|
|
|
|
def item
|
|
|
|
addr = _ptr
|
|
|
|
# With the current xml structure, currently _tg designate
|
|
|
|
return if addr == 0
|
|
|
|
# the type of the 'next' and 'prev' fields, not 'item'.
|
|
|
|
@_tg._at(addr)._get
|
|
|
|
# List head has item == NULL, so we can safely return nil.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#addr = _ptr
|
|
|
|
|
|
|
|
#return if addr == 0
|
|
|
|
|
|
|
|
#@_tg._at(addr)._get
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def item=(v)
|
|
|
|
def item=(v)
|
|
|
|
addr = _ptr
|
|
|
|
#addr = _ptr
|
|
|
|
raise 'null pointer' if addr == 0
|
|
|
|
#raise 'null pointer' if addr == 0
|
|
|
|
@_tg.at(addr)._set(v)
|
|
|
|
#@_tg.at(addr)._set(v)
|
|
|
|
|
|
|
|
raise 'null pointer'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def prev
|
|
|
|
def prev
|
|
|
|
addr = _prev
|
|
|
|
addr = _prev
|
|
|
|
return if addr == 0
|
|
|
|
return if addr == 0
|
|
|
|
_at(addr)
|
|
|
|
@_tg._at(addr)._get
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def next
|
|
|
|
def next
|
|
|
|
addr = _next
|
|
|
|
addr = _next
|
|
|
|
return if addr == 0
|
|
|
|
return if addr == 0
|
|
|
|
_at(addr)
|
|
|
|
@_tg._at(addr)._get
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
include Enumerable
|
|
|
|
include Enumerable
|
|
|
@ -639,8 +631,7 @@ class DfLinkedList < Compound
|
|
|
|
o = o.next
|
|
|
|
o = o.next
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def inspect ; "#<DfLinkedList #{item.inspect} prev=#{'0x%X' % _prev} next=#{'0x%X' % _next}>" ; end
|
|
|
|
def inspect ; "#<DfLinkedList prev=#{'0x%X' % _prev} next=#{'0x%X' % _next} #{item.inspect}>" ; end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
class Global < MemStruct
|
|
|
|
class Global < MemStruct
|
|
|
|