// File: /workspace/github_cpp_makefile_star2_O3/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
movq %r14, %rdi
movl $0x14, %edx
callq 0x21e0
movq (%r14), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x48(%rsp,%rax)
jne 0x701c
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2200
leaq 0x28(%rsp), %rdi
movl $0x14, %edx
movq %rbx, %rsi
callq 0x2260
cmpl $0x0, 0x10(%rbx)
je 0x6d73
xorl %r15d, %r15d
leaq 0x28(%rsp), %r14
xorl %r12d, %r12d
movl 0x4(%rbx), %edx
movl %r12d, %esi
imull %edx, %esi
shlq $0x3, %rsi
addq 0x18(%rbx), %rsi
shlq $0x3, %rdx
movq %r14, %rdi
callq 0x2260
movq 0x20(%rbx), %rsi
addq %r15, %rsi
movl $0x8, %edx
movq %r14, %rdi
callq 0x2260
movq 0x28(%rbx), %rsi
addq %r15, %rsi
movl $0x8, %edx
movq %r14, %rdi
callq 0x2260
incq %r12
movl 0x10(%rbx), %eax
addq $0x8, %r15
cmpq %rax, %r12
jb 0x6d1f
leaq 0x40(%rbx), %rsi
leaq 0x28(%rsp), %rdi
movl $0x14, %edx
callq 0x2260
cmpl $0x0, 0x50(%rbx)
je 0x6dd7
xorl %r15d, %r15d
leaq 0x28(%rsp), %r14
xorl %r12d, %r12d
movq 0x58(%rbx), %rsi
addq %r15, %rsi
movl $0x8, %edx
movq %r14, %rdi
callq 0x2260
movq 0x58(%rbx), %rax
movq 0x60(%rbx), %rcx
movq (%rcx,%r15), %rsi
movl 0x4(%rax,%r15), %edx
shlq $0x3, %rdx
movq %r14, %rdi
callq 0x2260
incq %r12
movl 0x50(%rbx), %eax
addq $0x8, %r15
cmpq %rax, %r12
jb 0x6d97
cmpl $0x8, 0x8(%rbx)
jae 0x6e34
xorl %r12d, %r12d
leaq 0x28(%rsp), %r14
leaq 0x10(%rsp), %r15
movl 0x68(%rbx,%r12,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, 0x10(%rsp)
movl $0x2, %edx
movq %r14, %rdi
movq %r15, %rsi
callq 0x2260
incq %r12
cmpq $0x4000, %r12           # imm = 0x4000
jne 0x6dea
jmp 0x6fbe
leaq 0x28(%rsp), %rdi
callq 0x2160
leaq 0x10(%rsp), %rsi
movl %eax, (%rsi)
leaq 0x28(%rsp), %rdi
movl $0x4, %edx
callq 0x2260
leaq 0x68(%rbx), %rbp
addq $0x6c, %rbx
xorl %r15d, %r15d
leaq 0x28(%rsp), %r14
leaq 0x16(%rsp), %r13
movslq %r15d, %rax
leaq (,%rax,4), %r12
addq %rbp, %r12
movl (%r12), %ecx
leaq (%rbx,%rax,4), %rax
xorl %edx, %edx
movq %rdx, %rsi
incq %rdx
cmpl (%rax,%rsi,4), %ecx
je 0x6e81
movl %edx, 0x18(%rsp)
cmpq $0x2, %rdx
jb 0x6ee6
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, 0xe(%rsp)
movl $0x2, %edx
movq %r14, %rdi
leaq 0x18(%rsp), %rsi
callq 0x2260
movl $0x2, %edx
movq %r14, %rdi
leaq 0xe(%rsp), %rsi
callq 0x2260
addl 0x18(%rsp), %r15d
jmp 0x6f79
movq %r15, 0x20(%rsp)
xorl %edx, %edx
leaq 0x1(%rdx), %rcx
cmpq $0xfe, %rdx
ja 0x6f06
movl (%rax,%rdx,4), %esi
cmpl %esi, -0x4(%rax,%rdx,4)
movq %rcx, %rdx
jne 0x6eed
movq %rbp, %r15
movl $0x1, %eax
subl %ecx, %eax
movw %ax, 0xe(%rsp)
movl $0x2, %edx
movq %r14, %rdi
leaq 0xe(%rsp), %rsi
callq 0x2260
notw 0xe(%rsp)
xorl %ebp, %ebp
movl (%r12,%rbp,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, 0x16(%rsp)
movl $0x2, %edx
movq %r14, %rdi
movq %r13, %rsi
callq 0x2260
incq %rbp
cmpw 0xe(%rsp), %bp
jbe 0x6f2e
movq 0x20(%rsp), %rax
addl %ebp, %eax
movq %r15, %rbp
movq %rax, %r15
cmpl $0x4000, %r15d          # imm = 0x4000
jl 0x6e69
leaq 0x28(%rsp), %rdi
callq 0x2160
movslq 0x10(%rsp), %rsi
subl %esi, %eax
addl $-0x4, %eax
movl %eax, 0x1c(%rsp)
leaq 0x28(%rsp), %rdi
xorl %edx, %edx
callq 0x2200
leaq 0x28(%rsp), %rdi
leaq 0x1c(%rsp), %rsi
movl $0x4, %edx
callq 0x2260
leaq 0x28(%rsp), %rdi
callq 0x2290
movq 0x28(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x48(%rsp,%rax)
jne 0x7025
movq 0x7fe9(%rip), %rax      # 0xefc8
movq (%rax), %rcx
movq 0x18(%rax), %rax
leaq 0x30(%rsp), %rdi
movq %rcx, -0x8(%rdi)
movq -0x18(%rcx), %rcx
movq %rax, 0x28(%rsp,%rcx)
callq 0x2150
leaq 0x120(%rsp), %rdi
callq 0x2080
addq $0x228, %rsp            # imm = 0x228
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3370(%rip), %rbx      # 0xa393
jmp 0x702c
leaq 0x338c(%rip), %rbx      # 0xa3b8
movl $0x18, %edi
callq 0x20e0
movq %rax, %r14
movq %rax, %rdi
movl $0x1, %esi
movq %rbx, %rdx
callq 0x8330
leaq 0x7d40(%rip), %rsi      # 0xed90
leaq 0x1305(%rip), %rdx      # 0x835c
movq %r14, %rdi
callq 0x2320
jmp 0x7073
jmp 0x7073
jmp 0x7073
jmp 0x7073
jmp 0x7073
jmp 0x7073
jmp 0x7073
jmp 0x7073
jmp 0x7073
jmp 0x7073
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x22b0
movq %rbx, %rdi
callq 0x2350