Page 1 of 3

NIER Xbox360

Posted: Fri Dec 24, 2010 2:22 am
by chrrox
Image

BMS Script

Code: Select all

endian big
get name FILENAME
string name + ".dec"
get lzo long
get version long
get subversion long
get files long
get TotalUncompSize long
get unk long
goto 0x20
comtype LZO1X
for i = 1 to files
get memoffset long
get size long
get zsize long
savepos offset
if size == zsize
append
log MEMORY_FILE offset zsize
append
else
append
clog MEMORY_FILE offset zsize size
append
endif
math offset + zsize
goto offset
Padding 0x10000
next i
log NAME 0 TotalUncompSize MEMORY_FILE
here is the Max script.

This is a great import with bones and materials.

Code: Select all

if (heapSize < 200000) then
   heapSize = 30000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"

fname = getOpenFileName \
caption:"NIER Model File" \
types:"NIER Model File(*.mdv)|*.mdv" \
historyCategory:"NIERObjectPresets"
f = fopen fname "rb"
fname2 = ((getFilenamePath fname) + (getFilenameFile fname)) + ".MDP.dec"
g = fopen fname2 "rb"

fn ReadBEShort fstream = (
short = readshort fstream #unsigned
short = bit.swapBytes short 2 1
b = (bit.get short 16)
for i = 17 to 32 do short = bit.set short i b
return short
)

fn PrintOffset Var =
(
   local Var = Var
print ("This is the offset 0x" + (bit.intAsHex Var) as string)
   Var
)

fn floatSwap2 f =
(
   i = bit.floatAsInt f
   h = bit.intashex i
   while h.count < 8 do h = "0" + h
   
   s = (substring h 7 2) + (substring h 5 2) + (substring h 3 2) + (substring h 1 2)
   bit.intAsFloat (bit.hexasint s)
)   

