#include "blue-dream.h"

void md_pattern_name_set_resource(
	t_md_pattern_name *pn,
	t_byte *resource,
	int index)
{
	int z = unpack_word(resource, index * 2);

	pn->priority = (z & 0x8000) >> 15;
	pn->palette_id = (z & 0x7000) >> 13;
	pn->vflip = (z & 0x1000) >> 12;
	pn->hflip = (z & 0x0800) >> 11;
	pn->pattern_id = z & 0x07ff;
}

void plot_etd_tile(
	t_plot_state *ps,
	t_plot_state *pp,
	t_md_pattern_name *pn,
	int x, int y)
{
	if ((x + pp->source_w) < 0) return;
	if ((y + pp->source_h) < 0) return;
	if (x >= pp->destination_w) return;
	if (y >= pp->destination_h) return;

	t_plot_state *next = plot_state_add_vacant(ps);

	plot_state_set_palette(
		next,
		pp->palette,
		16,
		64,
		pn->palette_id);

	plot_state_set_source(
		next,
		pp->source,
		pp->source_w,
		pp->source_h);

	next->source_size = pp->source_size;

	plot_state_set_destination(
		next,
		pp->destination,
		pp->destination_w,
		pp->destination_h);
	
	set_horizontal_clip(
		x,
		next->source_w,
		next->destination_w,
		next->source_clip,
		next->destination_clip
	);

	set_vertical_clip(
		y,
		next->source_h,
		next->destination_h,
		next->source_clip,
		next->destination_clip
	);
	
	plot_state_set_source_region(
		next,
		0, 0, 8, 8,
		pn->pattern_id);
	
	next->mode = pp->mode;
	if (pn->priority == 0)
		next->mode |= PS_SHADOW;
		
	if (NOT_ZERO(pn->vflip) && NOT_ZERO(pn->hflip))
		next->input = ps_input_vhflip;
	else  if (NOT_ZERO(pn->vflip))
		next->input = ps_input_vflip;
	else if (NOT_ZERO(pn->hflip))
		next->input = ps_input_hflip;
	else
		next->input = ps_input_default;

	next->output = ps_output_default;
	next->plot = ps_plot_md_indexed;
}

void plot_etd_metatile(
	t_plot_state *ps,
	t_plot_state *pp,
	t_byte *resource,
	int position_x, int position_y,
	int w, int h)
{
	int x = 0, y = 0, z = 0;

	t_md_pattern_name *pn = m_alloc(t_md_pattern_name, 1);

	for (y = 0; y < h; y++)
	{
		for (x = 0; x < w; x++)
		{
			md_pattern_name_set_resource(pn, resource, z);

			plot_etd_tile(
				ps,
				pp,
				pn,
				position_x + (x * 8),
				position_y + (y * 8));

			z++;
		}
	}

	free(pn);
}

t_dword *get_metatile_offset_table(t_byte *resource, int offset, int total)
{
	int index = 0;
	t_dword *table = NULL;
		
	table = m_array(t_dword, total);
	if (table == NULL) return NULL;

	for (index = 0; index < total; index++)
		table[index] = unpack_word(
			resource, offset + (index * 4));

	return table;
}

t_dword *get_metatile_ptable(t_byte *resource, int offset, int total)
{
	int index = 0;
	t_dword *ptable = NULL;

	ptable = m_array(t_dword, total);
	if (ptable == NULL) return NULL;

	for (index = 0; index < total; index++)
		ptable[index] = unpack_dword(
			resource, offset + (index * 4));

	return ptable;
}

t_md_metatile *get_md_metatile(
	t_byte *resource,
	int offset,
	int w,
	int h
)
{
	int index = 0, size = 0;
	t_byte *u = 0;

	t_byte *raw = NULL;
	t_md_metatile *metatile = NULL;

	u = &resource[offset];
	if (w == 0 || h == 0)
	{
		w = u[0];
		h = u[1];
		u = &resource[offset + 2];
	}

	size = w * h * 2;
	raw = m_array(t_byte, size);
	if (raw == NULL) return NULL;

	for (index = 0; index < size; index++)
		raw[index] = 0;

	for (index = 0; index < size; index++)
		raw[index] = u[index];

	metatile = m_alloc(t_md_metatile);
	if (metatile == NULL) goto _RELEASE;

	metatile->w = w;
	metatile->h = h;
	metatile->raw = raw;

	return metatile;

_RELEASE:

	if (NOT_NULL(raw))
		free(raw);

	return NULL;
}

