/******************************************************************************

	sprite.c

	MVS スプライトマネージャ

******************************************************************************/

#include "mvs.h"


/******************************************************************************
	定数/マクロ等
******************************************************************************/

#define MAKE_FIX_KEY(code, color)	(code | (color << 24))
#define MAKE_SPR_KEY(code, attr)	(code | ((attr & 0xff00) << 16) | ((attr & 0x0c) << 20))

#define CNVCOL15TO32(c)	((GETB15(c) << 16) | (GETG15(c) << 8) | GETR15(c))


/******************************************************************************
	ローカル変数/構造体
******************************************************************************/

typedef struct sprite_t SPRITE __attribute__((aligned(16)));

struct sprite_t
{
	u32 key;
	int used;
	u16 pal;
	u16 index;
	SPRITE *next;
};

static RECT mvs_src_clip = { 8, 16, 8 + 304, 16 + 224 };

/*--------------------------------------------------------------------
  ※上下1ドット空けてあるのは、他のフレームに干渉するのを防ぐため。
    (テクスチャが拡大される時、周囲1ドットも影響が出る)
    また、272だと値が半端なため、テクスチャのぼけが多くなる。
--------------------------------------------------------------------*/

static RECT mvs_clip[4] = 
{
	{ 88, 24, 88 + 304, 24 + 224 },	// option_stretch = 0  (304x224  4:3)
	{ 60,  1, 60 + 360,  1 + 270 },	// option_stretch = 1  (360x270  4:3)
	{ 30,  1, 30 + 420,  1 + 270 },	// option_stretch = 2  (420x270 14:9)
	{  0,  1,  0 + 480,  1 + 270 }	// option_stretch = 3  (480x270 16:9)
};

static int clip_min_y;
static int clip_max_y;


/*------------------------------------------------------------------------
	※上下1ドット空けてあるのは、他のフレームに干渉するのを防ぐため。
	  (テクスチャが拡大される時、周囲1ドットも影響が出る)
	  また、272だと値が半端なため、テクスチャのぼけが多くなる。
------------------------------------------------------------------------*/

static u8 palette_is_dirty[256];


/*------------------------------------------------------------------------
	FIX: サイズ/位置8pixel固定のスプライト

	size:    8x8 pixels
	palette: 0〜15番を使用
------------------------------------------------------------------------*/

#define FIX_TEXTURE_SIZE	((BUF_WIDTH/8)*(208/8))
#define FIX_HASH_MASK		0xff
#define FIX_HASH_SIZE		0x100
#define FIX_MAX_SPRITES		((320/8)*(256/8))

static SPRITE *fix_head[FIX_HASH_SIZE];
static SPRITE fix_data[FIX_TEXTURE_SIZE];
static SPRITE *fix_free_head;

static u16 *tex_fix;
static s16 fix_x[FIX_MAX_SPRITES];
static s16 fix_y[FIX_MAX_SPRITES];
static u16 fix_idx[FIX_MAX_SPRITES];
static u16 fix_num;
static u16 fix_texture_num;
static u8 fix_texture_clear;
static u8 fix_palette_is_dirty;


/*------------------------------------------------------------------------
	SPR: 可変サイズのスプライト
	     縮小、拡大、反転、ライン毎に描画が可能
	     特殊な機能としてチェーンスプライト、オートアニメーション機能あり

	size:    2x1 pixels 〜 16x16 pixels (可変)
	palette: 0〜255番を使用
------------------------------------------------------------------------*/

#define SPR_TEXTURE_SIZE	((BUF_WIDTH/16)*((512*2)/16))
#define SPR_HASH_MASK		0x1ff
#define SPR_HASH_SIZE		0x200
#define SPR_MAX_SPRITES		0x3000
#define SPR_AUTOANIME		(3 << 20)
#define SPR_AUTOANIME4		(1 << 20)
#define SPR_AUTOANIME8		(2 << 20)

static SPRITE *spr_head[SPR_HASH_SIZE];
static SPRITE spr_data[SPR_TEXTURE_SIZE];
static SPRITE *spr_free_head;

static u16 *tex_spr1;
static u16 *tex_spr2;
static s16 spr_x[SPR_MAX_SPRITES];
static s16 spr_y[SPR_MAX_SPRITES];
static u16 spr_w[SPR_MAX_SPRITES];
static u16 spr_h[SPR_MAX_SPRITES];
static u16 spr_idx[SPR_MAX_SPRITES];
static u16 spr_atr[SPR_MAX_SPRITES];
static u16 spr_num;
static u16 spr_texture_num;
static u8 spr_texture_clear;
static u8 spr_palette_is_dirty;
static u8 spr_disable_this_frame;