fn ReadBEword fstream = (
return (bit.swapBytes (readshort fstream #unsigned) 1 2)
)

   fn convertTo32 input16 = (
      inputAsInt = input16
      sign = bit.get inputAsInt 16
      exponent = (bit.shift (bit.and inputAsInt (bit.hexasint "7C00")) -10) as integer - 16
      fraction = bit.and inputAsInt (bit.hexasint "03FF")
      if sign==true then sign = 1 else sign = 0
      exponentF = exponent + 127
      --Ouput 32 bit integer representing a 32 bit float
      outputAsFloat = bit.or (bit.or (bit.shift fraction 13) (bit.shift exponentF 23)) (bit.shift sign 31)
      --Output Check   
      return bit.intasfloat outputasfloat
   )

fn ReadBEHalfFloat fstream = (
return convertTo32(ReadBEword fstream)
)

fn ReadBElong fstream = (
long = readlong fstream
long = bit.swapBytes long 1 4
long = bit.swapBytes long 2 3
return long
)

fn ReadBEfloat fstream = (
return floatSwap2(readfloat fstream)
)

fn ReadFixedString bstream fixedLen =
(
   local str = ""
   for i = 1 to fixedLen do
   (
      str += bit.intAsChar (ReadByte bstream #unsigned)
   )
   str
)

struct weight_data
(
   boneids,weights
)
--0x20 size is an lod can delete them
fseek f 0x10#seek_set
BoneOff = ReadBElong f + 0x80
fseek f 0x110#seek_set
NODToff = ReadBElong f + 0x100
heapoff = ReadBElong f + 0x100

fseek f 0x180#seek_set
MESH1 = ReadFixedString f 4
MESH1Size = ReadBElong f
MESH1Off = (ftell f) + MESH1Size
REM0 = ReadFixedString f 4
REM0Size = ReadBElong f
REM0Name = ReadFixedString f REM0Size

STRB = ReadFixedString f 4
STRBSize = ReadBElong f
STRBOff = (ftell f) + STRBSize
STRBCount = ReadBElong f
STRL = ReadFixedString f 4
STRLSize = ReadBElong f
Name2_Array = #()
for a = 1 to STRBCount Do (
Name2 = readstring f
append Name2_Array  Name2
)
print Name2_Array
fseek f STRBOff#seek_set
meditMaterials[1] = Multimaterial ()
MatID_array = #()
MatSlotTexID = #()
While (ftell f) != MESH1Off Do (
Name1 = ReadFixedString f 4
print Name1
Name1Size = ReadBElong f
if Name1 == "DSNA" Do (
fseek f Name1Size#seek_cur
)
if Name1 == "TRSP" Do (
fseek f Name1Size#seek_cur
)
if Name1 == "EFFE" Do (
fseek f 0x10#seek_cur
)
if Name1 == "TPAS" Do (
fseek f Name1Size#seek_cur
)
if Name1 == "CSTS" Do (
fseek f 0x4#seek_cur
)
if Name1 == "CSTV" Do (
fseek f Name1Size#seek_cur
)

if Name1 == "SAMP" Do (
MatID = ReadBElong f + 1
append MatID_array MatID
print ("This is the material info for slot " + MatID as string)
)
if Name1 == "SSTV" Do (
MatSlot = ReadBElong f
TexID = ReadBElong f + 1
MatNameID = ReadBElong f

if MatSlot == 29 Do (
print ("The Diffuse Texture is " + Name2_Array[TexID])
meditMaterials[1].materialList[MatID_array.count].diffuseMap = Bitmaptexture fileName:((getFilenamePath fname) + (Name2_Array[TexID] + ".tga"))
meditMaterials[1].materialList[MatID_array.count].opacityMap = Bitmaptexture fileName:((getFilenamePath fname) + (Name2_Array[TexID] + ".tga"))
meditMaterials[1].materialList[MatID_array.count].opacityMap.monoOutput = 1
meditMaterials[1].materialList[MatID_array.count].opacityMapEnable = on
meditMaterials[1].materialList[MatID_array.count].diffuseMap.alphaSource = 2
)
if MatSlot == 32 Do (
print ("The Normal Texture is " + Name2_Array[TexID])
meditMaterials[1].materialList[MatID_array.count].bumpMap = Normal_Bump ()
meditMaterials[1].materialList[MatID_array.count].bumpMap.normal_map = Bitmaptexture fileName:((getFilenamePath fname) + (Name2_Array[TexID] + ".tga"))
meditMaterials[1].materialList[MatID_array.count].bumpMap.normal_map.Output.Invert = true
)
if MatSlot == 35 Do (
print ("The Specular Texture is " + Name2_Array[TexID])
meditMaterials[1].materialList[MatID_array.count].specularLevelMap = Bitmaptexture fileName:((getFilenamePath fname) + (Name2_Array[TexID] + ".tga"))
meditMaterials[1].materialList[MatID_array.count].specularLevelMapEnable = off
)
if MatSlot == 44 Do (
print ("The 2nd Normal Texture is " + Name2_Array[TexID])
meditMaterials[1].materialList[MatID_array.count].specularMap = Bitmaptexture fileName:((getFilenamePath fname) + (Name2_Array[TexID] + ".tga"))
meditMaterials[1].materialList[MatID_array.count].specularMapEnable = off
)
)
if Name1 == "MATE" Do (
MatSlotID = ReadBElong f + 1
MatSlotN1 = ReadBElong f + 1
MatSlotN2 = ReadBElong f + 1
MatSlotID2 = ReadBElong f
MatSlotTexID1 = ReadBElong f + 1
MatSlotN = ReadBElong f
MatSlotN = ReadBElong f
MatSlotTexID2 = ReadBElong f + 1
meditMaterials[1].names[MatSlotID] = Name2_Array[MatSlotN1]
meditMaterials[1][MatSlotID].name = Name2_Array[MatSlotN2]
)
if Name1 == "VARI" Do (
fseek f 0x10#seek_cur   
)
if Name1 == "PRIM" Do (
MshSlotID = ReadBElong f
MshSlotID = ReadBElong f
MshSlotID = ReadBElong f
MshSlotID = ReadBElong f
MshSlotID = ReadBElong f
MshMatID = ReadBElong f + 1
MshSlotID = ReadBElong f
   append MatSlotTexID MshMatID
)
if Name1 == "BONE" Do (
fseek f 0x4#seek_cur   
)
if Name1 == "BOIF" Do (
fseek f Name1Size#seek_cur      
)
if Name1 == "IMTX" Do (
fseek f Name1Size#seek_cur      
)
if Name1 == "" Do (
   
)
)

fseek f BoneOff#seek_set
CJF = ReadFixedString f 4
RigName = ReadFixedString f 0x20
BoneCount = ReadBElong f
Unk01Count = ReadBElong f
BoneNameStart = ReadBElong f + BoneOff
Unk01Start = ReadBElong f + BoneOff
BoneParentStart = ReadBElong f + BoneOff
BoneMatrixStart = ReadBElong f + BoneOff
BoneInvMatrixStart = ReadBElong f + BoneOff

Bone_Name_Array = #()
Bone_Parent_Array = #()
struct Bone_Info_Struct
(
   BonePID01,BonePID02,BonePID03
)
fseek f BoneNameStart#seek_set
with undo off with redraw off for a = 1 to BoneCount Do (
Unk01 = ReadBElong f
BoneName = ReadFixedString f 0x20
append Bone_Name_Array BoneName
)
print Bone_Name_Array
fseek f BoneParentStart#seek_set
with undo off with redraw off for a = 1 to BoneCount Do (
BonePID01 = ReadBEword f + 1
append Bone_Parent_Array BonePID01
)
print Bone_Parent_Array
fseek f BoneMatrixStart#seek_set
BNArr = #()
with undo off with redraw off for a = 1 to BoneCount Do (
m11 = ReadBEFloat f; m12 = ReadBEFloat f; m13 = ReadBEFloat f; m14 = ReadBEFloat f
m21 = ReadBEFloat f; m22 = ReadBEFloat f; m23 = ReadBEFloat f; m24 = ReadBEFloat f
m31 = ReadBEFloat f; m32 = ReadBEFloat f; m33 = ReadBEFloat f; m34 = ReadBEFloat f
m41 = ReadBEFloat f; m42 = ReadBEFloat f; m43 = ReadBEFloat f; m44 = ReadBEFloat f
tfm = matrix3 [m11,m12,m13] [m21,m22,m23] [m31,m32,m33] [m41,m42,m43]

   newBone = bonesys.createbone   \
              tfm.row4   \
              (tfm.row4 + 0.01 * (normalize tfm.row1)) \
              (normalize tfm.row3)
         newBone.name = Bone_Name_Array[a]
         newBone.width  = 0.01
         newBone.height = 0.01
         newBone.transform = tfm
         newBone.setBoneEnable false 0
         newBone.wirecolor = yellow
         newbone.showlinks = true
         newBone.pos.controller      = TCB_position ()
         newBone.rotation.controller = TCB_rotation ()
   append BNArr newBone
)
with undo off with redraw off for a = 1 to BoneCount Do (
select BNArr[a]
if (Bone_Parent_Array[a] != 0) then
$.parent = BNArr[(Bone_Parent_Array[a])]
)


fseek f heapoff#seek_set
HEAP = ReadFixedString f 4
Null1= ReadBElong f
SectSize= ReadBElong f
Heap1Size= ReadBElong f
Count1= ReadBElong f
NameSize= ReadBElong f
Null1= ReadBElong f
HeapCount= ReadBElong f
myoff = (ftell f)
fseek f (heapoff + Heap1Size)#seek_set
Mesh_Name_array = #()
while (ftell f) <= (heapoff + Count1) do (
Mesh_Name = readstring f
if Mesh_Name != "" do (
append Mesh_Name_array Mesh_Name
)
)
print Mesh_Name_array
fseek f myoff#seek_set
IXBF_array = #()
VXBF_array = #()
VXST_array = #()
struct Mesh_Info_Struct
(
   HEAPID,Size,Offset,TotalSize
)

for a = 1 to HeapCount do (
HEAPID = ReadFixedString f 4
print HEAPID
fseek f 0x1C#seek_cur
if HEAPID == "IXBF" do (
fseek f -0x10#seek_cur
Size = ReadBElong f
Offset = ReadBElong f
TotalSize = ReadBElong f
Null1 = ReadBElong f
append IXBF_array (Mesh_Info_Struct HEAPID:HEAPID Size:Size Offset:Offset TotalSize:TotalSize)
)
if HEAPID == "VXBF" do (
fseek f -0x10#seek_cur
Size = ReadBElong f
Offset = ReadBElong f
TotalSize = ReadBElong f
Null1 = ReadBElong f
append VXBF_array (Mesh_Info_Struct HEAPID:HEAPID Size:Size Offset:Offset TotalSize:TotalSize)
)
if HEAPID == "VXST" do (
fseek f -0x14#seek_cur
Offset = (ReadBElong f)  + ((Count1 + heapoff) + 0x30)
print Offset
fseek f 0x10#seek_cur
append VXST_array Offset
)
)
print IXBF_array
print VXBF_array
print VXST_array
vsize_array = #()

for a = 1 to VXST_array.count do (
fseek f VXST_array[a]#seek_set
vertsize = ReadBElong f
append vsize_array vertsize
)
print vsize_array
with undo off with redraw off for a = 1 to IXBF_array.count Do (
Vert_array = #()
Normal_array = #()
UV_array = #()
Face_array = #()
used_id_array =#()
Weight_array = #()
fseek g IXBF_array[a].offset#seek_set
FaceEnd = (IXBF_array[a].offset + (IXBF_array[a].TotalSize))
StartDirection = -1
f1 = ReadBEword g + 1
f2 = ReadBEword g + 1
IndexCounter = 2
FaceDirection = StartDirection
do (
f3 = ReadBEword g
IndexCounter += 1
if (f3==0xFFFF) then (
f1 = ReadBEword g + 1
f2 = ReadBEword g + 1
IndexCounter += 2
FaceDirection = StartDirection   
) else (
f3 += 1
FaceDirection *= -1
if (f1!=f2)AND(f2!=f3)AND(f3!=f1) then (
if FaceDirection > 0 then append Face_array [(f1),(f2),(f3)]
else append Face_array [(f1),(f3),(f2)]
)
f1 = f2
f2 = f3
) 
)while (ftell g) <= FaceEnd
printoffset (ftell g)
fseek g VXBF_array[a].offset#seek_set
VertCount = (VXBF_array[a].TotalSize / vsize_array[a])
for b = 1 to VertCount Do (
if vsize_array[a] == 12 do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
tu =0
tv = 0
   
weight1 = 0
weight2 = 0
weight3 = 0
weight4 = 0
bone1 = 1
bone2 = 1
bone3 = 1
bone4 = 1
)
if vsize_array[a] == 20 do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
tu = 0
tv = 0
weight1 = readbyte g#unsigned
weight2 = readbyte g#unsigned
weight3 = readbyte g#unsigned
weight4 = readbyte g#unsigned
bone1 = readbyte g#unsigned
bone2 = readbyte g#unsigned
bone3 = readbyte g#unsigned
bone4 = readbyte g#unsigned

)
if vsize_array[a] == 24 do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
weight1 = readbyte g#unsigned
weight2 = readbyte g#unsigned
weight3 = readbyte g#unsigned
weight4 = readbyte g#unsigned
bone1 = readbyte g#unsigned
bone2 = readbyte g#unsigned
bone3 = readbyte g#unsigned
bone4 = readbyte g#unsigned
tu = ReadBEHalfFloat g * 2
tv = ReadBEHalfFloat g * -2

)
if vsize_array[a] == 28 do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
weight1 = readbyte g#unsigned
weight2 = readbyte g#unsigned
weight3 = readbyte g#unsigned
weight4 = readbyte g#unsigned
bone1 = readbyte g#unsigned
bone2 = readbyte g#unsigned
bone3 = readbyte g#unsigned
bone4 = readbyte g#unsigned
tu = ReadBEHalfFloat g * 2
tv = ReadBEHalfFloat g * -2
unk24 = ReadBEfloat g
)
if vsize_array[a] == 32   do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g

weight1 = readbyte g#unsigned
weight2 = readbyte g#unsigned
weight3 = readbyte g#unsigned
weight4 = readbyte g#unsigned
bone1 = readbyte g#unsigned
bone2 = readbyte g#unsigned
bone3 = readbyte g#unsigned
bone4 = readbyte g#unsigned
nz = ReadBEfloat g
tu = ReadBEHalfFloat g * 2
tv = ReadBEHalfFloat g * -2
unk24 = ReadBEfloat g   
)
if vsize_array[a] == 36 do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
weight1 = readbyte g#unsigned
weight2 = readbyte g#unsigned
weight3 = readbyte g#unsigned
weight4 = readbyte g#unsigned
bone1 = readbyte g#unsigned
bone2 = readbyte g#unsigned
bone3 = readbyte g#unsigned
bone4 = readbyte g#unsigned
nz = ReadBEfloat g
tu = ReadBEHalfFloat g * 2
tv = ReadBEHalfFloat g * -2
unk24 = ReadBEfloat g
unk24 = ReadBEfloat g   

)
if vsize_array[a] == 40 do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
weight1 = readbyte g#unsigned
weight2 = readbyte g#unsigned
weight3 = readbyte g#unsigned
weight4 = readbyte g#unsigned
bone1 = readbyte g#unsigned
bone2 = readbyte g#unsigned
bone3 = readbyte g#unsigned
bone4 = readbyte g#unsigned
nz = ReadBEfloat g
tu = ReadBEHalfFloat g * 2
tv = ReadBEHalfFloat g * -2
unk24 = ReadBEfloat g
unk24 = ReadBEfloat g   
unk24 = ReadBEfloat g   

)
if vsize_array[a] == 44 do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
weight1 = readbyte g#unsigned
weight2 = readbyte g#unsigned
weight3 = readbyte g#unsigned
weight4 = readbyte g#unsigned
bone1 = readbyte g#unsigned
bone2 = readbyte g#unsigned
bone3 = readbyte g#unsigned
bone4 = readbyte g#unsigned
nz = ReadBEfloat g
tu = ReadBEHalfFloat g * 2
tv = ReadBEHalfFloat g * -2
unk24 = ReadBEfloat g
unk24 = ReadBEfloat g   
unk24 = ReadBEfloat g
unk24 = ReadBEfloat g

)
if vsize_array[a] == 48 do (
vx = ReadBEfloat g
vy = ReadBEfloat g
vz = ReadBEfloat g
weight1 = readbyte g#unsigned
weight2 = readbyte g#unsigned
weight3 = readbyte g#unsigned
weight4 = readbyte g#unsigned
bone1 = readbyte g#unsigned
bone2 = readbyte g#unsigned
bone3 = readbyte g#unsigned
bone4 = readbyte g#unsigned
nz = ReadBEfloat g
tu = ReadBEHalfFloat g * 2
tv = ReadBEHalfFloat g * -2
unk24 = ReadBEfloat g
unk24 = ReadBEfloat g   
unk24 = ReadBEfloat g
unk24 = ReadBEfloat g   
unk24 = ReadBEfloat g

)


