I was going to explore modding the game, but fell lazy of solving the rest of the structures.
credit goes to chrrox as to helping me discover the face info
Overview:
Files are archived in CRIware's CPK Container. I Used Luigi's BMS script to unpack the files ->
http://aluigi.altervista.org/quickbms.htm
Once files are unpacked you'll be seeing two common file extensions (*.DAT,*.DTT)
DAT is a general resource container and DTT from what I can tell is just a texture dump file.
The xbox360 DTT has no headers, however the PS3 DTT has GTF headers.
GTF is a PS3 format, there file structure is documented in the PS3 SDK literature.
I cannot post the structs from the SDK doc {illegal?}, but I'll be sharing the struct I had prior to finding the structs in the SDK
As for files within the DAT once unpacked, there is ALOT. I'll document only two; (WMB,WPA)
WMB is there model binary format, WTA, is an offset table that relates to the DTT file.
> Format for Xbox360: Data is Big Endian and all integers in are unsigned unless otherwise noted
DAT Format
Description:
you collect the count and the offsets, then jump to each table.
the tables hold basic info like file offset, file size, filename, file extension, etc..
you can then parse the DAT file and dump the containing files.
dat_header { // all offsets relative to begining of DAT header
LONG file_count
LONG offset_file_table
LONG offset_extension_table
LONG offset_name_table
LONG offset_size_table
LONG offset_unknown_data
LONG null
}
file_table { // n = file_count
LONG[n] offset
}
extension_table { // string length fixed at 4
STRING file_ext // Example: "wmb", "wta", "bxm", "mot", "eff"
}
name_table {
LONG string_length
}
name_table_entries { // n = string_length
STRING name[n]
}
size_table { // n = file_count
LONG[n] size
}
WMB Format ("WMB4" Only) "WonderfulModelBinary4"??
Description:
Gah O_o it would take alot of paragraphs to explain this so yeah PM me if you need specifics
Just bare in mind I didn't document all the tables, cause franky they'd just be a bunch of unknowns..
so still alot of work ahead for whom ever wants to continue it --vertex def is also incomplete
wmb_header { // all offsets relative to begining of WMB header
LONG magic "WMB4"
LONG version // ? always -1
SHORT vertex_stride // ? vertex stride 0x00 = 24 | 0x01 = 32
SHORT ukn02
SHORT primitive_type // 0x00=trilist | 0x01= trilist
SHORT ukn03
LONG ukn04
LONG ukn05
LONG ukn06
LONG ukn07
LONG ukn08
LONG ukn09
LONG buffer_table_offset // offset to vertex buffer header offset? lol
LONG buffer_count
LONG element_table_offset // offset to unknown data, after faces buffer
LONG element_count
LONG material_table_offset
LONG bone_table_offset
LONG bone_count
LONG ukn17_offset
LONG ukn17_count
LONG ukn18_offset
LONG ukn18_count
LONG ukn19_offset // material related?
LONG ukn19_count
LONG ukn20_offset
LONG ukn20_count
LONG mesh_table_offset
LONG mesh_count
LONG ukn21_offset // offsets to another table, that then offsets to mesh names
LONG ukn22 //always 0?
LONG ukn23 //always 0?
LONG ukn24 //always 0?
LONG ukn25 //always 0?
}
buffer_table {
LONG vert_offset // offset to vertex buffer
LONG ukn33 // offset to vertex colour buffer?
LONG ukn34 // always 0?
LONG ukn35 // always 0?
LONG num_verts
LONG face_offset
LONG num_faces
}
element_table {
LONG buffer_index
LONG vert_start
LONG face_start
LONG vert_count
LONG face_count
}
material_table {
LONG ukn31_table_offset
LONG count
LONG ukn33
LONG ukn34
LONG ukn35
LONG ukn36
LONG ukn37
LONG ukn38
}
ukn31_table {
LONG index
LONG name_index
SHORT ukn40
SHORT ukn41
LONG ukn42
}
vertex_def { // stride either 24 or 32, based off flag from WMB4 header? unconfirmed
FLOAT32 pos_x
FLOAT32 pos_x
FLOAT32 pos_x
FLOAT16 tex_u
FLOAT16 tex_v
}
WTA Format "WonderfulTextureAddresses"??
Description:
I only document the header not the tables after, sorry.. but the tables are nearly self-explainitory
wta_header { // all offsets relative to begining of WTA header
LONG magic // "WTB"
LONG version // ?
LONG count
LONG offset_texture_offsets
LONG offset_texture_sizes
LONG offset_flag_data
LONG offset_file_hashes
LONG offset_XPR2_headers
}
Luigi's CPK BMS
Code: Select all
# CRI CPK archives (script 0.2.2)
# derived from cpk_unpack of hcs (http://hcs64.com/vgm_ripping.html)
# script for QuickBMS http://quickbms.aluigi.org
quickbmsver 0.3.12
endian big
comtype cpk
idstring "CPK "
set query->offset long 0
set query->index long 0
set query->name string "TocOffset"
callfunction query_utf 1
set toc_offset long UTF_VALUE
set query->offset long 0
set query->index long 0
set query->name string "ContentOffset"
callfunction query_utf 1
set content_offset long UTF_VALUE
set query->offset long 0
set query->index long 0
set query->name string "Files"
callfunction query_utf 1
set CpkHeader_count long UTF_VALUE
goto toc_offset
getdstring signature 4
if signature != "TOC "
print "TOC signature not found"
cleanexit
endif
set query->offset long toc_offset
set query->index long 0
set query->name string ""
callfunction query_utf 1
set CpkHeader_count long UTF_VALUE
set toc_entries long table_info.rows # it remains saved after the call
if content_offset < 0 # "if" can't be unsigned
set add_offset long toc_offset
elif toc_offset < 0
set add_offset long content_offset
elif content_offset < toc_offset
set add_offset long content_offset
else
set add_offset long toc_offset
endif
for mytoc = 0 < toc_entries
set query->offset long toc_offset
set query->index long mytoc
set query->name string "DirName"
callfunction query_utf 1
set file_name string UTF_VALUE
set query->offset long toc_offset
set query->index long mytoc
set query->name string "FileName"
callfunction query_utf 1
set file_name2 string UTF_VALUE
string file_name += /
string file_name += file_name2
set query->offset long toc_offset
set query->index long mytoc
set query->name string "FileSize"
callfunction query_utf 1
set file_size long UTF_VALUE
set query->offset long toc_offset
set query->index long mytoc
set query->name string "ExtractSize"
callfunction query_utf 1
set extract_size long UTF_VALUE
set query->offset long toc_offset
set query->index long mytoc
set query->name string "FileOffset"
callfunction query_utf 1
set file_offset long UTF_VALUE
math file_offset += add_offset
if extract_size > file_size
clog file_name file_offset file_size extract_size
else
log file_name file_offset file_size
endif
next mytoc
startfunction query_utf
set COLUMN_STORAGE_MASK long 0xf0
set COLUMN_STORAGE_PERROW long 0x50
set COLUMN_STORAGE_CONSTANT long 0x30
set COLUMN_STORAGE_ZERO long 0x10
set COLUMN_TYPE_MASK long 0x0f
set COLUMN_TYPE_DATA long 0x0b
set COLUMN_TYPE_STRING long 0x0a
set COLUMN_TYPE_FLOAT long 0x08
set COLUMN_TYPE_8BYTE2 long 0x07
set COLUMN_TYPE_8BYTE long 0x06
set COLUMN_TYPE_4BYTE2 long 0x05
set COLUMN_TYPE_4BYTE long 0x04
set COLUMN_TYPE_2BYTE2 long 0x03
set COLUMN_TYPE_2BYTE long 0x02
set COLUMN_TYPE_1BYTE2 long 0x01
set COLUMN_TYPE_1BYTE long 0x00
set UTF_VALUE string ""
math offset = query->offset
math offset += 0x10 # needed by the tool
goto offset
set table_info.table_offset long offset
getdstring UTF_signature 4
if UTF_signature != "@UTF"
print "not a @UTF table at %offset%"
cleanexit
endif
get table_info.table_size long
set table_info.schema_offset long 0x20
get table_info.rows_offset long
get table_info.string_table_offset long
get table_info.data_offset long
get table_name_string long
get table_info.columns short
get table_info.row_width short
get table_info.rows long
for i = 0 < table_info.columns
get schema.type byte
get schema.column_name long
putarray 0 i schema.type
putarray 1 i schema.column_name
putarray 2 i -1 # schema.constant_offset
math TMP = schema.type
math TMP &= COLUMN_STORAGE_MASK
if TMP == COLUMN_STORAGE_CONSTANT
savepos schema.constant_offset
putarray 2 i schema.constant_offset
math TMP = schema.type
math TMP &= COLUMN_TYPE_MASK
if TMP == COLUMN_TYPE_STRING
getdstring DUMMY 4
elif TMP == COLUMN_TYPE_DATA
getdstring DUMMY 8
elif TMP == COLUMN_TYPE_FLOAT
getdstring DUMMY 4
elif TMP == COLUMN_TYPE_8BYTE2
getdstring DUMMY 8
elif TMP == COLUMN_TYPE_8BYTE
getdstring DUMMY 8
elif TMP == COLUMN_TYPE_4BYTE2
getdstring DUMMY 4
elif TMP == COLUMN_TYPE_4BYTE
getdstring DUMMY 4
elif TMP == COLUMN_TYPE_2BYTE2
getdstring DUMMY 2
elif TMP == COLUMN_TYPE_2BYTE
getdstring DUMMY 2
elif TMP == COLUMN_TYPE_1BYTE2
getdstring DUMMY 1
elif TMP == COLUMN_TYPE_1BYTE
getdstring DUMMY 1
else
print "unknown type for constant"
cleanexit
endif
endif
next i
math TMP = table_info.string_table_offset
math TMP += 8
math TMP += offset
math string_table_size = table_info.data_offset
math string_table_size -= table_info.string_table_offset
log MEMORY_FILE TMP string_table_size
for i = query->index < table_info.rows
math TMP = i
math TMP *= table_info.row_width
math row_offset = table_info.table_offset
math row_offset += 8
math row_offset += table_info.rows_offset
math row_offset += TMP
for j = 0 < table_info.columns
getarray type 0 j
getarray column_name 1 j
getarray constant_offset 2 j
if constant_offset >= 0
math data_offset = constant_offset
else
math data_offset = row_offset
endif
math TMP = type
math TMP &= COLUMN_STORAGE_MASK
if TMP == COLUMN_STORAGE_ZERO
set value long 0
else
goto data_offset
math TMP = type
math TMP &= COLUMN_TYPE_MASK
if TMP == COLUMN_TYPE_STRING
get string_offset long
goto string_offset MEMORY_FILE
get value string MEMORY_FILE
elif TMP == COLUMN_TYPE_DATA
get vardata_offset long
get vardata_size long
goto vardata_offset MEMORY_FILE
getdstring value vardata_size MEMORY_FILE
elif TMP == COLUMN_TYPE_FLOAT
get value long
elif TMP == COLUMN_TYPE_8BYTE2
get DUMMY long # no 64 bit support!
get value long
elif TMP == COLUMN_TYPE_8BYTE
get DUMMY long # no 64 bit support!
get value long
elif TMP == COLUMN_TYPE_4BYTE2
get value long
elif TMP == COLUMN_TYPE_4BYTE
get value long
elif TMP == COLUMN_TYPE_2BYTE2
get value short
elif TMP == COLUMN_TYPE_2BYTE
get value short
elif TMP == COLUMN_TYPE_1BYTE2
get value byte
elif TMP == COLUMN_TYPE_1BYTE
get value byte
else
print "unknown normal type"
cleanexit
endif
if constant_offset < 0
savepos row_offset # row_offset += bytes_read
endif
endif
goto column_name MEMORY_FILE
get column_name string MEMORY_FILE
if column_name == query->name
set UTF_VALUE string value # result.value.value (qthis)
math i = table_info.rows # break
math j = table_info.columns # break
endif
next j
next i
endfunction
My MaxScript
Code: Select all
fsource = GetOpenFileName \
caption:"Select a File" \
types: "All files (*.*)|*.dat|"
delete $*
tristrip = false
fn readBElong fstream = (bit.swapBytes (bit.swapBytes (readlong fstream #unsigned) 1 4) 2 3)
fn readBEshort fstream = (bit.swapBytes (readshort fstream #unsigned) 1 2)
fn readBEtriplet fstream = (((readbyte f #unsigned)*0x00010000)+((readbyte f #unsigned)*0x00000100)+((readbyte f #unsigned)*0x00000001))
fn ReadBEfloat fstream = (
bit.intAsFloat (bit.swapBytes (bit.swapBytes (readlong fstream #unsigned) 1 4) 2 3)
)
fn readBEHalfFloat fstream = (
hf=bit.swapBytes (readshort fstream #unsigned) 1 2
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 readFixedString bstream fixedLen = (
local str = ""
for i = 1 to fixedLen do (
str += bit.intAsChar (ReadByte bstream #unsigned))
str
)
fn writeBElong fstream num = (
writelong fstream (bit.swapBytes (bit.swapBytes (num) 1 4) 2 3) #unsigned)
fn paddstring len instring = (
instring=instring as string
local str="";if instring.count <=len then(
for i = 1 to (len-instring.count) do(str+="0")
str = (str+instring))else(
for i = 1 to len do(str+="0";str[i]=instring[i]));str
)
fn uppercase instring = (
local upper, lower, outstring
upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lower="abcdefghijklmnopqrstuvwxyz"
outstring=copy instring
for i=1 to outstring.count do (
j=findString lower outstring[i]
if (j != undefined) do outstring[i]=upper[j])
outstring)
fn printblockpos bname badr = (
str=((bit.intAsHex badr)as string)
if str[str.count]=="L" do(str = substring str 1 (str.count-1))
format "% @ 0xDD%\n" bname (paddstring 6 (uppercase str))
)
fn printblockpos bname badr = (
str=((bit.intAsHex badr)as string)
if str[str.count]=="L" do(str = substring str 1 (str.count-1))
format "% @ 0x%\n" bname (paddstring 8 (uppercase str))
)
fn writeDDSheader fstream texW texH texM texC = (
texP=0
writelong fstream 0x20534444 #unsigned -- File ID
writelong fstream 0x7C #unsigned -- Header Size
case of( -- dwFlags
(texC==#DXT1): (writelong fstream 0x00081007 #unsigned;texP=((texW*texH)/0x02))
(texC==#DXT3): (writelong fstream 0x00081007 #unsigned;texP=(texW*texH))
(texC==#DXT5): (writelong fstream 0x00081007 #unsigned;texP=(texW*texH))
(texC==#ATI1): (writelong fstream 0x000A1007 #unsigned;texP=((texW*texH)/0x20))
(texC==#ATI2): (writelong fstream 0x000A1007 #unsigned;texP=(texW*texH))
(texC==#P8): (writelong fstream 0x000A1007 #unsigned;texP=((texW*texH)/0x02))
(texC==#ARGB16): (writelong fstream 0x00081007 #unsigned;texP=(((texW*texH)/0x8)*0x10))
(texC==#ARBG32): (writelong fstream 0x00081007 #unsigned;texP=(((texW*texH)/0x4)*0x10)))
writelong fstream texW #unsigned -- Texture Width
writelong fstream texH #unsigned -- Texture Height
writelong fstream texP #unsigned -- Pitch (#of bytes in a single row across the texture)
writelong fstream 0x00 #unsigned -- Image Depth? Not Used, for Image Volume
writelong fstream texM #unsigned -- Texture MIP Count
for i = 1 to 11 do writelong fstream 0x00 #unsigned -- Reserved Space
writelong fstream 0x20 #unsigned -- Size of PIXEL_FORMAT info, always 32bytes;
case of(
(texC==#DXT1): (writelong fstream 0x04;writelong fstream 0x31545844 #unsigned
writelong s 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte s 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte s 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte s 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte s 0x00;writelong fstream 0x00001000 #unsigned)
(texC==#DXT3): (writelong fstream 0x04;writelong fstream 0x33545844 #unsigned
writelong s 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte s 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte s 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte s 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writelong fstream 0x00001000 #unsigned)
(texC==#DXT5): (writelong fstream 0x04;writelong fstream 0x35545844 #unsigned
writelong fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writelong fstream 0x00001000 #unsigned)
(texC==#ATI1): (writelong fstream 0x04;writelong fstream 0x31495441 #unsigned
writelong fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writelong fstream 0x00401008 #unsigned)
(texC==#ATI2): (writelong fstream 0x04;writelong fstream 0x32495441 #unsigned
writelong fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writelong fstream 0x00401008 #unsigned)
(texC==#P8): (writelong fstream 0x20;writelong fstream 0x20203850 #unsigned
writelong fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writelong fstream 0x00401008 #unsigned)
(texC==#ARGB16): (writelong fstream 0x41;writelong fstream 0x00000000 #unsigned
writelong fstream 0x10;writebyte fstream 0x00;writebyte fstream 0x0F;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0xF0;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x0F;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0xF0;writebyte fstream 0x00
writebyte fstream 0x00;writelong fstream 0x00001000 #unsigned)
(texC==#ARBG32): (writelong fstream 0x41;writelong fstream 0x00000000 #unsigned
writelong fstream 0x20;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0xFF
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0xFF;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0xFF;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00;writebyte fstream 0x00
writebyte fstream 0xFF;writelong fstream 0x00001000 #unsigned))
for i = 1 to 4 do writelong fstream 0x00 #unsigned -- Reserved Space for CAPS
)
fn Get_PS3FORMAT id = (
case id of ( -- replaced a few from offical ones, for backwards compatiblity
0x86: #DXT1
0x88: #DXT5
default: #UNKNOWN
)
)
if (fsource!=undefined) then (
fpath=getFilenamePath fsource
fname=getFilenameFile fsource
fsize=getFileSize fsource
fext=getFilenameType fsource
if ((doesFileExist fsource)==true) then (
clearlistener ()
f = fopen fsource "rb"
struct package_resource (offset,type,name,size,data)
struct model_binary_4 (header,buffer,element,skeleton,ukn10,ukn11,material,ukn12,mesh)
struct model_binary_4_header (magic,ukn01,ukn02,ukn03,ukn04,ukn05,info,ukn06,ukn07,ukn08,ukn09)
struct offset_and_count (offset,count)
datArray = (package_resource \
offset:#() \
type:#() \
name:#() \
size:#() \
data:#())
case (readFixedString f 4) of (
"DAT":(
dat_offsets = #()
dat_01 = readBElong f -- count: files
dat_02 = readBElong f -- offset: offset table
dat_03 = readBElong f -- offset: extension table
dat_04 = readBElong f -- offset: name table
dat_05 = readBElong f -- offset: size table
dat_06 = readBElong f -- offset: ?? unknown data
dat_07 = readBElong f -- Blank? Reserved?
fseek f dat_02 #seek_set
for i = 1 to dat_01 do (datArray.offset[i] = readBElong f)
fseek f dat_03 #seek_set
for i = 1 to dat_01 do (datArray.type[i] = uppercase (readFixedString f 4))
fseek f dat_04 #seek_set;str_len = readBElong f
for i = 1 to dat_01 do (datArray.name[i] = readFixedString f str_len)
fseek f dat_05 #seek_set
for i = 1 to dat_01 do (datArray.size[i] = readBElong f)
for i = 1 to dat_01 do (datArray.data[i] = #())
for d = 1 to dat_01 do (
fseek f datArray.offset[d] #seek_set
case datArray.type[d] of (
"WTA":(
ukn00 = readBElong f -- "WTB"
ukn01 = readBElong f -- version?
ukn02 = readBElong f -- count
ukn03 = (readBElong f)+datArray.offset[d] -- offset to texture offsets
ukn04 = (readBElong f)+datArray.offset[d] -- offset to texture sizes
ukn05 = (readBElong f)+datArray.offset[d] -- offset to flag data?
ukn06 = (readBElong f)+datArray.offset[d] -- offset to file hashes?
ukn07 = (readBElong f)+datArray.offset[d] -- offset to XPR2 headers
fn stringtobytes str fstream= (
str = str as string
for t = 1 to 24 do (
if t<=str.count then (
writebyte fstream (bit.charAsInt str[t]) #unsigned
)else(writebyte fstream 0)
)
)
for i = 1 to ukn02 do (
g = fopen (fpath+fname+".dtt") "rb"
s = fopen (fpath+fname+(paddstring 3 (i as string))+".xpr") "wb"
fseek f (ukn03+((i-1)*4)) #seek_set
pos = readBElong f
fseek f (ukn04+((i-1)*4)) #seek_set
dumpsize = readBElong f
fseek g (pos+0x1000) #seek_set
writeBElong s 0x58505232
writeBElong s 0x00000800
writeBElong s dumpsize
writeBElong s 0x00000001
writeBElong s 0x54583244
writeBElong s 0x00000030
writeBElong s 0x00000034
writeBElong s 0x00000018
writeBElong s 0x00000000
stringtobytes (fname+(paddstring 3 (i as string))) s
fseek f (ukn07+((i-1)*(4*13))) #seek_set
for x = 1 to (4*11) do (writebyte s (readbyte f #unsigned) #unsigned)
writeBElong s 0x00000000
writeBElong s 0x00000A00
for x = 1 to 1948 do (writebyte s 0)
for x = 1 to dumpsize do (writebyte s (readbyte g #unsigned) #unsigned)
fclose s
fclose g
)
)
"WTA (PS3)":( -- disabled
ukn00 = readBElong f -- "WTB"
ukn01 = readBElong f -- version?
ukn02 = readBElong f -- count
ukn03 = (readBElong f)+datArray.offset[d] -- offset to texture offsets
ukn04 = (readBElong f)+datArray.offset[d] -- offset to texture sizes
ukn05 = (readBElong f)+datArray.offset[d] -- offset to flag data?
ukn06 = (readBElong f)+datArray.offset[d] -- offset to file hashes?
ukn07 = (readBElong f)+datArray.offset[d] -- offset to XPR2 headers
for i = 1 to ukn02 do (
ssource = (fpath+fname+".dtt")
if ((doesFileExist ssource)==true) then (
g = fopen ssource "rb"
s = fopen (fpath+fname+(paddstring 3 (i as string))+".dds") "wb"
fseek f (ukn03+((i-1)*4)) #seek_set;pos = readBElong f
fseek f (ukn04+((i-1)*4)) #seek_set;dumpsize = readBElong f
fseek g (pos+0x1000) #seek_set
struct gft_header (
magic, -- "0x02010100" Version, possibly a fourcc
streamsize,
num_textures, -- forced to 1? :-P
ukn02, -- always 0?
stream_offset,
ukn03, -- offsets to end of stream?
d3d_format, -- fourCC, probably describes d3d compression
ukn04, --offset?
height,
width,
depth,
ukn05, -- always 0?
null -- reserved space
)
gftArray = (gft_header \
magic:(readBElong g) \
streamsize:(readBElong g) \
num_textures:(readBElong g) \
ukn02:(readBElong g) \
stream_offset:(readBElong g) \
ukn03:(readBElong g) \
d3d_format:([(readbyte g #unsigned),(readbyte g #unsigned),(readbyte g #unsigned),(readbyte g #unsigned)]) \
ukn04:(readBElong g) \ --remap?
height:(readBEshort g) \
width:(readBEshort g) \
depth:(readBEshort g) \
ukn05:(readBEshort g) \
null:#() \
);fseek g 88 #seek_cur
format "%: (% x %) \tFormat:%\n" (paddstring 3 i) (paddstring 4 gftArray.width) (paddstring 4 gftArray.height) gftArray.d3d_format
writeDDSheader s gftArray.width gftArray.height 1 (Get_D3DFORMAT gftArray.d3d_format[1])
for x = 1 to dumpsize do (writebyte s (readbyte g #unsigned) #unsigned)
fclose s
fclose g
)else(messagebox "failed to find relating dtt file")
)
)
"WMB":(magic = uppercase (readFixedString f 4)
case magic of (
"WMB4":(
ukn01 = readBElong f -- always -1
ukn02a = readBEshort f -- vertex stride?: 0x00 = 24 | 0x01 = 32
ukn02b = readBEshort f
ukn03a = readBEshort f -- primitive type flag 0x00=trilist | 0x01= trilist
ukn03b = readBEshort f
ukn04 = readBElong f
ukn05 = readBElong f
ukn06 = readBElong f
ukn07 = readBElong f
ukn08 = readBElong f
ukn09 = readBElong f
ukn10 = (readBElong f)+datArray.offset[d] -- offset to vertex buffer header offset? lol
ukn11 = readBElong f -- unknown count?
ukn12 = (readBElong f)+datArray.offset[d] -- offset to unknown data, after faces buffer
ukn13 = readBElong f
ukn14 = (readBElong f)+datArray.offset[d]
ukn15 = (readBElong f)+datArray.offset[d]
ukn16 = readBElong f
ukn17 = (readBElong f)+datArray.offset[d]
ukn18 = readBElong f
ukn19 = (readBElong f)+datArray.offset[d]
ukn20 = readBElong f
ukn21 = (readBElong f)+datArray.offset[d]
ukn22 = readBElong f
ukn23 = (readBElong f)+datArray.offset[d]
ukn24 = readBElong f
ukn25 = (readBElong f)+datArray.offset[d]
ukn26 = readBElong f
ukn27 = (readBElong f)+datArray.offset[d] -- offsets to another table, that then offsets to mesh names
ukn28 = readBElong f -- always 0?
ukn29 = readBElong f -- always 0?
ukn30 = readBElong f -- always 0?
ukn31 = readBElong f -- always 0?
bufferArray = #()
printblockpos ("Mesh/Buffer Table: ("+(ukn11 as string)+")") ukn10
fseek f ukn10 #seek_set
for i = 1 to ukn11 do (
vert_offset = (readBElong f)+datArray.offset[d] -- offset to vertex buffer
ukn33 = (readBElong f)+datArray.offset[d] -- offset to colour buffer
ukn34 = readBElong f -- always 0?
ukn35 = readBElong f -- always 0?
num_verts = readBElong f
face_offset = (readBElong f)+datArray.offset[d]
num_faces = readBElong f -- count
bufferArray[i]=[num_verts,num_faces,vert_offset,face_offset]
printblockpos "Vert" vert_offset
printblockpos "Face" face_offset
)
printblockpos "\tMesh/Buffer Table END" (ftell f);format "\n"
printblockpos "Buffers" (bufferArray[1][3]);format "\n"
printblockpos ("Element Table: ("+(ukn13 as string)+")") ukn12
fseek f ukn12 #seek_set
struct element (buffer_index,vert_start,face_start,vert_count,face_count)
mshArray=(element buffer_index:#() vert_start:#() face_start:#() vert_count:#() face_count:#())
for i = 1 to ukn13 do (
mshArray.buffer_index[i] = (readBElong f)+1 -- buffer index
mshArray.vert_start[i] = readBElong f -- vert start
mshArray.face_start[i] = readBElong f -- face start
mshArray.vert_count[i] = readBElong f -- vert count
mshArray.face_count[i] = readBElong f -- face count
format "%\n" mshArray.buffer_index[i]
)
printblockpos "\tElement Table END" (ftell f);format "\n"
fseek f ukn14 #seek_set
ukn31 = (readBElong f)+datArray.offset[d]
ukn32 = readBElong f -- count
ukn33 = readBElong f -- always 0?
ukn34 = readBElong f -- always 0?
ukn35 = readBElong f -- always 0?
ukn36 = readBElong f -- always 0?
ukn37 = readBElong f -- always 0?
ukn38 = readBElong f -- always 0?
printblockpos ("Material Names?: ("+(ukn32 as string)+")") ukn14
fseek f ukn31 #seek_set
for i = 1 to ukn32 do (
ukn38 = readBElong f -- index
ukn39 = readBElong f -- indexing to name
ukn40a = readBEshort f -- flag?
ukn40b = readBEshort f -- flag?
ukn41 = readBElong f -- always 0x00 01 00 00 ?
format "% | % | % | %\n" ukn39 ukn39 ukn40a ukn40b
)
printblockpos "\tMaterial Names? END" (ftell f);format "\n"
printblockpos ("Bones: ("+(ukn16 as string)+")") ukn15
fseek f ukn15 #seek_set
for i = 1 to ukn16 do ( -- bones?
ukn42 = readBEshort f -- ???
ukn43 = readBEshort f -- ???
ukn44 = readBEshort f -- parent
ukn45 = readBEshort f -- always 0?
ukn46 = readBEfloat f -- position?
ukn47 = readBEfloat f
ukn48 = readBEfloat f
ukn49 = readBEfloat f
ukn50 = readBEfloat f
ukn51 = readBEfloat f
)
printblockpos "\tBones END" (ftell f);format "\n"
printblockpos ("Block5: ("+(ukn18 as string)+")") ukn17
fseek f ukn17 #seek_set
for i = 1 to ukn18 do (
ukn52 = readbyte f #unsigned --? float, divide by 0xFF
)
printblockpos "\tBlock5 END" (ftell f);format "\n"
printblockpos ("Block6: ("+(ukn20 as string)+")") ukn19
fseek f ukn19 #seek_set
tempArray = #()
for i = 1 to ukn20 do (
ukn53 = (readBElong f)+datArray.offset[d]
ukn54a = readbyte f #unsigned -- count
ukn54b = readbyte f #unsigned -- 0?
ukn54c = readbyte f #unsigned -- 0?
ukn54d = readbyte f #unsigned -- 0?
tempArray[i] = [ukn53,ukn54a]
)
for i = 1 to ukn20 do (
fseek f tempArray[i][1] #seek_set
for x = 1 to tempArray[i][2] do (
ukn57 = readbyte f #unsigned -- indexes
)
)
printblockpos "\tBlock6 END" (ftell f);format "\n"
printblockpos ("Material Table?: ("+(ukn22 as string)+")") ukn21
fseek f ukn21 #seek_set
for i = 1 to ukn22 do (
ukn58 = (readBElong f)+datArray.offset[d] -- offset to string
ukn59 = (readBElong f)+datArray.offset[d] -- offset to stuff after string
ukn60 = readBElong f -- always 0?
ukn61 = (readBElong f)+datArray.offset[d] -- offset to matrix data?
ukn62 = readBEshort f
ukn63 = readBEshort f
ukn64 = readBEshort f
ukn65 = readBEshort f -- string count
)
printblockpos "\tMaterial Table? END" (ftell f);format "\n"
printblockpos ("Block8: ("+(ukn24 as string)+")") ukn23
fseek f ukn23 #seek_set
for i = 1 to ukn24 do (
ukn66 = readBElong f -- count?
ukn67 = readBElong f -- float or hash?
)
printblockpos "\tBlock8 END" (ftell f);format "\n"
printblockpos ("Mesh Properties: ("+(ukn26 as string)+")") ukn25
pos = ukn25
nameArray=#()
for i = 1 to ukn26 do (
fseek f pos #seek_set
ukn68 = (readBElong f)+datArray.offset[d] -- offset to name
ukn69 = readBEfloat f -- position ?
ukn70 = readBEfloat f
ukn71 = readBEfloat f
ukn72 = readBEfloat f -- rotation ?
ukn73 = readBEfloat f
ukn74 = readBEfloat f
ukn75 = (readBElong f)+datArray.offset[d] -- offset to index data that comes after name
ukn76 = readBElong f -- count for above offset
ukn77 = readBElong f -- 0?
ukn78 = readBElong f -- 0?
ukn79 = readBElong f -- 0?
ukn80 = readBElong f -- 0?
ukn81 = readBElong f -- 0?
ukn82 = readBElong f -- 0?
ukn83 = (readBElong f)+datArray.offset[d] -- offset to index data that comes after name
ukn84 = readBElong f -- count for above offset
pos = ftell f
fseek f ukn68 #seek_set
mshName = (readstring f);print mshName
append nameArray mshName
fseek f ukn75 #seek_set
for x = 1 to ukn76 do (
ukn85 = (readBEshort f)+1
)
fseek f ukn83 #seek_set
for x = 1 to ukn84 do (
ukn86 = (readBEshort f)+1
)
)
printblockpos "\tBlock9 END" (ftell f);format "\n"
if ukn03a == 1 do (tristrip = true)
-- ukn13=0 --ignore faces
for i = 1 to ukn13 do (
vertArray=#()
normArray=#()
uvwArray=#()
faceArray=#()
matidArray=#()
num_verts=mshArray.vert_count[i] --bufferArray[(mshArray.buffer_index[i])][1]
num_faces=mshArray.face_count[i] --bufferArray[(mshArray.buffer_index[i])][2]
-- num_verts=bufferArray[(mshArray.buffer_index[i])][1]
-- num_faces=bufferArray[(mshArray.buffer_index[i])][2]
vert_offset=bufferArray[(mshArray.buffer_index[i])][3]
face_offset=bufferArray[(mshArray.buffer_index[i])][4]
-- stride = ((face_offset-vert_offset)/num_verts) as integer
-- format "Calculated Stride: %\n" stride
case ukn02a of (
0x00:(stride = 24)
0x01:(stride = 32)
default:(stride = 32;format "New Stride: %\n" ukn02a)
)
stride = 32
vert_offset+=mshArray.vert_start[i]*stride
face_offset+=mshArray.face_start[i]*2
fseek f vert_offset #seek_set
for x = 1 to num_verts do (
pos = (ftell f)+stride
vx = ReadBEfloat f
vy = ReadBEfloat f
vz = ReadBEfloat f
tu = readBEHalfFloat f
tv = readBEHalfFloat f
-- nx = ReadBEfloat f
-- ny = ReadBEfloat f
-- nz = ReadBEfloat f
-- b1 = readbyte f #unsigned
-- b2 = readbyte f #unsigned
-- b3 = readbyte f #unsigned
-- b4 = readbyte f #unsigned
-- w1 = (readbyte f #unsigned)/255.0
-- w2 = (readbyte f #unsigned)/255.0
-- w3 = (readbyte f #unsigned)/255.0
-- w4 = (readbyte f #unsigned)/255.0
append vertArray ([vx,-vz,vy]*100)
append uvwArray [tu,(1-tv),0]
fseek f pos #seek_set
)
fseek f face_offset #seek_set
format "% Faces % + % @ 0x%\n" i num_faces num_verts ((bit.intAsHex(ftell f))as string)
fa=fb=fc=1
face_flip = false
face_reset = true
face_add = 1
if tristrip == true then (
x=1;while x<= num_faces do (x+=1
if face_reset == true then (
x+=2;face_reset=false;face_flip = false;append matidArray i
fa = (ReadBEshort f) + face_add
fb = (ReadBEshort f) + face_add
fc = (ReadBEshort f) + face_add
if face_flip == true then (append faceArray [fa,fb,fc];face_flip=false)
else(append faceArray [fa,fc,fb];face_flip=true)
)else(fa = fb;fb = fc;fc = ReadBEshort f
if fc!=0xFFFF then (fc += face_add;append matidArray i
if face_flip == true then (append faceArray [fa,fb,fc];face_flip=false)
else(append faceArray [fa,fc,fb];face_flip=true)
)else(face_reset=true)
)
)
)else(
for x = 1 to (num_faces/3) do (
fa = (ReadBEshort f) + face_add
fb = (ReadBEshort f) + face_add
fc = (ReadBEshort f) + face_add
faceArray[x]=[fa,fc,fb]
matidArray[x]=i
)
)
-- while IndexCounter !=num_faces
format "\t\t\t\t\tFaceEnd @ 0x%\n" ((bit.intAsHex(ftell f))as string)
-- faceArray=#()
msh = mesh vertices:vertArray tverts:uvwArray faces:faceArray --materialIDs:matidArray
buildTVFaces msh
-- msh.name = nameArray[i]
msh.material = multimaterial numsubs:ukn13
msh.displayByLayer = false
msh.backfacecull = on
msh.wirecolor = random (color 0 0 0) (color 255 255 255)
-- convertTo msh PolyMeshObject
-- select msh
-- subobjectLevel = 1
for j = 1 to uvwArray.count do setTVert msh j uvwArray[j]
for j = 1 to faceArray.count do setTVFace msh j faceArray[j]
for j = 1 to msh.material.count do (msh.material.materialList[j].Diffuse = random (color 0 0 0) (color 255 255 255))
)
)
default:(printblockpos ("WMB Not Supported: "+magic) datArray.offset[d])
)
)
default:(printblockpos ("Type Unknown: "+datArray.type[d]) datArray.offset[d])
)
)
)
default:(format "File Unknown: %\n" (magic as string))
)
format "Last Read @ 0x%\n" ((bit.intAsHex(ftell f))as string)
format "Flie Closed: %\n" fname
fclose f
) else (Print "Failed to Locate File")) else (Print "Aborted.")