# Assassin's Creed: Origins model plugin for Noesis
# Version 1.0
# by theawesomecoder61 (pineapples721)
#
# Version 1.0 (3/27/2019):
# - initial version

from inc_noesis import *
import math
import os
import struct

from inc_noesis import *
import subprocess

MDL_MAGIC = 1096652136
MSH_DATA =  105229237

class mytex(object):
	def __init__(self):
		width = 0
		hight = 0
		DXT = 0
		name = ""
		texture = 0


def registerNoesisTypes():
	handle = noesis.register("Assassin's Creed: Origins textures", ".acortex")
	noesis.setHandlerTypeCheck(handle, texCheckType)
	noesis.setHandlerLoadRGBA(handle, texLoadDDS)

	noesis.logPopup()
	return 1

def texCheckType(data):
	bs = NoeBitStream(data)
	#print(bs)
	loc_mgic = bs.readInt()
	print("magic " + hex(loc_mgic))
	if loc_mgic != MDL_MAGIC:
		print("Not a model file")
		return 1
	return 1


def readtex (bs, t_width, t_height, DXT, FileName):
	texFmt = 0
	datasize2 = 0
	ddsData = 0
	'''
	DXT0 = 0,
	DXT1 = 1,
	DXT1_ = 2,
	DXT1__ = 3,
	DXT3 = 4,
	DXT5 = 5,
	DXT5_ = 6,
	DXT0_ = 7,
	DX10 = 8,
	DX10_ = 9,
	DXT5__ = 12,
	DX10__ = 16
	'''
	
	
	tex1 = 0
	if(DXT == 0): 
		texFmt = noesis.NOESISTEX_DXT0
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT1)
		
	if(DXT == 1): 
		texFmt = noesis.NOESISTEX_DXT0
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT1)
		
	if(DXT == 2): 
		texFmt = noesis.NOESISTEX_DXT1
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT1)

	if(DXT == 3): 
		texFmt = noesis.NOESISTEX_DXT1
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT1)
		
	if(DXT == 4): 
		texFmt = noesis.NOESISTEX_DXT3
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT3)
		
	if(DXT == 5): 
		texFmt = noesis.NOESISTEX_DXT5
		datasize2 = t_width * t_height // 2  * 2
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT5)
		
	if(DXT == 6): 
		texFmt = noesis.NOESISTEX_DXT6
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT5)
		
	if(DXT == 7): 
		texFmt = noesis.NOESISTEX_DXT0
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT1)
		
	if(DXT == 12): 
		texFmt = noesis.NOESISTEX_DXT5
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_DXT5)
		
		
	if(DXT == 9): 

		texFmt = noesis.NOESISTEX_DXT1
		datasize2 = t_width * t_height // 2 *2
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_BC7)


	if(DXT == 8): 

		texFmt = noesis.NOESISTEX_DXT1
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_BC7)

	if(DXT == 16): 

		texFmt = noesis.NOESISTEX_DXT1
		datasize2 = t_width * t_height // 2 
		ddsData = bs.readBytes(datasize2)
		ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_BC7)

		
	ddsData = rapi.imageFlipRGBA32(ddsData, t_width, t_height, 0, 1)
	texFmt = noesis.NOESISTEX_RGBA32
	tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))	
		
	tex2 = mytex()
	tex2.width = t_width
	tex2.height = t_height
	tex2.name = FileName
	tex2.DXT = DXT
	tex2.texture = tex1
	return (tex2)

	
	
	
	
	
	
	
	
	
	
	

def fnd4byte (bs, bytes_ar):
	old_offest = bs.tell()
	byte1 = bs.readUByte()
	byte2 = bs.readUByte()
	byte3 = bs.readUByte()
	byte4 = bs.readUByte()
	
	
	val2 = 0
	val = byte1 + byte2 * 0x100 + byte3 * 0x10000 + byte4 * 0x1000000

	while(val != bytes_ar):
		old_offest1 = bs.tell()
		byte1 = bs.readUByte()
		byte2 = bs.readUByte()
		byte3 = bs.readUByte()
		byte4 = bs.readUByte()
		
		val = byte1 + byte2 * 0x100 + byte3 * 0x10000 + byte4 * 0x1000000
		
		#str1 = hex(val)[2:]
		#while (len(str1) < 8): str1 = "0" + str1
		#print("0x" + str1)
		bs.seek(-3 , NOESEEK_REL)
		val2 = val2 +1 
		old_offest2 = bs.tell()
		if(old_offest1 == old_offest2): 
			bs.seek(old_offest, NOESEEK_ABS)
			return -1
	
	
	new_offest = bs.tell()
	bs.seek(old_offest, NOESEEK_ABS)	
	return new_offest - 1

	
	


