--joqqyhez@gmail.com

--/*
--////// FileDialog //////
fname = getOpenFileName \ 
caption:"Mtl File" \
types:"CryTek mtl File(*.mtl)|*.mtl" \
historyCategory:"CryTek mtl Presets"
f = fopen fname "rb"
p = getFilenamePath fname -- return the path "c:\\test\\"
CryXmlB_path = fname -- return the file "test"
--*/


xmlB_arr = #( \
					#(), 	--Binary XML header		[1]
					#(), 	--node structs			[2]
					#(), 	--child index				[3]
					#()	--attrib_child_indices	[4]
				)

--XMLBinaryHeaders.h---------------------
struct _Node
(
	nTagStringOffset 			= 0,  	--uint32 --offset in CBinaryXmlData::pStringData
		nTagString					= "",
	nContentStringOffset 		= 0,   	--uint32 --offset in CBinaryXmlData::pStringData
	nAttributeCount 				= 0,		--uint16
	nChildCount 					= 0,		--uint16
	nParentIndex 					= 0, 		--uint32(p?) -1 prob means root node	--NodeIndex 	 	typedef uint32 NodeIndex;  // note: only uint32 or uint16 are supported
	nFirstAttributeIndex 			= 0,  	--uint32(p?)				--NodeIndex 		typedef uint32 NodeIndex;  // note: only uint32 or uint16 are supported
	nFirstChildIndex				= 0,		--uint32(p?)				--NodeIndex 		typedef uint32 NodeIndex;  // note: only uint32 or uint16 are supported
	
	Pad 								= 1 		--int32(p?) (1 readlong)	--Pad<sizeof(uint32) - sizeof(NodeIndex)> reserved_for_alignment; 
)

struct Attribute
(
	nKeyStringOffset = 0,        		--uint32 --offset in CBinaryXmlData::pStringData
	nValueStringOffset = 0      		--uint32 --offset in CBinaryXmlData::pStringData
)

struct BinaryFileHeader
(
	szSignature 				= "", 		--char [8]
	nXMLSize 					= 0, 		--uint32
	nNodeTablePosition 		= 0, 		--uint32
	nNodeCount 				= 0,		--uint32
	nAttributeTablePosition = 0, 		--uint32
	nAttributeCount 			= 0, 		--uint32
	nChildTablePosition 		= 0, 		--uint32
	nChildCount 				= 0, 		--uint32
	nStringDataPosition 		= 0,		--uint32
	nStringDataSize			= 0 		--uint32
)
----------------------------------------------

szSignature = "CryXmlB"

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

fn read_BinaryFileHeader  \
									bstream \
									struct2fill \
									signature2check =
(
	--if the signature is "CryXmlB", then we can proceed
	if struct2fill.szSignature == signature2check then
	(
		format "Correct signature, we continue parsing...\n"	
		
		struct2fill.nXMLSize 						= readlong bstream #unsigned			
		struct2fill.nNodeTablePosition 		= readlong bstream #unsigned		
		struct2fill.nNodeCount 					= readlong bstream #unsigned		
		struct2fill.nAttributeTablePosition 	= readlong bstream #unsigned
		struct2fill.nAttributeCount 			= readlong bstream #unsigned
		struct2fill.nChildTablePosition			= readlong bstream #unsigned
		struct2fill.nChildCount 					= readlong bstream #unsigned
		struct2fill.nStringDataPosition 		= readlong bstream #unsigned
		struct2fill.nStringDataSize 				= readlong bstream #unsigned			
		
		--Append header to array
		Append xmlB_arr[1] struct2fill
	)
	else
	(
		format "Wrong signature. Signature must be %. We cannot continue - aborting!" signature2check
	)
)

fn read_Node \
					bstream \					
					struct2read =