w = (weight_data boneids:#() weights:#())
maxweight = 0
   
if(weight1 != 0) then
   maxweight = maxweight + weight1
if(weight2 != 0) then
   maxweight = maxweight + weight2
if(weight3 != 0) then
   maxweight = maxweight + weight3
if(weight4 != 0) then
   maxweight = maxweight + weight4

if(maxweight != 0) then
   (
      if(weight1 != 0) then
      (
         w1 = weight1 as float
         append w.boneids (bone1 + 2)
         append w.weights (w1 / 100)
         append used_id_array (bone1)
      )
      if(weight2 != 0) then
      (
         w2 = weight2 as float
         append w.boneids (bone2 + 2)
         append w.weights (w2 / 100)
         append used_id_array (bone2 )
      )
      if(weight3 != 0) then
      (
         w3 = weight3 as float
         append w.boneids (bone3 + 2)
         append w.weights (w3 / 100)
         append used_id_array (bone3)
      )
      if(weight4 != 0) then
      (
         w4 = weight4 as float
         append w.boneids (bone4 + 2)
         append w.weights (w4 / 100)
         append used_id_array (bone4)
      )      
   )   
append Weight_array w
append Vert_array [vx,vy,vz]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
msh = mesh vertices:Vert_array faces:Face_array
msh.numTVerts = UV_array.count
buildTVFaces msh
msh.name = Mesh_Name_array[a]
msh.material = meditMaterials[1].materialList[(MatSlotTexID[a])]
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]
   