def texLoadDDS(data, texList):

	tmp_tex = []
	bs = NoeBitStream(data)
	submeshes = []
	meshes = []
	meshes2 = []
	vertex_pos = 0
	face_pos = 0
	WatchUV = False

	print("")
	print("")
	print("")
	print("New File")

	print("cur_offset1: " + hex(bs.tell()))

	ResourceIdentifier = bs.readUInt()
	FileSize = bs.readUInt()
	FileNameSize = bs.readUInt()
	
	print("ResourceIdentifier: " + hex(ResourceIdentifier) + "  " + str(ResourceIdentifier) )
	print("FileSize: " +  hex(FileSize) + "  " + str(FileSize) )
	print("FileNameSize: " +  hex(FileNameSize) + "  " + str(FileNameSize) )

	FileName = NoeBitStream(bs.readBytes(FileNameSize)).readString()
	print("FileName: " +  FileName )
	print("")
	bs.seek(14, NOESEEK_REL)
	print("cur_offset2: " + hex(bs.tell()))
	t_width = bs.readUInt()
	t_height = bs.readUInt()
	print("	original t_width: " +  hex(t_width) + "  " + str(t_width) )
	print("	original t_height: " +  hex(t_height) + "  " + str(t_height) )





	#reader.BaseStream.Seek(8, SeekOrigin.Current); // 8 skipped bytes
	#textureMap.DXT = (DXT)reader.ReadInt32();
	#reader.BaseStream.Seek(8, SeekOrigin.Current); // 8 skipped bytes
	#textureMap.Mipmaps = reader.ReadInt32();
	#reader.BaseStream.Seek(20, SeekOrigin.Current); // 5 skipped ints

	#reader.BaseStream.Seek(2, SeekOrigin.Current);
	bs.seek(8, NOESEEK_REL)
	DXT = bs.readUInt()
	print("DXT: " +  hex(DXT) + "  " + str(DXT) )
	Mipmaps = bs.readUInt()
	print("Mipmaps: " +  hex(Mipmaps) + "  " + str(Mipmaps) )

	bs.seek(20, NOESEEK_REL)
	bs.seek(2, NOESEEK_REL)
	bs.seek(34, NOESEEK_REL)
	bs.seek(1, NOESEEK_REL)
	bs.seek(12, NOESEEK_REL)

	bs.seek(16, NOESEEK_REL)

	print("cur_offset1_1: " + hex(bs.tell()))

	t2_width = bs.readUInt()
	t2_height = bs.readUInt()
	print("t2_width: " +  hex(t2_width) + "  " + str(t2_width) )
	print("t2_height: " +  hex(t2_height) + "  " + str(t2_height) )

	bs.seek(8, NOESEEK_REL)

	Mipmaps2 = bs.readUInt()
	print("Mipmaps2: " +  hex(Mipmaps2) + "  " + str(Mipmaps2) )
	DXT2 = bs.readUInt()
	print("DXT2: " +  hex(DXT2) + "  " + str(DXT2) )
	bs.seek(29, NOESEEK_REL)
	print("cur_offset1_2: " + hex(bs.tell()))
	bs.seek(4, NOESEEK_REL)

	tex1 = readtex(bs, t2_width, t2_height, DXT2, FileName)
	tmp_tex.append( tex1)
	
	
	bs.seek(FileSize + 8, NOESEEK_ABS)
	print("go to file end mip, offset: " + hex(bs.tell()))	
	
	print("go to top mip")
	val2 = fnd4byte(bs, 491489187)
	print("magic model start offset : " + hex(val2))
	dtest = 0
	if(val2 > 0):
		bs.seek(val2, NOESEEK_ABS)
		print("")
		print("cur_offset3: " + hex(bs.tell()))

		loc_mgic2 = bs.readUInt()
		print("	magic model vlaue: " + hex(loc_mgic2))
		#ResourceIdentifier = bs.readUInt()
		MipFileSize = bs.readUInt()
		MipFileNameSize = bs.readUInt()
		
		#print("ResourceIdentifier: " + hex(ResourceIdentifier) + "  " + str(ResourceIdentifier) )
		print("	MIP FileSize: " +  hex(MipFileSize) + "  " + str(MipFileSize) )
		start_mip_offset = bs.tell()
		
		print("	MIP FileNameSize: " +  hex(MipFileNameSize) + "  " + str(MipFileNameSize) )
		MipFileName = NoeBitStream(bs.readBytes(MipFileNameSize)).readString()
		print("	MIP	FileName: " +  MipFileName )

		bs.seek(18, NOESEEK_REL)
		end_mip_offset = bs.tell()
		print("	cur_offset4: " + hex(bs.tell()))
		tex1 = readtex(bs, t_width, t_height, DXT, FileName)
		tmp_tex.append( tex1)
		
		
		#datasize = MipFileSize - (end_mip_offset - start_mip_offset)
		#print("	datasize: " + hex(datasize) + " " + str(datasize))
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	max_value = 0
	max_index = 0
	for i in range (0,len(tmp_tex)):
		tmp_value = tmp_tex[i].width * tmp_tex[i].height
		if tmp_value >= max_value:
			max_value = tmp_value
			max_index = i
			
	print("		current width " + hex(tmp_tex[max_index].width) + " "+ str(tmp_tex[max_index].width))
	print("		current height " + hex(tmp_tex[max_index].height) + " " +str(tmp_tex[max_index].height))
	if(tmp_tex[max_index].width != t_width) or (tmp_tex[max_index].height != t_height):
		print(	"		ERROR: UNCORRECT SIZE!!!")
	
	texList.append(tmp_tex[max_index].texture)
					
					
					
					
					
					















	'''

	bs.seek(FileSize + 8, NOESEEK_ABS)
	print("go to file end mip, offset: " + hex(bs.tell()))	
	
	print("go to top mip")
	val2 = fnd4byte(bs, 491489187)
	print("magic model start offset : " + hex(val2))
	dtest = 0
	if(val2 > 0):
		bs.seek(val2, NOESEEK_ABS)
		print("")
		print("cur_offset3: " + hex(bs.tell()))

		loc_mgic2 = bs.readUInt()
		print("	magic model vlaue: " + hex(loc_mgic2))
		#ResourceIdentifier = bs.readUInt()
		MipFileSize = bs.readUInt()
		MipFileNameSize = bs.readUInt()
		
		#print("ResourceIdentifier: " + hex(ResourceIdentifier) + "  " + str(ResourceIdentifier) )
		print("	MIP FileSize: " +  hex(MipFileSize) + "  " + str(MipFileSize) )
		start_mip_offset = bs.tell()
		
		print("	MIP FileNameSize: " +  hex(MipFileNameSize) + "  " + str(MipFileNameSize) )
		MipFileName = NoeBitStream(bs.readBytes(MipFileNameSize)).readString()
		print("	MIP	FileName: " +  MipFileName )

		bs.seek(18, NOESEEK_REL)
		end_mip_offset = bs.tell()
		print("	cur_offset4: " + hex(bs.tell()))
		#datasize = MipFileSize - (end_mip_offset - start_mip_offset)
		#print("	datasize: " + hex(datasize) + " " + str(datasize))
		
		
		texFmt = 0
		datasize2 = 0
		
		tex1 = 0
		if(DXT == 0): 
			texFmt = noesis.NOESISTEX_DXT0
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize2)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)
		if(DXT == 1): 
			texFmt = noesis.NOESISTEX_DXT0
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize2)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)
		if(DXT == 2): 
			texFmt = noesis.NOESISTEX_DXT1
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize2)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)
		if(DXT == 3): 
			texFmt = noesis.NOESISTEX_DXT1
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize2)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)
		if(DXT == 4): 
			texFmt = noesis.NOESISTEX_DXT3
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize2)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)
		if(DXT == 5): 
			texFmt = noesis.NOESISTEX_DXT5
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize5)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)
		if(DXT == 6): 
			texFmt = noesis.NOESISTEX_DXT6
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize5)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)			
		if(DXT == 7): 
			texFmt = noesis.NOESISTEX_DXT0
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize5)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)
		if(DXT == 12): 
			texFmt = noesis.NOESISTEX_DXT5
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize5)
			tex1 = (NoeTexture(FileName, t_width, t_height, ddsData, texFmt))
			#texList.append(tex1)
			
			
		if(DXT == 9): 

			texFmt = noesis.NOESISTEX_DXT5
			datasize2 = t_width * t_height // 2 *2
			ddsData = bs.readBytes(datasize2)
			ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height), noesis.FOURCC_BC7)
			texFmt = noesis.NOESISTEX_RGBA32
			tex1 = (NoeTexture(FileName, t_width, int(t_height), ddsData, texFmt))
			#texList.append(tex1)

		if(DXT == 8): 

			texFmt = noesis.NOESISTEX_DXT5
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize2)
			ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height/2), noesis.FOURCC_BC7)
			texFmt = noesis.NOESISTEX_RGBA32
			tex1 = (NoeTexture(FileName, t_width, int(t_height/2), ddsData, texFmt))
			#texList.append(tex1)
		if(DXT == 16): 

			texFmt = noesis.NOESISTEX_DXT5
			datasize2 = t_width * t_height // 2 
			ddsData = bs.readBytes(datasize2)
			ddsData = rapi.imageDecodeDXT(ddsData, t_width, int(t_height/2), noesis.FOURCC_BC7)
			texFmt = noesis.NOESISTEX_RGBA32
			tex1 = (NoeTexture(FileName, t_width, int(t_height/2), ddsData, texFmt))
			#texList.append(tex1)
		texList.append(tex1)
		texList.append(tex1)				
		#FOURCC_ATI2
		#FOURCC_BC5
		#FOURCC_ATI1
		#FOURCC_DXT1NORMAL
		#FOURCC_DXT1
	'''
			

	

		
		


		

	
	return 1
	