(
	for i=1 to struct2read.nNodeCount do
	(
		--create struct instance
		struct2fill = _Node()
		
		struct2fill.nTagStringOffset = readlong bstream #unsigned		
		struct2fill.nContentStringOffset = readlong bstream #unsigned		
		struct2fill.nAttributeCount = readshort bstream #unsigned		
		struct2fill.nChildCount = readshort bstream #unsigned
		
		---------------------------------- Nodeindices ----------------------------------
		struct2fill.nParentIndex = readlong bstream #unsigned	
		struct2fill.nFirstAttributeIndex = readlong bstream #unsigned
		struct2fill.nFirstChildIndex = readlong bstream #unsigned			
		
		--pad
		for i=1 to struct2fill.Pad do
		(
			readlong bstream
		)
		
		--Append all the node structs to the array
		Append xmlB_arr[2] struct2fill
	)
)

fn read_nChildTable \
							bstream \
							struct2read =
(
	fseek bstream struct2read.nChildTablePosition #seek_set
	
	for i=1 to struct2read.nChildCount do
	(
		childIndex = readlong bstream #unsigned
		
		Append xmlB_arr[3] childIndex
	)	
)

struct attrib_child_indices
(
	nFirstAttributeIndex 		= 0,
	nFirstChildIndex 			= 0,
	
	nFirstAttribute_val 		= "",
	nFirstChild_val 			= ""
)

fn read_nTagString \
							bstream \
							struct2read =
(	
	for i=1 to xmlB_arr[2].count do
	(
		fseek bstream (struct2read.nStringDataPosition + xmlB_arr[2][i].nTagStringOffset)  #seek_set		
	
		xmlB_arr[2][i].nTagString = ReadString bstream
	)
)

fn read_nAttributeTable \
									bstream \
									struct2read =
