pgtools 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +25 -0
  3. data/bin/bxm_decoder +2 -0
  4. data/bin/bxm_encoder +2 -0
  5. data/bin/clh_convert +2 -0
  6. data/bin/clp_convert +2 -0
  7. data/bin/clw_convert +2 -0
  8. data/bin/dat_creator +2 -0
  9. data/bin/dat_extractor +2 -0
  10. data/bin/dat_ls +2 -0
  11. data/bin/eff_idd_creator +2 -0
  12. data/bin/eff_idd_extractor +2 -0
  13. data/bin/exp_convert_wiiu_pc +2 -0
  14. data/bin/exp_tool +2 -0
  15. data/bin/mot_convert_wiiu_pc +2 -0
  16. data/bin/mot_tool +2 -0
  17. data/bin/pkz_extractor +2 -0
  18. data/bin/scr_creator +2 -0
  19. data/bin/scr_extractor +2 -0
  20. data/bin/wmb_cleanup +2 -0
  21. data/bin/wmb_common_bones +2 -0
  22. data/bin/wmb_convert_pc_switch +2 -0
  23. data/bin/wmb_convert_wiiu_pc +2 -0
  24. data/bin/wmb_export_assimp +2 -0
  25. data/bin/wmb_get_bone_map +2 -0
  26. data/bin/wmb_import_assimp +2 -0
  27. data/bin/wmb_import_nier +2 -0
  28. data/bin/wmb_import_wiiu +2 -0
  29. data/bin/wtb_convert_wiiu_pc +2 -0
  30. data/bin/wtx_creator +2 -0
  31. data/bin/wtx_extractor +2 -0
  32. data/lib/bayonetta/alignment.rb +14 -0
  33. data/lib/bayonetta/bone.rb +55 -0
  34. data/lib/bayonetta/bxm.rb +180 -0
  35. data/lib/bayonetta/clh.rb +159 -0
  36. data/lib/bayonetta/clp.rb +212 -0
  37. data/lib/bayonetta/clw.rb +166 -0
  38. data/lib/bayonetta/dat.rb +261 -0
  39. data/lib/bayonetta/eff.rb +314 -0
  40. data/lib/bayonetta/endianness.rb +53 -0
  41. data/lib/bayonetta/exp.rb +768 -0
  42. data/lib/bayonetta/linalg.rb +416 -0
  43. data/lib/bayonetta/material_database.yaml +2581 -0
  44. data/lib/bayonetta/mot.rb +763 -0
  45. data/lib/bayonetta/pkz.rb +63 -0
  46. data/lib/bayonetta/scr.rb +393 -0
  47. data/lib/bayonetta/tools/bxm_decoder.rb +23 -0
  48. data/lib/bayonetta/tools/bxm_encoder.rb +37 -0
  49. data/lib/bayonetta/tools/clh_convert.rb +60 -0
  50. data/lib/bayonetta/tools/clp_convert.rb +70 -0
  51. data/lib/bayonetta/tools/clw_convert.rb +60 -0
  52. data/lib/bayonetta/tools/dat_creator.rb +57 -0
  53. data/lib/bayonetta/tools/dat_extractor.rb +94 -0
  54. data/lib/bayonetta/tools/dat_ls.rb +106 -0
  55. data/lib/bayonetta/tools/eff_idd_creator.rb +66 -0
  56. data/lib/bayonetta/tools/eff_idd_extractor.rb +73 -0
  57. data/lib/bayonetta/tools/exp_convert_wiiu_pc.rb +33 -0
  58. data/lib/bayonetta/tools/exp_tool.rb +48 -0
  59. data/lib/bayonetta/tools/mot_convert_wiiu_pc.rb +33 -0
  60. data/lib/bayonetta/tools/mot_tool.rb +60 -0
  61. data/lib/bayonetta/tools/pkz_extractor.rb +75 -0
  62. data/lib/bayonetta/tools/scr_creator.rb +63 -0
  63. data/lib/bayonetta/tools/scr_extractor.rb +78 -0
  64. data/lib/bayonetta/tools/wmb_cleanup.rb +250 -0
  65. data/lib/bayonetta/tools/wmb_common_bones.rb +45 -0
  66. data/lib/bayonetta/tools/wmb_convert_pc_switch.rb +35 -0
  67. data/lib/bayonetta/tools/wmb_convert_wiiu_pc.rb +33 -0
  68. data/lib/bayonetta/tools/wmb_export_assimp.rb +479 -0
  69. data/lib/bayonetta/tools/wmb_get_bone_map.rb +50 -0
  70. data/lib/bayonetta/tools/wmb_import_assimp.rb +735 -0
  71. data/lib/bayonetta/tools/wmb_import_geometry_wiiu_pc.rb +472 -0
  72. data/lib/bayonetta/tools/wmb_import_nier.rb +309 -0
  73. data/lib/bayonetta/tools/wtb_convert_wiiu_pc.rb +95 -0
  74. data/lib/bayonetta/tools/wtb_import_textures.rb +103 -0
  75. data/lib/bayonetta/tools/wtx_creator.rb +69 -0
  76. data/lib/bayonetta/tools/wtx_extractor.rb +85 -0
  77. data/lib/bayonetta/vertex_types.yaml +213 -0
  78. data/lib/bayonetta/vertex_types2.yaml +164 -0
  79. data/lib/bayonetta/vertex_types_nier.yaml +145 -0
  80. data/lib/bayonetta/wmb.rb +2443 -0
  81. data/lib/bayonetta/wmb3.rb +759 -0
  82. data/lib/bayonetta/wtb.rb +481 -0
  83. data/lib/bayonetta.rb +60 -0
  84. metadata +254 -0
