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,309 @@
1
+ require 'optparse'
2
+ require 'set'
3
+ require_relative '../../bayonetta.rb'
4
+ require 'yaml'
5
+ require 'shellwords'
6
+ include Bayonetta
7
+
8
+ def merge_bones(wmb1, wmb2)
9
+
10
+ tt1 = wmb1.bone_index_translate_table.table
11
+ tt2_orig = wmb2.bone_index_translate_table.table
12
+ tt2 = tt2_orig.invert
13
+
14
+ bones1 = wmb1.get_bone_structure
15
+ if $options[:bone_map]
16
+ common_mapping = YAML::load_file( $options[:bone_map] )
17
+ else
18
+ common_mapping = {}
19
+ end
20
+
21
+ mapping = {}
22
+
23
+ tt2.each { |key, val|
24
+ mapping[key] = tt1[common_mapping[val]]
25
+ }
26
+ mapping = mapping.to_a.sort { |e1, e2| e1.first <=> e2.first }.to_h
27
+
28
+ if $options[:update_bones]
29
+ mapping.select { |k,v| v }.each { |k,v|
30
+ bones1[v].position = wmb2.bones[k].position
31
+ }
32
+ end
33
+
34
+ mapping[-1] = -1
35
+ missing_bones = mapping.select { |k,v| v.nil? }.collect { |k,v| k }
36
+ if $options[:filter_bones]
37
+ missing_bones -= $options[:filter_bones]
38
+ end
39
+ new_bone_index = bones1.size
40
+ new_bone_indexes = []
41
+ missing_bones.each { |bi|
42
+ mapping[bi] = new_bone_index
43
+ new_bone_indexes.push(new_bone_index)
44
+
45
+ b = Bone::new(wmb2.bones[bi].position)
46
+ b.index = new_bone_index
47
+ b.parent = bones1[mapping[wmb2.bones[bi].parent_index]] if wmb2.bones[bi].parent_index != -1
48
+ b.symmetric = -1
49
+ b.flag = 5
50
+
51
+ bones1.push b
52
+ new_bone_index += 1
53
+ }
54
+ wmb1.set_bone_structure(bones1)
55
+ missing_bones_count = missing_bones.length
56
+ raise "Too many bones to add!" if missing_bones_count > 0x100
57
+ (align(missing_bones_count, 0x10) - missing_bones_count).times {
58
+ new_bone_indexes.push(0xfff)
59
+ }
60
+
61
+ used_indexes = tt1.keys
62
+ start_index = nil
63
+
64
+ (0x250..(0x1000-new_bone_indexes.size)).step(0x10) { |s_index|
65
+ if (used_indexes & (s_index..(s_index+new_bone_indexes.size)).to_a) == []
66
+ start_index = s_index
67
+ break
68
+ end
69
+ }
70
+ raise "No room available in translate table!" unless start_index
71
+ new_tt = wmb1.bone_index_translate_table.table.dup
72
+ new_bone_indexes.each_with_index { |ind, i|
73
+ new_tt[i+start_index] = ind
74
+ common_mapping[tt2[missing_bones[i]]] = i + start_index if i < missing_bones.length && missing_bones[i]
75
+ }
76
+ wmb1.bone_index_translate_table.table = new_tt
77
+
78
+ if wmb1.bone_symmetries
79
+ (-missing_bones_count..-1).each { |i|
80
+ symmetric = common_mapping[wmb1.bone_symmetries[i]]
81
+ symmetric = -1 unless symmetric
82
+ wmb1.bone_symmetries[i] = symmetric
83
+ }
84
+ end
85
+
86
+ [common_mapping, mapping]
87
+ end
88
+
89
+ def get_texture_map(tex1, tex2)
90
+ offset = tex1.each.count
91
+ tex_map = {}
92
+ tex2.each.each_with_index { |t,i|
93
+ info, _ = t
94
+ _, _, idx = info
95
+ idx = i unless idx
96
+ tex_map[idx] = i+offset
97
+ }
98
+ tex_map
99
+ end
100
+
101
+ def merge_geometry(wmb1, wmb2, bone_mapping)
102
+ new_meshes = wmb2.header.info_meshes.number.times.collect { WMBFile::Mesh::new }
103
+ new_meshes.each_with_index { |m, i|
104
+ m.header.name = wmb2.meshes[i].name
105
+ m.header.id = i + wmb1.header.num_meshes
106
+ }
107
+
108
+ batch_infos_map = {}
109
+ wmb2.lods.each { |l|
110
+ l.batch_infos.each_with_index { |batch_info, i|
111
+ batch_infos_map[i+l.header.batch_start] = batch_info
112
+ }
113
+ }
114
+
115
+ vertex_types = wmb1.get_vertex_types
116
+
117
+ wmb2.batches.each_with_index { |n_b, batch_index|
118
+ v_g = wmb2.vertex_groups[n_b.vertex_group_index]
119
+ b_s = wmb2.bone_sets[n_b.bone_set_index]
120
+ b = WMBFile::Batch::new
121
+ first_vertex_index = wmb1.vertexes.length
122
+ indices = v_g.indices.slice(n_b.index_start, n_b.num_indices)
123
+ index_set = indices.uniq.sort
124
+ num_vertex = index_set.length
125
+ index_map = index_set.each_with_index.collect { |ind, i|
126
+ [ind, i+first_vertex_index]
127
+ }
128
+
129
+
130
+ wmb1.vertexes += num_vertex.times.collect {
131
+ vertex_types[0]::new
132
+ }
133
+ if wmb1.vertexes_ex_data
134
+ wmb1.vertexes_ex_data += num_vertex.times.collect {
135
+ vertex_types[1]::new
136
+ }
137
+ end
138
+ wmb1.header.num_vertexes += num_vertex
139
+
140
+ fields = wmb1.get_vertex_fields
141
+ fields.each { |field|
142
+ unless v_g.get_vertex_field(field, 0)
143
+ warn "Couldn't find vertex field #{field} in model 2"
144
+ if field == :color
145
+ warn "Using default value 0xc0 0xc0 0xc0 0xff"
146
+ c = Color::new
147
+ c.r = 0xc0
148
+ c.g = 0xc0
149
+ c.b = 0xc0
150
+ c.a = 0xff
151
+ index_map.each { |ind, i|
152
+ wmb1.set_vertex_field(field, i, c)
153
+ }
154
+ elsif field == :mapping2
155
+ warn "Using mapping as default"
156
+ index_map.each { |ind, i|
157
+ wmb1.set_vertex_field(field, i, v_g.get_vertex_field(:mapping, ind))
158
+ }
159
+ else
160
+ warn "No suitable default found"
161
+ end
162
+ else
163
+ if field == :normal
164
+ index_map.each { |ind, i|
165
+ n = Normal::new
166
+ n2 = v_g.get_vertex_field(:normal, ind)
167
+ n.x = n2.x
168
+ n.y = n2.y
169
+ n.z = n2.z
170
+ wmb1.set_vertex_field(field, i, n)
171
+ }
172
+ else
173
+ index_map.each { |ind, i|
174
+ wmb1.set_vertex_field(field, i, v_g.get_vertex_field(field, ind))
175
+ }
176
+ end
177
+ end
178
+ }
179
+
180
+ index_map = index_map.to_h
181
+
182
+ batch_info = batch_infos_map[batch_index]
183
+ mesh = new_meshes[batch_info.mesh_index]
184
+
185
+ b.header.material_id = batch_info.material_index + wmb1.header.num_materials
186
+ b.header.mesh_id = mesh.header.id
187
+ b.header.num_indices = indices.length
188
+ b.indices = indices.collect { |ind| index_map[ind] }
189
+ b.recompute_from_absolute_indices
190
+ b.bone_refs = b_s.bone_indices.collect { |bi| bone_mapping[wmb2.bone_map[bi]] }
191
+ b.num_bone_ref = b.bone_refs.length
192
+
193
+ mesh.batches.push b
194
+ mesh.header.num_batch += 1
195
+ }
196
+
197
+ wmb1.meshes += new_meshes
198
+ wmb1.header.num_meshes += new_meshes.length
199
+
200
+ end
201
+
202
+ def merge_materials(wmb1, wmb2, tex_map)
203
+ new_mat_offset = wmb1.header.num_materials
204
+ mat_offset = wmb1.materials_offsets.last + wmb1.materials.last.__size
205
+ new_materials_offsets = []
206
+ new_materials = []
207
+
208
+ wmb2.materials.each_with_index { |e, i|
209
+ #biggest known material( in fact biggset is 0x174)
210
+ new_materials_offsets.push(mat_offset + i*0x124)
211
+ m = WMBFile::Material::new
212
+ m.type = 0x0
213
+ m.flag = 0x0
214
+ m.material_data = [0x0]*(0x120/4)
215
+ albedo = e.textures.find { |t| t.name.match("g_AlbedoMap") }
216
+ normal = e.textures.find { |t| t.name.match("g_NormalMap") }
217
+ m.material_data[0] = (albedo ? tex_map[albedo.texture_id] : 0x80000000)
218
+ m.material_data[1] = (normal ? tex_map[normal.texture_id] : 0x80000000)
219
+ m.material_data[0] = (m.material_data[0] ? m.material_data[0] : 0x80000000)
220
+ m.material_data[1] = (m.material_data[1] ? m.material_data[1] : 0x80000000)
221
+ new_materials.push(m)
222
+ }
223
+
224
+ wmb1.header.num_materials += wmb2.header.info_materials.number
225
+ wmb1.materials += new_materials
226
+ wmb1.materials_offsets += new_materials_offsets
227
+ end
228
+
229
+ $options = {}
230
+
231
+ OptionParser.new do |opts|
232
+ opts.banner = "Usage: wmb_import_geometry_wiiu_pc.rb target_file source_file [options]"
233
+
234
+ opts.on("-bFILE", "--bone-map=FILE", "Bone map") do |bone_map|
235
+ $options[:bone_map] = bone_map
236
+ end
237
+
238
+ opts.on("-u", "--update-bones", "Update recognized bone positions") do |update_bones|
239
+ $options[:update_bones] = update_bones
240
+ end
241
+
242
+ opts.on("-t", "--[no-]import-textures", "Import textures also") do |import_textures|
243
+ $options[:import_textures] = import_textures
244
+ end
245
+
246
+ opts.on("-o", "--[no-]overwrite", "Overwrite destination files") do |overwrite|
247
+ $options[:overwrite] = overwrite
248
+ end
249
+
250
+ opts.on("-f", "--filter-bones=REJECT_LIST", "Don't import all bones") do |filter_bones|
251
+ $options[:filter_bones] = eval(filter_bones)
252
+ end
253
+
254
+ opts.on("-h", "--help", "Prints this help") do
255
+ puts opts
256
+ exit
257
+ end
258
+
259
+ end.parse!
260
+
261
+ input_file1 = ARGV[0]
262
+ input_file2 = ARGV[1]
263
+
264
+ raise "Invalid file #{input_file1}" unless File::file?(input_file1)
265
+ raise "Invalid file #{input_file2}" unless File::file?(input_file2)
266
+
267
+ Dir.mkdir("wmb_output") unless Dir.exist?("wmb_output")
268
+
269
+ wmb1 = WMBFile::load(input_file1)
270
+ wmb2 = WMBFile::load(input_file2)
271
+
272
+ tex_map = {}
273
+
274
+ if $options[:import_textures]
275
+ tex1_file_name = input_file1.gsub(/wmb\z/,"wtb")
276
+ tex1 = WTBFile::new(File::new(tex1_file_name, "rb"))
277
+ begin
278
+ tex2_file_name = input_file2.gsub(/wmb\z/,"wta")
279
+ tex2 = WTBFile::new(File::new(tex2_file_name, "rb"), true, File::new(input_file2.gsub(/wmb\z/,"wtp"), "rb"))
280
+ rescue
281
+ tex2_file_name = input_file2.gsub(/wmb\z/,"wtb")
282
+ tex2 = WTBFile::new(File::new(tex2_file_name, "rb"))
283
+ end
284
+
285
+ tex_map = get_texture_map(tex1, tex2)
286
+ end
287
+
288
+ common_mapping, bone_mapping = merge_bones(wmb1, wmb2)
289
+
290
+ merge_geometry(wmb1, wmb2, bone_mapping)
291
+
292
+ merge_materials(wmb1, wmb2, tex_map)
293
+
294
+ wmb1.recompute_relative_positions
295
+ wmb1.recompute_layout
296
+
297
+ File::open(File.join("wmb_output", "#{File::basename(input_file2,".wmb")}_#{File::basename(input_file1,".wmb")}_bone_map.yaml"), "w") { |f|
298
+ f.write YAML::dump(common_mapping)
299
+ }
300
+
301
+ if $options[:overwrite]
302
+ wmb1.dump(input_file1)
303
+ else
304
+ wmb1.dump(File.join("wmb_output", File.basename(input_file1)))
305
+ end
306
+
307
+ if $options[:import_textures]
308
+ `ruby #{Shellwords.escape File.join(__dir__,"wtb_import_textures.rb")} #{Shellwords.escape tex1_file_name} #{Shellwords.escape tex2_file_name}#{$options[:overwrite] ? " --overwrite" : ""}`
309
+ end
@@ -0,0 +1,95 @@
1
+ require 'optparse'
2
+ require_relative '../../bayonetta'
3
+ require 'shellwords'
4
+ include Bayonetta
5
+
6
+ # https://stackoverflow.com/a/5471032
7
+ def which(cmd)
8
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
9
+ exe = File.join(path, cmd)
10
+ return exe if File.executable?(exe) && !File.directory?(exe)
11
+ end
12
+ nil
13
+ end
14
+
15
+ $options = {
16
+ output: nil
17
+ }
18
+
19
+ OptionParser.new do |opts|
20
+ opts.banner = <<EOF
21
+ Usage: wtb_convert_wiiu_pc target_file
22
+ EOF
23
+ opts.on("-h", "--help", "Prints this help") do
24
+ puts opts
25
+ exit
26
+ end
27
+
28
+ opts.on("-o", "--output=filename", "file to output result") do |name|
29
+ $options[:output] = name
30
+ end
31
+
32
+ end.parse!
33
+
34
+ input_file = ARGV[0]
35
+
36
+ raise "Invalid file #{input_file}" unless input_file && File::file?(input_file)
37
+
38
+ if File.extname(input_file) == ".wta"
39
+ fl = WTBFile::new(File::new(input_file, "rb"), true, File::new(input_file.gsub(/wta\z/,"wtp"), "rb"))
40
+ else
41
+ fl = WTBFile::new(File::new(input_file, "rb"))
42
+ end
43
+ Dir.mkdir("tex_output") unless Dir.exist?("tex_output")
44
+ prefix = File.join("tex_output", File.basename(input_file, ".wtb"))
45
+ texs = fl.each.each_with_index.collect { |info_f, i|
46
+ info, f = info_f
47
+ ext, flags, idx = info
48
+ tex_name = "#{prefix}_#{"%03d"%i}#{ext}"
49
+ File::open(tex_name, "wb") { |f2|
50
+ f.rewind
51
+ f2.write(f.read)
52
+ }
53
+ [tex_name, [flags, idx]]
54
+ }
55
+
56
+ tex_conv_path = which("TexConv2.exe")
57
+ if !tex_conv_path
58
+ tex_conv_path = File.join(".", "TexConv2.exe")
59
+ if (!File.exist?(tex_conv_path))
60
+ tex_conv_path = File.join(File.expand_path(File.join(File.dirname(__FILE__), *[".."]*3)), "TexConv2.exe")
61
+ if (!File.exist?(tex_conv_path))
62
+ tex_conv_path = nil
63
+ end
64
+ end
65
+ end
66
+
67
+ fl2 = WTBFile::new
68
+ fl2.unknown = fl.unknown
69
+
70
+ texs.each { |name, info|
71
+ flags, idx = info
72
+ if File.extname(input_file) == ".wta"
73
+ flags &= 0xffffffdf #remove 0x20 flag
74
+ if flags == 0x70000000
75
+ flags = 0x10000000
76
+ else
77
+ flags = 0x20000000
78
+ end
79
+ else
80
+ flags &= 0xfffffffd #remove 0x2 flag
81
+ end
82
+ new_name = name.gsub("gtx","dds")
83
+ raise "could not locate TexConv2.exe, put it in your PATH" unless tex_conv_path
84
+ res = `#{Shellwords.escape tex_conv_path} -i #{Shellwords.escape name} -o #{Shellwords.escape new_name}`
85
+ raise "could not execute TexConv2.exe:\n#{res}" if !$?.success?
86
+ fl2.push( File::new(new_name, "rb"), flags, idx )
87
+ }
88
+
89
+ output_file = $options[:output]
90
+ if !output_file
91
+ Dir.mkdir("wtb_output") unless Dir.exist?("wtb_output")
92
+ output_file = File.join("wtb_output", "#{File.basename(input_file.gsub(/wta\z/,"wtb"))}")
93
+ end
94
+ fl2.dump(output_file)
95
+
@@ -0,0 +1,103 @@
1
+ require 'optparse'
2
+ require_relative '../../bayonetta.rb'
3
+ require 'shellwords'
4
+ include Bayonetta
5
+
6
+ # https://stackoverflow.com/a/5471032
7
+ def which(cmd)
8
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
9
+ exe = File.join(path, cmd)
10
+ return exe if File.executable?(exe) && !File.directory?(exe)
11
+ end
12
+ nil
13
+ end
14
+
15
+ $options = {}
16
+
17
+ OptionParser.new do |opts|
18
+ opts.banner = "Usage: wtb_import_textures.rb target_file source_file [options]"
19
+
20
+ opts.on("-o", "--[no-]overwrite", "Overwrite destination file") do |overwrite|
21
+ $options[:overwrite] = overwrite
22
+ end
23
+
24
+ opts.on("-h", "--help", "Prints this help") do
25
+ puts opts
26
+ exit
27
+ end
28
+
29
+ end.parse!
30
+
31
+ input_file1 = ARGV[0]
32
+ input_file2 = ARGV[1]
33
+ raise "Invalid file #{input_file1}" unless File::file?(input_file1)
34
+ fl0 = WTBFile::new(File::new(input_file1, "rb"))
35
+
36
+
37
+ raise "Invalid file #{input_file2}" unless File::file?(input_file2)
38
+ if File.extname(input_file2) == ".wta"
39
+ fl = WTBFile::new(File::new(input_file2, "rb"), true, File::new(input_file2.gsub(/wta\z/,"wtp"), "rb"))
40
+ else
41
+ fl = WTBFile::new(File::new(input_file2, "rb"))
42
+ end
43
+ Dir.mkdir("tex_output") unless Dir.exist?("tex_output")
44
+ prefix = File.join("tex_output", File.basename(input_file2, ".wtb"))
45
+ texs = fl.each.each_with_index.collect { |info_f, i|
46
+ info, f = info_f
47
+ ext, flags, idx = info
48
+ tex_name = "#{prefix}_#{"%03d"%i}#{ext}"
49
+ File::open(tex_name, "wb") { |f2|
50
+ f.rewind
51
+ f2.write(f.read)
52
+ }
53
+ [tex_name, [flags, idx]]
54
+ }
55
+
56
+ tex_conv_path = which("TexConv2.exe")
57
+ if !tex_conv_path
58
+ tex_conv_path = File.join(".", "TexConv2.exe")
59
+ if (!File.exist?(tex_conv_path))
60
+ tex_conv_path = File.join(File.expand_path(File.join(File.dirname(__FILE__), *[".."]*3)), "TexConv2.exe")
61
+ if (!File.exist?(tex_conv_path))
62
+ tex_conv_path = nil
63
+ end
64
+ end
65
+ end
66
+
67
+ fl2 = WTBFile::new
68
+ fl2.unknown = fl.unknown
69
+
70
+ fl0.each { |info, f|
71
+ ext, flags, idx = info
72
+ fl2.push( f, flags, idx )
73
+ }
74
+
75
+ texs.each { |name, info|
76
+ flags, idx = info
77
+ if File.extname(input_file2) == ".wta"
78
+ flags &= 0xffffffdf #remove 0x20 flag
79
+ if flags == 0x70000000
80
+ flags = 0x10000000
81
+ else
82
+ flags = 0x20000000
83
+ end
84
+ elsif fl.big
85
+ flags &= 0xfffffffd #remove 0x2 flag
86
+ end
87
+ if File.extname(name) == ".gtx"
88
+ new_name = name.gsub("gtx","dds")
89
+ raise "could not locate TexConv2.exe, put it in your PATH" unless tex_conv_path
90
+ res = `#{Shellwords.escape tex_conv_path} -i #{Shellwords.escape name} -o #{Shellwords.escape new_name}`
91
+ raise "could not execute TexConv2.exe:\n#{res}" if !$?.success?
92
+ else
93
+ new_name = name
94
+ end
95
+ fl2.push( File::new(new_name, "rb"), flags, nil )
96
+ }
97
+
98
+ if $options[:overwrite]
99
+ fl2.dump(input_file1)
100
+ else
101
+ Dir.mkdir("wtb_output") unless Dir.exist?("wtb_output")
102
+ fl2.dump(File.join("wtb_output", File.basename(input_file1)))
103
+ end
@@ -0,0 +1,69 @@
1
+ require 'optparse'
2
+ require 'yaml'
3
+ require_relative '../../bayonetta'
4
+ include Bayonetta
5
+
6
+ $options = {
7
+ output: nil
8
+ }
9
+ OptionParser.new do |opts|
10
+ opts.banner = <<EOF
11
+ Usage: wtx_creator target_directory
12
+ EOF
13
+ opts.on("-h", "--help", "Prints this help") do
14
+ puts opts
15
+ exit
16
+ end
17
+
18
+ opts.on("-o", "--output=filename", "file to output result") do |name|
19
+ $options[:output] = name
20
+ end
21
+
22
+ end.parse!
23
+
24
+ input_dir = ARGV[0]
25
+
26
+ raise "Not a directory: #{input_dir}!" unless input_dir && File.directory?(input_dir)
27
+
28
+ files = Dir.entries(input_dir)
29
+ pwd = Dir.pwd
30
+ Dir.chdir(input_dir)
31
+ files.select! { |f| File.file?(f) && [".gtx", ".dds", ".bntx", ".xt1"].include?( File.extname(f) ) }
32
+ files.sort!
33
+ puts files
34
+ files.collect! { |fname| File::new(fname, "rb") }
35
+
36
+ big = false
37
+ big = YAML::load_file(".metadata/big.yaml") if File.exist?(".metadata/big.yaml")
38
+ extension = ".wtb"
39
+ extension = YAML::load_file(".metadata/extension.yaml") if File.exist?(".metadata/extension.yaml")
40
+ flags = []
41
+ flags = YAML::load_file(".metadata/texture_flags.yaml") if File.exist?(".metadata/texture_flags.yaml")
42
+ idx = []
43
+ idx = YAML::load_file(".metadata/texture_idx.yaml") if File.exist?(".metadata/texture_idx.yaml")
44
+ infos = []
45
+ infos = YAML::load_file(".metadata/texture_infos.yaml") if File.exist?(".metadata/texture_infos.yaml")
46
+ unknown = 0
47
+ unknown = YAML::load_file(".metadata/unknown.yaml") if File.exist?(".metadata/unknown.yaml")
48
+
49
+
50
+ wtb = WTBFile::new(nil, big, extension == ".wta")
51
+ files.each { |f|
52
+ wtb.push(f)
53
+ }
54
+ wtb.texture_flags = flags
55
+ wtb.texture_infos = infos
56
+ wtb.texture_idx = idx
57
+ wtb.unknown = unknown
58
+
59
+ output_file = $options[:output]
60
+ if !output_file
61
+ Dir.mkdir("wtx_output") unless Dir.exist?("wtx_output")
62
+ Dir.chdir("wtx_output")
63
+ output_file = File.basename(ARGV[0]).gsub("_wta","").gsub("_wtb", "") << extension
64
+ else
65
+ Dir.chdir(pwd)
66
+ end
67
+
68
+ wtb.dump(output_file)
69
+
@@ -0,0 +1,85 @@
1
+ require 'optparse'
2
+ require 'yaml'
3
+ require_relative '../../bayonetta'
4
+
5
+ $options = {
6
+ output: nil
7
+ }
8
+
9
+ OptionParser.new do |opts|
10
+ opts.banner = <<EOF
11
+ Usage: wtx_extractor file [wtp_file]
12
+ EOF
13
+ opts.on("-h", "--help", "Prints this help") do
14
+ puts opts
15
+ exit
16
+ end
17
+
18
+ opts.on("-o", "--output=dirname", "directory to output result") do |name|
19
+ $options[:output] = name
20
+ end
21
+
22
+ end.parse!
23
+
24
+ save_pwd = Dir.pwd
25
+
26
+ filename = ARGV[0]
27
+ raise "Invalid file: #{filename}!" unless filename && File.exist?(filename)
28
+ wtp_name = ARGV[1]
29
+ raise "Invalid file: #{filename}!" if wtp_name && !File.exist?(wtp_name)
30
+
31
+ directory = File.dirname(filename)
32
+ name = File.basename(filename)
33
+ ext_name = File.extname(name)
34
+
35
+ raise "Invalid file: #{filename}!" unless ext_name == ".wta" || ext_name == ".wtb"
36
+
37
+ f = File::open(filename, "rb")
38
+
39
+ Dir.chdir(directory)
40
+ tex_name = File.basename(name, ext_name)
41
+ if ext_name == ".wta"
42
+ wtp_name = tex_name + ".wtp" unless wtp_name
43
+ f_wtp = File::open(wtp_name, "rb")
44
+ dir_name = tex_name + "_wta"
45
+ else
46
+ f_wtp = nil
47
+ dir_name = tex_name + "_wtb"
48
+ end
49
+ if $options[:output]
50
+ Dir.chdir(save_pwd)
51
+ Dir.chdir($options[:output])
52
+ end
53
+ Dir.mkdir(dir_name) unless Dir.exist?(dir_name)
54
+ Dir.chdir(dir_name)
55
+
56
+ wtb = Bayonetta::WTBFile::new(f, true, f_wtp)
57
+
58
+ wtb.each.each_with_index { |info_f, i|
59
+ info, f = info_f
60
+ ext, _, _ = info
61
+ File::open("#{tex_name}_#{"%03d"%i}#{ext}", "wb") { |f2|
62
+ f.rewind
63
+ f2.write(f.read)
64
+ }
65
+ }
66
+ Dir.mkdir(".metadata") unless Dir.exist?(".metadata")
67
+ Dir.chdir(".metadata")
68
+ File::open("texture_flags.yaml", "w") { |fl|
69
+ fl.print YAML::dump( wtb.texture_flags )
70
+ }
71
+ File::open("texture_idx.yaml", "w") { |fl|
72
+ fl.print YAML::dump( wtb.texture_idx )
73
+ }
74
+ File::open("texture_infos.yaml", "w") { |fl|
75
+ fl.print YAML::dump( wtb.texture_infos )
76
+ }
77
+ File::open("big.yaml","w") { |fl|
78
+ fl.print YAML::dump( wtb.big )
79
+ }
80
+ File::open("unknown.yaml","w") { |fl|
81
+ fl.print YAML::dump( wtb.unknown )
82
+ }
83
+ File::open("extension.yaml", "w") { |fl|
84
+ fl.print YAML::dump( ext_name )
85
+ }