(
	fseek bstream struct2read.nAttributeTablePosition #seek_set
	
	for i=1 to struct2read.nAttributeCount do
	(
		struct2fill = attrib_child_indices()
		
		--These are the offsets from where we read the strings, starting from the nStringDataPosition offset (last chunk of the file)
		struct2fill.nFirstAttributeIndex 	= 		(readlong bstream #unsigned)
		struct2fill.nFirstChildIndex 			= 		(readlong bstream #unsigned)	
		
		Append xmlB_arr[4] struct2fill
	)
	
	for i=1 to struct2read.nAttributeCount do
	(
		fseek bstream struct2read.nStringDataPosition #seek_set		
			fseek bstream xmlB_arr[4][i].nFirstAttributeIndex #seek_cur
				xmlB_arr[4][i].nFirstAttribute_val = ReadString bstream
		
		fseek bstream struct2read.nStringDataPosition #seek_set
			fseek bstream xmlB_arr[4][i].nFirstChildIndex #seek_cur
				xmlB_arr[4][i].nFirstChild_val = ReadString bstream
	)
)

--////////////// Open binary stream //////////////
xbs = fopen CryXmlB_path "rb"
-------------------------------------------

inst_BinaryFileHeader = BinaryFileHeader()
inst_BinaryFileHeader.szSignature = ReadFixedString xbs 8


clearlistener()
------		------		------		------		------		------		------		------		------		------		------		------		------
format "inst_BinaryFileHeader.szSignature: %\n" inst_BinaryFileHeader.szSignature
------		------		------		------		------		------		------		------		------		------		------		------		------


read_BinaryFileHeader \
								xbs \
								inst_BinaryFileHeader \
								szSignature

read_Node \
				xbs \
				inst_BinaryFileHeader

read_nChildTable \
						xbs \
						inst_BinaryFileHeader

read_nAttributeTable \
								xbs \
								inst_BinaryFileHeader

read_nTagString \
						xbs \
						inst_BinaryFileHeader


ftell xbs
--////////////// Close binarystream //////////////
fclose xbs


fn debug_xmlB_arr \
						xmlArr =
(	
	---------	---------	---------	---------	---------	---------	---------	---------	---------	---------	---------
	-- 	xmlB_arr = #( \
	-- 					#(), 	--Binary XML header		[1]
	-- 					#(), 	--node structs			[2]
	-- 					#(), 	--child index				[3]
	-- 					#()	--attrib_child_indices	[4]
	-- 				)

	(
		format "\n\n\n REPORT - remember all indices are zero based (must be converted to 1 based in max\n\n"
		format "---------------------------This is the header table info-------------------------------\n\n"
		for i=1 to xmlArr[1].count do
		(
			format "struct2fill.nXMLSize: % \n"		 																				xmlArr[1][i].nXMLSize
			format "struct2fill.nNodeTablePosition: % \n"																			xmlArr[1][i].nNodeTablePosition
			format "struct2fill.nNodeCount: % \n" 																					xmlArr[1][i].nNodeCount
			format "struct2fill.nAttributeTablePosition: % \n"																	xmlArr[1][i].nAttributeTablePosition
			format "struct2fill.nAttributeCount: % \n" 																			xmlArr[1][i].nAttributeCount
			format "struct2fill.nChildTablePosition: % \n" 																		xmlArr[1][i].nChildTablePosition
			format "struct2fill.nChildCount: % (Root NOT included-so these are the children for the root)\n" 	xmlArr[1][i].nChildCount
			format "struct2fill.nStringDataPosition: % \n"																			xmlArr[1][i].nStringDataPosition
			format "struct2fill.nStringDataSize: % \n" 																			xmlArr[1][i].nStringDataSize
		)
		format "-------------------------------------------------------------------------------------\n\n\n"

		format "-----------These are the children (the node with nParentIndex: -1 is the root node)-----------\n\n"
		for i=1 to xmlArr[2].count do
		(
			tab = "\t" --for children
			
			if xmlArr[2][i].nFirstChildIndex == 0 AND xmlArr[2][i].nParentIndex == -1 then --Root
			(
				tab = ""
			)
			-------------------------
			format "%\t struct2fill.nTagStringOffset: %\n" 			tab xmlArr[2][i].nTagStringOffset
				format "%\t struct2fill.nTagStringOffset: <%>\n" 	tab xmlArr[2][i].nTagString
			format "%\t struct2fill.nContentStringOffset: %\n" 	tab xmlArr[2][i].nContentStringOffset
			format "%\t struct2fill.nAttributeCount: %\n" 			tab xmlArr[2][i].nAttributeCount
			format "%\t struct2fill.nChildCount: %   (this is the count from xmlArr[3][i] <---this val counts these nodes from the starting node (see last for each of these nodes) \n" 					tab xmlArr[2][i].nChildCount
			format "%\t struct2fill.nParentIndex: %\n" 				tab xmlArr[2][i].nParentIndex
			format "%\t struct2fill.nFirstAttributeIndex: %\n" 		tab xmlArr[2][i].nFirstAttributeIndex
			format "%\t struct2fill.nFirstChildIndex: %   (xmlArr[3][i] <---this val, points to the starting node in these nodes (children to the root) here) \n" 			tab xmlArr[2][i].nFirstChildIndex
			-------------------------
			format "\n"
		)	
		format "------------------------------------------------------------------------------------------\n\n\n"


		format "-----------These are the childrens to the root (i.e. the root is not included here!)-----------\n\n"
		for i=1 to xmlArr[3].count do
		(
			format "nFirstChildIndex %: \n" xmlArr[3][i]
		)
		format "------------------------------------------------------------------------------------------\n\n\n"




		format "-------------These are the attributes (the root will reference these as well)-------------\n\n"
		for i=1 to xmlArr[4].count do
		(
			format 	"nFirstAttributeIndex %: \n" 	xmlArr[4][i].nFirstAttributeIndex
			format 	"nFirstChildIndex %: \n" 		xmlArr[4][i].nFirstChildIndex
			format "\n"
		)
		format "--------------------------------------------------------------------------------------\n"
		
		for i=1 to xmlArr[4].count do
		(
			format 	"nFirstAttributeIndex %: \n" 	xmlArr[4][i].nFirstAttributeIndex
				format 	"\t nFirstAttribute_val %: \n" 	xmlArr[4][i].nFirstAttribute_val
			format "\n"
			
			format 	"nFirstChildIndex %: \n" 		xmlArr[4][i].nFirstChildIndex	
				format 	"\t nFirstChild_val %: \n" 	xmlArr[4][i].nFirstChild_val
			format "\n"
			
		)
		
		format "END OF REPORT\n\n\n"
	)
	---------	---------	---------	---------	---------	---------	---------	---------	---------	---------	---------
)

debug_xmlB_arr \
					xmlB_arr





