display-name: "Images/FLIC animation"

file-format animation-flic
{
	unsigned32 file-size
	unsigned16 magic // == 0xAF11 OR 0xAF12

	unsigned16 frame-count
	unsigned16 width
	unsigned16 height

	if (file-size != 0xC) //Bullfrog FLIC handling
	{
		unsigned16 bit-depth

		unsigned16 flags
		unsigned32 speed

		unsigned16 reserved1
		unsigned32 created
		unsigned32 creator

		unsigned32 updated
		unsigned32 updator

		unsigned16  aspect-dx
		unsigned16  aspect-dy
		unsigned16  egi-flags
		unsigned16  egi-keyframes
		unsigned16  egi-totalframes
		unsigned32 egi-req-memory
		unsigned16  egi-max-regions
		unsigned16  egi-transp-num
		data(24)  reserved2
		unsigned32 oframe1
		unsigned32 oframe2
		data(40) reserved3
	}

	previous-frame: [](width * height)
	palette: [](256 * 3)

	if ((magic == 0xAF12) and (file-size != 0xC))
	{
		at oframe1:
	}

	image-layout-width: 6400
	image-layout
	{

	loop(frame-count): frame
	{
		frame-start: file.position
		unsigned32 bytes-in-frame
		unsigned16 magic == 0xF1FA
		unsigned16 chunk-count
		data(8) unused

		loop (chunk-count)
		{
			chunk-start: file.position

			unsigned32 chunk-size
			unsigned16 chunk-type

			if (chunk-type == 4)
			{
				//FLI_COLOR
				unsigned16 packet-count-11
				palette-index: 0
				loop (packet-count-11)
				{
					unsigned8 color-skip
					palette-index = palette-index + (color-skip * 3)
					unsigned8 color-change

					if (color-change == 0)
					{
						color-change = 256
					}

					loop (color-change * 3): pal-col
					{
						read unsigned8 col

						if (file-size == 0xC)
						{
							palette[palette-index + pal-col] = col << 2
						}
						else
						{
							palette[palette-index + pal-col] = col
						}
					}
				}
			}
			else if (chunk-type == 7)
			{
				compressed[chunk-size - 6] "fli-ss2"
				{
					image
					{
						format: "I8"
					}

					at 0:
					unsigned8[width * height] decompressed-data
					previous-frame = decompressed-data
				}
			}
			else if (chunk-type == 11)
			{
				//FLI_COLOR
				unsigned16 packet-count-11
				palette-index: 0
				loop (packet-count-11)
				{
					unsigned8 color-skip
					palette-index = palette-index + (color-skip * 3)
					unsigned8 color-change

					if (color-change == 0)
					{
						color-change = 256
					}

					loop (color-change * 3): pal-col
					{
						read unsigned8 col
						palette[palette-index + pal-col] = col << 2
					}
				}
			}
			else if (chunk-type == 12)
			{
				compressed[chunk-size - 6] "fli-lc"
				{
					image
					{
						format: "I8"
					}

					at 0:
					unsigned8[width * height] decompressed-data
					previous-frame = decompressed-data
				}
			}
			else if (chunk-type == 13)
			{
				loop (width * height)
				{
					compressed[chunk-size - 6] "fli-black"
					{
						image
						{
							format: "I8"
						}

						at 0:
						unsigned8[width * height] decompressed-data
						previous-frame = decompressed-data
					}
				}
			}
			else if (chunk-type == 15)
			{
				compressed[chunk-size - 6] "fli-brun"
				{
					image
					{
						format: "I8"
					}

					at 0:
					unsigned8[width * height] decompressed-data
					previous-frame = decompressed-data
				}
			}
			else if (chunk-type == 16)
			{
				image
				{
					format: "I8"
				}
			}
			else
			{
				//log("Unknown chunk " + chunk-type)
				data(chunk-size - 6) unused
			}

			at chunk-start + chunk-size:
		}

		at frame-start + bytes-in-frame:		
	}

	}
}

function fli-brun
{
	decompressed-this:[](width * height)

	loop (/*height*/160): y
	{
		x: 0
		unsigned8 packet-count-brun

		loop (packet-count-brun)
		{
			signed8 count
			
			if (count > 0)
			{
				read unsigned8 pixel-fill
				loop (count): i
				{
					decompressed-this[(y * width) + x + i] = pixel-fill
				}

				x = x + count
			}
			else
			{
				loop (0 - count): j
				{
					read unsigned8 pixel
					decompressed-this[(y * width) + x + j] = pixel
				}

				x = x + (0 - count)
			}

		}
	}

	write unsigned8 decompressed-this
}

function fli-black
{
	decompressed-this:[](width * height)
	write unsigned8 decompressed-this
}

function fli-lc
{
	decompressed-this:[](width * height)
	loop(width*height): ohno
	{
		decompressed-this[ohno] = previous-frame[ohno]
	}

	unsigned16 start-y
	//log("Start: " + start-y)

	loop (start-y * width): i
	{
		decompressed-this[i] = previous-frame[i]
	}

	unsigned16 lines-changed

	loop (lines-changed): y
	{
		x: 0
		current-y: y + start-y

		unsigned8 packet-count

		loop (packet-count)
		{
			unsigned8 skip-count
			x = x + skip-count

			signed8 size-count

			if (size-count > 0)
			{
				loop (size-count): i
				{
					read unsigned8 pixel
					decompressed-this[(current-y * width) + x + i] = pixel
				}

				x = x + size-count
			}
			else if (size-count != 0)
			{
				read unsigned8 pixel-fill
				loop (0 - size-count): j
				{
					decompressed-this[(current-y * width) + x + j] = pixel-fill
				}

				x = x + (0 - size-count)
			}
		}
	}

	write unsigned8 decompressed-this
}

function fli-ss2
{
	decompressed-this:[](width * height)
	loop(width*height): ohno
	{
		decompressed-this[ohno] = previous-frame[ohno]
	}

	unsigned16 lines-changed
	y: 0

	loop (lines-changed)
	{
		x: 0

		found-packet-count: false
		packet-count: 0

		loop while(found-packet-count == false)
		{
			unsigned16 opcode

			optype: opcode >> 14
			if (optype == 0)
			{
				found-packet-count = true
				packet-count = opcode
			}
			else if (optype == 2)
			{
				decompressed-this[(y * width) + (width - 1)] = (opcode & 0xFF)
			}
			else if (optype == 3)
			{
				at file.position - 2
				{
					signed16 line-skip
					y = y + (0 - line-skip)
				}
			}
		}

		loop (packet-count)
		{
			unsigned8 skip-count
			x = x + skip-count

			signed8 size-count

			if (size-count > 0)
			{
				loop (size-count): i
				{
					read unsigned16 pixel
					decompressed-this[(y * width) + x + (i * 2) + 1] = (pixel >> 8)
					decompressed-this[(y * width) + x + (i * 2)] = (pixel & 0xFF)
				}

				x = x + (size-count * 2)
			}
			else if (size-count != 0)
			{
				read unsigned16 pixel-fill
				loop (0 - size-count): j
				{
					decompressed-this[(y * width) + x + (j * 2) + 1] = (pixel-fill >> 8)
					decompressed-this[(y * width) + x + (j * 2)] = (pixel-fill & 0xFF)
				}

				x = x + ((0 - size-count) * 2)
			}
		}

		y = y + 1
	}

	write unsigned8 decompressed-this
}

if (file.name like "*.*") {
	interpret-as "animation-flic"
}