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 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 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
)
fn DisplayVerts msh = (
	select msh
	poly = Edit_Poly()
	modPanel.addModToSelection poly ui:off
	setselectionlevel poly #vertex
	poly.select #vertex #{1}
)
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 ApplyNormals2 amesh nArr toggle= (
	max modify mode
	cui.expertModeOn()

	with redraw off (
	   --your import code
		
	   for face = 1 to amesh.numfaces do setFaceSmoothGroup amesh face 1
		
	   select amesh
	   addmodifier amesh (Edit_Normals ()) ui:off
	   amesh.Edit_Normals.MakeExplicit selection:#{1..nArr.count}
	   EN_convertVS = amesh.Edit_Normals.ConvertVertexSelection
	   EN_setNormal = amesh.Edit_Normals.SetNormal
	   normID = #{}
		
	   for v = 1 to nArr.count do
	   (
		  free normID
		  EN_convertVS #{v} &normID
		  for id in normID do EN_setNormal id nArr[v]
	   )
	   
	   if toggle == 1 do collapseStack amesh
	)

	cui.expertModeOff()
)
fn addHexaDecimalPadding nr = (
	case of (
		(nr <= 15): ("0" + ((bit.intAsHex(nr))as string))
		(nr > 15): ((bit.intAsHex(nr))as string)
	)
)	
fn ReadFixedByteString bstream fixedLen = (
   local str = ""
   for i = 1 to fixedLen do
   (
      str += addHexaDecimalPadding (ReadByte bstream #unsigned)
	  if mod i 1 == 0 do str += " "
   )
   str
)


fname = GetOpenFileName caption:"Dragon Ball Xenoverse EMO" types:"(*.emo)|*.emo"
If (fname!=undefined) and ((DoesFileExist fname)==true) then (--)
f = fopen fname "rb"   --open file in read only format
FileName = getFileNameFile fname
FileExtension = getFileNameType  fname
clearlistener()
fscale=50
delete $*

print (FileName + FileExtension) as string

GeomOffset=#()
VertCount=#()
VertSize=#()
VertOffset=#()
ukwcount=#()
NameOffset=#()
NameLength=#()
Name_array=#()
PolyElmCount=#()
FaceOffset=#()
FaceOffsetTable=#()



FileType = ReadFixedString f 4
fseek f 0x10 #seek_set
BoneOffset = ReadBElong f
VertStart = ReadBElong f
fseek f 0x20 #seek_set
GeomCount = ReadBEshort f
ukw = ReadBEshort f
NameTableOffset = ReadBElong f + 0x20

	-- Getting Geometry Offsets --
For x=1 to GeomCount do (
	GeomOffset[x] = (ReadBElong f + 0x30)
-- 	Print ("GeomOffset @ 0x"+((bit.intAsHex(GeomOffset[x]))as string))
)
	-- Getting Name Offsets --
fseek f NameTableOffset #seek_set
For x=1 to GeomCount do (
	NameOffset[x] = ReadBElong f + 0x20
-- 	Print ("NameOffset @ 0x"+((bit.intAsHex(NameOffset[x]))as string))

)
	-- Reading Names --
For x=1 to GeomCount do (
	fseek f NameOffset[x] #seek_set
	Name_array[x] = readstring f
)

-- print Name_array as string


Struct FaceOffsetArray_Group (
	FaceOffsetArray
)
Struct FaceOffset2Array_Group (
	FaceOffset2Array
)
Struct FaceCountArray_Group (
	FaceCountArray
)
Struct MeshNameArray_Group (
	MeshNameArray
)

FaceOffset_array=#()
FaceOffset2_array=#()
FaceCount_array=#()
MeshName_array=#()


	-- Getting Geometry Data --
For x=1 to GeomCount do (
	FaceOffset=#()
	FaceOffset2=#() -- Actual face offset
	FaceCount=#()
	MeshName=#()
	
	fseek f GeomOffset[x] #seek_set
	SubType = ReadFixedString f 4
	ukw = ReadBEshort f
	ukw2 = ReadBEshort f
	DataSkip = ReadBElong f
	fseek f 0x4 #seek_cur
	fseek f DataSkip #seek_cur
-- 	print (dataskip / 10) as string
	VertCount[x] = ReadBEshort f
	VertSize[x] = ReadBEshort f
	VertOffset[x] = (ReadBElong f + GeomOffset[x] + 0x10)
	PolyElmCount[x] = ReadBElong f
	FaceOffsetTable = (ReadBElong f + GeomOffset[x] + 0x10)
	fseek f FaceOffsetTable #seek_set
	
	For y=1 to PolyElmCount[x] do (
		FaceOffset[y] = (ReadBElong f + GeomOffset[x] + 0x20)
-- 		Print ("FaceOffset is 0x"+((bit.intAsHex(FaceOffset[y]))as string))
	)
	For y=1 to PolyElmCount[x] do (
		fseek f FaceOffset[y] #seek_set
		FaceBufferID = ReadBEshort f
		FaceCount[y] = ReadBEshort f
		BackJump = ftell f
		ukw1 = ReadBEshort f
		MeshName[y] = readstring f
-- 		Print (" Read @ 0x"+((bit.intAsHex(ftell f))as string))
		fseek f BackJump #seek_set
		fseek f 0x22 #seek_cur
		FaceOffset2[y] = ftell f
	)
	
	
	append FaceOffset_array (FaceOffsetArray_Group FaceOffsetArray:FaceOffset)
	append FaceOffset2_array (FaceOffset2Array_Group FaceOffset2Array:FaceOffset2)
	append FaceCount_array (FaceCountArray_Group FaceCountArray:FaceCount)
	append MeshName_array (MeshNameArray_Group MeshNameArray:MeshName)
	
-- 	Print "____________________________________"

	

-- 	Print ("Dataskip2 is 0x"+((bit.intAsHex(dataskip2))as string))
-- 	Print ("Vertsize is 0x"+((bit.intAsHex(VertSize[x]))as string))
-- 	Print ("Vertcount is 0x"+((bit.intAsHex(VertCount[x]))as string))
-- 	Print ("Facecount is 0x"+((bit.intAsHex(FaceCount[x]))as string))
-- 	Print ("PolyElmCount is 0x"+((bit.intAsHex(PolyElmCount[x]))as string))
-- 	Print ("FaceOffsetTable is 0x"+((bit.intAsHex(FaceOffsetTable))as string))
-- 	Print ("FaceOffsetTable is 0x"+((bit.intAsHex(FaceOffsetTable))as string))
)

-- print polyelmcount as string
-- print FaceOffset2_array as string
-- print FaceCount_array as string
-- print MeshName_array as string

BoneNameOffset=#()
BoneName=#()

	-- Reading Bones --
fseek f BoneOffset #seek_set
BoneCount = ReadBEshort f
Ukw2 = ReadBEshort f
Ukw3 = ReadBElong f
BoneStart1 = (ReadBElong f + BoneOffset)	-- This bone matrix is weird
BoneNameTable = (ReadBElong f + BoneOffset)
fseek f 0x8 #seek_cur
Ukw4 = ReadBElong f	-- Really no reason why this here
BoneStart2 = (ReadBElong f + BoneOffset)


fseek f BoneNameTable #seek_set
For x=1 to BoneCount do (
	BoneNameOffset[x] = (ReadBElong f + BoneOffset)
)
For x=1 to BoneCount do (
	fseek f BoneNameOffset[x] #seek_set
	BoneName[x] = readstring f
-- 	Print BoneName[x] as string
)

-- Print ("BoneOffset @ 0x"+((bit.intAsHex(BoneOffset))as string))

-- fseek f BoneStart #seek_set
-- for x=1 to BoneCount do (
-- 	read = ReadFixedByteString f 0x10
-- 	fseek f 0x40 #seek_cur
-- 	print read
-- )

fseek f BoneStart1 #seek_set
BNArr = #()
For x=1 to BoneCount do (
	BoneParentID = ReadBEshort f + 1
	BoneID = ReadBEshort f + 1
	BoneSiblingID = ReadBEshort f + 1
	fseek f 0xa #seek_cur
	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,m21,m31,m41] [m12,m22,m32,m42] [m13,m23,m33,m43] [m14,m24,m34,m44]	
	newBone = bonesys.createbone	\
	tfm.row4	\
	(tfm.row4 + 0.01 * (normalize tfm.row1)) \
	(normalize tfm.row3)
	newBone.width = 0.1
	newBone.height = 0.1
	newBone.wirecolor = yellow
	newbone.showlinks = true
	newBone.name = BoneName[x]

	
	pos = [m41,m42,m43]
	pos = pos * tfm

	newBone.pos.x += ((fscale)*pos.x)
	newBone.pos.y += ((fscale)*pos.z)
	newBone.pos.z += ((fscale)*pos.y)	

	newBone.setBoneEnable false 0
	newBone.pos.controller = TCB_position ()
	newBone.rotation.controller = TCB_rotation ()

	if (BoneParentID != 0) then (
	newBone.parent = BNArr[BoneParentID]
	newBone.transform *= newBone.parent.transform
   )
   	append BNArr newBone
)


	-- Reading Geometry --