/******************************************************************************
	FIXスプライト管理
******************************************************************************/

/*------------------------------------------------------------------------
	FIXテクスチャをリセットする
------------------------------------------------------------------------*/

static void fix_reset_sprite(void)
{
	int i;

	for (i = 0; i < FIX_TEXTURE_SIZE - 1; i++)
		fix_data[i].next = &fix_data[i + 1];

	fix_data[i].next = NULL;
	fix_free_head = &fix_data[0];

	memset(fix_head, 0, sizeof(SPRITE *) * FIX_HASH_SIZE);

	fix_texture_num = 0;
	fix_texture_clear = 0;
	fix_palette_is_dirty = 0;
}


/*------------------------------------------------------------------------
	FIXテクスチャからスプライト番号を取得
------------------------------------------------------------------------*/

static int fix_get_sprite(int key)
{
	SPRITE *p = fix_head[key & FIX_HASH_MASK];

	while (p)
	{
		if (p->key == key)
		{
			p->used = frames_displayed;
			return p->index;
	 	}
		p = p->next;
	}
	return -1;
}


/*------------------------------------------------------------------------
	FIXテクスチャにスプライトを登録
------------------------------------------------------------------------*/

static int fix_insert_sprite(u32 key)
{
	u16 hash = key & FIX_HASH_MASK;
	SPRITE *p = fix_head[hash];
	SPRITE *q = fix_free_head;

	if (!q) return -1;

	fix_free_head = fix_free_head->next;

	q->next = NULL;
	q->key  = key;
	q->pal  = key >> 24;
	q->used = frames_displayed;

	if (!p)
	{
		fix_head[hash] = q;
	}
	else
	{
		while (p->next) p = p->next;
		p->next = q;
	}

	fix_texture_num++;

	return q->index;
}


/*------------------------------------------------------------------------
	FIXテクスチャから一定時間を経過したスプライトを削除
------------------------------------------------------------------------*/

static void fix_delete_sprite(int delay)
{
	int i;
	SPRITE *p, *prev_p;

	for (i = 0; i < FIX_HASH_SIZE; i++)
	{
		prev_p = NULL;
		p = fix_head[i];

		while (p)
		{
			if (frames_displayed - p->used > delay)
			{
				fix_texture_num--;

				if (!prev_p)
				{
					fix_head[i] = p->next;
					p->next = fix_free_head;
					fix_free_head = p;
					p = fix_head[i];
				}
				else
				{
					prev_p->next = p->next;
					p->next = fix_free_head;
					fix_free_head = p;
					p = prev_p->next;
				}
			}
			else
			{
				prev_p = p;
				p = p->next;
			}
		}
	}
}


/*------------------------------------------------------------------------
	FIXテクスチャからパレットが変更されたスプライトを削除
------------------------------------------------------------------------*/

static void fix_delete_dirty_palette(void)
{
	SPRITE *p, *prev_p;
	int i, palno;

	for (palno = 0; palno < 0x10; palno++)
	{
		if (!palette_is_dirty[palno]) continue;

		for (i = 0; i < FIX_HASH_SIZE; i++)
		{
			prev_p = NULL;
			p = fix_head[i];

			while (p)
			{
				if (p->pal == palno)
				{
					fix_texture_num--;

					if (!prev_p)
					{
						fix_head[i] = p->next;
						p->next = fix_free_head;
						fix_free_head = p;
						p = fix_head[i];
					}
					else
					{
						prev_p->next = p->next;
						p->next = fix_free_head;
						fix_free_head = p;
						p = prev_p->next;
					}
				}
				else
				{
					prev_p = p;
					p = p->next;
				}
			}
		}
	}

	fix_palette_is_dirty = 0;
}


/******************************************************************************
	SPRスプライト管理
******************************************************************************/

/*------------------------------------------------------------------------
	SPRテクスチャをリセットする
------------------------------------------------------------------------*/

