display-name: "Games/Battlechess 4000"
meta: {"Working": ["Packed file extraction", "Fullscreen images", "Sprites", "Sounds"], "Not working": "Music" }

if (file.name like "data640.dat")
{
	from "data640.off"
	{
		unsigned32[file.size / 4] offsets
	}

	from "data640.siz"
	{
		unsigned32[file.size / 4] sizes
	}
	
	name-offset: 0x65620
	i: 0
	file [offsets.length]
	{
		from "bc4000.exe" at name-offset + (i * 13)
		{
			fixed-string(13) name
		}

		decompressed-size: sizes[i]

		if (name == "dummy")
		{
			name = name + i
		}

		/*if ((name == "dummy") and (decompressed-size == 307978))
		{
			interpret-as "bc4000-rix3"
		}*/

		offset: offsets[i]

		if ((decompressed-size != 0xFFFFFFFF) and (decompressed-size != 0) and !(name like ["*.snd", "*.dat"]))
		{
			compressed "bc4000-lzss"
		}

		i = i + 1

		skip-if (decompressed-size == 0)
	}
}

if (file.name like ["*-*-*", "*}", "*{", "all?sefs", "dummy21"])
{
	folder: "Sprites"
	interpret-as "bc4000-sprite-atlas"
}

if (file.name like "*.xmi")
{
	folder: "Music"
}

file-format bc4000-sprite-atlas
{
	unsigned32 fat-offset
	unsigned32 after-fat //?

	at fat-offset:
	data(0x10) unknown

	loop (((after-fat - fat-offset) - 0x10) / 0x10)
	{
		unsigned16 width
		unsigned16 height
		signed16 paint-offset
		unsigned16 total-width
		unsigned32 sprite-offset
		data(4) unknown

		at sprite-offset
		{
			if (file.name like ["all?sefs", "dummy*", "p-w-s"])
			{
				image
				{
					padding-left: 0 - paint-offset
					format: "I8"
					transparent-index: 0
					palette: "board3d.scf"
				}
			}
			else
			{
				compressed[file.size - sprite-offset] "bc4000-sprite"
				{
					image
					{
						padding-left: 0 - paint-offset
						format: "I8"
						transparent-index: 0
						palette: "board3d.scf"
					}
				}
			}
		}

	}
}

if (file.name like ["smallexp.snd", "pawn.snd", "sounds1.dat", "walks1.dat"])
{
	text
}

if (file.name like ["*.scf", "dummy2"])
{
	interpret-as "bc4000-rix3"
}

if (file.name like "*.voc")
{
	interpret-as "sound-VOC"
}

file-format bc4000-rix3
{
	fixed-string(4) header == "RIX3"
	unsigned16 width
	unsigned16 height
	data (2) unknown

	palette
	{
		size: 256
		format: "R6G6B6"
	}

	data(5) unknown

	image
	{
		width: 640
		height: 480
		format: "I8"
	}
}

function bc4000-lzss
{
	decomp-buffer: [](4096)
	decomp-pointer: 0

	bytes-written: 0
	loop while (bytes-written < decompressed-size)
	{
		read unsigned8 mask

		loop (8)
		{
			if ((mask & 1) == 1)
			{
				read unsigned8 val
				write unsigned8 val
				decomp-buffer[decomp-pointer] = val
				decomp-pointer = (decomp-pointer + 1) & 0xFFF

				bytes-written = bytes-written + 1
			}
			else
			{
				read unsigned8 location
				read unsigned8 count

				location = location + ((count & 0xF0) << 4)
				location = location + 0x12

				count = count & 0xF

				count = count + 3

				loop (count): i
				{
					val: decomp-buffer[(location + i) & 0xFFF]
					write unsigned8 val
					decomp-buffer[decomp-pointer] = val
					decomp-pointer = (decomp-pointer + 1) & 0xFFF
				}

				bytes-written = bytes-written + count
			}

			mask = mask >> 1
		}
	}
}

function bc4000-sprite
{
	//data(12) unknown
	bytes-written: 0

	result-size: width * height

	loop while (bytes-written < result-size)
	{
		read unsigned8 token
		if ((token & 0x80) != 0)
		{
			loop (0xFF - token + 1)
			{
				read unsigned8 val
				write unsigned8 val
			}	
			bytes-written = bytes-written + (0xFF - token + 1)
		}
		else
		{
			read unsigned8 pixel
			loop (token + 1)
			{
				write unsigned8 pixel
			}
			bytes-written = bytes-written + token + 1
		}
	}
}