// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %rbx
movq %rdi, %r14
movl $0x14, %edx
movq %rsi, %rdi
movq %r14, %rsi
callq 0x2240
imull $0xaaaaaaab, 0x10(%r14), %eax # imm = 0xAAAAAAAB
cmpl $0x55555556, %eax       # imm = 0x55555556
jae 0x5f46
movq %r14, %rdi
callq 0x5fee
cmpl $0x0, 0x10(%r14)
je 0x5ce3
movl 0x4(%r14), %esi
xorl %r12d, %r12d
xorl %r13d, %r13d
movl %esi, %edx
imull %r13d, %esi
shlq $0x3, %rsi
addq 0x18(%r14), %rsi
shlq $0x3, %rdx
movq %rbx, %rdi
callq 0x2240
leaq (,%r13,8), %r15
movq 0x20(%r14), %rsi
addq %r15, %rsi
movl $0x8, %edx
movq %rbx, %rdi
callq 0x2240
addq 0x28(%r14), %r15
movl $0x8, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2240
movss 0x46f8(%rip), %xmm1     # 0xa2f0
movl 0x4(%r14), %esi
testq %rsi, %rsi
je 0x5c77
movq 0x18(%r14), %rax
movq 0x30(%r14), %rcx
movl %esi, %edx
imull %r12d, %edx
movl %esi, %edi
imull %r13d, %edi
movq %rsi, %r8
movl %edi, %r9d
movswl (%rax,%r9,8), %r10d
xorps %xmm0, %xmm0
cvtsi2ss %r10d, %xmm0
mulss %xmm1, %xmm0
movl %edx, %r10d
movss %xmm0, (%rcx,%r10,4)
movswl 0x2(%rax,%r9,8), %r10d
xorps %xmm0, %xmm0
cvtsi2ss %r10d, %xmm0
mulss %xmm1, %xmm0
leal 0x1(%rdx), %r10d
movss %xmm0, (%rcx,%r10,4)
movswl 0x4(%rax,%r9,8), %r9d
xorps %xmm0, %xmm0
cvtsi2ss %r9d, %xmm0
mulss %xmm1, %xmm0
leal 0x2(%rdx), %r9d
movss %xmm0, (%rcx,%r9,4)
addl $0x3, %edx
incl %edi
decq %r8
jne 0x5c18
movq 0x20(%r14), %rax
movswl (%rax,%r13,8), %ecx
xorps %xmm0, %xmm0
cvtsi2ss %ecx, %xmm0
movq 0x38(%r14), %rcx
mulss %xmm1, %xmm0
leal (%r13,%r13,2), %edx
movss %xmm0, (%rcx,%rdx,4)
movswl 0x2(%rax,%r13,8), %edx
xorps %xmm0, %xmm0
cvtsi2ss %edx, %xmm0
mulss %xmm1, %xmm0
leal 0x1(%r13,%r13,2), %edx
movss %xmm0, (%rcx,%rdx,4)
movswl 0x4(%rax,%r13,8), %eax
xorps %xmm0, %xmm0
cvtsi2ss %eax, %xmm0
mulss %xmm1, %xmm0
leal 0x2(%r13,%r13,2), %eax
movss %xmm0, (%rcx,%rax,4)
incq %r13
movl 0x10(%r14), %eax
addl $0x3, %r12d
cmpq %rax, %r13
jb 0x5ba6
leaq 0x40(%r14), %rsi
movl $0x14, %edx
movq %rbx, %rdi
callq 0x2240
movl 0x50(%r14), %r12d
leaq (,%r12,8), %r15
movq %r15, %rdi
callq 0x2030
movq %rax, 0x58(%r14)
movq %r15, %rdi
callq 0x2030
movq %rax, 0x60(%r14)
testq %r12, %r12
je 0x5d91
xorl %r15d, %r15d
xorl %r12d, %r12d
movq 0x58(%r14), %rsi
addq %r15, %rsi
movl $0x8, %edx
movq %rbx, %rdi
callq 0x2240
movq 0x58(%r14), %rax
movl 0x4(%rax,%r15), %edi
testq %rdi, %rdi
je 0x5d75
shlq $0x3, %rdi
callq 0x2030
movq 0x60(%r14), %rcx
movq %rax, (%rcx,%r15)
movq 0x58(%r14), %rax
movq 0x60(%r14), %rcx
movq (%rcx,%r15), %rsi
movl 0x4(%rax,%r15), %edx
shlq $0x3, %rdx
movq %rbx, %rdi
callq 0x2240
jmp 0x5d81
movq 0x60(%r14), %rax
movq $0x0, (%rax,%r15)
incq %r12
movl 0x50(%r14), %eax
addq $0x8, %r15
cmpq %rax, %r12
jb 0x5d23
cmpl $0x8, 0x8(%r14)
jae 0x5ded
xorl %r12d, %r12d
leaq 0x6(%rsp), %r15
movl $0x2, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2240
movzwl 0x6(%rsp), %eax
movl %eax, %ecx
shll $0x13, %ecx
movl %eax, %edx
shrl $0x7, %edx
shll $0x6, %eax
andl $0xf800, %eax           # imm = 0xF800
orl %ecx, %eax
andl $0xf8, %edx
orl %eax, %edx
orl $0xff000000, %edx       # imm = 0xFF000000
movl %edx, 0x68(%r14,%r12,4)
incq %r12
cmpq $0x4000, %r12           # imm = 0x4000
jne 0x5da0
jmp 0x5f29
leaq 0x14(%rsp), %r12
movl $0x4, %edx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2240
movq %rbx, %rdi
callq 0x2340
movq %rax, %r15
addl (%r12), %r15d
js 0x5f72
movq %rbx, %rdi
callq 0x2340
movl %r15d, %r15d
cmpq %r15, %rax
jge 0x5f29
xorl %r12d, %r12d
movq %rsp, %rbp
leaq 0x2(%rsp), %r13
movq %r15, 0x8(%rsp)
movl $0x2, %edx
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2240
cmpw $0xff00, (%rsp)         # imm = 0xFF00
jae 0x5eb1
movl $0x2, %edx
movq %rbx, %rdi
leaq 0x4(%rsp), %rsi
callq 0x2240
movzwl (%rsp), %eax
testl %eax, %eax
je 0x5f18
movzwl 0x4(%rsp), %edx
movl %edx, %ecx
shrl $0x7, %ecx
movl %edx, %esi
shll $0x13, %esi
shll $0x6, %edx
andl $0xf800, %edx           # imm = 0xF800
orl %esi, %edx
andl $0xf8, %ecx
orl %edx, %ecx
orl $0xff000000, %ecx       # imm = 0xFF000000
leal (%r12,%rax), %edx
movl %r12d, %esi
incl %r12d
movl %ecx, 0x68(%r14,%rsi,4)
decl %eax
jne 0x5e9d
movl %edx, %r12d
jmp 0x5f18
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
leal (%r15,%r12), %ebp
incl %ebp
movl $0x2, %edx
movq %rbx, %rdi
movq %r13, %rsi
callq 0x2240
movzwl 0x2(%rsp), %eax
movl %eax, %ecx
shll $0x13, %ecx
movl %eax, %edx
shrl $0x7, %edx
shll $0x6, %eax
andl $0xf800, %eax           # imm = 0xF800
orl %ecx, %eax
andl $0xf8, %edx
orl %eax, %edx
orl $0xff000000, %edx       # imm = 0xFF000000
movl %edx, 0x68(%r14,%rbp,4)
movzwl (%rsp), %eax
xorl $0xffff, %eax           # imm = 0xFFFF
incl %r15d
cmpl %eax, %r15d
jb 0x5eb7
addl %r15d, %r12d
incl %r12d
movq 0x8(%rsp), %r15
movq %rsp, %rbp
movq %rbx, %rdi
callq 0x2340
cmpq %r15, %rax
jl 0x5e3b
movq (%rbx), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x20(%rbx,%rax)
jne 0x5f5c
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x18, %edi
callq 0x20e0
movq %rax, %rbx
leaq 0x43f6(%rip), %rdx      # 0xa350
jmp 0x5f86
movl $0x18, %edi
callq 0x20e0
movq %rax, %rbx
leaq 0x42ca(%rip), %rdx      # 0xa23a
jmp 0x5f86
movl $0x18, %edi
callq 0x20e0
movq %rax, %rbx
leaq 0x43ec(%rip), %rdx      # 0xa372
movq %rax, %rdi
movl $0x1, %esi
callq 0x8330
leaq 0x8df6(%rip), %rsi      # 0xed90
leaq 0x23bb(%rip), %rdx      # 0x835c
movq %rbx, %rdi
callq 0x2320
nop