static void spr_reset_sprite(void)
{
	int i;

	for (i = 0; i < SPR_TEXTURE_SIZE - 1; i++)
		spr_data[i].next = &spr_data[i + 1];

	spr_data[i].next = NULL;
	spr_free_head = &spr_data[0];

	memset(spr_head, 0, sizeof(SPRITE *) * SPR_HASH_SIZE);

	spr_texture_num = 0;
	spr_texture_clear = 0;
	spr_palette_is_dirty = 0;
}


/*------------------------------------------------------------------------
	SPRテクスチャからスプライト番号を取得
------------------------------------------------------------------------*/

static int spr_get_sprite(int key)
{
	SPRITE *p = spr_head[key & SPR_HASH_MASK];

	while (p)
	{
		if (p->key == key)
		{
			if (p->used != frames_displayed)
			{
				if (update_cache) update_cache((key << 7) & 0x3ffffff);
				p->used = frames_displayed;
			}
			return p->index;
		}
		p = p->next;
	}
	return -1;
}


/*------------------------------------------------------------------------
	SPRテクスチャにスプライトを登録
------------------------------------------------------------------------*/

static int spr_insert_sprite(u32 key)
{
	u16 hash = key & SPR_HASH_MASK;
	SPRITE *p = spr_head[hash];
	SPRITE *q = spr_free_head;

	if (!q) return -1;

	spr_free_head = spr_free_head->next;

	q->next = NULL;
	q->key  = key;
	q->pal  = key >> 24;
	q->used = frames_displayed;

	if (!p)
	{
		spr_head[key & SPR_HASH_MASK] = q;
	}
	else
	{
		while (p->next) p = p->next;
		p->next = q;
	}

	spr_texture_num++;

	return q->index;
}


/*------------------------------------------------------------------------
	SPRテクスチャから一定時間を経過したスプライトを削除
------------------------------------------------------------------------*/

static void spr_delete_sprite(int delay, int clear_all)
{
	int i;
	SPRITE *p, *prev_p;

	if (clear_all)
	{
		for (i = 0; i < SPR_HASH_SIZE; i++)
		{
			prev_p = NULL;
			p = spr_head[i];

			while (p)
			{
				if (frames_displayed - p->used > delay)
				{
					spr_texture_num--;

					if (!prev_p)
					{
						spr_head[i] = p->next;
						p->next = spr_free_head;
						spr_free_head = p;
						p = spr_head[i];
					}
					else
					{
						prev_p->next = p->next;
						p->next = spr_free_head;
						spr_free_head = p;
						p = prev_p->next;
					}
				}
				else
				{
					prev_p = p;
					p = p->next;
				}
			}
		}
	}
	else
	{
		int unused_frames;

		for (i = 0; i < SPR_HASH_SIZE; i++)
		{
			prev_p = NULL;
			p = spr_head[i];

			while (p)
			{
				unused_frames = frames_displayed - p->used;

				if (unused_frames > delay)
				{
					int clear = 1;

					switch (p->key & SPR_AUTOANIME)
					{
					case SPR_AUTOANIME4:
						if (unused_frames <= (neogeo_frame_counter << 2))
							clear = 0;
						break;

					case SPR_AUTOANIME8:
						if (unused_frames <= (neogeo_frame_counter << 3))
							clear = 0;
						break;
					}

					if (clear)
					{
						spr_texture_num--;

						if (!prev_p)
						{
							spr_head[i] = p->next;
							p->next = spr_free_head;
							spr_free_head = p;
							p = spr_head[i];
						}
						else
						{
							prev_p->next = p->next;
							p->next = spr_free_head;
							spr_free_head = p;
							p = prev_p->next;
						}
					}
					else
					{
						prev_p = p;
						p = p->next;
					}
				}
				else
				{
					prev_p = p;
					p = p->next;
				}
			}
		}
	}
}


/*------------------------------------------------------------------------
	SPRテクスチャからパレットが変更されたスプライトを削除
------------------------------------------------------------------------*/

static void spr_delete_dirty_palette(void)
{
	SPRITE *p, *prev_p;
	int i, palno;

	for (palno = 0; palno < 0x100; palno++)
	{
		if (!palette_is_dirty[palno]) continue;

		for (i = 0; i < SPR_HASH_SIZE; i++)
		{
			prev_p = NULL;
			p = spr_head[i];

			while (p)
			{
				if (p->pal == palno)
				{
					spr_texture_num--;

					if (!prev_p)
					{
						spr_head[i] = p->next;
						p->next = spr_free_head;
						spr_free_head = p;
						p = spr_head[i];
					}
					else
					{
						prev_p->next = p->next;
						p->next = spr_free_head;
						spr_free_head = p;
						p = prev_p->next;
					}
				}
				else
				{
					prev_p = p;
					p = p->next;
				}
			}
		}
	}

	spr_palette_is_dirty = 0;
}


