// File: /workspace/github_cpp_makefile_star2_O2/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
pushq $0x14
popq %rdx
movq %rsi, %rdi
movq %r14, %rsi
callq 0x2220
movl 0x10(%r14), %eax
xorl %r13d, %r13d
pushq $0x3
popq %rcx
xorl %edx, %edx
divl %ecx
testl %edx, %edx
jne 0x54fe
movq %r14, %rdi
callq 0x559c
pushq $0x8
popq %r15
xorl %ebp, %ebp
movl 0x10(%r14), %eax
cmpq %rax, %rbp
jae 0x52bd
movl 0x4(%r14), %edx
movl %edx, %esi
imull %ebp, %esi
shlq $0x3, %rsi
addq 0x18(%r14), %rsi
shlq $0x3, %rdx
movq %rbx, %rdi
callq 0x2220
leaq (,%rbp,8), %r12
movq 0x20(%r14), %rsi
addq %r12, %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x2220
addq 0x28(%r14), %r12
movq %rbx, %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x2220
movss 0x40f8(%rip), %xmm1     # 0x92f0
movl 0x4(%r14), %eax
movq 0x18(%r14), %rcx
movq 0x30(%r14), %rdx
movl %eax, %esi
imull %r13d, %esi
movl %eax, %edi
imull %ebp, %edi
subq $0x1, %rax
jb 0x5268
movl %edi, %r8d
movswl (%rcx,%r8,8), %r9d
cvtsi2ss %r9d, %xmm0
mulss %xmm1, %xmm0
movl %esi, %r9d
movss %xmm0, (%rdx,%r9,4)
movswl 0x2(%rcx,%r8,8), %r9d
cvtsi2ss %r9d, %xmm0
mulss %xmm1, %xmm0
leal 0x1(%rsi), %r9d
movss %xmm0, (%rdx,%r9,4)
movswl 0x4(%rcx,%r8,8), %r8d
cvtsi2ss %r8d, %xmm0
mulss %xmm1, %xmm0
leal 0x2(%rsi), %r8d
movss %xmm0, (%rdx,%r8,4)
addl $0x3, %esi
incl %edi
jmp 0x520f
movq 0x20(%r14), %rax
movswl (%rax,%rbp,8), %ecx
cvtsi2ss %ecx, %xmm0
movq 0x38(%r14), %rcx
mulss %xmm1, %xmm0
leal (%rbp,%rbp,2), %edx
movss %xmm0, (%rcx,%rdx,4)
movswl 0x2(%rax,%rbp,8), %edx
cvtsi2ss %edx, %xmm0
mulss %xmm1, %xmm0
leal 0x1(%rbp,%rbp,2), %edx
movss %xmm0, (%rcx,%rdx,4)
movswl 0x4(%rax,%rbp,8), %eax
cvtsi2ss %eax, %xmm0
mulss %xmm1, %xmm0
leal 0x2(%rbp,%rbp,2), %eax
movss %xmm0, (%rcx,%rax,4)
incq %rbp
addl $0x3, %r13d
jmp 0x519a
leaq 0x40(%r14), %rsi
pushq $0x14
popq %rdx
movq %rbx, %rdi
callq 0x2220
movl 0x50(%r14), %ebp
movq %rbp, %r15
shlq $0x3, %r15
movq %r15, %rdi
callq 0x2030
movq %rax, 0x58(%r14)
movq %r15, %rdi
callq 0x2030
movq %rax, 0x60(%r14)
xorl %r12d, %r12d
pushq $0x8
popq %r15
xorl %r13d, %r13d
movl %ebp, %eax
cmpq %rax, %r13
jae 0x5366
movq 0x58(%r14), %rsi
addq %r12, %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x2220
movq 0x58(%r14), %rax
movl 0x4(%rax,%r12), %edi
testq %rdi, %rdi
je 0x5350
shlq $0x3, %rdi
callq 0x2030
movq 0x60(%r14), %rcx
movq %rax, (%rcx,%r12)
movq 0x58(%r14), %rax
movq 0x60(%r14), %rcx
movq (%rcx,%r12), %rsi
movl 0x4(%rax,%r12), %edx
shlq $0x3, %rdx
movq %rbx, %rdi
callq 0x2220
jmp 0x5359
movq 0x60(%r14), %rax
andq $0x0, (%rax,%r12)
incq %r13
movl 0x50(%r14), %ebp
addq $0x8, %r12
jmp 0x52f9
cmpl $0x8, 0x8(%r14)
jae 0x53c5
xorl %r13d, %r13d
leaq 0x6(%rsp), %r15
pushq $0x2
popq %r12
cmpq $0x4000, %r13           # imm = 0x4000
je 0x54e1
movq %rbx, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x2220
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,%r13,4)
incq %r13
jmp 0x5379
leaq 0x14(%rsp), %r15
pushq $0x4
popq %rdx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2220
movq %rbx, %rdi
callq 0x2310
addl (%r15), %eax
js 0x5526
movl %eax, %r13d
xorl %r15d, %r15d
movq %rsp, %rbp
pushq $0x2
popq %r12
movq %r13, 0x8(%rsp)
movq %rbx, %rdi
callq 0x2310
cmpq %r13, %rax
jge 0x54e1
movq %rbx, %rdi
movq %rbp, %rsi
movq %r12, %rdx
callq 0x2220
movzwl (%rsp), %eax
cmpw $0xff00, %ax            # imm = 0xFF00
jae 0x5479
movq %rbx, %rdi
leaq 0x4(%rsp), %rsi
movq %r12, %rdx
callq 0x2220
movzwl 0x4(%rsp), %edx
movl %edx, %esi
shll $0x13, %esi
movl %edx, %eax
shrl $0x7, %eax
movzwl (%rsp), %ecx
shll $0x6, %edx
andl $0xf800, %edx           # imm = 0xF800
orl %esi, %edx
andl $0xf8, %eax
orl %edx, %eax
orl $0xff000000, %eax       # imm = 0xFF000000
leal (%r15,%rcx), %edx
subl $0x1, %ecx
jb 0x5474
movl %r15d, %esi
incl %r15d
movl %eax, 0x68(%r14,%rsi,4)
jmp 0x5462
movl %edx, %r15d
jmp 0x53fb
xorl %r13d, %r13d
leal (%r15,%r13), %ebp
notl %eax
movzwl %ax, %eax
cmpl %eax, %r13d
ja 0x54d1
movq %rbx, %rdi
leaq 0x2(%rsp), %rsi
movq %r12, %rdx
callq 0x2220
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 %ebp, %eax
movl %edx, 0x68(%r14,%rax,4)
incl %r13d
movzwl (%rsp), %eax
jmp 0x547c
movl %ebp, %r15d
movq 0x8(%rsp), %r13
movq %rsp, %rbp
jmp 0x53fb
movq (%rbx), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x20(%rbx,%rax)
jne 0x5512
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x18
popq %rdi
callq 0x20e0
movq %rax, %rbx
leaq 0x3e40(%rip), %rdx      # 0x9350
jmp 0x5538
pushq $0x18
popq %rdi
callq 0x20e0
movq %rax, %rbx
leaq 0x3d16(%rip), %rdx      # 0x923a
jmp 0x5538
pushq $0x18
popq %rdi
callq 0x20e0
movq %rax, %rbx
leaq 0x3e3a(%rip), %rdx      # 0x9372
pushq $0x1
popq %rsi
movq %rax, %rdi
callq 0x7628
leaq 0x984e(%rip), %rsi      # 0xed98
leaq 0x2103(%rip), %rdx      # 0x7654
movq %rbx, %rdi
callq 0x22f0
nop