void release_md_metatile(t_md_metatile *md_metatile)
{
	if (NOT_NULL(md_metatile))
	{
		if (NOT_NULL(md_metatile->raw))
		{
			free(md_metatile->raw);
			md_metatile->raw = NULL;
		}

		free(md_metatile);
	}
}

t_md_metatile **create_md_metatile_table(int total)
{
	int index = 0;
	t_md_metatile **table = NULL;

	table = m_parray(t_md_metatile, total);
	if (table == NULL) return NULL;

	for (index = 0; index < total; index++)
		table[index] = NULL;

	return table;
}

void release_md_metatile_table(t_md_metatile **table, int total)
{
	int index = 0;

	if (NOT_NULL(table))
	{
		for (index = 0; index < total; index++)
		{
			if (NOT_NULL(table[index]))
			{
				release_md_metatile(table[index]);
				table[index] = NULL;
			}
		}

		free(table);
		table = NULL;
	}
}

int get_ram_md_metatile_table(
	t_md_metatile **md_metatile,
	t_byte *ram,
	t_dword *ptable,
	int total,
	int w,
	int h
)
{
	int index = 0, z = 0;

	for (index = 0; index < total; index++)
	{
		z = ptable[index];

		if (NOT_ZERO(z) && AND_EQUAL(z, MD_RAM_ADDRESS))
		{
			z = z & MD_RAM_MASK;

			md_metatile[index] = get_md_metatile(ram, z, w, h);
			if (md_metatile[index] == NULL)
			{
					release_md_metatile_table(md_metatile, total);
					return -1;
			}
		}
	}

	return 0;
}

int get_rom_md_metatile_table(
	t_md_metatile **md_metatile,
	t_byte *rom,
	t_dword *ptable,
	int total,
	int w,
	int h
)
{
	int index = 0, z = 0;

	for (index = 0; index < total; index++)
	{
		z = ptable[index];

		if (NOT_ZERO(z) && AND_NEQUAL(z, MD_RAM_ADDRESS))
		{
			md_metatile[index] = get_md_metatile(rom, z, w, h);
			if (md_metatile[index] == NULL)
			{
				release_md_metatile_table(md_metatile, total);
				return -1;
			}
		
		}
	}

	return 0;
}

t_bitmap **create_mtile_table(
	t_plot_state *ps,
	t_plot_state *pp,
	t_md_metatile **md_metatile,
	int total
)
{
	int index = 0, z = 0;
	int w = 0, h = 0;

	t_byte *u = NULL;

	t_bitmap *bitmap = NULL;
	t_bitmap **table = NULL;
	
	table = m_parray(t_bitmap, total);
	if (table == NULL) goto _ERROR;

	for (index = 0; index < total; index++)
		table[index] = NULL;

	for (index = 0; index < total; index++)
	{
		if (NOT_NULL(md_metatile[index]))
		{
			w = md_metatile[index]->w;
			h = md_metatile[index]->h;

			bitmap = create_bitmap(w * 8, h * 8);
			if (bitmap == NULL) goto _ERROR;

			plot_state_set_destination(
				pp,
				bitmap->resource,
				bitmap->w,
				bitmap->h);

			plot_etd_metatile(
				ps,
				pp,
				md_metatile[index]->raw,
				0, 0,
				w, h);

			plot_state_plot_all(ps);
			table[index] = bitmap;
			
		}
		else table[index] = NULL;
	}

	return table;

_ERROR:

	return NULL;
}