max modify mode
select msh
skinMod = skin ()
addModifier msh skinMod
for i = 1 to BNArr.count do
(
   maxbone = getnodebyname BNArr[i].name
   if i != BNArr.count then
      skinOps.addBone skinMod maxbone 0
   else
      skinOps.addBone skinMod maxbone 1
   
)

modPanel.setCurrentObject skinMod

for i = 1 to Weight_array.count do (
   w = Weight_array[i]
   bi = #() --bone index array
   wv = #() --weight value array
   
   for j = 1 to w.boneids.count do
   (
      boneid = w.boneids[j]
      weight = w.weights[j]
      append bi boneid
      append wv weight
   )   
   
   skinOps.ReplaceVertexWeights skinMod i bi wv
   
)
max create mode
)
actionMan.executeAction 0 "63508"  -- Views: Standard Display with Maps

fclose f
fclose g


if you have problems please tell me the file name

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 6:20 am
by Tosyk
hi, chrrox, what about skeleton and textures?

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 12:10 pm
by logansan25
I am a noobie, How come use this script?
Plis!!!!!!!!

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 12:27 pm
by EternaL
Thanks Chrrox for your work,
I was waiting for this :D

P.s. for Logan
It's a MAXScript

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 1:38 pm
by chrrox
Textures are swizzled with the standard xbox swizzle i am working on a way to mass convert them.

