class Metasm::NDS

Nintendo DS executable file format

Attributes

arm7[RW]
arm9[RW]
fat[RW]
files[RW]
header[RW]
icon[RW]

Public Class Methods

new(cpu=nil) click to toggle source
Calls superclass method Metasm::ExeFormat.new
# File metasm/exe_format/nds.rb, line 81
def initialize(cpu=nil)
        @endianness = (cpu ? cpu.endianness : :little)
        super(cpu)
end

Public Instance Methods

cpu_from_headers() click to toggle source
# File metasm/exe_format/nds.rb, line 162
def cpu_from_headers
        ARM.new
end
decode() click to toggle source
# File metasm/exe_format/nds.rb, line 96
def decode
        decode_header
        decode_icon
        @arm9 = @encoded[@header.arm9off, @header.arm9sz]
        @arm7 = @encoded[@header.arm7off, @header.arm7sz]
        @arm9.add_export('entrypoint', @header.arm9entry - @header.arm9addr)
        @arm7.add_export('entrypoint_arm7', @header.arm7entry - @header.arm7addr)
end
decode_byte(edata = @encoded) click to toggle source
# File metasm/exe_format/nds.rb, line 70
def decode_byte(edata = @encoded) edata.decode_imm(:u8,  @endianness) end
decode_fat() click to toggle source
# File metasm/exe_format/nds.rb, line 105
def decode_fat
        # decode the files section
        # it is just the tree structure of a file hierarchy
        # no indication whatsoever on where to find individual file content
        f = @encoded[@fnameoff, @fnamesz]
        f.ptr = 0
        idx = []
        # 1st word = size of index subsection
        idxsz = decode_word(f)
        f.ptr = 0
        # index seems to be an array of word, half, half (offset of name, index of name of first file, index of name of first subdir)
        (idxsz/8).times { idx << [decode_word(f), decode_half(f), decode_half(f)] }
        # follows a serie of filenames : 1-byte length, name
        # if length has high bit set, name is a directory, content = index[half following the name]
        dat = []
        idx.each { |off, idf, idd|
                f.ptr = off
                dat << []
                while (l = decode_byte(f)) > 0
                        name = f.read(l&0x7f)
                        if l & 0x80 > 0
                                i = decode_half(f)
                                dat.last << { name => i.to_s(16) }
                        else
                                dat.last << name
                        end
                end
        }

        # build the tree from the serialized data
        # directory = array of [hash (subdirname => directory) or string (filename)]
        tree = dat.map { |dt| dt.map { |d| d.dup } }
        tree.each { |br|
                br.grep(Hash).each { |b|
                        b.each { |k, v| b[k] = tree[v.to_i(16) & 0xfff] }
                }
        }
        tree = tree.first

        # flatten the tree to a list of fullpath
        iter = lambda { |ar, cur|
                ret = []
                ar.each { |elem|
                        case elem
                        when Hash; ret.concat iter[elem.values.first, cur + elem.keys.first + '/']
                        else ret << (cur + elem)
                        end
                }
                ret
        }

        @files = tree #iter[tree, '/']

        encoded.ptr = @fatoff
        @fat = encoded.read(@fatsz)
end
decode_half(edata = @encoded) click to toggle source
# File metasm/exe_format/nds.rb, line 71
def decode_half(edata = @encoded) edata.decode_imm(:u16, @endianness) end
decode_header() click to toggle source

decodes the header from the current offset in self.encoded

# File metasm/exe_format/nds.rb, line 87
def decode_header
        @header = Header.decode(self)
end
decode_icon() click to toggle source
# File metasm/exe_format/nds.rb, line 91
def decode_icon
        @encoded.ptr = @header.iconoff
        @icon = Icon.decode(self)
end
decode_word(edata = @encoded) click to toggle source
# File metasm/exe_format/nds.rb, line 72
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
each_section() { |arm9, arm9addr| ... } click to toggle source
# File metasm/exe_format/nds.rb, line 166
def each_section
        yield @arm9, @header.arm9addr
        yield @arm7, @header.arm7addr
end
encode_byte(val) click to toggle source
# File metasm/exe_format/nds.rb, line 67
def encode_byte(val) Expression[val].encode(:u8,  @endianness) end
encode_half(val) click to toggle source
# File metasm/exe_format/nds.rb, line 68
def encode_half(val) Expression[val].encode(:u16, @endianness) end
encode_word(val) click to toggle source
# File metasm/exe_format/nds.rb, line 69
def encode_word(val) Expression[val].encode(:u32, @endianness) end
get_default_entrypoints() click to toggle source
# File metasm/exe_format/nds.rb, line 171
def get_default_entrypoints
        [@header.arm9entry, @header.arm7entry]
end
sizeof_byte() click to toggle source
# File metasm/exe_format/nds.rb, line 73
def sizeof_byte ; 1 ; end
sizeof_half() click to toggle source
# File metasm/exe_format/nds.rb, line 74
def sizeof_half ; 2 ; end
sizeof_word() click to toggle source
# File metasm/exe_format/nds.rb, line 75
def sizeof_word ; 4 ; end