t_bitmap **etd_create_mtile_table(
	t_plot_state *ps,
	t_plot_state *pp,
	t_byte *ram,
	t_byte *resource,
	t_dword offset,
	int total,
	int flag
)
{
	int index = 0;
	int x = 0, y = 0, z = 0;
	int width = 0, height = 0;
	int size = 0;

	t_byte *u = NULL;

	t_dword *ptable = NULL;
	t_dword *otable = NULL;
	t_byte *raw = NULL;

	t_bitmap *bitmap = NULL;
	t_bitmap **table = NULL;
	t_md_metatile *metatile = NULL;
	t_md_metatile **_metatile = NULL;

	ptable = get_metatile_ptable(ram, offset, total);
	if (ptable == NULL) return NULL;

	otable = get_metatile_offset_table(resource, 0x73c52, 24);

	/*
	for (index = 0; index < 24; index++)
		ptable[index]+= otable[index] * 2;
		*/
	_metatile = m_parray(t_md_metatile, 0x100);
	for (index = 0; index < total; index++)
		_metatile[index] = NULL;

	u = resource;
	for (index = 0; index < total; index++)
	{
		z = ptable[index];
		if (z == 0) continue;

		if (AND_NEQUAL(z, MD_RAM_ADDRESS))
		{
			_metatile[index] = get_md_metatile(u, z, 16, 16);
		}
	}

	u = ram;
	for (index = 0; index < total; index++)
	{
		z = ptable[index];
		if (z == 0) continue;

		if (AND_EQUAL(z, MD_RAM_ADDRESS))
		{
			z = z & 0x0000ffff;
			_metatile[index] = get_md_metatile(u, z, 16, 16);
		}
	}

	table = m_parray(t_bitmap, 0x100);
	if (table == NULL) goto _ERROR;

	for (index = 0; index < 0x100; index++)
		table[index] = NULL;

	for (x = 0; x < total; x++)
	{
		if (NOT_NULL(_metatile[x]))
		{
			width = _metatile[x]->w;
			height = _metatile[x]->h;

			bitmap = create_bitmap(width * 8, height * 8);
			if (bitmap == NULL) goto _ERROR;

			plot_state_set_destination(
				pp,
				bitmap->resource,
				bitmap->w,
				bitmap->h);

			plot_etd_metatile(
				ps,
				pp,
				_metatile[x]->raw,
				0, 0,
				width, height);

			plot_state_plot_all(ps);
			table[x] = bitmap;

		}
		else table[x] = NULL;
	}

	free(ptable);
	free(raw);

	index = 0;

	plot_state_set_destination(
		pp,
		table[index]->resource,
		table[index]->w,
		table[index]->h);

	return table;

_ERROR:

	if (NOT_NULL(ptable))
		free(ptable);

	if (NOT_NULL(raw))
		free(raw);

	if (NOT_NULL(table))
	{
		for (index = 0; index < ETD_METATILE_SIZE; index++)
			if (NOT_NULL(table[index]))
				free(table[index]);
	}

	return NULL;
}

void set_etd_level_cell(t_etd_level_cell *x, int y)
{
	x->hflip = (y >> 7) & 0x1;
	x->vflip = (y >> 6) & 0x1;
	x->mtile_id = y & 0x3f;

	if (x->vflip == 1)
		x->vflip = PS_VFLIP;
	if (x->hflip == 1)
		x->hflip = PS_HFLIP;
}

void set_level_cell1(t_level_cell1 *x, int y)
{
	x->table_id = y >> 8;
	x->hflip = (y >> 9) & 0x1;
	x->vflip = (y >> 8) & 0x1;
	x->mtile_id = y & 0x00ff;

	if (x->vflip == 1)
		x->vflip = PS_VFLIP;
	if (x->hflip == 1)
		x->hflip = PS_HFLIP;
}