/******************************************************************************
	スプライト描画インタフェース関数
******************************************************************************/

/*------------------------------------------------------------------------
	全てのスプライトを即座にクリアする
------------------------------------------------------------------------*/

void blit_clear_all_sprite(void)
{
	fix_reset_sprite();
	spr_reset_sprite();
	memset(palette_is_dirty, 0, sizeof(palette_is_dirty));
	spr_disable_this_frame = 0;
}


/*------------------------------------------------------------------------
	FIXスプライトのクリアフラグを立てる
------------------------------------------------------------------------*/

void blit_clear_fix_sprite(void)
{
	fix_texture_clear = 1;
	fix_palette_is_dirty = 0;
}


/*------------------------------------------------------------------------
	SPRスプライトのクリアフラグを立てる
------------------------------------------------------------------------*/

void blit_clear_spr_sprite(void)
{
	spr_texture_clear = 1;
	spr_palette_is_dirty = 0;
}


/*------------------------------------------------------------------------
	パレット変更フラグを立てる
------------------------------------------------------------------------*/

void blit_palette_mark_dirty(int palno)
{
	palette_is_dirty[palno] = 1;

	if (palno < 0x10) fix_palette_is_dirty = 1;
	spr_palette_is_dirty = 1;
}


/*------------------------------------------------------------------------
	スプライト処理のリセット
------------------------------------------------------------------------*/

void blit_reset(void)
{
	int i;
	u16 *work_buffer;

	screen_is_dirty = 0;

	work_buffer = video_frame_addr(work_frame, 0, 0);
	tex_spr1 = work_buffer + BUF_WIDTH * 256;
	tex_spr2 = tex_spr1 + BUF_WIDTH * 512;
	tex_fix  = tex_spr2 + BUF_WIDTH * 512;

	for (i = 0; i < FIX_TEXTURE_SIZE - 1; i++)
		fix_data[i].index = i;

	for (i = 0; i < SPR_TEXTURE_SIZE - 1; i++)
		spr_data[i].index = i;

	blit_clear_all_sprite();

	if (neogeo_bios != ASIA_AES) spr_disable_this_frame = 1;
}


/*------------------------------------------------------------------------
	スプライト描画開始
------------------------------------------------------------------------*/

void blit_start(void)
{
	RECT clip = { 0, 0, 512, 256 };

	if (fix_texture_clear) fix_reset_sprite();
	if (spr_texture_clear) spr_reset_sprite();

	if (fix_palette_is_dirty) fix_delete_dirty_palette();
	if (spr_palette_is_dirty) spr_delete_dirty_palette();
	memset(palette_is_dirty, 0, sizeof(palette_is_dirty));

	if (neogeo_selected_vectors) spr_disable_this_frame = 0;

	if (screen_is_dirty > 0)
	{
		video_clear_frame(draw_frame);
		screen_is_dirty--;
	}
	video_clear_rect(work_frame, &clip);
	video_fill_rect(work_frame, CNVCOL15TO32(video_palette16[4095]), &mvs_src_clip);
}


/*------------------------------------------------------------------------
	画面の一部更新開始
------------------------------------------------------------------------*/

void blit_partial_start(int start, int end)
{
	clip_min_y  = start;
	clip_max_y  = end + 1;

	fix_num = 0;
	spr_num = 0;

	if (start == FIRST_VISIBLE_LINE)
		blit_start();
}


/*------------------------------------------------------------------------
	スプライト描画終了
------------------------------------------------------------------------*/

void blit_finish(void)
{
	video_copy_rect(work_frame, draw_frame, &mvs_src_clip, &mvs_clip[option_stretch]);
}


/*------------------------------------------------------------------------
	FIXを描画リストに登録
------------------------------------------------------------------------*/

