Class: Bayonetta::BXMFile

Inherits:
LibBin::Structure
  • Object
show all
Defined in:
lib/bayonetta/bxm.rb

Overview

begin

Defined Under Namespace

Classes: Datum, Header, Node

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_xml(xml, tag = "BXM\x00".b) ⇒ Object



130
131
132
133
# File 'lib/bayonetta/bxm.rb', line 130

def self.from_xml(xml, tag="BXM\x00".b)
  bxm = self.new
  bxm.from_xml(xml, tag)
end

.is_big?(f) ⇒ Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/bayonetta/bxm.rb', line 135

def self.is_big?(f)
  true
end

.load(input_name) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/bayonetta/bxm.rb', line 139

def self.load(input_name)
  if input_name.respond_to?(:read) && input_name.respond_to?(:seek)
    input = input_name
  else
    File.open(input_name, "rb") { |f|
      input = StringIO::new(f.read, "rb")
    }
  end
  tag = input.read(4).unpack("a4").first
  raise "invalid file type #{tag}!" if tag != "XML\x00".b && tag != "BXM\x00".b
  input.rewind
  bxm = self.new
  big = input_big = is_big?(input)
  bxm.instance_variable_set(:@__was_big, big)
  bxm.__load(input, big)
  input.close unless input_name.respond_to?(:read) && input_name.respond_to?(:seek)
  bxm
end

Instance Method Details

#build_xml_tree(doc, index, datas) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/bayonetta/bxm.rb', line 49

def build_xml_tree(doc, index, datas)
  node = nodes[index]
  name, value = datas[node.datum_index]
  n = Nokogiri::XML::Node.new(name, doc)
  n.content = value if value
  node.attribute_count.times { |i|
    name, value = datas[node.datum_index + i + 1]
    n[name] = value
  }
  node.child_count.times { |i|
    n << build_xml_tree(doc, node.first_child_index + i, datas)
  }
  n
end

#dump(output_name, output_big = true) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/bayonetta/bxm.rb', line 158

def dump(output_name, output_big = true)
  if output_name.respond_to?(:write) && output_name.respond_to?(:seek)
    output = output_name
  else
    output = StringIO::new("".b, "wb")
  end

  __set_dump_state(output, output_big, nil, nil)
  __dump_fields
  __unset_dump_state

  unless output_name.respond_to?(:write) && output_name.respond_to?(:seek)
    File.open(output_name, "wb") { |f|
      f.write output.string
    }
    output.close
  end
  self
end

#from_xml(xml, tag) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/bayonetta/bxm.rb', line 102

def from_xml(xml, tag)
  @header = Header.new
  @nodes = []
  @datums = []
  @data = Set.new
  header.id = tag
  header.unknown = 0
  process_node(xml.children.first, 0, 1)
  header.node_count = nodes.length
  header.datum_count = datums.length
  io = StringIO::new("", "wb")
  data_map = data.collect { |d|
    pos = io.tell
    io.write(d, "\0")
    [d, pos]
  }.to_h
  data_map[nil] = -1
  datums.collect! { |n, v|
    d = Datum.new
    d.name_offset = data_map[n]
    d.value_offset = data_map[v]
    d
  }
  @data = io.string
  header.data_size = data.bytesize
  self
end

#get_data_stringsObject



33
34
35
36
37
38
39
40
41
42
# File 'lib/bayonetta/bxm.rb', line 33

def get_data_strings
  io = StringIO::new(data, "rb")
  pos = 0
  data_strings = {-1 => nil}
  while (l = io.gets("\0"))
    data_strings[pos] = l.unpack("Z*").first
    pos = io.tell
  end
  data_strings
end

#get_datasObject



44
45
46
47
# File 'lib/bayonetta/bxm.rb', line 44

def get_datas
  data_strings = get_data_strings
  datums.collect { |d| [data_strings[d.name_offset], data_strings[d.value_offset]] }
end

#process_node(node, index, next_node_index) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/bayonetta/bxm.rb', line 71

def process_node(node, index, next_node_index)
  name = node.name
  children = node.elements
  value = node.content if children.empty?
  value = value.strip if value
  value = nil if value == ''
  attributes = node.attributes

  n = Node.new
  n.child_count = children.size
  n.first_child_index = next_node_index
  n.attribute_count = attributes.size
  nodes[index] = n

  node_datums = [[name, value]]
  attributes.each { |k, v| node_datums.push [k, v.value] }
  datum_index = datums.each_cons(node_datums.size).find_index { |sub| sub == node_datums }
  if datum_index
    n.datum_index = datum_index
  else
    n.datum_index = datums.size
    datums.push *node_datums
    node_datums.flatten.each { |v| data.add v if v }
  end
  next_node_index += children.size
  children.each_with_index { |c, i|
    next_node_index = process_node(c, n.first_child_index + i, next_node_index)
  }
  next_node_index
end

#to_xmlObject



64
65
66
67
68
69
# File 'lib/bayonetta/bxm.rb', line 64

def to_xml
  datas = get_datas
  doc = Nokogiri::XML::Document::new
  doc << build_xml_tree(doc, 0, datas) if header.node_count > 0
  doc
end