Class: Bayonetta::SCR2File

Inherits:
Object
  • Object
show all
Includes:
Alignment, Endianness
Defined in:
lib/bayonetta/scr.rb

Constant Summary collapse

ALIGNMENTS =
{
  'wmb' => 0x80,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(f = nil, big = false) ⇒ SCR2File

Returns a new instance of SCR2File.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
101
102
103
104
105
106
107
108
109
110
# File 'lib/bayonetta/scr.rb', line 45

def initialize(f = nil, big = false)
  @big = big
  if f
    file_name_input = false
    unless f.respond_to?(:read) && f.respond_to?(:seek)
      file_name_input = true
      f = File::new(f, "rb")
    end
    @big = SCR2File.is_big?(f)

    f.rewind
    uint = get_uint
    ushort = get_ushort
    float = get_float
    short = get_short

    @id = f.read(4)
    raise "Invalid id #{id.inspect}!" if @id != "SCR\0".b
    @unknown, @num_models = f.read(4).unpack("#{ushort}2")
    @offset_offsets_models = f.read(4).unpack(uint).first

    f.seek(@offset_offsets_models)
    @offsets_models_meta = f.read(4*@num_models).unpack("#{uint}#{@num_models}")
    @offsets_models = []
    @sizes_models = []


    @models_metadata = @num_models.times.collect { |i|
      f.seek(@offsets_models_meta[i])
      offset = f.read(4).unpack(uint).first
      name = f.read(64)
      transform = f.read(4*9).unpack("#{float}9")
      u_a = f.read(18*2).unpack("#{short}18")
      @offsets_models.push(offset)
      {
        name: name,
        transform: transform,
        u_a: u_a
      }
    }
    @num_models.times { |i|
      if i == ( @num_models - 1 )
        @sizes_models.push( f.size - @offsets_models[i] )
      else
        @sizes_models.push( @offsets_models_meta[i+1] - @offsets_models[i] )
      end
    }
    @models = @num_models.times.collect { |i|
      f.seek(@offsets_models[i])
      StringIO::new( f.read(@sizes_models[i]), "rb")
    }
    @total_size = f.size
    f.close if file_name_input
  else
    @id = "SCR\0".b
    @unknown = 0x12
    @num_models = 0
    @offsets_models = []
    @sizes_models = []
    @models_metadata = []
    @offsets_models_meta = []
    @models = []
    @total_size = 0
    @offset_offsets_models = 0x10
  end
end

Instance Attribute Details

#bigObject (readonly)

Returns the value of attribute big.



5
6
7
# File 'lib/bayonetta/scr.rb', line 5

def big
  @big
end

#models_metadataObject

Returns the value of attribute models_metadata.



7
8
9
# File 'lib/bayonetta/scr.rb', line 7

def 
  @models_metadata
end

#unknownObject

Returns the value of attribute unknown.



6
7
8
# File 'lib/bayonetta/scr.rb', line 6

def unknown
  @unknown
end

Class Method Details

.is_bayo?(f) ⇒ Boolean

Returns:

  • (Boolean)


17
18
19
20
21
22
23
24
# File 'lib/bayonetta/scr.rb', line 17

def self.is_bayo?(f)
  f.rewind
  id = f.read(4)
  raise "Invalid id #{id.inspect}!" if id != "SCR\0".b
  a, b = f.read(4).unpack("S2")
  f.rewind
  a == 0 || b == 0
end

.is_big?(f) ⇒ Boolean

Returns:

  • (Boolean)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/bayonetta/scr.rb', line 26

def self.is_big?(f)
  f.rewind
  block = lambda { |int, short|
    id = f.read(4)
    raise "Invalid id #{id.inspect}!" if id != "SCR\0".b
    unknown = f.read(2).unpack(short).first
    model_number = f.read(2).unpack(short).first
    offset_model_offsets = f.read(4).unpack(int).first
    unknown >= 0 && model_number >=0 && (model_number * 0x8c + 0x10) < f.size &&
      offset_model_offsets >= 0 && offset_model_offsets < f.size
  }
  big = block.call("l>", "s>")
  f.rewind
  small = block.call("l<", "s<")
  f.rewind
  raise "Invalid data!" unless big ^ small
  return big
end

Instance Method Details

#[](i) ⇒ Object



122
123
124
# File 'lib/bayonetta/scr.rb', line 122

def [](i)
  return @models[i]
end

#bayo2?Boolean

Returns:

  • (Boolean)


13
14
15
# File 'lib/bayonetta/scr.rb', line 13

def bayo2?
  true
end

#compute_layoutObject



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/bayonetta/scr.rb', line 133

def compute_layout
  invalidate_layout
  current_offset = @offset_offsets_models + 0x4 * @num_models
  @num_models.times { |i|
     current_offset = align(current_offset, 0x20)
     @offsets_models_meta.push(current_offset)
     current_offset += 0x8c
     current_offset = align(current_offset, ALIGNMENTS["wmb"])
     @offsets_models.push(current_offset)
     current_offset += @sizes_models[i]
  }
  @total_size = align(current_offset, 0x20)
  self
end

#dump(name) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/bayonetta/scr.rb', line 160

def dump(name)
  compute_layout
  uint = get_uint
  ushort = get_ushort
  File.open(name,"wb") { |f|
    f.write("\0"*@total_size)
    f.rewind
    f.write([@id].pack("a4"))
    f.write([@unknown].pack(ushort))
    f.write([@num_models].pack(ushort))
    f.write([@offset_offsets_models].pack(uint))
    f.seek(@offset_offsets_models)
    f.write(@offsets_models_meta.pack("#{uint}#{@num_models}"))
    @num_models.times { |i|
      f.seek(@offsets_models_meta[i])
      f.write([@offsets_models[i]].pack(uint))
      f.write([@models_metadata[i][:name]].pack("a64"))
      f.write(@models_metadata[i][:transform].pack("#{get_float}9"))
      f.write(@models_metadata[i][:u_a].pack("#{get_short}18"))
      f.seek(@offsets_models[i])
      @models[i].rewind
      f.write(@models[i].read)
    }
  }
  self
end

#each_modelObject



112
113
114
115
116
117
118
119
120
# File 'lib/bayonetta/scr.rb', line 112

def each_model
  if block_given? then
    @num_models.times { |i|
      yield @models[i]
    }
  else
    to_enum(:each_model)
  end
end

#invalidate_layoutObject



126
127
128
129
130
131
# File 'lib/bayonetta/scr.rb', line 126

def invalidate_layout
  @offsets_models = []
  @offsets_models_meta = []
  @total_size = 0
  self
end

#push_model(file) ⇒ Object



148
149
150
151
152
153
154
# File 'lib/bayonetta/scr.rb', line 148

def push_model(file)
  invalidate_layout
  @models.push file
  @sizes_models.push file.size
  @num_models += 1
  self
end

#texturesObject



156
157
158
# File 'lib/bayonetta/scr.rb', line 156

def textures
  nil
end