void set_level_cell2(t_level_cell2 *x, int y)
{
	x->table3_index = y & 0xffff;

	x->relative_x = (y >> 8) & 0xf;
	x->relative_y = (y >> 12) & 0xf;

	x->mtile_id = y & 0x00ff;
}
/*
t_ecco2_level_table **get_ecco2_level_table(void)
{
	int index = 0, total = 0xff;

	t_ecco2_level_table **table = m_parray(
		t_ecco2_level_table, total);
	if (table == NULL) return NULL;

	for (index = 0; index < total; index++)
	{
		table[index] = m_alloc(t_ecco2_level_table);
		if (table[index] == NULL)
			goto _ERROR;
	}

	index = 0;

	table[index]->id = ECCO2_LEVEL_HOMEBAY;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x10afda;
	table[index]->palette_index_offset = 0x1152b2 + 0x11; // needs to be there!

	table[index]->mtile_total = 0x3d0 / 4;
	table[index]->mtile_custom_total = 0x28c / 4;

	table[index]->mtile_offset = 0x118326;
	table[index]->mtile_custom_offset = 0x12a6b4;

	table[index]->nametable_properties_offset = 0x10ba36;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/HOME_BAY.gsx");


	index = 1;

	table[index]->id = ECCO2_LEVEL_SEAOFGREEN;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0xecc1e + (0x80 * 0);

	table[index]->mtile_total = 0x11c / 4;
	table[index]->mtile_custom_total = 0x400 / 4;

	table[index]->mtile_offset = 0x0f5160;
	table[index]->mtile_custom_offset = 0x0fb726;

	table[index]->nametable_properties_offset = 0x195a9a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/SEA_OF_GREEN.gsx");

	index = 2;

	table[index]->id = ECCO2_LEVEL_MAZEOFSTONE;
	table[index]->foreground_w = 0x28;
	table[index]->foreground_h = 0x20;

	table[index]->background_w = 0x1f;
	table[index]->background_h = 0x1a;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x10afda + (0x80 * 1),

	table[index]->mtile_total = 0x3d0 / 4;
	table[index]->mtile_custom_total = 0x28c / 4;

	table[index]->mtile_offset = 0x118326;
	table[index]->mtile_custom_offset = 0x12a6b4;

	table[index]->bg_nametable_offset = 0xff15a6;
	table[index]->nametable_properties_offset = 0x195a9a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/MAZE_OF_STONE.gsx");

	index = 3;

	table[index]->id = ECCO2_LEVEL_DARKSEA;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x19396e;
	table[index]->palette_index_offset = 0x19703c + 0x11;

	table[index]->mtile_total = 0x18d / 4;
	table[index]->mtile_custom_total = 0x400 / 4;

	table[index]->mtile_offset = 0x19cb00;
	table[index]->mtile_custom_offset = 0x1a63ee;

	table[index]->nametable_properties_offset = 0x195a9a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/DARK_SEA.gsx");

	index = 4;

	table[index]->id = ECCO2_LEVEL_TRELLIASBAY;
	table[index]->foreground_w = 0x28;
	table[index]->foreground_h = 0x18;

	table[index]->background_w = 0x20;
	table[index]->background_h = 0x15;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x135a96 + (0x80 * 0x0),
	table[index]->palette_index_offset = 0x13643c + 0x11;

	table[index]->mtile_total = 0x224 / 4;
	table[index]->mtile_custom_total = 0x2f4 / 4;

	table[index]->mtile_offset = 0x13b338;
	table[index]->mtile_custom_offset = 0x148b3a;

	table[index]->bg_nametable_offset = 0xff15f8;
	table[index]->nametable_properties_offset = 0x13634c;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/TRELLIAS_BAY.gsx");

	index = 5;

	// ATLANTIS

	table[index]->id = index;
	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x1653ca;
	table[index]->palette_index_offset = 0x16653a + 0x11;

	table[index]->mtile_total = 0x15c / 4;
	table[index]->mtile_custom_total = 0x400 / 4;

	table[index]->mtile_offset = 0x16bcea;
	table[index]->mtile_custom_offset = 0x173e02;

	table[index]->nametable_properties_offset = 0x1664c2;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/ATLANTIS.gsx");

	index = 6;

	// TUBE OF MEDUSA
	table[index]->id = index;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x155936,
	table[index]->palette_index_offset = 0x16653a + 0x11;

	table[index]->mtile_total = 0x38 / 4;
	table[index]->mtile_custom_total = 0x38 / 4;

	table[index]->mtile_offset = 0x157fac;
	table[index]->mtile_custom_offset = 0x158cda;

	table[index]->nametable_properties_offset = 0x195a9a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/TUBE_OF_MEDUSA.gsx");

	index = 7;

	// BIG WATER
	table[index]->id = index;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x1d7a92;
	table[index]->palette_index_offset = 0x1d7c72 + 0x11;

	table[index]->mtile_total = 0x30 / 4;
	table[index]->mtile_custom_total = 0x18 / 4;

	table[index]->mtile_offset = 0x1d83ac;
	table[index]->mtile_custom_offset = 0x1d8f06;

	table[index]->nametable_properties_offset = 0x1d7c22;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/BIG_WATER.gsx");

	index = 8;

	// MORAY ABYSS
	table[index]->id = index;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x15f74e + (0x80 * 0x0),

	table[index]->mtile_total = 0x30 / 4;
	table[index]->mtile_custom_total = 0x14 / 4;

	table[index]->mtile_offset = 0x1d83ac; // big water
	table[index]->mtile_custom_offset = 0x16100e;

	table[index]->nametable_properties_offset = 0x195a9a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/MORAY_ABYSS.gsx");

	index = 9;

	// VORTEX QUEEN
	table[index]->id = index;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x1b3f1a + (0x80 * 0x0),

	table[index]->mtile_total = 0x88 / 4;
	table[index]->mtile_custom_total = 0xbc / 4;

	table[index]->mtile_offset = 0x1b42f0;
	table[index]->mtile_custom_offset = 0x1b597e;

	table[index]->nametable_properties_offset = 0x195a9a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/VORTEX_QUEEN.gsx");

	index = 10;

	// GLOBE HOLDER
	table[index]->id = index;
	table[index]->foreground_w = 0x28;
	table[index]->foreground_h = 0x18;

	table[index]->background_w = 0x20;
	table[index]->background_h = 0x15;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x106c0e + (0x80 * 0x0),

	table[index]->mtile_total = 0x7 / 4;
	table[index]->mtile_custom_total = 0x70 / 4;

	table[index]->mtile_offset = 0x10701a;
	table[index]->mtile_custom_offset = 0x1073e8;

	table[index]->bg_nametable_offset = 0xff15f8;
	table[index]->nametable_properties_offset = 0x195a9a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/GLOBE_HOLDER.gsx");

	index = 11;

	// VORTEX FUTURE
	table[index]->id = index;

	table[index]->palette_offset = 0x180b4e;
	table[index]->palette_index_offset = 0x183df4 + 0x11;

	table[index]->mtile_total = 0x8c / 4;
	table[index]->mtile_custom_total = 0x400 / 4;

	table[index]->mtile_offset = 0x187332;
	table[index]->mtile_custom_offset = 0x1890b2;

	table[index]->nametable_properties_offset = 0x181c7a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/VORTEX_FUTURE.gsx");

	index = 12;

	// TMACHINE
	table[index]->id = index;
	table[index]->foreground_w = 0x28;
	table[index]->foreground_h = 0x18;

	table[index]->background_w = 0x20;
	table[index]->background_h = 0x15;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x1dbfbe + (0x80 * 0x0),

	table[index]->mtile_total = 0x38 / 4;
	table[index]->mtile_custom_total = 0x120 / 4;

	table[index]->mtile_offset = 0x1dd056;
	table[index]->mtile_custom_offset = 0x1890b2;

	table[index]->bg_nametable_offset = 0xff15f8;
	table[index]->nametable_properties_offset = 0x195a9a;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/TMACHINE.gsx");

	index = 13;

	table[index]->id = 0;

	table[index]->palette_id = 0x00;
	table[index]->palette_offset = 0x155936;
	table[index]->palette_index_offset = 0x156748 + 0x11; // needs to be there!

	table[index]->mtile_total = 0x38 / 4;
	table[index]->mtile_custom_total = 0x40 / 4;

	table[index]->mtile_offset = 0x157fac;
	table[index]->mtile_custom_offset = 0x158cda;

	table[index]->nametable_properties_offset = 0x1560be;
	table[index]->save_state_filename = copy_string("data/ECCO_2_US_JUNE_1994/VORTEX_ARRIVED.gsx");


	return table;

_ERROR:

	if (NOT_NULL(table))
	{
		for (index = 0; index < total; index++)
		{
			if (NOT_NULL(table[index]))
			{
				free(table[index]);
				table[index] = NULL;
			}
		}

		free(table);
		table = NULL;
	}

	return NULL;
}
*/
int etd_generate_level_map
(
	t_plot_state *ps,
	t_plot_state *pp,
	t_byte *sav_resource,
	int level_w,
	int level_h,
	t_bitmap **mtile_table_1
)
{
	int index = 0;
	int w = 0, x = 0, y = 0, z = 0;
	t_byte *u = NULL;

	int level_size = level_w * level_h;
	int table_index = 0;

	t_dword *level_table_1 = (t_dword *)malloc(sizeof(t_dword) * level_size * 2);

	u = &sav_resource[level_size * 0];
	for (index = 0; index < level_size; index++)
		level_table_1[index] = u[index];

	t_bitmap *level_map = create_bitmap(level_w * 0x80, level_h * 0x80);

	for (index = 0; index < level_map->size; index++)
		level_map->resource[index] = 0;

	t_bitmap *bitmap = NULL;
	t_plot_state *next = NULL;

	t_etd_level_cell *cell1 = m_alloc(t_etd_level_cell);

	for (y = 0; y < level_h; y++)
	{
		for (x = 0; x < level_w; x++)
		{
			table_index = x + (y * level_w);

			if (table_index >= level_size)
				continue;

			z = level_table_1[table_index];
			if (z == 0xff) continue;

			set_etd_level_cell(cell1, z);

			bitmap = mtile_table_1[cell1->mtile_id];
			if (bitmap == NULL) continue;

			plot_bitmap_direct(
				ps,
				bitmap,
				level_map,
				x * 128, y * 128,
				(cell1->vflip | cell1->hflip));

			plot_state_plot_all(ps);
		}
	}

	plot_state_set_destination(
		pp,
		level_map->resource,
		level_map->w,
		level_map->h);

	return 0;
}