@@ -0,0 +1,763 @@
1
+ module Bayonetta
2
+
3
+ module MOTRemaper
4
+
5
+ def remap_bones(map)
6
+ @records.each { |r|
7
+ if map[r.bone_index]
8
+ r.bone_index = map[r.bone_index]
9
+ end
10
+ }
11
+ end
12
+
13
+ end
14
+
15
+ module MOTDecoder
16
+
17
+ def decode_frame(frame_index)
18
+ raise "Invalid frame number #{frame_index} (#{0} - #{@header.frame_count}!" if frame_index < 0 || frame_index >= @header.frame_count
19
+ tracks = Hash::new { |h,k| h[k] = {} }
20
+ @records.each_with_index { |r, i|
21
+ if r.interpolation_type != -1
22
+ if r.interpolation_type == 0
23
+ tracks[r.bone_index][r.animation_track] = r.value
24
+ else
25
+ tracks[r.bone_index][r.animation_track] = @interpolations[i].value(frame_index)
26
+ end
27
+ end
28
+ }
29
+ tracks
30
+ end
31
+
32
+ def decode
33
+ tracks = Hash::new { |h,k| h[k] = {} }
34
+ motion = {}
35
+ motion[:flag] = @header.flag
36
+ motion[:frame_count] = frame_count = @header.frame_count
37
+ motion[:tracks] = tracks
38
+ @records.each_with_index { |r, i|
39
+ if r.interpolation_type != -1
40
+ if r.interpolation_type == 0
41
+ tracks[r.bone_index][r.animation_track] = [r.value] * frame_count
42
+ else
43
+ tracks[r.bone_index][r.animation_track] = @interpolations[i].values(frame_count)
44
+ end
45
+ end
46
+ }
47
+ motion
48
+ end
49
+
50
+ end
51
+
52
+ module QuantizedValues
53
+ def get_p(i)
54
+ @p + @keys[i].cp * @dp
55
+ end
56
+
57
+ def get_m1(i)
58
+ @m1 + @keys[i].cm1 * @dm1
59
+ end
60
+
61
+ def get_m0(i)
62
+ @m0 + @keys[i].cm0 * @dm0
63
+ end
64
+ end
65
+
66
+ module DirectValues
67
+ def get_p(i)
68
+ @keys[i].p
69
+ end
70
+
71
+ def get_m1(i)
72
+ @keys[i].m1
73
+ end
74
+
75
+ def get_m0(i)
76
+ @keys[i].m0
77
+ end
78
+ end
79
+
80
+ module AbsoluteIndexes
81
+ def key_frame_indexes
82
+ @keys.collect { |k| k.index }
83
+ end
84
+ end
85
+
86
+ module RelativeIndexes
87
+ def key_frame_indexes
88
+ index = 0
89
+ @keys.collect { |k| index += k.index }
90
+ end
91
+ end
92
+
93
+ module KeyFrameInterpolate
94
+ def interpol(frame, start_index, stop_index, i)
95
+ p_0 = get_p(i)
96
+ p_1 = get_p(i+1)
97
+ m_0 = get_m1(i)
98
+ m_1 = get_m0(i+1)
99
+ t = (frame - start_index).to_f / (stop_index - start_index)
100
+ (2 * t*t*t - 3 * t*t + 1)*p_0 + (t*t*t - 2 * t*t + t)*m_0 + (-2 * t*t*t + 3 * t*t)*p_1 + (t*t*t - t * t)*m_1
101
+ end
102
+
103
+ def values(frame_count)
104
+ vs = [0.0]*frame_count
105
+ kfis = key_frame_indexes
106
+ kfis.each_cons(2).each_with_index { |(start_index, stop_index), i|
107
+ (start_index..stop_index).each { |frame|
108
+ vs[frame] = interpol(frame, start_index, stop_index, i)
109
+ }
110
+ }
111
+ (0...kfis.first).each { |i|
112
+ vs[i] = vs[kfis.first]
113
+ }
114
+ ((kfis.last+1)...frame_count).each { |i|
115
+ vs[i] = vs[kfis.last]
116
+ }
117
+ vs
118
+ end
119
+
120
+ def value(frame_index)
121
+ kfis = key_frame_indexes
122
+ if frame_index <= kfis.first
123
+ return get_p(0)
124
+ elsif frame_index >= kfis.last
125
+ return get_p(kfis.length - 1)
126
+ else
127
+ kfis.each_cons(2).each_with_index { |(start_index, stop_index), i|
128
+ if frame_index <= stop_index && frame_index >= start_index
129
+ return interpol(frame_index, start_index, stop_index, i)
130
+ end
131
+ }
132
+ end
133
+ end
134
+
135
+ end
136
+
137
+ class MOT2File < LibBin::Structure
138
+ include MOTDecoder
139
+ include MOTRemaper
140
+
141
+ class Interpolation1 < LibBin::Structure
142
+ float :keys, count: '..\records[__index]\num_keys'
143
+
144
+ def values(frame_count)
145
+ count = frame_count
146
+ @keys + [@keys.last] * (count - keys.length)
147
+ end
148
+
149
+ def value(frame_index)
150
+ v = @keys[frame_index]
151
+ v = @keys.last unless v
152
+ v
153
+ end
154
+
155
+ end
156
+
157
+ class Interpolation2 < LibBin::Structure
158
+ float :p
159
+ float :dp
160
+ uint16 :keys, count: '..\records[__index]\num_keys'
161
+
162
+ def values(frame_count)
163
+ count = frame_count
164
+ res = @keys.collect { |k| @p + k*@dp }
165
+ res + [res.last] * (frame_count - keys.length)
166
+ end
167
+
168
+ def value(frame_index)
169
+ cp = @keys[frame_index]
170
+ cp = @keys.last unless cp
171
+ @p + cp*@dp
172
+ end
173
+
174
+ end
175
+
176
+ class Interpolation3 < LibBin::Structure
177
+ pghalf :p
178
+ pghalf :dp
179
+ uint8 :keys, count: '..\records[__index]\num_keys'
180
+
181
+ def values(frame_count)
182
+ count = frame_count
183
+ res = @keys.collect { |k| @p + k*@dp }
184
+ res + [res.last] * (frame_count - keys.length)
185
+ end
186
+
187
+ def value(frame_index)
188
+ cp = @keys[frame_index]
189
+ cp = @keys.last unless cp
190
+ @p + cp*@dp
191
+ end
192
+
193
+ end
194
+
195
+ class Key4 < LibBin::Structure
196
+ uint16 :index
197
+ uint16 :dummy
198
+ float :p
199
+ float :m0
200
+ float :m1
201
+
202
+ def __size
203
+ 16
204
+ end
205
+
206
+ end
207
+
208
+ class Interpolation4 < LibBin::Structure
209
+ include DirectValues
210
+ include AbsoluteIndexes
211
+ include KeyFrameInterpolate
212
+ register_field :keys, Key4, count: '..\records[__index]\num_keys'
213
+
214
+ def __size
215
+ @keys.length * 16
216
+ end
217
+
218
+ end
219
+
220
+ class Key5 < LibBin::Structure
221
+ uint16 :index
222
+ uint16 :cp
223
+ uint16 :cm0
224
+ uint16 :cm1
225
+ end
226
+
227
+ class Interpolation5 < LibBin::Structure
228
+ include QuantizedValues
229
+ include AbsoluteIndexes
230
+ include KeyFrameInterpolate
231
+ float :p
232
+ float :dp
233
+ float :m0
234
+ float :dm0
235
+ float :m1
236
+ float :dm1
237
+ register_field :keys, Key5, count: '..\records[__index]\num_keys'
238
+
239
+ def __size
240
+ 24 + @keys.length * 8
241
+ end
242
+
243
+ end
244
+
245
+ class Key6 < LibBin::Structure
246
+ uint8 :index
247
+ uint8 :cp
248
+ uint8 :cm0
249
+ uint8 :cm1
250
+ end
251
+
252
+ class Interpolation6 < LibBin::Structure
253
+ include QuantizedValues
254
+ include AbsoluteIndexes
255
+ include KeyFrameInterpolate
256
+ pghalf :p
257
+ pghalf :dp
258
+ pghalf :m0
259
+ pghalf :dm0
260
+ pghalf :m1
261
+ pghalf :dm1
262
+ register_field :keys, Key6, count: '..\records[__index]\num_keys'
263
+
264
+ def __size
265
+ 12 + @keys.length * 4
266
+ end
267
+
268
+ end
269
+
270
+ class Key7 < LibBin::Structure
271
+ uint8 :index
272
+ uint8 :cp
273
+ uint8 :cm0
274
+ uint8 :cm1
275
+ end
276
+
277
+ class Interpolation7 < LibBin::Structure
278
+ include QuantizedValues
279
+ include RelativeIndexes
280
+ include KeyFrameInterpolate
281
+ pghalf :p
282
+ pghalf :dp
283
+ pghalf :m0
284
+ pghalf :dm0
285
+ pghalf :m1
286
+ pghalf :dm1
287
+ register_field :keys, Key7, count: '..\records[__index]\num_keys'
288
+
289
+ def __size
290
+ 12 + @keys.length * 4
291
+ end
292
+
293
+ end
294
+
295
+ class Key8 < LibBin::Structure
296
+ uint8 :index_proxy, count: 2
297
+ uint8 :cp
298
+ uint8 :cm0
299
+ uint8 :cm1
300
+ def index
301
+ @index_proxy.pack("C2").unpack("S>").first
302
+ end
303
+
304
+ def index=(v)
305
+ @index_proxy = [v].pack("S>").unpack("C2")
306
+ v
307
+ end
308
+ end
309
+
310
+ class Interpolation8 < LibBin::Structure
311
+ include QuantizedValues
312
+ include AbsoluteIndexes
313
+ include KeyFrameInterpolate
314
+ pghalf :p
315
+ pghalf :dp
316
+ pghalf :m0
317
+ pghalf :dm0
318
+ pghalf :m1
319
+ pghalf :dm1
320
+ register_field :keys, Key8, count: '..\records[__index]\num_keys'
321
+
322
+ def __size
323
+ 12 + @keys.length * 4
324
+ end
325
+
326
+ end
327
+
328
+ class Record < LibBin::Structure
329
+ int16 :bone_index
330
+ int8 :animation_track
331
+ int8 :interpolation_type
332
+ int16 :num_keys
333
+ int16 :u_a
334
+ uint32 :offset
335
+
336
+ def value
337
+ raise "Only animation track 1 have a value" unless @interpolation_type == 0
338
+ [@offset].pack("L").unpack("F").first
339
+ end
340
+
341
+ def __size
342
+ 12
343
+ end
344
+ end
345
+
346
+ class Header < LibBin::Structure
347
+ string :id, 4
348
+ uint32 :version
349
+ uint16 :flag
350
+ uint16 :frame_count
351
+ uint32 :offset_records
352
+ uint32 :num_records
353
+ int8 :u_a, count: 4
354
+ string :name, 16
355
+ end
356
+
357
+ register_field :header, Header
358
+ register_field :records, Record, count: 'header\num_records', offset: 'header\offset_records'
359
+ register_field :terminator, Record, offset: 'header\offset_records + 12*header\num_records'
360
+ register_field :interpolations,
361
+ 'interpolation_type_selector(records[__iterator]\interpolation_type)',
362
+ count: 'header\num_records', sequence: true,
363
+ offset: 'records[__iterator]\offset + header\offset_records + 12*__iterator',
364
+ condition: 'records[__iterator]\interpolation_type != 0 && records[__iterator]\interpolation_type != -1'
365
+
366
+ def interpolation_type_selector(interpolation_type)
367
+ interpolation = nil
368
+ case interpolation_type
369
+ when 1
370
+ interpolation = Interpolation1
371
+ when 2
372
+ interpolation = Interpolation2
373
+ when 3
374
+ interpolation = Interpolation3
375
+ when 4
376
+ interpolation = Interpolation4
377
+ when 5
378
+ interpolation = Interpolation5
379
+ when 6
380
+ interpolation = Interpolation6
381
+ when 7
382
+ interpolation = Interpolation7
383
+ when 8
384
+ interpolation = Interpolation8
385
+ when -1, 0
386
+ interpolation = nil
387
+ else
388
+ raise "Unknown interpolation type: #{interpolation_type}, please report!"
389
+ end
390
+ interpolation
391
+ end
392
+
393
+ def self.is_bayo2?(f)
394
+ f.rewind
395
+ id = f.read(4)
396
+ raise "Invalid id #{id.inspect}!" if id != "mot\0".b
397
+ uint = "L"
398
+ version = f.read(4).unpack(uint).first
399
+ f.rewind
400
+ return true if version == 0x20120405 || version == 0x05041220
401
+ return false
402
+ end
403
+
404
+ def self.is_big?(f)
405
+ f.rewind
406
+ block = lambda { |int|
407
+ id = f.read(4)
408
+ raise "Invalid id #{id.inspect}!" if id != "mot\0".b
409
+ f.read(4).unpack(int).first == 0x20120405
410
+ }
411
+ big = block.call("l>")
412
+ f.rewind
413
+ small = block.call("l<")
414
+ f.rewind
415
+ raise "Invalid data!" unless big ^ small
416
+ return big
417
+ end
418
+
419
+ def self.convert(input_name, output_name, input_big = true, output_big = false)
420
+ input = File.open(input_name, "rb")
421
+ id = input.read(4).unpack("a4").first
422
+ raise "Invalid file type #{id}!" unless id == "mot\0".b
423
+ output = File.open(output_name, "wb")
424
+ output.write("\x00"*input.size)
425
+ input.seek(0);
426
+ output.seek(0);
427
+
428
+ unless is_bayo2?(input)
429
+ mot = MOTFile::new
430
+ else
431
+ mot = self::new
432
+ end
433
+ mot.__convert(input, output, input_big, output_big)
434
+
435
+ input.close
436
+ output.close
437
+ end
438
+
439
+ def self.load(input_name)
440
+ if input_name.respond_to?(:read) && input_name.respond_to?(:seek)
441
+ input = input_name
442
+ else
443
+ input = File.open(input_name, "rb")
444
+ end
445
+
446
+ unless is_bayo2?(input)
447
+ input.close unless input_name.respond_to?(:read) && input_name.respond_to?(:seek)
448
+ return MOTFile::load(input_name)
449
+ end
450
+
451
+ input_big = is_big?(input)
452
+
453
+ mot = self::new
454
+ mot.instance_variable_set(:@__was_big, input_big)
455
+ mot.__load(input, input_big)
456
+ input.close unless input_name.respond_to?(:read) && input_name.respond_to?(:seek)
457
+
458
+ mot
459
+ end
460
+
461
+ def dump(output_name, output_big = false)
462
+ if output_name.respond_to?(:write) && output_name.respond_to?(:seek)
463
+ output = output_name
464
+ else
465
+ output = File.open(output_name, "wb")
466
+ end
467
+ output.rewind
468
+
469
+ __set_dump_state(output, output_big, nil, nil)
470
+ __dump_fields
471
+ __unset_dump_state
472
+ sz = output.size
473
+ sz = align(sz, 0x4)
474
+ if sz > output.size
475
+ output.seek(sz-1)
476
+ output.write("\x00")
477
+ end
478
+
479
+ output.close unless output_name.respond_to?(:write) && output_name.respond_to?(:seek)
480
+ self
481
+ end
482
+
483
+ def was_big?
484
+ @__was_big
485
+ end
486
+
487
+ end
488
+
489
+ class MOTFile < LibBin::Structure
490
+ include MOTDecoder
491
+ include MOTRemaper
492
+
493
+ class Interpolation1 < LibBin::Structure
494
+ float :keys, count: '..\records[__index]\num_keys'
495
+
496
+ def values(frame_count)
497
+ count = frame_count
498
+ @keys + [@keys.last] * (count - keys.length)
499
+ end
500
+
501
+ def value(frame_index)
502
+ v = @keys[frame_index]
503
+ v = @keys.last unless v
504
+ v
505
+ end
506
+
507
+ end
508
+
509
+ class Key4 < LibBin::Structure
510
+ uint16 :index
511
+ uint16 :cp
512
+ uint16 :cm0
513
+ uint16 :cm1
514
+
515
+ def initialize
516
+ @index = 0
517
+ @cp = 0
518
+ @cm0 = 0
519
+ @cm1 = 0
520
+ end
521
+
522
+ end
523
+
524
+ class Interpolation4 < LibBin::Structure
525
+ include QuantizedValues
526
+ include AbsoluteIndexes
527
+ include KeyFrameInterpolate
528
+ float :p
529
+ float :dp
530
+ float :m0
531
+ float :dm0
532
+ float :m1
533
+ float :dm1
534
+ register_field :keys, Key4, count: '..\records[__index]\num_keys'
535
+
536
+ def __size
537
+ 24 + @keys.length*8
538
+ end
539
+
540
+ end
541
+
542
+ class Key6 < LibBin::Structure
543
+ uint8 :index
544
+ uint8 :cp
545
+ uint8 :cm0
546
+ uint8 :cm1
547
+
548
+ def initialize
549
+ @index = 0
550
+ @cp = 0
551
+ @cm0 = 0
552
+ @cm1 = 0
553
+ end
554
+
555
+ def __size
556
+ 4
557
+ end
558
+
559
+ end
560
+
561
+ class Interpolation6 < LibBin::Structure
562
+ include QuantizedValues
563
+ include RelativeIndexes
564
+ include KeyFrameInterpolate
565
+ pghalf :p
566
+ pghalf :dp
567
+ pghalf :m0
568
+ pghalf :dm0
569
+ pghalf :m1
570
+ pghalf :dm1
571
+ register_field :keys, Key6, count: '..\records[__index]\num_keys'
572
+
573
+ def __size
574
+ 12 + @keys.length*4
575
+ end
576
+
577
+ end
578
+
579
+ class Key7 < LibBin::Structure
580
+ uint16 :index
581
+ uint8 :dummy
582
+ uint8 :cp
583
+ uint8 :cm0
584
+ uint8 :cm1
585
+
586
+ def initialize
587
+ @index = 0
588
+ @dummy = 0
589
+ @cp = 0
590
+ @cm0 = 0
591
+ @cm1 = 0
592
+ end
593
+
594
+ def __size
595
+ 6
596
+ end
597
+
598
+ end
599
+
600
+ class Interpolation7 < LibBin::Structure
601
+ include QuantizedValues
602
+ include AbsoluteIndexes
603
+ include KeyFrameInterpolate
604
+ pghalf :p
605
+ pghalf :dp
606
+ pghalf :m0
607
+ pghalf :dm0
608
+ pghalf :m1
609
+ pghalf :dm1
610
+ register_field :keys, Key7, count: '..\records[__index]\num_keys'
611
+
612
+ def __size
613
+ 12 + @keys.length * 6
614
+ end
615
+
616
+ end
617
+
618
+ class Record < LibBin::Structure
619
+ int16 :bone_index
620
+ int8 :animation_track
621
+ int8 :interpolation_type
622
+ int16 :num_keys
623
+ int16 :u_a
624
+ uint32 :offset
625
+
626
+ def value
627
+ raise "Only animation track 1 have a value" unless @interpolation_type == 0
628
+ [@offset].pack("L").unpack("F").first
629
+ end
630
+
631
+ def __size
632
+ 12
633
+ end
634
+ end
635
+
636
+ class Header < LibBin::Structure
637
+ string :id, 4
638
+ uint16 :flag
639
+ uint16 :frame_count
640
+ uint32 :offset_records
641
+ uint32 :num_records
642
+ end
643
+
644
+ register_field :header, Header
645
+ register_field :records, Record, count: 'header\num_records', offset: 'header\offset_records'
646
+ register_field :interpolations,
647
+ 'interpolation_type_selector(records[__iterator]\interpolation_type)',
648
+ count: 'header\num_records',
649
+ sequence: true,
650
+ offset: 'records[__iterator]\offset',
651
+ condition: 'records[__iterator]\interpolation_type != 0'
652
+
653
+ def interpolation_type_selector(interpolation_type)
654
+ interpolation = nil
655
+ case interpolation_type
656
+ when 1
657
+ interpolation = Interpolation1
658
+ when 4
659
+ interpolation = Interpolation4
660
+ when 6
661
+ interpolation = Interpolation6
662
+ when 7
663
+ interpolation = Interpolation7
664
+ when -1, 0
665
+ interpolation = nil
666
+ else
667
+ raise "Unknown interpolation type: #{interpolation_type}, please report!"
668
+ end
669
+ end
670
+
671
+ def self.is_bayo2?(f)
672
+ f.rewind
673
+ id = f.read(4)
674
+ raise "Invalid id #{id.inspect}!" if id != "mot\0".b
675
+ uint = "L"
676
+ version = f.read(4).unpack(uint).first
677
+ f.rewind
678
+ return true if version == 0x20120405 || version == 0x05041220
679
+ return false
680
+ end
681
+
682
+ def self.is_big?(f)
683
+ f.rewind
684
+ block = lambda { |int|
685
+ id = f.read(4)
686
+ raise "Invalid id #{id.inspect}!" if id != "mot\0".b
687
+ f.read(4)
688
+ offset_records = f.read(4).unpack(int).first
689
+ num_records = f.read(4).unpack(int).first
690
+ num_records >= 0 && num_records*12 < f.size && offset_records > 0 && offset_records < f.size
691
+ }
692
+ big = block.call("l>")
693
+ f.rewind
694
+ small = block.call("l<")
695
+ f.rewind
696
+ raise "Invalid data!" unless big ^ small
697
+ return big
698
+ end
699
+
700
+ def self.convert(input_name, output_name, input_big = true, output_big = false)
701
+ input = File.open(input_name, "rb")
702
+ id = input.read(4).unpack("a4").first
703
+ raise "Invalid file type #{id}!" unless id == "mot\0".b
704
+ output = File.open(output_name, "wb")
705
+ output.write("\x00"*input.size)
706
+ input.seek(0);
707
+ output.seek(0);
708
+
709
+ if is_bayo2?(input)
710
+ mot = MOT2File::new
711
+ else
712
+ mot = self::new
713
+ end
714
+ mot.__convert(input, output, input_big, output_big)
715
+
716
+ input.close
717
+ output.close
718
+ end
719
+
720
+ def self.load(input_name)
721
+ if input_name.respond_to?(:read) && input_name.respond_to?(:seek)
722
+ input = input_name
723
+ else
724
+ input = File.open(input_name, "rb")
725
+ end
726
+
727
+ if is_bayo2?(input)
728
+ input.close unless input_name.respond_to?(:read) && input_name.respond_to?(:seek)
729
+ return MOT2File::load(input_name)
730
+ end
731
+
732
+ input_big = is_big?(input)
733
+
734
+ mot = self::new
735
+ mot.instance_variable_set(:@__was_big, input_big)
736
+ mot.__load(input, input_big)
737
+ input.close unless input_name.respond_to?(:read) && input_name.respond_to?(:seek)
738
+
739
+ mot
740
+ end
741
+
742
+ def was_big?
743
+ @__was_big
744
+ end
745
+
746
+ def dump(output_name, output_big = false)
747
+ if output_name.respond_to?(:write) && output_name.respond_to?(:seek)
748
+ output = output_name
749
+ else
750
+ output = File.open(output_name, "wb")
751
+ end
752
+ output.rewind
753
+
754
+ __set_dump_state(output, output_big, nil, nil)
755
+ __dump_fields
756
+ __unset_dump_state
757
+ output.close unless output_name.respond_to?(:write) && output_name.respond_to?(:seek)
758
+ self
759
+ end
760
+
761
+ end
762
+
763
+ end