// File: /workspace/github_cpp_makefile_star2_O2/ticky[P]ps2iconsys/src/ps2_ps2icon.cpp
// Function: PS2Icon::WriteFile(char const*) const
void PS2Icon::WriteFile(const char * fname) const {
	std::ofstream fout(fname, std::ios_base::out | std::ios_base::binary);
	if(fout.fail()) { 
		throw( Ghulbus::gbException( Ghulbus::gbException::GB_FAILED,
			                         "Output icon file could not be opened") );
	}
	fout.seekp(std::ios::beg);

	//write header:
	fout.write( reinterpret_cast<char const*>(&header), sizeof(Icon_Header) );

	//write vertex segment:
	for(unsigned int i=0; i<header.n_vertices; i++) {
		//vertex coordinates, one for each shape:
		fout.write( reinterpret_cast<char*>(&vertices[i*header.animation_shapes]),
			        sizeof(Vertex_Coord) * header.animation_shapes );
		//normal coordinates:
		fout.write( reinterpret_cast<char*>(&normals[i]), sizeof(Vertex_Coord) );
		//texture coordinates:
		fout.write( reinterpret_cast<char*>(&vert_texture[i]), sizeof(Texture_Data) );
	}

	//write animation segment:
	//header:
	fout.write( reinterpret_cast<char const*>(&anim_header), sizeof(Animation_Header) );
	//data:
	for(unsigned int i=0; i<anim_header.n_frames; i++) {
		fout.write( reinterpret_cast<char*>(&animation[i]), sizeof(Frame_Data) );
		fout.write( reinterpret_cast<char*>(anim_keys[i]), sizeof(Frame_Key) * animation[i].n_keys );
	}

	//write texture segment:
	if(header.texture_type <= 0x07) {
		//uncompressed:
		unsigned short c;
		for(int i=0; i<16384; i++) {
			unsigned char r = static_cast<unsigned char>( (texture[i] >> 16) & 0xff );
			unsigned char g = static_cast<unsigned char>( (texture[i] >>  8) & 0xff );
			unsigned char b = static_cast<unsigned char>(  texture[i]        & 0xff );
			c = static_cast<unsigned short>( ((r >> 3) & 0x001f) | ((g << 2) & 0x03e0) | ((b << 7) & 0x7c00) );
			fout.write( reinterpret_cast<char*>(&c), 2 );
		}
	} else {
		//compressed textures:
		//allocate space for size info:
		int base = fout.tellp();
		unsigned int size = 0;
		fout.write( reinterpret_cast<char*>(&base), 4 );	//dummy data
		//rle main loop:
		int i=0;
		while(i<16384) {
			//rle step 1: count replication
			int rep_count = 1;
			while( (texture[i] == texture[i+rep_count]) ) { rep_count++; }
			if(rep_count > 1) {		//pixels are replicated rep_count times
				unsigned char r = static_cast<unsigned char>( (texture[i] >> 16) & 0xff );
				unsigned char g = static_cast<unsigned char>( (texture[i] >>  8) & 0xff );
				unsigned char b = static_cast<unsigned char>(  texture[i]        & 0xff );
				unsigned short c = ((unsigned short)(r >> 3) | (g << 2) | (b << 7) );
				fout.write( reinterpret_cast<char*>(&rep_count), 2 );
				fout.write( reinterpret_cast<char*>(&c), 2 );
				i += rep_count;
			} else {				//no replication
				unsigned short pix_count = 0;	//number of non equal subsequent pixels
				while((texture[i+pix_count] != texture[i+pix_count+1]) &&
				      (pix_count < 255) ) { pix_count++; }
				pix_count = 0xFFFF ^ (pix_count-1);
				fout.write( reinterpret_cast<char*>(&pix_count), 2 );
				pix_count ^= 0xFFFF;
				for(unsigned short j=0; j<=pix_count; j++) {		//insert pixels:
					unsigned char r = static_cast<unsigned char>( (texture[i] >> 16) & 0xff );
					unsigned char g = static_cast<unsigned char>( (texture[i] >>  8) & 0xff );
					unsigned char b = static_cast<unsigned char>(  texture[i]        & 0xff );
					unsigned short c = ((unsigned short)(r >> 3) | (g << 2) | (b << 7) );
					fout.write( reinterpret_cast<char*>(&c), 2 );
					i++;
				}
			}
		}
		//finalize: write size of the encoded segment to base:
		size = fout.tellp();
		size -= (base + 4);

		fout.seekp(base);
		fout.write( reinterpret_cast<char*>(&size), 4 );
	}

	fout.close();
	if(fout.fail()) { 
		throw( Ghulbus::gbException( Ghulbus::gbException::GB_FAILED,
			                         "Error while writing output icon file") );
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x228, %rsp            # imm = 0x228
movq %rdi, %rbx
leaq 0x28(%rsp), %r14
pushq $0x14
popq %rdx
movq %r14, %rdi
callq 0x21c0
movq (%r14), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x48(%rsp,%rax)
jne 0x64a7
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21e0
leaq 0x28(%rsp), %rdi
pushq $0x14
popq %rdx
movq %rbx, %rsi
callq 0x2240
xorl %r12d, %r12d
leaq 0x28(%rsp), %r14
pushq $0x8
popq %r15
xorl %r13d, %r13d
movl 0x10(%rbx), %eax
cmpq %rax, %r13
jae 0x621d
movl 0x4(%rbx), %edx
movl %r13d, %esi
imull %edx, %esi
shlq $0x3, %rsi
addq 0x18(%rbx), %rsi
shlq $0x3, %rdx
movq %r14, %rdi
callq 0x2240
movq 0x20(%rbx), %rsi
addq %r12, %rsi
movq %r14, %rdi
movq %r15, %rdx
callq 0x2240
movq 0x28(%rbx), %rsi
addq %r12, %rsi
movq %r14, %rdi
movq %r15, %rdx
callq 0x2240
incq %r13
addq $0x8, %r12
jmp 0x61cb
leaq 0x40(%rbx), %rsi
leaq 0x28(%rsp), %rdi
pushq $0x14
popq %rdx
callq 0x2240
xorl %r12d, %r12d
leaq 0x28(%rsp), %r14
pushq $0x8
popq %r15
xorl %r13d, %r13d
movl 0x50(%rbx), %eax
cmpq %rax, %r13
jae 0x627d
movq 0x58(%rbx), %rsi
addq %r12, %rsi
movq %r14, %rdi
movq %r15, %rdx
callq 0x2240
movq 0x58(%rbx), %rax
movq 0x60(%rbx), %rcx
movq (%rcx,%r12), %rsi
movl 0x4(%rax,%r12), %edx
shlq $0x3, %rdx
movq %r14, %rdi
callq 0x2240
incq %r13
addq $0x8, %r12
jmp 0x623d
cmpl $0x8, 0x8(%rbx)
jae 0x62dd
xorl %r13d, %r13d
leaq 0x28(%rsp), %r14
leaq 0x8(%rsp), %r15
pushq $0x2
popq %r12
cmpq $0x4000, %r13           # imm = 0x4000
je 0x6471
movl 0x68(%rbx,%r13,4), %eax
movl %eax, %ecx
shrl $0x13, %ecx
andl $0x1f, %ecx
movl %eax, %edx
shrl $0x6, %edx
andl $0x3e0, %edx            # imm = 0x3E0
orl %ecx, %edx
shll $0x7, %eax
andl $0x7c00, %eax           # imm = 0x7C00
orl %edx, %eax
movw %ax, 0x8(%rsp)
movq %r14, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x2240
incq %r13
jmp 0x6294
leaq 0x28(%rsp), %rdi
callq 0x2150
leaq 0x8(%rsp), %rsi
movl %eax, (%rsi)
leaq 0x28(%rsp), %rdi
pushq $0x4
popq %rdx
callq 0x2240
leaq 0x68(%rbx), %r13
addq $0x6c, %rbx
xorl %eax, %eax
leaq 0x28(%rsp), %r14
pushq $0x2
popq %r12
leaq 0xe(%rsp), %rbp
movq %r13, 0x20(%rsp)
cmpl $0x3fff, %eax           # imm = 0x3FFF
jg 0x643b
movq %rax, 0x18(%rsp)
cltq
leaq (,%rax,4), %r15
addq %r13, %r15
movl (%r15), %ecx
leaq (%rbx,%rax,4), %rax
xorl %edx, %edx
movq %rdx, %rsi
incq %rdx
cmpl (%rax,%rsi,4), %ecx
je 0x633e
movl %edx, 0x10(%rsp)
cmpq $0x2, %rdx
jb 0x63a3
movl %ecx, %eax
shrl $0x13, %eax
andl $0x1f, %eax
movl %ecx, %edx
shrl $0x6, %edx
andl $0x3fc, %edx            # imm = 0x3FC
orl %eax, %edx
movzbl %cl, %eax
shll $0x7, %eax
orl %edx, %eax
movw %ax, 0x6(%rsp)
movq %r14, %rdi
leaq 0x10(%rsp), %rsi
movq %r12, %rdx
callq 0x2240
movq %r14, %rdi
leaq 0x6(%rsp), %rsi
movq %r12, %rdx
callq 0x2240
movq 0x18(%rsp), %rax
addl 0x10(%rsp), %eax
jmp 0x6318
xorl %edx, %edx
leaq 0x1(%rdx), %rcx
cmpq $0xfe, %rdx
ja 0x63be
movl (%rax,%rdx,4), %esi
cmpl %esi, -0x4(%rax,%rdx,4)
movq %rcx, %rdx
jne 0x63a5
pushq $0x1
popq %rax
subl %ecx, %eax
movw %ax, 0x6(%rsp)
movq %r14, %rdi
leaq 0x6(%rsp), %rsi
movq %r12, %rdx
callq 0x2240
movzwl 0x6(%rsp), %eax
notl %eax
movw %ax, 0x6(%rsp)
xorl %r13d, %r13d
cmpw %ax, %r13w
ja 0x6429
movl (%r15,%r13,4), %eax
movl %eax, %ecx
movzbl %al, %edx
shrl $0x13, %eax
andl $0x1f, %eax
shrl $0x6, %ecx
andl $0x3fc, %ecx            # imm = 0x3FC
orl %eax, %ecx
shll $0x7, %edx
orl %ecx, %edx
movw %dx, 0xe(%rsp)
movq %r14, %rdi
movq %rbp, %rsi
movq %r12, %rdx
callq 0x2240
movzwl 0x6(%rsp), %eax
incq %r13
jmp 0x63e7
movq 0x18(%rsp), %rax
addl %r13d, %eax
movq 0x20(%rsp), %r13
jmp 0x6318
leaq 0x28(%rsp), %rdi
callq 0x2150
movslq 0x8(%rsp), %rsi
subl %esi, %eax
addl $-0x4, %eax
movl %eax, 0x14(%rsp)
leaq 0x28(%rsp), %rdi
xorl %edx, %edx
callq 0x21e0
leaq 0x28(%rsp), %rdi
leaq 0x14(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0x2240
leaq 0x28(%rsp), %rdi
callq 0x2270
movq 0x28(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x48(%rsp,%rax)
jne 0x64b0
leaq 0x28(%rsp), %rdi
callq 0x2290
addq $0x228, %rsp            # imm = 0x228
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2ee5(%rip), %rbx      # 0x9393
jmp 0x64b7
leaq 0x2f01(%rip), %rbx      # 0x93b8
pushq $0x18
popq %rdi
callq 0x20e0
movq %rax, %r14
pushq $0x1
popq %rsi
movq %rax, %rdi
movq %rbx, %rdx
callq 0x7628
leaq 0x88c1(%rip), %rsi      # 0xed98
leaq 0x1176(%rip), %rdx      # 0x7654
movq %r14, %rdi
callq 0x22f0
jmp 0x64fa
jmp 0x64fa
jmp 0x64fa
jmp 0x64fa
jmp 0x64fa
jmp 0x64fa
jmp 0x64fa
jmp 0x64fa
jmp 0x64fa
jmp 0x64fa
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x2290
movq %rbx, %rdi
callq 0x2320
nop