-
Notifications
You must be signed in to change notification settings - Fork 3
/
MGSV FMDL PS3.ms
450 lines (385 loc) · 9.8 KB
/
MGSV FMDL PS3.ms
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
--made by Jayveer for savemgo.com
--f = fopen "E:\\3d3b40_39.fmdl" "rb" --big boss
--f = fopen "E:\\1915a8_89.fmdl" "rb" --horn
--f = fopen "E:\\39be78_112.fmdl" "rb" --rubble
fsource = GetOpenFileName \
caption:"Select FMDL File" \
types: "fmdl(*.fmdl)|*.fmdl|All files (*.*)|*.*|"
if fsource != undefined then (
f = fopen fsource "rb"
clearlistener()
fn readBElong fstream = (
long = readlong fstream
long = bit.swapBytes long 1 4
long = bit.swapBytes long 2 3
return long
)
fn readBEshort fstream = (
short = readshort fstream #unsigned
short = bit.swapBytes short 1 2
return short
)
fn readBEHalfFloat fstream = (
hf=readBEshort fstream
sign = bit.get hf 16
exponent = (bit.shift (bit.and hf (bit.hexasint "7C00")) -10) as integer - 16
fraction = bit.and hf (bit.hexasint "03FF")
if sign==true then sign = 1 else sign = 0
exponentF = exponent + 127
outputAsFloat = bit.or (bit.or (bit.shift fraction 13) \
(bit.shift exponentF 23)) (bit.shift sign 31)
return bit.intasfloat outputasfloat*2
)
fn ReadBEfloat fstream = (
fpt=readfloat fstream
itger = bit.floatAsInt fpt
hih = bit.intashex itger
while hih.count < 8 do hih = "0" + hih
shn = (substring hih 7 2) + \
(substring hih 5 2) + \
(substring hih 3 2) + \
(substring hih 1 2)
bit.intAsFloat (bit.hexasint shn)
)
fn whereTheFuckAmI = (
print (bit.intAsHex(ftell f))
)
fn readBEFixedString bstream fixedLen = (
local str = ""
for i = 1 to fixedLen do
(
str += bit.intAsChar (readbyte bstream #unsigned)
)
str
)
struct sections
(
sectionOffset=#(),
sectionLength=#()
)
struct indexTable
(
entryId=#(),
entryBlocks=#(),
entryOffset=#()
)
struct secondIndexTable
(
entryId=#(),
entryOffset=#(),
entrySize=#()
)
struct bufferTable
(
bufferOffset=#(),
bufferSize=#()
)
struct stringTable
(
dataType=#(),
stringLength=#(),
stringOffset=#()
)
struct meshList
(
stringArrayEntry=#(),
unknown=#(),
meshParent=#(),
unknown2=#()
)
fmdlSections= sections()
fmdlEntries = indexTable()
fmdlEntries2 = secondIndexTable()
fmdlBuffers = bufferTable()
fmdlStrings = stringTable()
Face_array=#()
Vert_array=#()
UV_array=#()
Normal_array=#()
String_array=#()
Weight_array=#()
vertSize = #()
faceSize= #()
BNArr = #()
vBufSize =#()
--
faceOffset=#()
aFaceSize=#()
fseek f 0x20 #seek_set
noEntries = readBElong f
noEntries2 = readBElong f
for i = 1 to 2 do
(
fmdlSections.sectionOffset[i] = readBElong f
fmdlSections.sectionLength[i] = readBElong f
)
fseek f 0x08 #seek_cur
for i = 1 to noEntries do
(
id = readshort f
if id == 0 then
(
id = 99 --annoying that maxscript cant accept 0 as an array index, so I have to do this shit hack
)
fmdlEntries.entryId[id] = id
fmdlEntries.entryBlocks[id] = readBEshort f
fmdlEntries.entryOffset[id] = readBElong f
)
for i = 1 to noEntries2 do
(
id = readbyte f
fseek f 0x03 #seek_cur
if id == 0 then
(
id = 99 --annoying that maxscript cant accept 0 as an array index, so I have to do this shit hack
)
fmdlEntries2.entryId[id] = id
fmdlEntries2.entryOffset[id] = readBElong f
fmdlEntries2.entrySize[id] = readBElong f
)
--id 00 = Bone Table
--id 01 = Mesh list
--id 02 = Mesh Group Table
--id 03 = Vertex + Face index table
--id 04 =
--id 05 = Bone Lookup Table
--id 06 = Tex list
--id 07 = Mat list
--id 08 =
--id 09 =
--id 0A = something to do with vdef
--id 0B = ?? big mystery
--id 0C = String Def Table
--id 0D = floats, the same as bones
--id 0E = Buffer Offset Table
--id 11 = face index table
/**
They may have taken the string table out for FMDLs in TPP so removing this for now
--id 0C = string table
fseek f (fmdlSections.sectionOffset[1] + fmdlEntries.entryOffset[0x0C]) #seek_set
for x = 1 to (fmdlEntries.entryBlocks[0x0C]) do
(
fmdlStrings.dataType[x] = readBEshort f
fmdlStrings.stringLength[x] = readBEshort f
fmdlStrings.stringOffset[x] = readBElong f
)
--populate String Array
for x = 1 to (fmdlEntries.entryBlocks[0x0C]) do
(
fseek f (fmdlSections.sectionOffset[2] + fmdlEntries2.entryOffset[3] + fmdlStrings.stringOffset[x]) #seek_set
String_array[x] = readBEFixedString f fmdlStrings.stringLength[x]
)
*/
--id 0A = Vert Def Table, or something
fseek f (fmdlSections.sectionOffset[1] + fmdlEntries.entryOffset[0x0A]) #seek_set
for x = 1 to (fmdlEntries.entryBlocks[0x03] ) do
(
fseek f 0x0A #seek_cur
vBufSize[x] = readbyte f
if vBufSize[x] == 0x1C or vBufSize[x] == 0x14 then
(
fseek f 0xD #seek_cur
)
else
(
fseek f 0x15 #seek_cur
)
)
/*
--id 00 = bones, oh sorry, 99 because maxscript is a piece of shit (if it doesnt have this id it doesn't have bones)
if (fmdlEntries.entryBlocks[99] != undefined) then
(
fseek f (fmdlSections.sectionOffset[1] + fmdlEntries.entryOffset[99]) #seek_set
for x = 1 to (fmdlEntries.entryBlocks[99]) do
(
boneid = (readBEshort f) as string
boneparent = (readBEshort f) +1
boneidx = readBEshort f
unknown = readBEshort f--mostly always 0x01?
unknown = readBElong f--always 0
unknown = readBElong f --always 0
b1x = readBEfloat f
b1y = readBEfloat f
b1z = readBEfloat f
b1w = readBEfloat f
b2x = readBEfloat f
b2y = readBEfloat f
b2z = readBEfloat f
b2w = readBEfloat f
tfm = (quat 0 0 0 1) as matrix3
tfm.row4 = [b1x,b1y,b1z]
if isvalidnode (getNodeByName boneid) == true Do
(
append BNArr (getNodeByName boneid)
)
if isvalidnode (getNodeByName boneid) != true Do
(
if (boneparent != 0) do
(
tfm = tfm * BNArr[boneparent].objecttransform
)
newBone = bonesys.createbone tfm.row4 (tfm.row4 + 0.01 * (normalize tfm.row1)) (normalize tfm.row3)
newBone.name = String_array[((boneid as integer)+1)]
newBone.width = 0.01
newBone.height = 0.01
newBone.transform = tfm
--newBone.wirecolor = white
newBone.showlinks = true
newBone.setBoneEnable true 0
newBone.pos.controller = TCB_position ()
newBone.rotation.controller = TCB_rotation ()
if (boneparent != 0) then
newBone.parent = BNArr[boneparent]
append BNArr newBone
)
)
)
*/
--id 03 = vertex index table
fseek f (fmdlSections.sectionOffset[1] + fmdlEntries.entryOffset[3]) #seek_set
for x=1 to fmdlEntries.entryBlocks[3] do
(
fseek f 0xA #seek_cur
print("vertsizeoffset")
whereTheFuckAmI()
--vertSize[x] = readBElong f
vertSize[x] = readBEshort f
fseek f 0x02 #seek_cur
uk = readBEshort f
uk = readBEshort f
--faceOffset[x] = readBElong f
faceOffset[x] = readBEshort f
print(bit.intAsHex(faceOffset[x]))
--aFaceSize[x] = readBElong f
fseek f 0x02 #seek_cur
aFaceSize[x] = readBEshort f
fseek f 0x18 #seek_cur
)
/*
--id 03 = face index table
fseek f (fmdlSections.sectionOffset[1] + fmdlEntries.entryOffset[0x11]) #seek_set
for x=1 to fmdlEntries.entryBlocks[3] do
(
if (fmdlEntries.entryBlocks[0x11] == fmdlEntries.entryBlocks[0x03]) then
(
print("It was this type")
fseek f 0x4 #seek_cur
faceSize[x] = readBElong f
)
else
(
fseek f 0x18 #seek_cur
val1 = readBElong f
val2 = readBElong f
faceSize[x] = val1 + val2
)
)
*/
--id 0E = Buffer offset table
fseek f (fmdlSections.sectionOffset[1] + fmdlEntries.entryOffset[0x0E]) #seek_set
for x=1 to fmdlEntries.entryBlocks[0x0E] do
(
fseek f 0x4 #seek_cur
fmdlBuffers.bufferSize[x] = readBElong f
fmdlBuffers.bufferOffset[x] = readBElong f
fseek f 0x4 #seek_cur
)
--id 02 of second index = vertex buffer
vertexOffset = (fmdlSections.sectionOffset[2] +fmdlEntries2.entryOffset[2])--0x5C00
fseek f vertexOffset #seek_set
--id 02 of second index = vertex buffer + 3rd entry of buffer table = face buffer
lastFacePos = ((fmdlSections.sectionOffset[2] +fmdlEntries2.entryOffset[2]) + fmdlBuffers.bufferOffset[3])--0x78450
--id 02 of second index = vertex buffer + 2nd entry of buffer table = vdef buffer
lastUVPos = ((fmdlSections.sectionOffset[2] +fmdlEntries2.entryOffset[2]) + fmdlBuffers.bufferOffset[2])--0x25860
for n = 1 to fmdlEntries.entryBlocks[3] do
(
print("vbuf offset")
print(whereTheFuckAmI())
print(vertSize[n])
--vertex buffer
for x=1 to vertSize[n] do
(
vx=readBEfloat f
vy=readBEfloat f
vz=readBEfloat f
append Vert_array[vx,vy,vz]
--comment below if you want to give UVs a try
append UV_array[0,0,0]
)
while mod (ftell f) 16 !=0 do
(
fseek f 0x4 #seek_cur
)
lastVertPos = ftell f
--uncomment below if you want to give uv's a try, wont always work isn't completely ported
/*
--temp testing
fseek f lastUVPos #seek_set
whereTheFuckAmI()
for x =1 to vertSize[n] do
(
nx = readBEhalffloat f
ny = readBEhalffloat f
nz = readBEhalffloat f
nw = readBEhalffloat f
uk = readBEhalffloat f
uk = readBEhalffloat f
uk = readBEhalffloat f
uk = readBEhalffloat f
if vBufSize[n] == 0x20 or vBufSize[n] == 0x1C then
(
bw1 = readbyte f#unsigned / 255
bw2 = readbyte f#unsigned / 255
bw3= readbyte f#unsigned / 255
bw4 = readbyte f#unsigned / 255
bidx1 = readbyte f
bidx2 = readbyte f
bidx3 = readbyte f
bidx4 = readbyte f
if vBufSize[n] == 0x20 then
(
uk = readBEfloat f
)
)
tu = readBEhalffloat f
tv = readBEhalffloat f*-1
append UV_array[tu,tv,0]
append Normal_array[nx,ny,nz]
)
while mod (ftell f) 16 !=0 do
(
fseek f 0x4 #seek_cur
)
lastUVPos = ftell f
*/
--face buffer
--fseek f lastFacePos #seek_set
fseek f (lastFacePos + (faceOffset[n]*2)) #seek_set
for n=1 to aFaceSize[n]/3 do
(
fa=readBEShort f +1
fb=readBEShort f +1
fc=readBEShort f +1
append Face_array[fc, fb, fa]
)
--lastFacePos = ftell f
msh = mesh vertices:Vert_array faces:Face_array
msh.numTVerts = UV_array.count
buildTVFaces msh
for j = 1 to UV_array.count do setTVert msh j UV_array[j]
for j = 1 to Face_array.count do setTVFace msh j Face_array[j]
--for j = 1 to Normal_array.count do setnormal msh j Normal_array[j]
--print Normal_Array
Face_array=#()
Vert_array=#()
UV_array=#()
Normal_array=#()
fseek f lastvertPos #seek_set
)
gc()
fclose f
)
else
(
clearlistener()
)