please let me know what files give trouble and ill fix it.

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 2:53 pm
by valvoga
Wow that was awesome
Oh yeah chrrox by any chance can you make a model extractor for guilty gear 2 overture x360
Cause the game got a lot of good model

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 3:02 pm
by chrrox
You would need to start a new topic and post samples if you want help on a model format.
Stages also work now.

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 8:31 pm
by EternaL
Some .mdp file can't be decompress, it's normal?
Like bookb011

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 9:46 pm
by chrrox
Once I finish up the script ill fix it for 2011. 2011 is very picky and hates text that is commented out and spaces.
I am very close :)

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 10:03 pm
by EternaL
I feel so stupid, i was trying a undecompress mdp file........

Your script work like a charm in 3DS max 2011

Re: NIER Xbox360

Posted: Fri Dec 24, 2010 11:28 pm
by mariokart64n
Image
Image

Re: NIER Xbox360

Posted: Sat Dec 25, 2010 5:23 am
by chrrox
Here is a script mario made for the textures in max ill make a bms for this later for speed.
you will need unbundler in the same directory as the main mesh files.
do not ask for that file here.

If anyone can help with bone parent id's or material info that would be great.

Re: NIER Xbox360

Posted: Mon Dec 27, 2010 1:52 pm
by epopoe
thanks chrrox!

and here is cpk.bms

layer1.cpk -- 2.93gb

layer2.cpk -- 1.37gb

Code: Select all

# CRI CPK archives (script 0.2.2)
#   derived from cpk_unpack of hcs
# script for QuickBMS http://aluigi.org/papers.htm#quickbms

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


Re: NIER Xbox360

Posted: Mon Dec 27, 2010 5:22 pm
by epopoe
This program can convert xpr to dds.

Re: NIER Xbox360

Posted: Mon Dec 27, 2010 6:50 pm
by mariokart64n
does that really work? DOA used tpr, which was different then a normal xpr