have_pyglet = False

try:
	from pyglet import clock, window
	from pyglet.gl import *
	from pyglet.image import *
	have_pyglet = True
except:
	pass

import sys, os
sys.path.append(os.path.realpath(os.path.dirname(sys.argv[0]))+"/../Common")
from Struct import Struct
import struct
import pywii as wii

def LZ77Decompress(data):
	inp = 0
	dlen = len(data)
	data += '\0' * 16
	
	ret = []
	
	while inp < dlen:
		bitmask = ord(data[inp])
		inp += 1
		
		for i in xrange(8):
			if bitmask & 0x80:
				rep = ord(data[inp])
				repLength = (rep >> 4) + 3
				inp += 1
				repOff = ord(data[inp]) | ((rep & 0x0F) << 8)
				inp += 1
				
				assert repOff <= len(ret)
				
				while repLength > 0:
					ret.append(ret[-repOff - 1])
					repLength -= 1
			else:
				ret.append(data[inp])
				inp += 1
			
			bitmask <<= 1
	
	return ''.join(ret)

class U8(object):
	class U8Header(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.Tag = Struct.string(4)
			self.RootNode = Struct.uint32
			self.HeaderSize = Struct.uint32
			self.DataOffset = Struct.uint32
			self.Zeroes = Struct.uint8[0x10]
	
	class U8Node(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.Type = Struct.uint16
			self.NameOffset = Struct.uint16
			self.DataOffset = Struct.uint32
			self.Size = Struct.uint32
	
	def __init__(self, data=None):
		self.Files = {}
		
		if data != None:
			self.Unpack(data)
	
	def Unpack(self, data):
		pos = 0
		u8 = self.U8Header()
		u8.unpack(data[pos:pos+len(u8)])
		pos += len(u8)
		
		assert u8.Tag == 'U\xAA8-'
		pos += u8.RootNode - 0x20
		
		root = self.U8Node()
		root.unpack(data[pos:pos+len(root)])
		pos += len(root)
		
		children = []
		for i in xrange(root.Size - 1):
			child = self.U8Node()
			child.unpack(data[pos:pos+len(child)])
			pos += len(child)
			children.append(child)
		
		stringTable = data[pos:pos + u8.DataOffset - len(u8) - root.Size * len(root)]
		pos += len(stringTable)
		
		currentOffset = u8.DataOffset
		
		path = ['.']
		pathDepth = [root.Size - 1]
		for offset,child in enumerate(children):
			name = stringTable[child.NameOffset:].split('\0', 1)[0]
			if child.Type == 0x0100:
				path.append(name)
				pathDepth.append(child.Size-offset-1)
			elif child.Type == 0:
				name = '/'.join(path + [name])
				
				if currentOffset < child.DataOffset:
					diff = child.DataOffset - currentOffset
					assert diff <= 32
					
					pos += diff
					currentOffset += diff
				
				currentOffset += child.Size
				
				self.Files[name.lower()] = data[pos:pos+child.Size]
				pos += child.Size
			
			pathDepth[-1] -= 1
			if pathDepth[-1] == 0:
				path = path[:-1]
				pathDepth = pathDepth[:-1]

class IMD5Header(Struct):
	__endian__ = Struct.BE
	def __format__(self):
		self.Tag = Struct.string(4)
		self.Size = Struct.uint32
		self.Zeroes = Struct.uint8[8]
		self.MD5 = Struct.uint8[0x10]

def IMD5(data):
	imd5 = IMD5Header()
	imd5.unpack(data[:len(imd5)])
	assert imd5.Tag == 'IMD5'
	pos = len(imd5)
	
	if data[pos:pos+4] == 'LZ77':
		return LZ77Decompress(data[pos+8:])
	else:
		return data[pos:]

class TPL(object):
	class TPLHeader(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.Magic = Struct.string(4)
			self.Count = Struct.uint32
			self.Size = Struct.uint32
	
	class TexOffsets(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.HeaderOff = Struct.uint32
			self.PaletteOff = Struct.uint32
	
	class TexHeader(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.Size = Struct.uint16[2]
			self.Format = Struct.uint32
			self.DataOff = Struct.uint32
			self.Wrap = Struct.uint32[2]
			self.Filter = Struct.uint32[2]
			self.LODBias = Struct.float
			self.EdgeLOD = Struct.uint8
			self.LOD = Struct.uint8[2]
			self.Unpacked = Struct.uint8
	
	class PalHeader(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.Count = Struct.uint16
			self.Unpacked = Struct.uint8
			self.Pad = Struct.uint8
			self.Format = Struct.uint32
			self.DataOff = Struct.uint32
	
	def __init__(self, data=None):
		self.Textures = []
		
		if data != None:
			self.Unpack(data)
	
	def Unpack(self, data):
		header = self.TPLHeader()
		header.unpack(data[:len(header)])
		pos = len(header)
		
		assert header.Magic == '\x00\x20\xAF\x30'
		assert header.Size == 0xc
		
		for i in xrange(header.Count):
			offs = self.TexOffsets()
			offs.unpack(data[pos:pos+len(offs)])
			pos += len(offs)
			
			self.Textures.append(self.ParseTexture(data, offs))
	
	def ParseTexture(self, data, offs):
		texHeader = self.TexHeader()
		texHeader.unpack(data[offs.HeaderOff:offs.HeaderOff+len(texHeader)])
		format = texHeader.Format
		self.format = format
		rgba = None
		if format == 0:
			rgba = self.I4(data[texHeader.DataOff:], texHeader.Size)
		elif format == 1:
			rgba = self.I8(data[texHeader.DataOff:], texHeader.Size)
		elif format == 2:
			rgba = self.IA4(data[texHeader.DataOff:], texHeader.Size)
		elif format == 3:
			rgba = self.IA8(data[texHeader.DataOff:], texHeader.Size)
		elif format == 4:
			rgba = self.RGB565(data[texHeader.DataOff:], texHeader.Size)
		elif format == 5:
			rgba = self.RGB5A3(data[texHeader.DataOff:], texHeader.Size)
		elif format == 6:
			rgba = self.RGBA8(data[texHeader.DataOff:], texHeader.Size)
		elif format == 14:
			rgba = self.S3TC(data[texHeader.DataOff:], texHeader.Size)
		else:
			print 'Unknown texture format', format
		
		if rgba == None:
			rgba = '\0\0\0\0' * texHeader.Size[0] * texHeader.Size[1]
		
		image = ImageData(texHeader.Size[1], texHeader.Size[0], 'RGBA', rgba)
		print format
		return image
	
	def I4(self, data, (y, x)):
		out = [0 for i in xrange(x * y)]
		outp = 0
		inp = 0
		for i in xrange(0, y, 8):
			for j in xrange(0, x, 8):
				ofs = 0
				for k in xrange(8):
					off = min(x - j, 8)
					for sub in xrange(0, off, 2):
						texel = ord(data[inp])
						high, low = texel >> 4, texel & 0xF
						if (outp + ofs + sub) < (x*y):
							out[outp + ofs + sub] = (high << 4) | (high << 20) | (high << 12) | 0xFF<<24
						
						if sub + 1 < off:
							if (outp + ofs + sub + 1) < (x*y):
								out[outp + ofs + sub + 1] = (low << 4) | (low << 20) | (low << 12) | 0xFF<<24
						
						inp += 1
					
					ofs += x
					inp += (8 - off) / 2
				outp += off
			outp += x * 7
		
		return ''.join(Struct.uint32(p) for p in out)
	
	def I8(self, data, (y, x)):
		out = [0 for i in xrange(x * y*2)]
		outp = 0
		inp = 0
		for i in xrange(0, y, 4):
			for j in xrange(0, x, 4):
				ofs = 0
				for k in xrange(4):
					off = min(x - j, 4)
					for sub in xrange(off):
						texel = ord(data[inp])
						out[outp + ofs + sub] = (texel << 24) | (texel << 16) | (texel << 8) | 0xFF
						inp += 1
					
					ofs += x
					inp += 4 - off * 2
				outp += off
			outp += x * 3
		
		return ''.join(Struct.uint32(p) for p in out)
	
	def IA4(self, data, (y, x)):
		out = [0 for i in xrange(x * y)]
		outp = 0
		inp = 0
		for i in xrange(0, y, 4):
			for j in xrange(0, x, 8):
				ofs = 0
				for k in xrange(4):
					off = min(x - j, 8)
					for sub in xrange(off):
						texel = ord(data[inp])
						alpha, inte = texel >> 4, texel & 0xF
						if (outp + ofs + sub) < (x*y):
							out[outp + ofs + sub] = (inte << 4) | (inte << 12) | (inte << 20) | (alpha << 28)
						inp += 1
					
					ofs += x
					inp += 8 - off
				outp += off
			outp += x * 3
		
		return ''.join(Struct.uint32(p) for p in out)
	
	def IA8(self, data, (y, x)):
		out = [0 for i in xrange(x * y)]
		outp = 0
		inp = 0
		for i in xrange(0, y, 4):
			for j in xrange(0, x, 4):
				ofs = 0
				for k in xrange(4):
					off = min(x - j, 4)
					for sub in xrange(off):
						if (outp + ofs + sub) < (x*y):
							texel = Struct.uint16(data[inp:inp + 2], endian='>')
							p  = (texel & 0xFF)
							p |= (texel & 0xFF) << 8
							p |= (texel & 0xFF) << 16
							p |= (texel >> 8)   << 24
							out[outp + ofs + sub] = p
						inp += 2
					
					ofs += x
					inp += (4 - off) * 2
				outp += off
			outp += x * 3
		
		return ''.join(Struct.uint32(p) for p in out)
	
	def RGB565(self, data, (y, x)):
		out = [0 for i in xrange(x * y)]
		outp = 0
		inp = 0
		for i in xrange(0, y, 4):
			for j in xrange(0, x, 4):
				ofs = 0
				for k in xrange(4):
					off = min(x - j, 4)
					for sub in xrange(off):
						if (outp + ofs + sub) < (x*y):
							texel = Struct.uint16(data[inp:inp + 2], endian='>')
							p  = ((texel >> 11) & 0x1F) << 3
							p |= ((texel >> 5) & 0x3F) << 10
							p |= ( texel       & 0x1F) << 19
							p |= 0xFF<<24
							out[outp + ofs + sub] = p
						inp += 2
					
					ofs += x
					inp += (4 - off) * 2
				outp += off
			outp += x * 3
		
		return ''.join(Struct.uint32(p) for p in out)

	def RGB5A3(self, data, (y, x)):
		out = [0 for i in xrange(x * y)]
		outp = 0
		inp = 0
		for i in xrange(0, y, 4):
			for j in xrange(0, x, 4):
				ofs = 0
				for k in xrange(4):
					off = min(x - j, 4)
					for sub in xrange(off):
						texel = Struct.uint16(data[inp:inp + 2], endian='>')
						if texel & 0x8000:
							p  = ((texel >> 10) & 0x1F) << 3
							p |= ((texel >> 5) & 0x1F) << 11
							p |= ( texel       & 0x1F) << 19
							p |= 0xFF<<24
						else:
							p  = ((texel >> 12) & 0x07) << 29
							p |= ((texel >>  8) & 0x0F) << 4
							p |= ((texel >>  4) & 0x0F) << 12
							p |=  (texel        & 0x0F) << 20
						if (outp + ofs + sub) < (x*y):
							out[outp + ofs + sub] = p
						inp += 2
					
					ofs += x
					inp += (4 - off) * 2
				outp += off
			outp += x * 3
		
		return ''.join(Struct.uint32(p) for p in out)

	def RGBA8(self, data, (y, x)):
		out = [0 for i in xrange(x * y)]
		outp = 0
		inp = 0
		for i in xrange(0, y, 4):
			for j in xrange(0, x, 4):
				ofs = 0
				for k in xrange(4):
					off = min(x - j, 4)
					for sub in xrange(off):
						texel = Struct.uint16(data[inp:inp + 2], endian='>')<<16
						texel |= Struct.uint16(data[inp+32:inp + 34], endian='>')
						if (outp + ofs + sub) < (x*y):
							out[outp + ofs + sub] = texel&0xff000000 | ((texel>>16)&0xff) | (texel&0xff00) | ((texel<<16)&0xff0000)
						inp += 2
					
					ofs += x
					inp += (4 - off) * 2
				outp += off
				inp += 32
			outp += x * 3
		
		return ''.join(Struct.uint32(p) for p in out)

	def unpack_rgb565(self,texel):
		b = (texel&0x1f)<<3
		g = ((texel>>5)&0x3f)<<2
		r = ((texel>>11)&0x1f)<<3
		b |= b>>5
		g |= g>>6
		r |= r>>5
		return (0xff<<24) | (b<<16) | (g<<8) | r
	def icolor(self,a,b,fa,fb,fc):
		c = 0
		for i in xrange(0,32,8):
			xa = (a>>i)&0xff
			xb = (b>>i)&0xff
			xc = min(255,max(0,int((xa*fa + xb*fb)/fc)))
			c |= xc<<i
		return c
	
	def S3TC(self, data, (y, x)):
		out = [0 for i in xrange(x * y)]
		TILE_WIDTH = 8
		TILE_HEIGHT = 8
		inp = 0
		outp = 0
		for i in xrange(0, y, TILE_HEIGHT):
			for j in xrange(0, x, TILE_WIDTH):
				maxw = min(x - j,TILE_WIDTH)
				for k in xrange(2):
					for l in xrange(2):
						rgb = [0,0,0,0]
						texel1 = Struct.uint16(data[inp:inp + 2], endian='>')
						texel2 = Struct.uint16(data[inp + 2:inp + 4], endian='>')
						rgb[0] = self.unpack_rgb565(texel1)
						rgb[1] = self.unpack_rgb565(texel2)
						
						if texel1 > texel2:
							rgb[2] = self.icolor (rgb[0], rgb[1], 2, 1, 3) | 0xff000000
							rgb[3] = self.icolor (rgb[1], rgb[0], 2, 1, 3) | 0xff000000
						else:
							rgb[2] = self.icolor (rgb[0], rgb[1], 0.5, 0.5, 1) | 0xff000000
							rgb[3] = 0
						
						# color selection (00, 01, 10, 11)
						cm = map(ord,data[inp+4:inp+8])
						ofs = l*4
						for n in range(4):
							if (ofs + outp)<(x*y):
								# one row (4 texels)
								if maxw > (0 + l*4):
									out[ofs + 0 + outp] = rgb[(cm[n] & 0xc0) >> 6];
								if maxw > (1 + l*4):
									out[ofs + 1 + outp] = rgb[(cm[n] & 0x30) >> 4];
								if maxw > (2 + l*4):
									out[ofs + 2 + outp] = rgb[(cm[n] & 0x0c) >> 2];
								if maxw > (3 + l*4):
									out[ofs + 3 + outp] = rgb[(cm[n] & 0x03) >> 0];
							ofs += x
						inp += 8
					outp += x * 4
				outp += maxw - x * 8
			outp += x * (TILE_HEIGHT - 1)
		
		return ''.join(Struct.uint32(p) for p in out)

class Object(object):
	def __init__(self, name):
		self.Frame = 0
		self.Name = name
		self.Alpha = 255
		self.Animations = 0
	def __str__(self):
		return self.Name
	
class Pane(Object):
	def __init__(self, name, flags=0x104, alpha=255, coords=[0,0,0,0,0,0,1,1,0,0]):
		Object.__init__(self, name)
		self.Flags = flags
		self.Alpha = alpha
		self.Coords = list(coords)
		self.Children = []
		self.Enabled = True
		
	def getX(self): return self.Coords[0]
	def setX(self,v): self.Coords[0] = v
	def getY(self): return self.Coords[1]
	def setY(self,v): self.Coords[1] = v
	def getMagX(self): return self.Coords[6]
	def setMagX(self,v): self.Coords[6] = v
	def getMagY(self): return self.Coords[7]
	def setMagY(self,v): self.Coords[7] = v
	def getW(self): return self.Coords[8]
	def setW(self,v): self.Coords[8] = v
	def getH(self): return self.Coords[9]
	def setH(self,v): self.Coords[9] = v
	def getRot(self): return self.Coords[5]
	def setRot(self,v): self.Coords[5] = v
	
	X = property(getX,setX)
	Y = property(getY,setY)
	MagX = property(getMagX,setMagX)
	MagY = property(getMagY,setMagY)
	Width = property(getW,setW)
	Height = property(getH,setH)
	Rot = property(getRot,setRot)
	
	def Add(self, child):
		self.Children.append(child)
	
	def AnimDone(self):
		if not Object.AnimDone(self):
			return False
		
		for child in self.Children:
			if not child.AnimDone():
				return False
		
		return True

class Picture(Pane):
	def __init__(self, name, flags=0x504, alpha=255, coords=[0,0,0,0,0,0,1,1,0,0], unk=[0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff], mat=0, flags2=0x100, matcoord=[(0,0),(1,0),(0,1),(1,1)]):
		Pane.__init__(self, name, flags, alpha, coords)
		self.Unk = unk
		self.Material = mat
		self.Flags2 = flags2
		self.MaterialCoords = list(matcoord)
		
class ItemList(object):
	HDRLEN=4
	LSIZE=4
	OFFSET=0
	IS_ATOM=True
	def __init__(self, data=None):
		self.Items = []
		if data is not None:
			self.unpack(data)
	
	def add(self,n):
		self.Items.append(n)
	
	def unpack(self, data):
		pos = 0
		if self.IS_ATOM:
			pos = 8
		count = self.__unpkcnt__(data[pos:])
		pos = self.__getlistoff__(data[pos:])
		for i in xrange(count):
			off = Struct.uint32(data[pos:pos+4], endian='>') + self.OFFSET
			if i == (count-1):
				next = len(data)
			else:
				next = Struct.uint32(data[pos+self.LSIZE:pos+self.LSIZE+4], endian='>') + self.OFFSET
			pos += self.LSIZE
			self.unpack_item(i, data[off:next])
		# sanity check
		#dp = self.pack()
		#assert dp == data
	
	def pack(self,extra=None):
		
		extradata = ""
		if extra is not None:
			extradata = extra.pack()
		
		data = ""
		
		offsets = []
		
		for n,i in enumerate(self.Items):
			offsets.append(len(data))
			data += self.pack_item(n,i)
		
		listlen = len(self.Items) * self.LSIZE
		
		head = self.__mkheader__()
		outdata = ""
		if self.IS_ATOM:
			outdata += self.FOURCC + Struct.uint32((len(extradata) + listlen + len(data) + 8 + len(head) + 3) &(~3), endian='>')
		outdata += head
		
		dataoff = len(outdata) + listlen - self.OFFSET
		assert dataoff >= 0
		
		for n in offsets:
			outdata += Struct.uint32(n + dataoff, endian='>')
			if self.LSIZE > 4:
				outdata += (self.LSIZE-4)*"\x00"
		
		outdata += data
		outdata += extradata
		
		if len(outdata)%4 != 0:
			outdata += (4-len(outdata)%4)*"\x00"
		
		return outdata
	
	def __mkheader__(self):
		return Struct.uint16(len(self.Items), endian='>') + "\x00\x00"
	
	def __unpkcnt__(self, data):
		return Struct.uint16(data[0:2], endian='>')
	
	def __getlistoff__(self, data):
		off=self.HDRLEN
		if self.IS_ATOM:
			off += 8
		return off
	
	def __getitem__(self, n):
		return self.Items[n]

	def __len__(self):
		return len(self.Items)

class StdAtom(Struct):
	__endian__ = Struct.BE
	def __format__(self):
		self.FourCC = Struct.string(4)
		self.Size = Struct.uint32
	def pack(self):
		self.FourCC = self.FOURCC
		self.Size = len(self)
		return Struct.pack(self)

class Brlyt(object):
	class BrlytHeader(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.Magic = Struct.string(4)
			self.Unk = Struct.uint32
			self.Size = Struct.uint32
			self.UnkCount = Struct.uint16
			self.AtomCount = Struct.uint16
	
	class BrlytLYT1(StdAtom):
		FOURCC = "lyt1"
		def __format__(self):
			StdAtom.__format__(self)
			self.Flag = Struct.uint8
			self.pad = Struct.uint8[3]
			self.Width = Struct.float
			self.Height = Struct.float
	
	class BrlytTexture(object):
		def __init__(self, name, texture=None):
			self.Name = name
			self.Texture = texture
			self.GLTexture = None
		def create_texture(self):
			self.GLTexture = self.Texture.create_texture(Texture)
			
	class BrlytTXL1(ItemList):
		LSIZE = 8
		OFFSET = 12
		FOURCC = "txl1"
		def __init__(self, archive=None, data=None):
			self.Archive = archive
			ItemList.__init__(self, data)
		
		def unpack_item(self, i, data):
			fn = data.split('\0', 1)[0]
			print fn
			tex = TPL(self.Archive.Files['./arc/timg/' + fn.lower()]).Textures[0]
			self.Items.append(Brlyt.BrlytTexture(fn, tex))
		def pack_item(self, i, item):
			return item.Name + "\0"
	
	class BrlytMAT1(ItemList):
		LSIZE = 4
		OFFSET = 0
		FOURCC = "mat1"
		def __init__(self, data=None):
			ItemList.__init__(self, data)
		
		def unpack_item(self, num, data):
			mtl = Brlyt.BrlytMaterial()
			mtl.unpack(data)
			self.Items.append(mtl)

		def pack_item(self, i, item):
			return item.pack()
	
	class BrlytMaterialFlags(object):
		def __init__(self,value=None):
			if value is not None:
				self.unpack(value)
		def unpack(self,value):
			self.value = value
			self.NumTextures = value & 15
			self.NumCoords = (value>>4) & 15
			self.m_2 = (value>>8) & 15
			self.m_4 = bool((value>>12) & 1)
			self.m_6 = (value>>13) & 3
			self.m_5 = (value>>15) & 7
			self.m_3 = (value>>18) & 31
			self.m_9 = bool((value>>23) & 1)
			self.m_10 = bool((value>>24) & 1)
			self.m_7 = bool((value>>25) & 1)
			self.m_8 = bool((value>>27) & 1)
		
		def show(self):
			print "Flags: %08x"%self.value
			print "ReserveGXMem("
			print " r4        =",self.NumTextures
			print " r5        =",self.NumCoords
			print " r6        =",self.m_2
			print " r7        =",self.m_3
			print " r8        =",self.m_4
			print " r9        =",self.m_5
			print " r10       =",self.m_6
			print " 0x8(%sp)  =",self.m_7
			print " 0xC(%sp)  =",self.m_8
			print " 0x10(%sp) =",self.m_9
			print " 0x14(%sp) =",self.m_10
			print ")"
		
		def pack(self):
			val = 0
			val |= self.NumTextures
			val |= self.NumCoords << 4
			val |= self.m_2 << 8
			val |= self.m_4 << 12
			val |= self.m_6 << 13
			val |= self.m_5 << 15
			val |= self.m_3 << 18
			val |= self.m_9 << 23
			val |= self.m_10 << 24
			val |= self.m_7 << 25
			val |= self.m_8 << 27
			return val
	
	class BrlytMatHeader(Struct):
		__endian__ = Struct.BE
		
		def __format__(self):
			self.Name = Struct.string(0x14)
			self.Color1 = Struct.uint16[4]
			self.Color2 = Struct.uint16[4]
			self.Color3 = Struct.uint16[4]
			self.Blah = Struct.uint32[4]
			self.Flags = Struct.uint32
		
			# 0-3 num 0-8
			# 4-7 num 0-10
			# 8-11 num 0-8
			# 12 bool
			# 13-14 num 0-3
			# 15-17 num 0-4
			# 18-22 num 0-16
			# 23 bool
			# 24 bool
			# 25 bool a
			# 27 bool
			
			
			# if 25, xtra word
			# if 27, xtra word
			# if 12, xtra word
			# 13-14 * 0x14
			# 15-17 * 4
			# 18-22 * 16
			# if 23, xtra word
			# if 24, xtra word
	
	class BrlytMaterial(object):
		
		def __init__(self, name=None):
			if name is not None:
				self.Name = name
			self.Color1 = [0,0,0,0]
			self.Color2 = [255,255,255,255]
			self.Color3 = [255,255,255,255]
			self.Blah = [0xffffffff,0xffffffff,0xffffffff,0xffffffff]
			self.Textures = []
			self.TextureCoords = []
			self.SthB = []
			self.SthI = None
			self.SthJ = None
			self.SthC = None
			self.SthD = []
			self.SthE = []
			self.SthF = []
			self.SthG = 0x77000000
			self.SthH = None

		def unpack(self, data):
			wii.chexdump(data)
			hdr = Brlyt.BrlytMatHeader()
			hdr.unpack(data)
			self.FlagData = Brlyt.BrlytMaterialFlags(hdr.Flags)
			self.FlagData.show()
			
			self.Name = hdr.Name.split("\0",1)[0]
			self.Color1 = hdr.Color1
			self.Color2 = hdr.Color2
			self.Color3 = hdr.Color3
			self.Blah = hdr.Blah
			
			ptr = 0x40
			
			self.Textures = []
			self.TextureCoords = []
			self.SthB = []
			self.SthI = None
			self.SthJ = None
			self.SthC = None
			self.SthD = []
			self.SthE = []
			self.SthF = []
			self.SthG = None
			self.SthH = None
			
			for i in range(self.FlagData.NumTextures):
				texid = Struct.uint16(data[ptr:ptr+2], endian='>')
				texcs = Struct.uint8(data[ptr+2], endian='>')
				texct = Struct.uint8(data[ptr+3], endian='>')
				print "  * Texture: %04x %d %d"%(texid,texcs,texct)
				self.Textures.append((texid,texcs,texct))
				ptr += 4
			for i in range(self.FlagData.NumCoords):
				dat = []
				for j in range(5):
					dat.append(Struct.float(data[ptr+j*4:ptr+j*4+4], endian='>'))
				print "  * Coords: [",', '.join(["%f"%x for x in dat]),"]"
				ptr += 0x14
				self.TextureCoords.append(dat)
			for i in range(self.FlagData.m_2):
				dat = Struct.uint32(data[ptr:ptr+4], endian='>')
				self.SthB.append(dat)
				print "  * SthB: %08x"%dat
				ptr += 0x04
			if self.FlagData.m_7:
				self.SthI = Struct.uint32(data[ptr:ptr+4], endian='>')
				print "  SthI: %08x"%self.SthI
				ptr += 0x04
			if self.FlagData.m_8:
				self.SthJ = Struct.uint32(data[ptr:ptr+4], endian='>')
				print "  SthJ: %08x"%self.SthJ
				ptr += 0x04
			if self.FlagData.m_4:
				self.SthC = Struct.uint32(data[ptr:ptr+4], endian='>')
				print "  SthC: %08x"%self.SthC
				ptr += 0x04
			for i in range(self.FlagData.m_6):
				dat = []
				for j in range(5):
					dat.append(Struct.float(data[ptr+j*4:ptr+j*4+4], endian='>'))
				self.SthD.append(dat)
				print "  * SthD: [",', '.join(["%f"%x for x in dat]),"]"
				ptr += 0x14
			for i in range(self.FlagData.m_5):
				dat = Struct.uint32(data[ptr:ptr+4], endian='>')
				self.SthE.append(dat)
				print "  * SthE: %08x"%dat
				ptr += 0x04
			for i in range(self.FlagData.m_3):
				dat = []
				for j in range(4):
					dat.append(Struct.uint32(data[ptr+j*4:ptr+j*4+4], endian='>'))
				self.SthF.append(dat)
				print "  * SthF: [",', '.join(["%08x"%x for x in dat]),"]"
				ptr += 0x10
			if self.FlagData.m_9:
				dat = Struct.uint32(data[ptr:ptr+4], endian='>')
				self.SthG = dat
				print "  SthG: %08x"%dat
				ptr += 0x04
			if self.FlagData.m_10:
				dat = Struct.uint32(data[ptr:ptr+4], endian='>')
				self.SthH = dat
				print "  SthH: %08x"%dat
				ptr += 0x04
			
			#assert ptr == len(data)
			
		def pack(self):
			
			self.FlagData = Brlyt.BrlytMaterialFlags()
			
			self.FlagData.NumTextures = len(self.Textures)
			self.FlagData.NumCoords = len(self.TextureCoords)
			self.FlagData.m_2 = len(self.SthB)
			self.FlagData.m_7 = self.SthI is not None
			self.FlagData.m_8 = self.SthJ is not None
			self.FlagData.m_4 = self.SthC is not None
			self.FlagData.m_6 = len(self.SthD)
			self.FlagData.m_5 = len(self.SthE)
			self.FlagData.m_3 = len(self.SthF)
			self.FlagData.m_9 = self.SthG is not None
			self.FlagData.m_10 = self.SthH is not None
			
			self.Flags = self.FlagData.pack()

			hdr = Brlyt.BrlytMatHeader()

			hdr.Name = self.Name + "\x00"*(0x14-len(self.Name))
			hdr.Color1 = self.Color1
			hdr.Color2 = self.Color2
			hdr.Color3 = self.Color3
			hdr.Blah = self.Blah
			hdr.Flags = self.Flags

			data = hdr.pack()
			
			for i in self.Textures:
				data += Struct.uint16(i[0], endian='>')
				data += Struct.uint8(i[1], endian='>')
				data += Struct.uint8(i[2], endian='>')
			for i in self.TextureCoords:
				for j in i:
					data += Struct.float(j, endian='>')
			for i in self.SthB:
				data += Struct.uint32(i, endian='>')
			if self.SthI is not None:
				data += Struct.uint32(self.SthI, endian='>')
			if self.SthJ is not None:
				data += Struct.uint32(self.SthJ, endian='>')
			if self.SthC is not None:
				data += Struct.uint32(self.SthC, endian='>')
			for i in self.SthD:
				for j in i:
					data += Struct.float(j, endian='>')
			for i in self.SthE:
				data += Struct.uint32(i, endian='>')
			for i in self.SthF:
				for j in i:
					data += Struct.uint32(j, endian='>')
			if self.SthG is not None:
				data += Struct.uint32(self.SthG, endian='>')
			if self.SthH is not None:
				data += Struct.uint32(self.SthH, endian='>')
			return data
		
	class BrlytPAN1(StdAtom):
		FOURCC = "pan1"
		def __format__(self):
			StdAtom.__format__(self)
			self.Flags = Struct.uint16
			self.Alpha = Struct.uint16
			self.Name = Struct.string(0x18)
			self.Coords = Struct.float[10]
		
	class BrlytPIC1(BrlytPAN1):
		FOURCC = "pic1"
		def __format__(self):
			Brlyt.BrlytPAN1.__format__(self)
			self.unk = Struct.uint8[16]
			self.Material = Struct.uint16
			self.Flags2 = Struct.uint16
			self.MaterialCoords = Struct.float[8]
			
	def __init__(self, archive, data, renderer):
		self.Archive = archive
		self.Textures = Brlyt.BrlytTXL1()
		self.Materials = Brlyt.BrlytMAT1()
		self.LastPic = None
		self.RootPane = None
		self.RootPaneName = None
		self.Objects = {}
		self.PanePath = []
		self.PaneId = 0
		self.Language = "ENG"
		self.Renderer = renderer
		
		if data != None:
			self.Unpack(data)
	
	def Unpack(self, data):
		pos = 0
		header = self.BrlytHeader()
		header.unpack(data[:len(header)])
		print "BRLYT header:"
		wii.chexdump(data[:len(header)])
		print " unk1: %08x"%header.Unk
		print " unkc: %08x"%header.UnkCount
		pos += len(header)
		
		print " %d atoms"%header.AtomCount
		
		assert header.Magic == 'RLYT'
		
		for i in xrange(header.AtomCount):
			atom = StdAtom()
			atom.unpack(data[pos:pos+len(atom)])
			
			atomdata = data[pos:pos+atom.Size]
			if atom.FourCC == 'txl1':
				self.TXL1(atomdata)
			elif atom.FourCC == 'lyt1':
				self.LYT1(atomdata)
			elif atom.FourCC == 'mat1':
				self.MAT1(atomdata)
			elif atom.FourCC == 'pan1':
				self.PAN1(atomdata)
			elif atom.FourCC == 'pas1':
				self.PAS1(atomdata)
			elif atom.FourCC == 'pae1':
				self.PAE1(atomdata)
			elif atom.FourCC == 'pic1':
				self.PIC1(atomdata)
			elif atom.FourCC == "grp1":
				self.GRP1(atomdata)
			else:
				print "Unknown FOURCC:",atom.FourCC
				wii.chexdump(atomdata)
			
			pos += atom.Size
	
	def _PackObject(self, object):
		atoms = 0
		if isinstance(object,Pane):
			atoms += 1
			if isinstance(object,Picture):
				atom = Brlyt.BrlytPIC1()
			else:
				atom = Brlyt.BrlytPAN1()
			atom.Name = object.Name + "\x00"*(0x18-len(object.Name))
			atom.Alpha = int(object.Alpha * 256)
			atom.Flags = object.Flags
			atom.Coords = object.Coords
			if isinstance(object,Picture):
				atom.Flags2 = object.Flags2
				atom.Material = object.Material
				atom.unk = object.Unk
				atom.MaterialCoords = sum(map(list,object.MaterialCoords),[])
			data = atom.pack()
			
			if len(object.Children) > 0:
				atoms += 2
				data += "pas1\x00\x00\x00\x08"
				for child in object.Children:
					ac, dc = self._PackObject(child)
					data += dc
					atoms += ac
				data += "pae1\x00\x00\x00\x08"
			return atoms, data
		else:
			raise ValueError("Unknown object: "+repr(object))
	
	def Pack(self, extra=None):
		
		header = self.BrlytHeader()
		header.Unk = 0xfeff0008
		header.UnkCount = 0x10
		header.Magic = "RLYT"
		header.AtomCount = 0
		
		data = ""
		data += self.mkLYT1()
		header.AtomCount+=1
		
		data += self.mkTXL1()
		header.AtomCount+=1
		
		data += self.mkMAT1(extra)
		header.AtomCount+=1
		
		atoms, ndata = self._PackObject(self.RootPane)
		data += ndata
		header.AtomCount += atoms
		
		#uuugly. TODO: fix this crap.
		data += "grp1\x00\x00\x00\x1cRootGroup\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
		header.AtomCount += 1
		
		header.Size = len(data) + len(header)
		data = header.pack() + data
		
		return data
	
	def mkLYT1(self):
		lyt1 = self.BrlytLYT1()
		lyt1.Width = self.Width
		lyt1.Height = self.Height
		lyt1.Flag = 1
		for n in range(3):
			lyt1.pad[n] = 0
		return lyt1.pack()
	
	def mkTXL1(self):
		return self.Textures.pack()
	
	def mkMAT1(self, extra=None):
		return self.Materials.pack(extra)
	
	def LYT1(self, data):
		lyt1 = self.BrlytLYT1()
		lyt1.unpack(data)
		self.Width = lyt1.Width
		self.Height = lyt1.Height
		print "LYT1: %f x %f, flag %d"%(self.Width, self.Height, lyt1.Flag)
		self.Renderer.Create(int(self.Width), int(self.Height))

	def TXL1(self, data):
		self.Textures = self.BrlytTXL1(self.Archive, data)
		for i in self.Textures:
			i.create_texture()
	
	def ApplyMask(self, image, mask):
		print "Making mask:",image,mask
		print image.width,image.height,mask.width,mask.height
		if image.height != mask.height or image.width != mask.width:
			raise ValueError("Mask dimensions must be equal to mask dimensions")
		newdata = [0 for x in xrange(image.height * image.width * 4)]
		
		for pix in xrange(image.height * image.width):
			newdata[pix*4 + 0] = image.data[pix*4 + 0]
			newdata[pix*4 + 1] = image.data[pix*4 + 1]
			newdata[pix*4 + 2] = image.data[pix*4 + 2]
			newdata[pix*4 + 3] = mask.data[pix*4 + 0]
		
		return  ImageData(image.width, image.height, 'RGBA', ''.join(newdata))
	
	def MAT1(self, data):
		self.Materials = self.BrlytMAT1(data)
	
	def _addpane(self, p):
		self.CurPane = p
		self.Objects[p.Name] = p
		if self.RootPane is None:
			self.RootPane = p
		else:
			self.PanePath[-1].Add(p)
	
	def PAN1(self, data):
		wii.chexdump(data)
		pane = Brlyt.BrlytPAN1()
		pane.unpack(data)
		p = Pane(pane.Name.split('\0',1)[0], pane.Flags, pane.Alpha/256.0, pane.Coords)
		print 'Pane %s (flags %04x, alpha %f): ' % (p.Name, pane.Flags, pane.Alpha),pane.Coords
		self._addpane(p)
	
	def PAS1(self, data):
		wii.chexdump(data)
		if self.CurPane is None:
			raise ValueError("No current pane!")
		self.PanePath.append(self.CurPane)
		print "Pane start:",'.'.join(map(str,self.PanePath))
		self.CurPane = None
	
	def PAE1(self, data):
		print "Pane end:",'.'.join(map(str,self.PanePath))
		self.PanePath = self.PanePath[:-1]
	
	def PIC1(self, data):
		wii.chexdump(data)
		pic = Brlyt.BrlytPIC1()
		pic.unpack(data)
		mc = []
		for i in range(4):
			mc.append(pic.MaterialCoords[i*2:i*2+2])
		print mc
		p = Picture(pic.Name.split("\0",1)[0], pic.Flags, pic.Alpha/256.0, pic.Coords, pic.unk, pic.Material, pic.Flags2, mc)
		print repr(p.Name)
		mat = self.Materials[pic.Material]
		if mat is not None:
			self._addpane(p)
		else:
			print 'Picture %s with null material!'
		
	def GRP1(self, data):
		wii.chexdump(data)
		if len(data) < 0x1c:
			pass
		lang = data[0x8:0x18].split('\0', 1)[0]
		nitems = Struct.uint16(data[0x18:0x1a], endian='>')
		p = 0x1c
		items = []
		for i in xrange(nitems):
			items.append(data[p:].split('\0', 1)[0])
			p += 0x10
		for i in items:
			try:
				if lang != self.Language:
					self.Objects[i].Enabled = False
				else:
					self.Objects[i].Enabled = True
			except:
				pass

class Brlan(object):
	A_COORD = "RLPA"
	A_PARM = "RLVC"
	C_X = 0
	C_Y = 1
	C_ANGLE = 5
	C_MAGX = 6
	C_MAGY = 7
	C_WIDTH = 8
	C_HEIGHT = 9
	P_ALPHA = 0x10
	class BrlanHeader(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.Magic = Struct.string(4)
			self.Unk = Struct.uint32
			self.Size = Struct.uint32
			self.UnkCount = Struct.uint16
			self.AtomCount = Struct.uint16
	
	def __init__(self, data=None):
		self.Anim = None
		if data != None:
			self.Unpack(data)
		else:
			self.Anim = Brlan.BrlanPAI1()
	
	def Unpack(self, data):
		header = self.BrlanHeader()
		header.unpack(data[:len(header)])
		pos = len(header)
		
		assert header.Magic == 'RLAN'
		
		for i in xrange(header.AtomCount):
			atom = StdAtom()
			atom.unpack(data[pos:pos+len(atom)])
			atomdata = data[pos:pos+atom.Size]
			pos += atom.Size
			
			if atom.FourCC == 'pai1':
				self.PAI1(atomdata)
			else:
				print "Unknown animation atom: %s"%atom.FourCC
	
	class BrlanPAI1(ItemList):
		LSIZE=4
		OFFSET=0
		FOURCC="pai1"
		HDRLEN=12
		def unpack(self, data):
			self.FrameCount = Struct.uint16(data[8:10], endian='>')
			print self.FrameCount
			ItemList.unpack(self, data)
		def __mkheader__(self):
			hdr = Struct.uint16(self.FrameCount, endian='>')
			hdr += Struct.uint16(0x100, endian='>')
			hdr += Struct.uint32(len(self.Items), endian='>')
			hdr += Struct.uint32(0x14, endian='>')
			return hdr
		def __unpkcnt__(self, data):
			return Struct.uint32(data[4:8], endian='>')
		def __getlistoff__(self, data):
			return Struct.uint32(data[8:12], endian='>')
		def unpack_item	(self, num, data):
			self.Items.append(Brlan.BrlanAnimSet(data))
		def pack(self, offset, count):
			self.FrameCount = count
			self.Offset = offset
			return ItemList.pack(self)
		def pack_item (self, num, item):
			return item.pack(self.Offset)
		def __getitem__(self, n):
			if isinstance(n,str):
				for i in self.Items:
					if i.Name == n:
						return i
				raise KeyError("Key %s not found"%n)
			else:
				return ItemList.__getitem__(self, n)
					
		def __contains__(self, n):
			if isinstance(n,str):
				for i in self.Items:
					if i.Name == n:
						return True
				return False
			else:
				return n in self.Items
				
			
	
	class BrlanAnimSet(ItemList):
		LSIZE=4
		OFFSET=0
		HDRLEN=0x18
		IS_ATOM=False
		def __init__(self, data=None):
			if data is not None and len(data)<0x14:
				self.Name = data
				ItemList.__init__(self, None)
			else:
				ItemList.__init__(self, data)
		def unpack(self, data):
			self.Name = data[:0x14].split("\0",1)[0]
			print self.Name
			ItemList.unpack(self, data)
		def __mkheader__(self):
			hdr = self.Name + "\x00" * (0x14-len(self.Name))
			hdr += Struct.uint8(len(self.Items), endian='>')
			hdr += "\x00\x00\x00"
			return hdr
		def __unpkcnt__(self, data):
			return Struct.uint8(data[0x14:0x15], endian='>')
		def unpack_item	(self, num, data):
			self.Items.append(Brlan.BrlanAnimClass(data))
		def pack_item (self, num, item):
			return item.pack(self.Offset)
		def pack(self, offset):
			self.Offset = offset
			return ItemList.pack(self)
		def __getitem__(self, n):
			if isinstance(n,str):
				for i in self.Items:
					if i.Type == n:
						return i
				raise KeyError("Key %s not found"%n)
			else:
				return ItemList.__getitem__(self, n)
			
	class BrlanAnimClass(ItemList):
		LSIZE=4
		OFFSET=0
		HDRLEN=8
		IS_ATOM=False
		
		class BrlanAnimClassIterator(object):
			def __init__(self, cl):
				self.cl = cl
				self.item = 0
			def __iter__(self):
				return self
			def next(self):
				if self.item == len(self.cl.Items):
					raise StopIteration()
				else:
					self.item += 1
					return self.cl.Items[self.item-1]
		
		def __init__(self, data=None):
			if data is not None and len(data) == 4:
				self.Type = data
				ItemList.__init__(self, None)
			else:
				ItemList.__init__(self, data)
		def unpack(self, data):
			self.Type = data[0:4]
			print " ",self.Type
			ItemList.unpack(self, data)
		def __mkheader__(self):
			hdr = self.Type
			hdr += Struct.uint8(len(self.Items), endian='>')
			hdr += "\x00\x00\x00"
			return hdr
		def __unpkcnt__(self, data):
			return Struct.uint8(data[4:5], endian='>')
		def unpack_item (self, num, data):
			self.Items.append(Brlan.BrlanAnim(data))
		def pack(self, offset):
			self.Offset = offset
			return ItemList.pack(self)
		def pack_item (self, num, item):
			return item.pack(self.Offset)
		def __getitem__(self, n):
			for i in self.Items:
				if i.Type == n:
					return i
			raise KeyError("Key %d not found"%n)
		def __iter__(self):
			return self.BrlanAnimClassIterator(self)
			
	class BrlanAnim(object):
		def __init__(self, data=None):
			self.Triplets = []
			self.Unk = 0x200
			self.Type = 0
			if data is not None and isinstance(data,int):
				self.Type = data
			else:
				self.unpack(data)
		def unpack(self, data):
			self.Type = Struct.uint16(data[0:2], endian='>')
			self.Unk = Struct.uint16(data[2:4], endian='>')
			count = Struct.uint16(data[4:6], endian='>')
			pos = Struct.uint32(data[8:12], endian='>')
			print "  ",self.Type
			if self.Unk == 0x200:
				print "      Triplets:"
				for i in range(count):
					F = Struct.float(data[pos+0:pos+4], endian='>')
					P = Struct.float(data[pos+4:pos+8], endian='>')
					D = Struct.float(data[pos+8:pos+12], endian='>')
					print "         %11f %11f %11f"%(F,P,D)
					self.Triplets.append((F,P,D))
					pos += 12
			else:
				print "      Unknown format: %04x"%self.Unk
		def pack(self, offset):
			self.Triplets.sort(key=lambda x: x[0])
			t = self.Triplets
			self.Triplets = []
			lt = (None, None, None)
			for i in t:
				if i == lt:
					pass
				elif i[0] == lt[0]:
					raise ValueError("Duplicate triplet frame numbers with different data")
				else:
					self.Triplets.append(i)
				
			out = Struct.uint16(self.Type, endian='>')
			out += Struct.uint16(self.Unk, endian='>')
			out += Struct.uint16(len(self.Triplets), endian='>')
			out += "\x00\x00"
			out += Struct.uint32(0xc, endian='>')
			for F,P,D in self.Triplets:
				out += Struct.float(F-offset, endian='>')
				out += Struct.float(P, endian='>')
				out += Struct.float(D, endian='>')
			return out
		def add(self, F, P=None, D=None):
			if isinstance(F,tuple):
				self.Triplets.append(F)
			else:
				self.Triplets.append((F,P,D))
		def rep(self, start, end, times):
			replist = []
			for i in self.Triplets:
				if i[0] >= start and i[0] <= end:
					replist.append(i)
			if len(replist) == 0:
				return
			off = end-start
			for i in range(times-1):
				for a,b,c in replist:
					self.Triplets.append((a+off,b,c))
				off += end-start
			a,b,c = replist[0]
			if a == start:
				self.Triplets.append((a+off,b,c))
		def repsimple(self, start, end, times, sp, sd, ep, ed):
			step = float(end-start) / times
			self.Triplets.append((start, sp, sd))
			self.Triplets.append((start+step/2.0, ep, ed))
			self.rep(start, start+step, times)
		def calc(self, frame):
			for tn in range(len(self.Triplets)):
				if self.Triplets[tn][0] > frame:
					if tn == 0:
						return self.Triplets[0][1]
					else:
						start, value1, coef1 = self.Triplets[tn-1]
						end, value2, coef2 = self.Triplets[tn]
						t = (frame - start) / (end - start)
						nf = end - start
						return \
							coef1  * 1 * nf * (t + t**3 - 2*t**2) + \
							coef2  * 1 * nf * (t**3 - t**2) + \
							value1 * (1 + (2*t**3 - 3*t**2)) + \
							value2 * (-2*t**3 + 3*t**2)
			else:
				return self.Triplets[-1][1]
		def __getitem__(self, n):
			return self.Triplets[n]
	def PAI1(self, data):
		assert self.Anim is None
		self.Anim = self.BrlanPAI1(data)
		return
	def Pack(self, a=None, b=None):
		
		if a is None and b is None:
			frames = self.FrameCount
			offset = 0
		elif a is not None and b is None:
			frames = a
			offset = 0
		elif a is not None and b is not None:
			frames = b-a
			offset = a
		else:
			raise ValueError("WTF are you doing")
		
		header = self.BrlanHeader()
		header.Unk = 0xfeff0008
		header.UnkCount = 0x10
		header.Magic = "RLAN"
		header.AtomCount = 1
		
		data = self.Anim.pack(offset, frames)
		
		header.Size = len(data) + len(header)
		data = header.pack() + data
		
		return data

if have_pyglet:
	class BannerWindow(window.Window):
		def on_resize(self, width, height):
			glViewport(0, 0, width, height)
			glMatrixMode(GL_PROJECTION)
			glLoadIdentity()
			glOrtho(-width/2, width/2, -height/2, height/2, -1, 1)
			glMatrixMode(GL_MODELVIEW)


class Renderer(object):
	def __init__(self):
		self.Brlyt = None
		self.Brlan = None
	
	def Create(self, width, height):
		self.Width = width
		self.Height = height
		print "Render: %f x %f"%(self.Width,self.Height)
		self.Window = BannerWindow(self.Width, self.Height)
		self.Window.set_exclusive_mouse(False)
		
		glClearColor(0.0, 0.0, 0.0, 0.0)
		glClearDepth(1.0)
		glDepthFunc(GL_LEQUAL)
		glEnable(GL_DEPTH_TEST)
		
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
		glEnable(GL_BLEND)
		glEnable(GL_TEXTURE_2D)
		clock.set_fps_limit(60)
		
	
	def Render(self, item, wireframe=False):
		if not item.Enabled:
			return
		if isinstance(item, Picture):
			
			mat = self.Brlyt.Materials[item.Material]
			texture = self.Brlyt.Textures[mat.Textures[0][0]].GLTexture
			mtc = mat.TextureCoords[0]
			x, y, a, b, c, rot, xsc, ysc, xs, ys = item.Coords[:10]
			
			xs *= xsc
			ys *= ysc
			#print item.Name,x,y,xs,ys
			xc, yc = x-(xs/2),y-(ys/2)
			
			glPushMatrix()
			glMatrixMode( GL_MODELVIEW )
			glTranslatef( x, y, 0)
			glRotatef(rot,0,0,1)
			glScalef(xs,ys,0)
			
			if not wireframe:
				col = [x/255.0 for x in list(mat.Color2)]
				col[3] = col[3] * item.Alpha / 255.0
				
				tw = texture.tex_coords[6]
				th = texture.tex_coords[7]
				
				mc = item.MaterialCoords
				
				glMatrixMode( GL_TEXTURE )
				glPushMatrix()
				glTranslatef(0.5,0.5,0)
				glTranslatef(mtc[0],mtc[1],0)
				glScalef(mtc[3],mtc[4],0)
				glTranslatef(-0.5,-0.5,0)
				array = (GLfloat * 32)(
					mc[0][0] * tw,  mc[0][1] * th,  0,  1.,
					-0.5,      0.5,      0,     1.,
					mc[1][0] * tw,  mc[1][1] * th,  0,  1.,
						0.5,      0.5,      0,     1.,
					mc[3][0] * tw,  mc[3][1] * th,  0,  1.,
						0.5,     -0.5, 0,     1.,
					mc[2][0] * tw,  mc[2][1] * th,  0,  1.,
					-0.5,     -0.5, 0,     1.)
		
				glColor4f(*col)
				glPushAttrib(GL_ENABLE_BIT)
				glEnable(texture.target)
				glBindTexture(texture.target, texture.id)
				if mat.Textures[0][1] == 0x0:
					glTexParameteri(texture.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
				elif mat.Textures[0][1] == 0x1:
					glTexParameteri(texture.target, GL_TEXTURE_WRAP_S, GL_REPEAT)
				elif mat.Textures[0][1] == 0x2:
					glTexParameteri(texture.target, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT)
				else:
					glTexParameteri(texture.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
				if mat.Textures[0][2] == 0x0:
					glTexParameteri(texture.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
				elif mat.Textures[0][2] == 0x1:
					glTexParameteri(texture.target, GL_TEXTURE_WRAP_T, GL_REPEAT)
				elif mat.Textures[0][2] == 0x2:
					glTexParameteri(texture.target, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT)
				else:
					glTexParameteri(texture.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
					
				glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
				glInterleavedArrays(GL_T4F_V4F, 0, array)
				glDrawArrays(GL_QUADS, 0, 4)
				glPopClientAttrib()
				glPopAttrib()
				
				glBindTexture(texture.target, 0)
				glPopMatrix()
				glMatrixMode( GL_MODELVIEW )

			else:
				
				glColor3f(1,0,0)
				glBegin(GL_LINE_STRIP)
				glVertex2f(-0.5,-0.5)
				glVertex2f(0.5,-0.5)
				glVertex2f(0.5,0.5)
				glVertex2f(-0.5,0.5)
				glVertex2f(-0.5,-0.5)
				glColor3f(1,1,1)
				glEnd()
				pass
	
			glPopMatrix()
		if isinstance(item, Pane):
			if item.Coords is not None:
				x, y, a, b, c, rot, xsc, ysc, xs, ys = item.Coords[:10]
			else:
				x = y = 0
				xs = ys = 0
				xsc = 1
				ysc = 1
			glPushMatrix()
			glTranslatef(x, y, 0)
			glRotatef(rot,0,0,1)
			glScalef(xsc,ysc,0)
			#glScalef(xs,ys,1)
			for child in item.Children:
				self.Render(child,wireframe)
			glPopMatrix()

	def Animate(self, frame):
		for set in self.Brlan.Anim:
			for clss in set:
				for anim in clss:
					#print set.Name, clss.Type, anim.Type, anim.calc(frame), frame
					if clss.Type == Brlan.A_COORD:
						self.Brlyt.Objects[set.Name].Coords[anim.Type] = anim.calc(frame)
					elif clss.Type == Brlan.A_PARM:
						if anim.Type == Brlan.P_ALPHA:
							self.Brlyt.Objects[set.Name].Alpha = anim.calc(frame)

	def MainLoop(self, loop):
		frame = 0
		print "Starting mainloop: loop =",loop
		print "Length in frames:",self.Brlan.Anim.FrameCount	
		while not self.Window.has_exit:
			self.Window.dispatch_events()
			self.Window.clear()
			
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
			glLoadIdentity()
			glColor4f(1.0, 1.0, 1.0, 1.0)
			
			self.Render(self.Brlyt.RootPane,False)
			#self.Render(self.Brlyt.RootPane,True)
			
			#clock.tick()
			
			self.Window.flip()
			if self.Brlan is not None:
				self.Animate(frame)
				if frame >= self.Brlan.Anim.FrameCount:
					if not loop:
						print "Animation done!"
						return True
					else:
						print "Looping..."
						frame = -1
			frame += 1

class Alameda(object):
	class IMETHeader(Struct):
		__endian__ = Struct.BE
		def __format__(self):
			self.Zeroes = Struct.uint8[0x40]
			self.IMET = Struct.string(4)
			self.Fixed = Struct.uint8[8]
			self.Sizes = Struct.uint32[3]
			self.Flag1 = Struct.uint32
			self.Names = Struct.string(0x2A<<1, encoding='utf-16-be', stripNulls=True)[7]
			self.Zeroes = Struct.uint8[0x348]
			self.MD5 = Struct.uint8[0x10]
	
	def __init__(self, fn, type='icon'):
		renderer = Renderer()
		
		fp = file(fn, 'rb')
		
		imet = self.IMETHeader()
		try:
			imet.unpack(fp.read(len(imet)))
		except:
			imet = None
		if imet is None or imet.IMET != 'IMET':
			imet = self.IMETHeader()
			fp.seek(0x40)
			imet.unpack(fp.read(len(imet)))
			assert imet.IMET == 'IMET'
		
		print 'English title: %s' % imet.Names[1]
		
		
		root = U8(fp.read())
		if type == 'icon':
			banner = U8(IMD5(root.Files['./meta/icon.bin']))
			renderer.Brlyt = Brlyt(banner, banner.Files['./arc/blyt/icon.brlyt'], renderer)
			fd = None
			try:
				fd = banner.Files['./arc/anim/icon.brlan']
			except:
				pass
			if fd is not None:
				renderer.Brlan = Brlan(fd)

			loop = True
		else:
			banner = U8(IMD5(root.Files['./meta/banner.bin']))
			renderer.Brlyt = Brlyt(banner, banner.Files['./arc/blyt/banner.brlyt'], renderer)
			loop = not banner.Files.has_key('./arc/anim/banner_start.brlan')
			if not loop:
				renderer.Brlan = Brlan(banner.Files['./arc/anim/banner_start.brlan'])
			else:
				renderer.Brlan = Brlan(banner.Files['./arc/anim/banner.brlan'])
				
		if renderer.MainLoop(loop) and type == 'banner' and not loop:
			renderer.Brlan = Brlan(banner.Files['./arc/anim/banner_loop.brlan'])
			renderer.MainLoop(True)

if __name__=='__main__':
	Alameda(*sys.argv[1:])
