// File: ticky[P]ps2iconsys/src/ps2_ps2icon.cpp
// Function: PS2Icon::ReadFile(std::basic_ifstream<char, std::char_traits<char>>&)
void PS2Icon::ReadFile(std::ifstream & fin)
{
	//read header:
	fin.read( reinterpret_cast<char*>(&header), sizeof(header) );

	if(!CheckValidity(header)) {
		throw( Ghulbus::gbException( Ghulbus::gbException::GB_FAILED, "Icon Header seems to be corrupted" ) );
	}

	//allocate memory for vertex data:
	AllocateVertexMemory();

	//read icon data from file:
	///Vertex data
	// each vertex consists of animation_shapes tuples for vertex coordinates,
	// followed by one vertex coordinate tuple for normal coordinates
	// followed by one texture data tuple for texture coordinates and color
	for(unsigned int i=0; i<header.n_vertices; i++) {
		fin.read( reinterpret_cast<char*>(&vertices[i*header.animation_shapes]), 
			      sizeof(Vertex_Coord) * header.animation_shapes );
		fin.read( reinterpret_cast<char*>(&normals[i]), sizeof(Vertex_Coord) );
		fin.read( reinterpret_cast<char*>(&vert_texture[i]), sizeof(Texture_Data) );
		
		for(unsigned int j=0; j<header.animation_shapes; j++) {
			fvertices[(i*header.animation_shapes + j) * 3] = 
				convert_f16_to_f32(vertices[i*header.animation_shapes + j].f16_x);
			fvertices[(i*header.animation_shapes + j) * 3 + 1] = 
				convert_f16_to_f32(vertices[i*header.animation_shapes + j].f16_y);
			fvertices[(i*header.animation_shapes + j) * 3 + 2] = 
				convert_f16_to_f32(vertices[i*header.animation_shapes + j].f16_z);
		}
		fnormals[i*3]     = convert_f16_to_f32(normals[i].f16_x);
		fnormals[i*3 + 1] = convert_f16_to_f32(normals[i].f16_y);
		fnormals[i*3 + 2] = convert_f16_to_f32(normals[i].f16_z);
	}

	//animation data
	// preceeded by an animation header, there is a frame data/key set for every frame:
	fin.read( reinterpret_cast<char*>(&anim_header), sizeof(Animation_Header) );

	//allocate memory for animation data:
	animation = new Frame_Data[anim_header.n_frames];
	anim_keys = new Frame_Key*[anim_header.n_frames];
	//read animation data:
	for(unsigned int i=0; i<anim_header.n_frames; i++) {
		fin.read( reinterpret_cast<char*>(&animation[i]), sizeof(Frame_Data) );
		if(animation[i].n_keys > 0) {
			anim_keys[i] = new Frame_Key[animation[i].n_keys];
			fin.read( reinterpret_cast<char*>(anim_keys[i]), sizeof(Frame_Key)*animation[i].n_keys);
		} else {
			anim_keys[i] = NULL;
		}
	}

	//read texture data:
	if(header.texture_type <= 0x07) {	//uncompressed textures
		unsigned short c;
		for(int i=0; i<16384; i++) {
			fin.read( reinterpret_cast<char*>(&c), 2 );
			unsigned char r = static_cast<unsigned char>( ( c        & 0x1f) << 3 );
			unsigned char g = static_cast<unsigned char>( ((c >> 5)  & 0x1f) << 3 );
			unsigned char b = static_cast<unsigned char>( ((c >> 10)       ) << 3 );
			texture[i] =  static_cast<unsigned int>( (    (0xff)<<24) |
				                                     (((r)&0xff)<<16) | 
										             (((g)&0xff)<<8)  |
										             ( (b)&0xff)  );
		}
	} else {							//compressed textures
		//simple rle encoding:
		// first 32 bits hold size of texture data
		unsigned int data_size;
		fin.read( reinterpret_cast<char*>(&data_size), 4 );
		unsigned int limit = fin.tellg();
		limit += data_size;
		if(limit > INT_MAX) { throw( Ghulbus::gbException( Ghulbus::gbException::GB_FAILED, 
			                                               "File size is bigger than INT_MAX" ) ); }
		unsigned int index = 0;
		while( fin.tellg() < static_cast<int>(limit) ) {
			//next 16 bits indicate the type of data to follow:
			unsigned short rep_count;
			fin.read( reinterpret_cast<char*>(&rep_count), 2 );
			if(rep_count < 0xFF00) {			//repeat the pixel rep_count times
				unsigned short c;
				fin.read( reinterpret_cast<char*>(&c), 2 );
				unsigned char r = static_cast<unsigned char>( ( c        & 0x1f) << 3 );
				unsigned char g = static_cast<unsigned char>( ((c >> 5)  & 0x1f) << 3 );
				unsigned char b = static_cast<unsigned char>( ((c >> 10)       ) << 3 );
				for(int i=0; i<rep_count; i++) {
					texture[index++] = static_cast<unsigned int> (     ((0xff)<<24) |
				                                                   (((r)&0xff)<<16) | 
										                           (((g)&0xff)<<8)  |
										                           ( (b)&0xff)  );
				}
			} else {							//copy the next rep_count pixels directly
				for(unsigned int i=0; i<=(0xFFFF ^ static_cast<unsigned int>(rep_count)); i++) {
					unsigned short c;
					fin.read( reinterpret_cast<char*>(&c), 2 );
					unsigned char r = static_cast<unsigned char>( ( c        & 0x1f) << 3 );
					unsigned char g = static_cast<unsigned char>( ((c >> 5)  & 0x1f) << 3 );
					unsigned char b = static_cast<unsigned char>( ((c >> 10)       ) << 3 );
					texture[index++] = static_cast<unsigned int>(     ((0xff)<<24) |
				                                                  (((r)&0xff)<<16) | 
										                          (((g)&0xff)<<8)  |
										                          ( (b)&0xff)  );
				}
			}
		}
	}

	if(fin.fail()) { throw( Ghulbus::gbException( Ghulbus::gbException::GB_FAILED,
	                                              "File read error" ) ); }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rsi
movq %rsi, -0x78(%rbp)
movq -0x10(%rbp), %rdi
movl $0x14, %edx
callq 0x2260
movq -0x78(%rbp), %rdi
callq 0x9e40
testb $0x1, %al
jne 0xa0ff
movl $0x18, %edi
callq 0x20f0
movq %rax, %rdi
movq %rdi, -0x80(%rbp)
movl $0x1, %esi
leaq 0x717d(%rip), %rdx      # 0x11260
callq 0xf0b0
movq -0x80(%rbp), %rdi
leaq 0xdc9d(%rip), %rsi      # 0x17d90
leaq 0x5056(%rip), %rdx      # 0xf150
callq 0x2340
movq -0x78(%rbp), %rdi
callq 0xa830
movl $0x0, -0x14(%rbp)
movq -0x78(%rbp), %rcx
movl -0x14(%rbp), %eax
cmpl 0x10(%rcx), %eax
jae 0xa2fa
movq -0x78(%rbp), %rax
movq -0x10(%rbp), %rdi
movq 0x18(%rax), %rsi
movl -0x14(%rbp), %ecx
imull 0x4(%rax), %ecx
movl %ecx, %ecx
shlq $0x3, %rcx
addq %rcx, %rsi
movl 0x4(%rax), %eax
movl %eax, %edx
shlq $0x3, %rdx
callq 0x2260
movq -0x78(%rbp), %rax
movq -0x10(%rbp), %rdi
movq 0x20(%rax), %rsi
movl -0x14(%rbp), %eax
shlq $0x3, %rax
addq %rax, %rsi
movl $0x8, %edx
callq 0x2260
movq -0x78(%rbp), %rax
movq -0x10(%rbp), %rdi
movq 0x28(%rax), %rsi
movl -0x14(%rbp), %eax
shlq $0x3, %rax
addq %rax, %rsi
movl $0x8, %edx
callq 0x2260
movl $0x0, -0x18(%rbp)
movq -0x78(%rbp), %rcx
movl -0x18(%rbp), %eax
cmpl 0x4(%rcx), %eax
jae 0xa268
movq -0x78(%rbp), %rcx
movq 0x18(%rcx), %rdi
movl -0x14(%rbp), %eax
imull 0x4(%rcx), %eax
addl -0x18(%rbp), %eax
movl %eax, %eax
shlq $0x3, %rax
addq %rax, %rdi
callq 0xc6e0
movq -0x78(%rbp), %rcx
movq 0x30(%rcx), %rax
movl -0x14(%rbp), %edx
imull 0x4(%rcx), %edx
addl -0x18(%rbp), %edx
imull $0x3, %edx, %edx
movl %edx, %edx
movss %xmm0, (%rax,%rdx,4)
movq 0x18(%rcx), %rdi
movl -0x14(%rbp), %eax
imull 0x4(%rcx), %eax
addl -0x18(%rbp), %eax
movl %eax, %eax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x2, %rdi
callq 0xc6e0
movq -0x78(%rbp), %rcx
movq 0x30(%rcx), %rax
movl -0x14(%rbp), %edx
imull 0x4(%rcx), %edx
addl -0x18(%rbp), %edx
imull $0x3, %edx, %edx
addl $0x1, %edx
movl %edx, %edx
movss %xmm0, (%rax,%rdx,4)
movq 0x18(%rcx), %rdi
movl -0x14(%rbp), %eax
imull 0x4(%rcx), %eax
addl -0x18(%rbp), %eax
movl %eax, %eax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x4, %rdi
callq 0xc6e0
movq -0x78(%rbp), %rdx
movq 0x30(%rdx), %rax
movl -0x14(%rbp), %ecx
imull 0x4(%rdx), %ecx
addl -0x18(%rbp), %ecx
imull $0x3, %ecx, %ecx
addl $0x2, %ecx
movl %ecx, %ecx
movss %xmm0, (%rax,%rcx,4)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0xa190
movq -0x78(%rbp), %rax
movq 0x20(%rax), %rdi
movl -0x14(%rbp), %eax
shlq $0x3, %rax
addq %rax, %rdi
callq 0xc6e0
movq -0x78(%rbp), %rax
movq 0x38(%rax), %rcx
imull $0x3, -0x14(%rbp), %edx
movl %edx, %edx
movss %xmm0, (%rcx,%rdx,4)
movq 0x20(%rax), %rdi
movl -0x14(%rbp), %eax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x2, %rdi
callq 0xc6e0
movq -0x78(%rbp), %rax
movq 0x38(%rax), %rcx
imull $0x3, -0x14(%rbp), %edx
addl $0x1, %edx
movl %edx, %edx
movss %xmm0, (%rcx,%rdx,4)
movq 0x20(%rax), %rdi
movl -0x14(%rbp), %eax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x4, %rdi
callq 0xc6e0
movq -0x78(%rbp), %rax
movq 0x38(%rax), %rax
imull $0x3, -0x14(%rbp), %ecx
addl $0x2, %ecx
movl %ecx, %ecx
movss %xmm0, (%rax,%rcx,4)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xa10f
movq -0x78(%rbp), %rsi
movq -0x10(%rbp), %rdi
addq $0x40, %rsi
movl $0x14, %edx
callq 0x2260
movq -0x78(%rbp), %rax
movl 0x50(%rax), %eax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2040
movq %rax, %rcx
movq -0x78(%rbp), %rax
movq %rcx, 0x58(%rax)
movl 0x50(%rax), %eax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2040
movq %rax, %rcx
movq -0x78(%rbp), %rax
movq %rcx, 0x60(%rax)
movl $0x0, -0x1c(%rbp)
movq -0x78(%rbp), %rcx
movl -0x1c(%rbp), %eax
cmpl 0x50(%rcx), %eax
jae 0xa447
movq -0x78(%rbp), %rax
movq -0x10(%rbp), %rdi
movq 0x58(%rax), %rsi
movl -0x1c(%rbp), %eax
shlq $0x3, %rax
addq %rax, %rsi
movl $0x8, %edx
callq 0x2260
movq -0x78(%rbp), %rax
movq 0x58(%rax), %rax
movl -0x1c(%rbp), %ecx
cmpl $0x0, 0x4(%rax,%rcx,8)
jbe 0xa424
movq -0x78(%rbp), %rax
movq 0x58(%rax), %rax
movl -0x1c(%rbp), %ecx
movl 0x4(%rax,%rcx,8), %eax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2040
movq %rax, %rsi
movq -0x78(%rbp), %rax
movq 0x60(%rax), %rcx
movl -0x1c(%rbp), %edx
movq %rsi, (%rcx,%rdx,8)
movq -0x10(%rbp), %rdi
movq 0x60(%rax), %rcx
movl -0x1c(%rbp), %edx
movq (%rcx,%rdx,8), %rsi
movq 0x58(%rax), %rax
movl -0x1c(%rbp), %ecx
movl 0x4(%rax,%rcx,8), %eax
movl %eax, %edx
shlq $0x3, %rdx
callq 0x2260
jmp 0xa437
movq -0x78(%rbp), %rax
movq 0x60(%rax), %rax
movl -0x1c(%rbp), %ecx
movq $0x0, (%rax,%rcx,8)
jmp 0xa439
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0xa379
movq -0x78(%rbp), %rax
cmpl $0x7, 0x8(%rax)
ja 0xa4f2
movl $0x0, -0x24(%rbp)
cmpl $0x4000, -0x24(%rbp)    # imm = 0x4000
jge 0xa4ed
movq -0x10(%rbp), %rdi
leaq -0x1e(%rbp), %rsi
movl $0x2, %edx
callq 0x2260
movq -0x78(%rbp), %rax
movzwl -0x1e(%rbp), %ecx
andl $0x1f, %ecx
shll $0x3, %ecx
movb %cl, -0x25(%rbp)
movzwl -0x1e(%rbp), %ecx
sarl $0x5, %ecx
andl $0x1f, %ecx
shll $0x3, %ecx
movb %cl, -0x26(%rbp)
movzwl -0x1e(%rbp), %ecx
sarl $0xa, %ecx
shll $0x3, %ecx
movb %cl, -0x27(%rbp)
movzbl -0x25(%rbp), %edx
andl $0xff, %edx
shll $0x10, %edx
orl $0xff000000, %edx       # imm = 0xFF000000
movzbl -0x26(%rbp), %ecx
andl $0xff, %ecx
shll $0x8, %ecx
orl %ecx, %edx
movzbl -0x27(%rbp), %ecx
andl $0xff, %ecx
orl %ecx, %edx
movslq -0x24(%rbp), %rcx
movl %edx, 0x68(%rax,%rcx,4)
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0xa45c
jmp 0xa714
movq -0x10(%rbp), %rdi
leaq -0x2c(%rbp), %rsi
movl $0x4, %edx
callq 0x2260
movq -0x10(%rbp), %rdi
callq 0x2360
movq %rax, -0x40(%rbp)
movq %rdx, -0x38(%rbp)
leaq -0x40(%rbp), %rdi
callq 0xc710
movl %eax, -0x30(%rbp)
movl -0x2c(%rbp), %eax
addl -0x30(%rbp), %eax
movl %eax, -0x30(%rbp)
cmpl $0x7fffffff, -0x30(%rbp) # imm = 0x7FFFFFFF
jbe 0xa572
movl $0x18, %edi
callq 0x20f0
movq %rax, %rdi
movq %rdi, -0x88(%rbp)
movl $0x1, %esi
leaq 0x6d2f(%rip), %rdx      # 0x11282
callq 0xf0b0
movq -0x88(%rbp), %rdi
leaq 0xd82a(%rip), %rsi      # 0x17d90
leaq 0x4be3(%rip), %rdx      # 0xf150
callq 0x2340
movl $0x0, -0x44(%rbp)
movq -0x10(%rbp), %rdi
callq 0x2360
movq %rax, -0x58(%rbp)
movq %rdx, -0x50(%rbp)
leaq -0x58(%rbp), %rdi
callq 0xc710
movslq -0x30(%rbp), %rcx
cmpq %rcx, %rax
jge 0xa712
movq -0x10(%rbp), %rdi
leaq -0x5a(%rbp), %rsi
movl $0x2, %edx
callq 0x2260
movzwl -0x5a(%rbp), %eax
cmpl $0xff00, %eax           # imm = 0xFF00
jge 0xa662
movq -0x10(%rbp), %rdi
leaq -0x5c(%rbp), %rsi
movl $0x2, %edx
callq 0x2260
movzwl -0x5c(%rbp), %eax
andl $0x1f, %eax
shll $0x3, %eax
movb %al, -0x5d(%rbp)
movzwl -0x5c(%rbp), %eax
sarl $0x5, %eax
andl $0x1f, %eax
shll $0x3, %eax
movb %al, -0x5e(%rbp)
movzwl -0x5c(%rbp), %eax
sarl $0xa, %eax
shll $0x3, %eax
movb %al, -0x5f(%rbp)
movl $0x0, -0x64(%rbp)
movl -0x64(%rbp), %eax
movzwl -0x5a(%rbp), %ecx
cmpl %ecx, %eax
jge 0xa65d
movq -0x78(%rbp), %rax
movzbl -0x5d(%rbp), %edx
andl $0xff, %edx
shll $0x10, %edx
orl $0xff000000, %edx       # imm = 0xFF000000
movzbl -0x5e(%rbp), %ecx
andl $0xff, %ecx
shll $0x8, %ecx
orl %ecx, %edx
movzbl -0x5f(%rbp), %ecx
andl $0xff, %ecx
orl %ecx, %edx
movl -0x44(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x44(%rbp)
movl %ecx, %ecx
movl %edx, 0x68(%rax,%rcx,4)
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0xa604
jmp 0xa70d
movl $0x0, -0x68(%rbp)
movl -0x68(%rbp), %eax
movzwl -0x5a(%rbp), %ecx
xorl $0xffff, %ecx           # imm = 0xFFFF
cmpl %ecx, %eax
ja 0xa70b
movq -0x10(%rbp), %rdi
leaq -0x6a(%rbp), %rsi
movl $0x2, %edx
callq 0x2260
movq -0x78(%rbp), %rax
movzwl -0x6a(%rbp), %ecx
andl $0x1f, %ecx
shll $0x3, %ecx
movb %cl, -0x6b(%rbp)
movzwl -0x6a(%rbp), %ecx
sarl $0x5, %ecx
andl $0x1f, %ecx
shll $0x3, %ecx
movb %cl, -0x6c(%rbp)
movzwl -0x6a(%rbp), %ecx
sarl $0xa, %ecx
shll $0x3, %ecx
movb %cl, -0x6d(%rbp)
movzbl -0x6b(%rbp), %edx
andl $0xff, %edx
shll $0x10, %edx
orl $0xff000000, %edx       # imm = 0xFF000000
movzbl -0x6c(%rbp), %ecx
andl $0xff, %ecx
shll $0x8, %ecx
orl %ecx, %edx
movzbl -0x6d(%rbp), %ecx
andl $0xff, %ecx
orl %ecx, %edx
movl -0x44(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x44(%rbp)
movl %ecx, %ecx
movl %edx, 0x68(%rax,%rcx,4)
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0xa669
jmp 0xa70d
jmp 0xa579
jmp 0xa714
movq -0x10(%rbp), %rdi
movq (%rdi), %rax
addq -0x18(%rax), %rdi
callq 0x2030
testb $0x1, %al
jne 0xa72a
jmp 0xa769
movl $0x18, %edi
callq 0x20f0
movq %rax, %rdi
movq %rdi, -0x90(%rbp)
movl $0x1, %esi
leaq 0x6a5c(%rip), %rdx      # 0x111a6
callq 0xf0b0
movq -0x90(%rbp), %rdi
leaq 0xd633(%rip), %rsi      # 0x17d90
leaq 0x49ec(%rip), %rdx      # 0xf150
callq 0x2340
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)