void blit_draw_fix(int x, int y, u32 code, u32 attr)
{
	int idx;
	u32 key;

	if (fix_num == FIX_MAX_SPRITES) return;

	key = MAKE_FIX_KEY(code, attr);

	if ((idx = fix_get_sprite(key)) < 0)
	{
		int lines, u, v;
		u32 tile, *gfx;
		u16 *dst, *pal;

		if (fix_texture_num == FIX_TEXTURE_SIZE - 1)
		{
			fix_delete_sprite(0);
		}

		idx = fix_insert_sprite(key);

		gfx = (u32 *)&fix_memory[code << 5],
		pal = &video_palette16[attr << 4],

		u = (idx & 63) << 3;
		v = (idx >> 6) << 3;

		dst = &tex_fix[u + (v << 9)];

		lines = 8;
		while (lines--)
		{
			tile = *gfx++;
			dst[0] = pal[tile & 0x0f]; tile >>= 4;
			dst[1] = pal[tile & 0x0f]; tile >>= 4;
			dst[2] = pal[tile & 0x0f]; tile >>= 4;
			dst[3] = pal[tile & 0x0f]; tile >>= 4;
			dst[4] = pal[tile & 0x0f]; tile >>= 4;
			dst[5] = pal[tile & 0x0f]; tile >>= 4;
			dst[6] = pal[tile & 0x0f]; tile >>= 4;
			dst[7] = pal[tile & 0x0f];
			dst += BUF_WIDTH;
		}
	}

	fix_idx[fix_num] = idx;
	fix_x[fix_num] = x;
	fix_y[fix_num] = y;
	fix_num++;
}


/*------------------------------------------------------------------------
	FIX描画終了
------------------------------------------------------------------------*/

void blit_finish_fix(void)
{
	int i, u, v;
	struct Vertex *vertices, *vertices_tmp;

	if (!fix_num) return;

	sceGuStart(GU_DIRECT, gulist);

	sceGuDrawBufferList(GU_PSM_5551, (void *)(FRAMESIZE * work_frame), BUF_WIDTH);
	sceGuScissor(mvs_src_clip.left, mvs_src_clip.top, mvs_src_clip.right, mvs_src_clip.bottom);
	sceGuEnable(GU_ALPHA_TEST);
	sceGuTexFilter(GU_NEAREST, GU_NEAREST);

	sceGuTexImage(0, 512, 512, 512, tex_fix);

	vertices = (struct Vertex *)sceGuGetMemory(fix_num * 2 * sizeof(struct Vertex));
	if (vertices)
	{
		vertices_tmp = vertices;

		for (i = 0; i < fix_num; i++)
		{
			u = (fix_idx[i] & 63) << 3;
			v = (fix_idx[i] >> 6) << 3;

			vertices_tmp[0].u = u;
			vertices_tmp[0].v = v;
			vertices_tmp[0].x = fix_x[i];
			vertices_tmp[0].y = fix_y[i];

			vertices_tmp[1].u = u + 8;
			vertices_tmp[1].v = v + 8;
			vertices_tmp[1].x = fix_x[i] + 8;
			vertices_tmp[1].y = fix_y[i] + 8;

			vertices_tmp += 2;
		}

		sceGuDrawArray(GU_SPRITES, TEXTURE_FLAGS, 2 * fix_num, 0, vertices);
	}

	sceGuFinish();
	sceGuSync(0, 0);

	fix_num = 0;
}


/*------------------------------------------------------------------------
	SPRを描画リストに登録
------------------------------------------------------------------------*/