int generate_level_map
(
	t_plot_state *ps,
	t_plot_state *pp,
	t_byte *sav_resource,
	int level_w,
	int level_h,
	t_bitmap **mtile_table_1,
	t_bitmap **mtile_table_2
)
{
	int index = 0;
	int w = 0, x = 0, y = 0, z = 0;
	t_byte *u = NULL;

	int level_size = level_w * level_h;
	int table_index = 0;

	t_dword *level_table_1 = (t_dword *)malloc(sizeof(t_dword) * level_size * 2);
	t_dword *level_table_2 = (t_dword *)malloc(sizeof(t_dword) * level_size * 2);
	t_dword *level_table_3 = (t_dword *)malloc(sizeof(t_dword) * level_size * 8); // needs to be fixed

	u = &sav_resource[level_size * 0];
	for (index = 0; index < level_size; index++)
		level_table_1[index] = unpack_word(u, index * 2);

	u = &sav_resource[level_size * 2];
	for (index = 0; index < level_size; index++)
		level_table_2[index] = unpack_word(u, index * 2);

	u = &sav_resource[level_size * 4];
	for (index = 0; index < level_size * 8; index++)
		level_table_3[index] = unpack_word(u, index * 2);

	t_bitmap *level_map = create_bitmap(level_w * 0x80, level_h * 0x80);

	for (index = 0; index < level_map->size; index++)
		level_map->resource[index] = 0;

	t_bitmap *bitmap = NULL;
	t_plot_state *next = NULL;

	t_level_cell1 *cell1 = m_alloc(t_level_cell1);
	t_level_cell2 *cell2 = m_alloc(t_level_cell2);
	t_level_cell2 *cell3 = m_alloc(t_level_cell2);

	for (y = 0; y < level_h; y++)
	{
		for (x = 0; x < level_w; x++)
		{
			table_index = x + (y * level_w);

			if (table_index >= level_size)
				continue;

			z = level_table_1[table_index];
			set_level_cell1(cell1, z);

			if (cell1->table_id == 0)
				continue;

			if (NOT_ZERO(cell1->table_id & 0x04))
			{
				bitmap = mtile_table_1[cell1->mtile_id];
				if (bitmap == NULL) continue;

				plot_bitmap_direct(
					ps,
					bitmap,
					level_map,
					x * 128, y * 128,
					(cell1->vflip | cell1->hflip));
			}
			
			plot_state_plot_all(ps);

			if (NOT_ZERO(cell1->table_id & 0xf0))
			{
				z = level_table_2[table_index];
				set_level_cell2(cell2, z);

				if (NOT_EQUAL(cell1->table_id & 0xc0, 0xc0))
				{
					bitmap = mtile_table_2[cell2->mtile_id];
					if (bitmap == NULL) continue;

					plot_bitmap_direct(
						ps,
						bitmap,
						level_map,
						(cell2->relative_x * 8) + (x * 128),
						(cell2->relative_y * 8) + (y * 128),
						0);
				}
			
				if ((cell1->table_id & 0xc0) == 0xc0)
				{
					w = 0;
					while (1)
					{
						z = level_table_3[(cell2->table3_index / 2) + w];
						w++;

						if (z == 0xffff) break;

						set_level_cell2(cell3, z);

						bitmap = mtile_table_2[cell3->mtile_id];
						if (bitmap == NULL) continue;

						plot_bitmap_direct(
							ps,
							bitmap,
							level_map,
							(cell3->relative_x * 8) + (x * 128),
							(cell3->relative_y * 8) + (y * 128),
							0);
					}


				}
			}

			plot_state_plot_all(ps);
		}
	}

	plot_state_set_destination(
		pp,
		level_map->resource,
		level_map->w,
		level_map->h);

	return 0;
}