// File: 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
movq %rsp, %rbp
subq $0x300, %rsp            # imm = 0x300
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x2b0(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x2a8(%rbp)
movl $0x10, %edi
movl $0x4, %esi
callq 0x9de0
movq -0x2a8(%rbp), %rsi
movl %eax, %edx
leaq -0x210(%rbp), %rdi
callq 0x2200
movq -0x210(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x210(%rbp,%rax), %rdi
callq 0x2030
movb %al, -0x299(%rbp)
jmp 0xbf5d
movb -0x299(%rbp), %al
testb $0x1, %al
jne 0xbf69
jmp 0xbfd0
movl $0x18, %edi
callq 0x20f0
movq %rax, %rdi
movq %rdi, -0x2b8(%rbp)
leaq 0x531f(%rip), %rdx      # 0x112a3
movl $0x1, %esi
callq 0xf0b0
movq -0x2b8(%rbp), %rdi
leaq 0xbdf4(%rip), %rsi      # 0x17d90
leaq 0x31ad(%rip), %rdx      # 0xf150
callq 0x2340
jmp 0xc6b6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x218(%rbp)
movl %eax, -0x21c(%rbp)
leaq -0x210(%rbp), %rdi
callq 0x22e0
jmp 0xc6aa
xorl %eax, %eax
movl %eax, %esi
leaq -0x230(%rbp), %rdi
callq 0x9e00
jmp 0xbfe2
movq -0x230(%rbp), %rsi
movq -0x228(%rbp), %rdx
leaq -0x210(%rbp), %rdi
callq 0x2210
jmp 0xbffe
movq -0x2b0(%rbp), %rsi
leaq -0x210(%rbp), %rdi
movl $0x14, %edx
callq 0x2280
jmp 0xc018
movl $0x0, -0x234(%rbp)
movq -0x2b0(%rbp), %rcx
movl -0x234(%rbp), %eax
cmpl 0x10(%rcx), %eax
jae 0xc0cd
movq -0x2b0(%rbp), %rdx
movq 0x18(%rdx), %rax
movl -0x234(%rbp), %ecx
movl 0x4(%rdx), %edx
movl %edx, %esi
imull %esi, %ecx
leaq (%rax,%rcx,8), %rsi
shlq $0x3, %rdx
leaq -0x210(%rbp), %rdi
callq 0x2280
jmp 0xc067
movq -0x2b0(%rbp), %rax
movq 0x20(%rax), %rax
movl -0x234(%rbp), %ecx
leaq (%rax,%rcx,8), %rsi
leaq -0x210(%rbp), %rdi
movl $0x8, %edx
callq 0x2280
jmp 0xc08f
movq -0x2b0(%rbp), %rax
movq 0x28(%rax), %rax
movl -0x234(%rbp), %ecx
leaq (%rax,%rcx,8), %rsi
leaq -0x210(%rbp), %rdi
movl $0x8, %edx
callq 0x2280
jmp 0xc0b7
jmp 0xc0b9
movl -0x234(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x234(%rbp)
jmp 0xc022
movq -0x2b0(%rbp), %rsi
addq $0x40, %rsi
leaq -0x210(%rbp), %rdi
movl $0x14, %edx
callq 0x2280
jmp 0xc0eb
movl $0x0, -0x238(%rbp)
movq -0x2b0(%rbp), %rcx
movl -0x238(%rbp), %eax
cmpl 0x50(%rcx), %eax
jae 0xc173
movq -0x2b0(%rbp), %rax
movq 0x58(%rax), %rax
movl -0x238(%rbp), %ecx
leaq (%rax,%rcx,8), %rsi
leaq -0x210(%rbp), %rdi
movl $0x8, %edx
callq 0x2280
jmp 0xc12f
movq -0x2b0(%rbp), %rcx
movq 0x58(%rcx), %rax
movq 0x60(%rcx), %rdx
movl -0x238(%rbp), %ecx
movq (%rdx,%rcx,8), %rsi
movl 0x4(%rax,%rcx,8), %eax
movl %eax, %edx
shlq $0x3, %rdx
leaq -0x210(%rbp), %rdi
callq 0x2280
jmp 0xc160
jmp 0xc162
movl -0x238(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x238(%rbp)
jmp 0xc0f5
movq -0x2b0(%rbp), %rax
cmpl $0x7, 0x8(%rax)
ja 0xc243
movl $0x0, -0x240(%rbp)
cmpl $0x4000, -0x240(%rbp)   # imm = 0x4000
jge 0xc23e
movq -0x2b0(%rbp), %rax
movslq -0x240(%rbp), %rcx
movb 0x6a(%rax,%rcx,4), %cl
movb %cl, -0x241(%rbp)
movslq -0x240(%rbp), %rcx
movb 0x69(%rax,%rcx,4), %cl
movb %cl, -0x242(%rbp)
movslq -0x240(%rbp), %rcx
movb 0x68(%rax,%rcx,4), %al
movb %al, -0x243(%rbp)
movzbl -0x241(%rbp), %edx
shrl $0x3, %edx
movzbl -0x242(%rbp), %eax
andl $0xf8, %eax
movl %eax, %ecx
movl %edx, %eax
leal (%rax,%rcx,4), %eax
movzbl -0x243(%rbp), %ecx
shll $0x7, %ecx
andl $0x7c00, %ecx           # imm = 0x7C00
orl %ecx, %eax
movw %ax, -0x23a(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x23a(%rbp), %rsi
movl $0x2, %edx
callq 0x2280
jmp 0xc228
jmp 0xc22a
movl -0x240(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x240(%rbp)
jmp 0xc18e
jmp 0xc61a
leaq -0x210(%rbp), %rdi
callq 0x2180
movq %rdx, -0x2c8(%rbp)
movq %rax, -0x2c0(%rbp)
jmp 0xc25f
movq -0x2c8(%rbp), %rax
movq -0x2c0(%rbp), %rcx
movq %rcx, -0x258(%rbp)
movq %rax, -0x250(%rbp)
leaq -0x258(%rbp), %rdi
callq 0xc710
movq %rax, -0x2d0(%rbp)
jmp 0xc290
movq -0x2d0(%rbp), %rax
movl %eax, -0x248(%rbp)
movl $0x0, -0x25c(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x248(%rbp), %rsi
movl $0x4, %edx
callq 0x2280
jmp 0xc2c1
movl $0x0, -0x260(%rbp)
cmpl $0x4000, -0x260(%rbp)   # imm = 0x4000
jge 0xc55c
movl $0x1, -0x264(%rbp)
movq -0x2b0(%rbp), %rcx
movslq -0x260(%rbp), %rax
movl 0x68(%rcx,%rax,4), %eax
movl -0x260(%rbp), %edx
addl -0x264(%rbp), %edx
movslq %edx, %rdx
cmpl 0x68(%rcx,%rdx,4), %eax
jne 0xc31d
movl -0x264(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x264(%rbp)
jmp 0xc2e5
cmpl $0x1, -0x264(%rbp)
jle 0xc3d8
movq -0x2b0(%rbp), %rax
movslq -0x260(%rbp), %rcx
movb 0x6a(%rax,%rcx,4), %cl
movb %cl, -0x265(%rbp)
movslq -0x260(%rbp), %rcx
movb 0x69(%rax,%rcx,4), %cl
movb %cl, -0x266(%rbp)
movslq -0x260(%rbp), %rcx
movb 0x68(%rax,%rcx,4), %al
movb %al, -0x267(%rbp)
movzbl -0x265(%rbp), %eax
shrl $0x3, %eax
movzbl -0x266(%rbp), %ecx
shll $0x2, %ecx
orl %ecx, %eax
movzbl -0x267(%rbp), %ecx
shll $0x7, %ecx
orl %ecx, %eax
movw %ax, -0x26a(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x264(%rbp), %rsi
movl $0x2, %edx
callq 0x2280
jmp 0xc3a7
leaq -0x210(%rbp), %rdi
leaq -0x26a(%rbp), %rsi
movl $0x2, %edx
callq 0x2280
jmp 0xc3c1
movl -0x264(%rbp), %eax
addl -0x260(%rbp), %eax
movl %eax, -0x260(%rbp)
jmp 0xc557
movw $0x0, -0x26c(%rbp)
movq -0x2b0(%rbp), %rdx
movl -0x260(%rbp), %eax
movzwl -0x26c(%rbp), %ecx
addl %ecx, %eax
cltq
movl 0x68(%rdx,%rax,4), %ecx
movl -0x260(%rbp), %eax
movzwl -0x26c(%rbp), %esi
addl %esi, %eax
addl $0x1, %eax
movslq %eax, %rsi
xorl %eax, %eax
cmpl 0x68(%rdx,%rsi,4), %ecx
movb %al, -0x2d1(%rbp)
je 0xc435
movzwl -0x26c(%rbp), %eax
cmpl $0xff, %eax
setl %al
movb %al, -0x2d1(%rbp)
movb -0x2d1(%rbp), %al
testb $0x1, %al
jne 0xc441
jmp 0xc455
movw -0x26c(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x26c(%rbp)
jmp 0xc3e1
movw -0x26c(%rbp), %ax
negw %ax
movw %ax, -0x26c(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x26c(%rbp), %rsi
movl $0x2, %edx
callq 0x2280
jmp 0xc480
movzwl -0x26c(%rbp), %eax
xorl $0xffff, %eax           # imm = 0xFFFF
movw %ax, -0x26c(%rbp)
movw $0x0, -0x26e(%rbp)
movzwl -0x26e(%rbp), %eax
movzwl -0x26c(%rbp), %ecx
cmpl %ecx, %eax
jg 0xc555
movq -0x2b0(%rbp), %rax
movslq -0x260(%rbp), %rcx
movb 0x6a(%rax,%rcx,4), %cl
movb %cl, -0x26f(%rbp)
movslq -0x260(%rbp), %rcx
movb 0x69(%rax,%rcx,4), %cl
movb %cl, -0x270(%rbp)
movslq -0x260(%rbp), %rcx
movb 0x68(%rax,%rcx,4), %al
movb %al, -0x271(%rbp)
movzbl -0x26f(%rbp), %eax
shrl $0x3, %eax
movzbl -0x270(%rbp), %ecx
shll $0x2, %ecx
orl %ecx, %eax
movzbl -0x271(%rbp), %ecx
shll $0x7, %ecx
orl %ecx, %eax
movw %ax, -0x274(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x274(%rbp), %rsi
movl $0x2, %edx
callq 0x2280
jmp 0xc52f
movl -0x260(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x260(%rbp)
movw -0x26e(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x26e(%rbp)
jmp 0xc49c
jmp 0xc557
jmp 0xc2cb
leaq -0x210(%rbp), %rdi
callq 0x2180
movq %rdx, -0x2e8(%rbp)
movq %rax, -0x2e0(%rbp)
jmp 0xc578
movq -0x2e8(%rbp), %rax
movq -0x2e0(%rbp), %rcx
movq %rcx, -0x288(%rbp)
movq %rax, -0x280(%rbp)
leaq -0x288(%rbp), %rdi
callq 0xc710
movq %rax, -0x2f0(%rbp)
jmp 0xc5a9
movq -0x2f0(%rbp), %rax
movl %eax, -0x25c(%rbp)
movl -0x248(%rbp), %ecx
movl -0x25c(%rbp), %eax
subl %ecx, %eax
addl $-0x4, %eax
movl %eax, -0x25c(%rbp)
movslq -0x248(%rbp), %rsi
leaq -0x298(%rbp), %rdi
callq 0x9e00
jmp 0xc5e2
movq -0x298(%rbp), %rsi
movq -0x290(%rbp), %rdx
leaq -0x210(%rbp), %rdi
callq 0x2210
jmp 0xc5fe
leaq -0x210(%rbp), %rdi
leaq -0x25c(%rbp), %rsi
movl $0x4, %edx
callq 0x2280
jmp 0xc618
jmp 0xc61a
leaq -0x210(%rbp), %rdi
callq 0x22c0
jmp 0xc628
movq -0x210(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x210(%rbp,%rax), %rdi
callq 0x2030
movb %al, -0x2f1(%rbp)
jmp 0xc648
movb -0x2f1(%rbp), %al
testb $0x1, %al
jne 0xc654
jmp 0xc695
movl $0x18, %edi
callq 0x20f0
movq %rax, %rdi
movq %rdi, -0x300(%rbp)
leaq 0x4c59(%rip), %rdx      # 0x112c8
movl $0x1, %esi
callq 0xf0b0
movq -0x300(%rbp), %rdi
leaq 0xb709(%rip), %rsi      # 0x17d90
leaq 0x2ac2(%rip), %rdx      # 0xf150
callq 0x2340
jmp 0xc6b6
leaq -0x210(%rbp), %rdi
callq 0x22e0
addq $0x300, %rsp            # imm = 0x300
popq %rbp
retq
movq -0x218(%rbp), %rdi
callq 0x2370
nopw %cs:(%rax,%rax)