For x=1 to GeomCount do (
	Vert_array=#()
	UV_array=#()
	Normal_array=#()
	Face_array=#()
	Weight_array=#()
	
	fseek f VertOffset[x] #seek_set
	Print ("Verts @ 0x"+((bit.intAsHex(ftell f))as string))
	
	If VertSize[x] == 0x14 do (
		for x=1 to VertCount[x] do (
		vx = ReadBEfloat f
		vy = ReadBEfloat f
		vz = ReadBEfloat f
		fseek f 0x8 #seek_cur
		append Vert_array([vx,vz,vy]*fscale)
		append UV_array[0,0,0]
		)
	)
	If VertSize[x] == 0x18 do (
		for x=1 to VertCount[x] do (
		vx = ReadBEfloat f
		vy = ReadBEfloat f
		vz = ReadBEfloat f
		fseek f 0xc #seek_cur
		append Vert_array([vx,vz,vy]*fscale)
		append UV_array[0,0,0]
		)
	)
	If VertSize[x] == 0x1c do (	-- Always have trouble with this guy.
		for x=1 to VertCount[x] do (
		vx = ReadBEfloat f
		vy = ReadBEfloat f
		vz = ReadBEfloat f
		fseek f 0x10 #seek_cur
		append Vert_array([vx,vz,vy]*fscale)
		append UV_array[0,0,0]
		)
	)
	If VertSize[x] == 0x20 do (
		for x=1 to VertCount[x] do (
		vx = ReadBEfloat f
		vy = ReadBEfloat f
		vz = ReadBEfloat f
		n1 = ReadBEHalfFloat f	
		n2 = ReadBEHalfFloat f
		n3 = ReadBEHalfFloat f
		fseek f 0xe #seek_cur
		append Vert_array([vx,vz,vy]*fscale)
		append UV_array[0,0,0]
		append Normal_array [n1,n3,n2]
		)
	)
	If VertSize[x] == 0x24 do (
		for x=1 to VertCount[x] do (
		w = (weight_data boneids:#() weights:#())
		vx = ReadBEfloat f
		vy = ReadBEfloat f
		vz = ReadBEfloat f
		n1 = ReadBEHalfFloat f	
		n2 = ReadBEHalfFloat f
		n3 = ReadBEHalfFloat f
		null = ReadBEHalfFloat f	-- always 2
		tu=ReadBEHalfFloat f
		tv=ReadBEHalfFloat f
		
		bone4 = readbyte f #unsigned
		bone3 = readbyte f #unsigned
		bone2 = readbyte f #unsigned
		bone1 = readbyte f #unsigned
		weight1 = ReadBEHalfFloat f
		weight2 = ReadBEHalfFloat f
		weight3 = ReadBEHalfFloat f
		weight4 = ReadBEHalfFloat f
		weight4 = 1 - (weight1+weight2+weight3)
			
		maxweight = 0
		if(bone1 != 0xFF) then
			maxweight = maxweight + weight1
		if(bone2 != 0xFF) then
			maxweight = maxweight + weight2
		if(bone3 != 0xFF) then
			maxweight = maxweight + weight3
		if(bone4 != 0xFF) then
			maxweight = maxweight + weight4
			
		if(maxweight != 0) then (
			mxw = 255.0
			if(bone1 != 0xFF) then (
				w1 = weight1 as float
				append w.boneids (bone1+1)
				append w.weights (w1 / mxw)
			)
			if(bone2 != 0xFF) then (
				w2 = weight2 as float
				append w.boneids (bone2+1)
				append w.weights (w2 / mxw)
			)
			if(bone3 != 0xFF) then (
				w3 = weight3 as float
				append w.boneids (bone3+1)
				append w.weights (w3 / mxw)
			)
			if(bone4 != 0xFF) then (
				w4 = weight4 as float
				append w.boneids (bone4+1)
				append w.weights (w4 / mxw)
			)		
		)
		
		append Vert_array([vx,vz,vy]*fscale)
		append UV_array([tu,(tv*-1),0]*2)
		append Normal_array [n1,n3,n2]
		append Weight_array w
		)
	)
	If VertSize[x] == 0x2c do (
		for x=1 to VertCount[x] do (
		vx = ReadBEfloat f
		vy = ReadBEfloat f
		vz = ReadBEfloat f
		fseek f 0x20 #seek_cur
		append Vert_array([vx,vz,vy]*fscale)
		append UV_array[0,0,0]
		)
	)
	If VertSize[x] == 0x30 do (
		for x=1 to VertCount[x] do (
		w = (weight_data boneids:#() weights:#())
		vx = ReadBEfloat f
		vy = ReadBEfloat f
		vz = ReadBEfloat f
		n1 = ReadBEfloat f
		n2 = ReadBEfloat f
		n3 = ReadBEfloat f
		tu=ReadBEFloat f
		tv=ReadBEFloat f
		bone4 = readbyte f #unsigned
		bone3 = readbyte f #unsigned
		bone2 = readbyte f #unsigned
		bone1 = readbyte f #unsigned
		weight1 = ReadBEfloat f
		weight2 = ReadBEfloat f
		weight3 = ReadBEfloat f
		weight4 = 0
		weight4 = 1 - (weight1+weight2+weight3)
		maxweight = 0
		if(bone1 != 0xFF) then
			maxweight = maxweight + weight1
		if(bone2 != 0xFF) then
			maxweight = maxweight + weight2
		if(bone3 != 0xFF) then
			maxweight = maxweight + weight3
		if(bone4 != 0xFF) then
			maxweight = maxweight + weight4
			
		if(maxweight != 0) then (
			mxw = 255.0
			if(bone1 != 0xFF) then (
				w1 = weight1 as float
				append w.boneids (bone1+1)
				append w.weights (w1 / mxw)
			)
			if(bone2 != 0xFF) then (
				w2 = weight2 as float
				append w.boneids (bone2+1)
				append w.weights (w2 / mxw)
			)
			if(bone3 != 0xFF) then (
				w3 = weight3 as float
				append w.boneids (bone3+1)
				append w.weights (w3 / mxw)
			)
			if(bone4 != 0xFF) then (
				w4 = weight4 as float
				append w.boneids (bone4+1)
				append w.weights (w4 / mxw)
			)
		)
			
-- 		read = ReadFixedByteString f 0x10
-- 		print read
		append Vert_array([vx,vz,vy]*fscale)
		append UV_array([tu,(tv*-1),0]*2)
		append Normal_array [n1,n3,n2]
		append Weight_array w
		)
	)
	
	For y=1 to PolyElmCount[x] do (
		fseek f FaceOffset2_array[x].FaceOffset2Array[y] #seek_set
-- 		Print ("Face start @ 0x"+((bit.intAsHex(ftell f))as string))
-- 		Print ("Face count is 0x"+((bit.intAsHex(FaceCount_array[x].FaceCountArray[y]))as string))
		
		For z=1 to (FaceCount_array[x].FaceCountArray[y] / 3) do(
			fa=ReadBEShort f +1
			fb=ReadBEShort f +1
			fc=ReadBEShort f +1
			append Face_array[fc,fb,fa]
		)
		
	)
	msh = mesh vertices:Vert_array faces:Face_array
	msh.numTVerts = UV_array.count
	buildTVFaces msh
-- 	msh.name = Name_array[x]
	msh.name = (bit.intAsHex(VertSize[x]))
-- 	msh.wirecolor = (color 255 255 255)
	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]
-- 	ApplyNormals2 msh Normal_array 1
	Loadskel = false
	If LoadSkel == true do (
		-- Applying Skinning --
		count = msh.numverts
		max modify mode
		select msh
		skinMod = skin ()
		addModifier msh skinMod
		for i = 1 to BoneCount do (
			maxbone = getnodebyname BNArr[i].name
			skinOps.addBone skinMod maxbone 1
		)
		-- Applying Weights --
		select msh
		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
		)
	)
	
)




Print ("Last Read @ 0x"+((bit.intAsHex(ftell f))as string))
)

select $*
-- actionMan.executeAction 0 "310"  -- Tools: Zoom Extents Selected
deselect $*
/* 12/06/14
    1:23am lol
*/

gc()
fclose f