Notifications
Clear all

[Closed] reading a max file as a binary file

hey!
here’s the code that opens a max file as a binary stream (this would help extract important information about a max scene file without loading it):

(	
	thebytestream = fopen "D:\\file1.max" "rb"
	thesize = getfilesize "D:\\file1.max"
	i = 1
	while (i < thesize) do
	(

		thebyte = bit.intaschar (readbyte thebytestream)				
		format "%" ( thebyte)
		i+=1	

	)
	fclose thebytestream
)

here’s the important information amongst the avalanche of junk binary ouput

3ds Max Version: 120 UncompressedBuild: 1200106 Vertices: 0 Faces: 0 Objects: 0 Shapes: 0 Lights: 0 Cameras: 0 Helpers: 0 Space Warps: 0 Total: 0 … User Name=your user name Computer Name=your computer name Render Width=640Render Height=480&Render Aspect=100Renderer ClassIDA=1Renderer ClassIDB=0PRenderer Name=Default Scanline RendererAnimation Start=-307Animation End=401 Render Flags=32Scene Flags=57032RenderElements=14 true

my question is how do i extract this data without reading the whole max file ? on a blank max file the location of the string starts at about 181000th byte, but it changes as the scene is modified 🙁
maybe the information in the file could be parsed faster using header structures like in a bitmap file but i dunno the structures used in .max file 🙁

any help is appreciated thanks !

4 Replies

Hint: Check to see whether that chunk of data is always close to the END of the file. You could then reposition relative to the end of the file using a negative offset value and read just the end bytes instead of running through the whole file…

did some experimentation… The results:

--     Location =  244796  -- array of ports FileSize 294912
 --     Location =  327912  -- array of pots and spheres messed up, and random materials setup FileSize 331776
 --     Location = 133300 -- radius 10 segments 10 File Size = 184320
 --  Average running time O(filesize) in other words. order of seconds !!!

yes had a similar intuition at first ,but even by reading the file from the end the running time of the code is still order of seconds! maybe the code could be improved further. i am searching for the keyword “animation” in the file once it is obtained the rest of the string can easily be obtained! (which would be the next step, after i get the running time down to milliseconds atleast!) :

(		 
 	st = timestamp()		
 	
 	thebytestream = fopen "D:\\file1.max" "r"
 	thesize = getfilesize "D:\\file1.max"	
 	
	i =thesize-1
 	thearr = #("A","","n","","i","","m","","a","","t","","i","","o","","n")
 	
 	fseek thebytestream i #seek_set
 	
 	while ((i > 0)) do
 	(		
 -- 		thebyte = bit.intaschar (readbyte thebytestream)		
 		flag = 1
 		for j = 1 to thearr.count do 
 		(
 			thebyte = bit.intaschar (readbyte thebytestream)			
 			if (thebyte != thearr[j]) then
 			(					
 				flag = 0
 				exit
 			)
 		)		
 		if flag==1 do			
 		(
 			format "Location = % 
" i
 			exit
 		)
 		 i-=1			
 -- 		format "%" thebyte
 		fseek thebytestream i #seek_set		
 				
 	)
 		
 	fclose thebytestream
 	et = timestamp()
 	format "took % milliseconds" (et - st)
 )

But i still think a more elegant approach would be read the structure containing this information in the max file, i searched the SDK and google … but could not find information about it. only choice left is to reverse engineer the save action of max using IDA disassembler. Hopefully during the weekend maybe!

anyways… thanks for the post !

cheers !

I did not mean reading backwards.
I meant figuring out a good negative offset from the end that works for every file in existence, jumpint to it using #seek_end and then reading forward until you hit the search string. If your guess is right, it might be faster than moving backwards from the end one byte at a time.

alright i implemented the suggested algorithm. and the running time has reduced by order of 2!!! however there is a slight trade off with accuracy, and a very small chance of a miss, in finding the string.
would be great if some one could test the script for me … here’s the code( not the best code i have written so far but hopefully some one could optimize it more ?) :

(
 	-- Reduced accuracy (+- 10 bytes) but exponential increase in speed!! 
 	-- average running time 50 - 400 milliseconds only .. (compared to 4 seconds earlier)!!
 	-- dropped an inner loop therefore slight chance of a miss.
 
 	st = timestamp()
 	
 		thefilename = "D:\\file1.max"
 		thefilesize = getfilesize thefilename	
 		bytestream = fopen thefilename "r"		
 		offset = 6
 		previousOffset = offset
 		realIndex = 0
 		thestring = ""
 		fseek bytestream -offset #seek_end
 		
 		while (offset <= (thefilesize-1)) do
 		(
 			flag = 0				
 			for index = 1 to (abs previousOffset) do
 			(			
 				thebyte = bit.intaschar (readbyte bytestream)
 				if thebyte!= "" do
 					thestring += thebyte
 				if (mod index 30 == 0) do
 				(				
 					if (findstring thestring "Version" != undefined) do
 					(
 						flag = 1				
 						realIndex = index - findstring thestring "Version" - 13 -- size of version * 2 coz of unicode
 						exit
 					)								
 					thestring = ""
 				)
 				if flag==1 do
 					exit
 				index+=1
 			)
 			if flag==1 do
 				exit		
 			offset = offset*10		
 			previousOffset = offset - previousOffset
 			offset = amin offset (thefilesize)			
 			fseek bytestream -offset #seek_end
 		)
 		
 		et = timestamp()
 		
 		if flag == 1 then
 			format "Location = % 
" (thefilesize-offset+realIndex)
 		else
 			format "increase the (mod index 30) value by 10 to (mod index 40) and so on...  and try again
"
 	format "took % milliseconds" (et-st)
 	fclose  bytestream
 )

thanks once again for posting !

cheers