void blit_draw_spr(int x, int y, int w, int h, u32 code, u32 attr)
{
	int idx;
	u32 key;

	if (spr_disable_this_frame) return;
	if (spr_num == SPR_MAX_SPRITES) return;

	key = MAKE_SPR_KEY(code, attr);

	if ((idx = spr_get_sprite(key)) < 0)
	{
		int lines, u, v;
		u16 *dst, *pal;
		u32 *gfx, tile, offset;

		if (spr_texture_num == SPR_TEXTURE_SIZE - 1)
		{
			spr_delete_sprite(1, 0);

			if (spr_texture_num == SPR_TEXTURE_SIZE - 1)
			{
				spr_delete_sprite(0, 1);

				if (spr_texture_num == SPR_TEXTURE_SIZE - 1)
				{
					spr_disable_this_frame = 1;
					return;
				}
			}
		}

		idx = spr_insert_sprite(key);

		offset = code << 7;
		if (read_cache) offset = (*read_cache)(offset);
		gfx = (u32 *)&memory_region_gfx3[offset];
		pal = &video_palette16[(attr & 0xff00) >> 4],

		u = (idx & 31) << 4;
		v = (idx >> 5) << 4;

		if (v < 512)
			dst = &tex_spr1[u | (v << 9)];
		else
			dst = &tex_spr2[u | ((v & 511) << 9)];

		lines = 16;
		while (lines--)
		{
			tile = *gfx++;
			dst[ 0] = pal[tile & 0x0f]; tile >>= 4;
			dst[ 1] = pal[tile & 0x0f]; tile >>= 4;
			dst[ 2] = pal[tile & 0x0f]; tile >>= 4;
			dst[ 3] = pal[tile & 0x0f]; tile >>= 4;
			dst[ 4] = pal[tile & 0x0f]; tile >>= 4;
			dst[ 5] = pal[tile & 0x0f]; tile >>= 4;
			dst[ 6] = pal[tile & 0x0f]; tile >>= 4;
			dst[ 7] = pal[tile & 0x0f];
			tile = *gfx++;
			dst[ 8] = pal[tile & 0x0f]; tile >>= 4;
			dst[ 9] = pal[tile & 0x0f]; tile >>= 4;
			dst[10] = pal[tile & 0x0f]; tile >>= 4;
			dst[11] = pal[tile & 0x0f]; tile >>= 4;
			dst[12] = pal[tile & 0x0f]; tile >>= 4;
			dst[13] = pal[tile & 0x0f]; tile >>= 4;
			dst[14] = pal[tile & 0x0f]; tile >>= 4;
			dst[15] = pal[tile & 0x0f];
			dst += BUF_WIDTH;
		}
	}

	spr_idx[spr_num] = idx;
	spr_x[spr_num] = x;
	spr_y[spr_num] = y;
	spr_w[spr_num] = w;
	spr_h[spr_num] = h;
	spr_atr[spr_num] = attr;
	spr_num++;
}


/*------------------------------------------------------------------------
	SPR描画終了
------------------------------------------------------------------------*/

void blit_finish_spr(void)
{
	int i, u, v;
	struct Vertex *vertices, *vertices_tmp;

	if (!spr_num) return;

	sceGuStart(GU_DIRECT, gulist);

	sceGuDrawBufferList(GU_PSM_5551, (void *)(FRAMESIZE * work_frame), BUF_WIDTH);
	sceGuScissor(mvs_src_clip.left, clip_min_y, mvs_src_clip.right, clip_max_y);
	sceGuEnable(GU_ALPHA_TEST);
	sceGuTexFilter(GU_NEAREST, GU_NEAREST);

	vertices = (struct Vertex *)sceGuGetMemory(spr_num * 2 * sizeof(struct Vertex));
	if (vertices)
	{
		int total_spr, cur_tex;

		vertices_tmp = vertices;
		total_spr = 0;
		cur_tex = 0;

		sceGuTexImage(0, 512, 512, 512, tex_spr1);

		for (i = 0; i < spr_num; i++)
		{
			v = (spr_idx[i] >> 5) << 4;

			if ((v & 512) != cur_tex)
			{
				cur_tex ^= 512;
				sceGuDrawArray(GU_SPRITES, TEXTURE_FLAGS, 2 * total_spr, 0, vertices);

				total_spr = 0;
				vertices = vertices_tmp;
				sceGuTexImage(0, 512, 512, 512, (cur_tex ? tex_spr2 : tex_spr1));
			}

			v &= 511;
			u = (spr_idx[i] & 31) << 4;

			if (spr_atr[i] & 0x01)
			{
				// flipx
				vertices_tmp[0].u = u + 16;
				vertices_tmp[1].u = u;
			}
			else
			{
				vertices_tmp[0].u = u;
				vertices_tmp[1].u = u + 16;
			}

			if (spr_atr[i] & 0x02)
			{
				// flipy
				vertices_tmp[0].v = v + 16;
				vertices_tmp[1].v = v;
			}
			else
			{
				vertices_tmp[0].v = v;
				vertices_tmp[1].v = v + 16;
			}

			vertices_tmp[0].x = spr_x[i];
			vertices_tmp[0].y = spr_y[i];

			vertices_tmp[1].x = spr_x[i] + spr_w[i];
			vertices_tmp[1].y = spr_y[i] + spr_h[i];

			vertices_tmp += 2;
			total_spr++;
		}

		if (total_spr)
			sceGuDrawArray(GU_SPRITES, TEXTURE_FLAGS, 2 * total_spr, 0, vertices);
	}

	sceGuFinish();
	sceGuSync(0, 0);

	spr_num = 0;
}
