/* GnarlPlot simple sprite C code V0.30 22/2/08
   Copyright 2008 Jeffrey Lee
   This file is part of GnarlPlot.
   GnarlPlot is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   GnarlPlot is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   You should have received a copy of the GNU General Public License
   along with GnarlPlot.  If not, see <http://www.gnu.org/licenses/>. */

#ifndef _GP_SIMPSPR_C
#define _GP_SIMPSPR_C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kernel.h"
#include "swis.h"

#include "spr.h"
#include "col.h"

/* Format for simple sprite */
typedef struct { /* Must be the same as the one in sprplotgen.c! */
	int w,h,ox,oy;
	char d[0];
} _gp_simpspr;

/* Generic functions for that data */
static gp_spr *gp_spr_igen_create(gp_sprfmt *f,int w,int h,int ox,int oy)
{
	gp_spr *s;
	int sz,mt;
	_gp_simpspr *spr;
	if ((w < 1) || (h < 1))
		return 0;
	s = malloc(sizeof(gp_spr));
	if (s == 0)
		return 0;
	s->f = f;
	s->d = 0;
	sz = (f->getps)(s); /* Get block size */
	mt = (f->getmt)(s); /* Get mask type */
	if (mt == GP_MT_NONE)
		sz = (w*h) << sz;
	else if (mt == GP_MT_ONOFF)
	{
		mt = sz;
		if (sz == 0)
			sz = (w*h) << (sz+1);
		else
			sz = (w*h) << sz;
		spr = malloc(sizeof(_gp_simpspr) + sz);
		if (spr == 0)
		{
			free(s);
			return 0;
		}
		s->d = spr;
		spr->w = w;
		spr->h = h;
		spr->ox = ox;
		spr->oy = oy;
		if (mt == 2)
		{
			sz /= 4; /* Get no. of words */
			while (sz--)
				((unsigned int *) spr->d)[sz] = 0x80000000; /* Solid black */
		}
		else /* mt 0 or 1, in which case widen to 16 bits */
		{
			sz /= 2;
			while (sz--)
				((unsigned short *) spr->d)[sz] = 0x8000; /* Solid black */
		}
		return s;
	}
	else if (mt == GP_MT_GREY)
	{
		if (sz < 2)
			sz += 1; /* 8 -> 16, 16 -> 32 */
		sz = (w*h) << sz;
	}
	else /* GP_MT_RGB */
		sz = (w*h) << (sz+1);
	spr = malloc(sizeof(_gp_simpspr) + sz);
	if (spr == 0)
	{
		free(s);
		return 0;
	}
	s->d = spr;
	spr->w = w;
	spr->h = h;
	spr->ox = ox;
	spr->oy = oy;
	memset(spr->d,0,sz); /* Solid black sprite */
	return s;
}

static int gp_spr_igen_getsize(gp_spr *s)
{
	_gp_simpspr *spr;
	if (s == 0)
		return 0;
	if (s->f == &gp_spr_00)
	{
		spr = s->d;
		return sizeof(_gp_simpspr) + (spr->w*spr->h);
	}
	else if ((s->f == &gp_spr_10) || (s->f == &gp_spr_01) || (s->f == &gp_spr_11) || (s->f == &gp_spr_02) || (s->f == &gp_spr_03))
	{
		spr = s->d;
		return sizeof(_gp_simpspr) + (spr->w*spr->h*2);
	}
	else if ((s->f == &gp_spr_20) || (s->f == &gp_spr_21) || (s->f == &gp_spr_12) || (s->f == &gp_spr_22) || (s->f == &gp_spr_13))
	{
		spr = s->d;
		return sizeof(_gp_simpspr) + (spr->w*spr->h*4);
	}
	else /* gp_spr_23 */
	{
		spr = s->d;
		return sizeof(_gp_simpspr) + (spr->w*spr->h*8);
	}
}

static int gp_spr_igen_getps(gp_spr *s)
{
	if (s == 0)
		return 0;
	if ((s->f == &gp_spr_00) || (s->f == &gp_spr_01) || (s->f == &gp_spr_02) || (s->f == &gp_spr_03))
		return 0;
	else if ((s->f == &gp_spr_10) || (s->f == &gp_spr_11) || (s->f == &gp_spr_12) || (s->f == &gp_spr_13))
		return 1;
	else /* gp_spr_2* */
		return 2;
}

static int gp_spr_igen_getmt(gp_spr *s)
{
	if (s == 0)
		return 0;
	if ((s->f == &gp_spr_00) || (s->f == &gp_spr_10) || (s->f == &gp_spr_20)) return GP_MT_NONE;
	else if ((s->f == &gp_spr_01) || (s->f == &gp_spr_11) || (s->f == &gp_spr_21)) return GP_MT_ONOFF;
	else if ((s->f == &gp_spr_02) || (s->f == &gp_spr_12) || (s->f == &gp_spr_22)) return GP_MT_GREY;
	else /* gp_spr_*3 */ return GP_MT_RGB;
}

static int gp_spr_igen_getw(gp_spr *s)
{
	if (s)
		return ((_gp_simpspr *) s->d)->w;
	else
		return 0;
}

static int gp_spr_igen_geth(gp_spr *s)
{
	if (s)
		return ((_gp_simpspr *) s->d)->h;
	else
		return 0;
}

static int gp_spr_igen_getox(gp_spr *s)
{
	if (s)
		return ((_gp_simpspr *) s->d)->ox;
	else
		return 0;
}

static int gp_spr_igen_getoy(gp_spr *s)
{
	if (s)
		return ((_gp_simpspr *) s->d)->oy;
	else
		return 0;
}

static int gp_spr_igen_getpix(gp_spr *s,int x,int y,int ps)
{
	_gp_simpspr *spr;
	int i;
	if (s == 0)
		return 0;
	spr = s->d;
	i = x+y*spr->w;
	if ((x < 0) || (x >= spr->w) || (y < 0) || (y >= spr->h))
		return 0;
	else if (s->f == &gp_spr_00)
		return gp_col_conv(0,((char *) spr->d)[i],ps);
	else if (s->f == &gp_spr_01)
	{
		x = ((short *) spr->d)[i];
		if (x & 0xFF00)
			return gp_col_conv(0,x & 255,ps);
		else
			return 0; /* Return 0 if 'off', since it technically has no colour (and means conversions to other formats work) */
	}
	else if ((s->f == &gp_spr_02) || (s->f == &gp_spr_03))
		return gp_col_conv(0,((short *) spr->d)[i] & 255,ps);
	else if (s->f == &gp_spr_10)
		return gp_col_conv(1,((short *) spr->d)[i],ps);
	else if (s->f == &gp_spr_11)
	{
		x = ((short *) spr->d)[i];
		if (x & 0x8000)
			return gp_col_conv(1,x & 0x7FFF,ps);
		else
			return 0;
	}
	else if ((s->f == &gp_spr_12) || (s->f == &gp_spr_13))
		return gp_col_conv(1,((int *) spr->d)[i] & 0xFFFF,ps);
	else if (s->f == &gp_spr_20)
		return gp_col_conv(2,((int *) spr->d)[i],ps);
	else if (s->f == &gp_spr_21)
	{
		x = ((int *) spr->d)[i];
		if (x & 0xFF000000)
			return gp_col_conv(2,x & 0xFFFFFF,ps);
		else
			return 0;
	}
	else if (s->f == &gp_spr_22)
		return gp_col_conv(2,((int *) spr->d)[i] & 0xFFFFFF,ps);
	else /* gp_spr_23 */
		return gp_col_conv(2,((int *) spr->d)[i*2],ps);
}

static int gp_spr_igen_getmask(gp_spr *s,int x,int y,int mt,int ps)
{
	_gp_simpspr *spr;
	int i;
	if ((s == 0) || (mt == GP_MT_NONE))
		return 0;
	spr = s->d;
	i = x+y*spr->w;
	if ((x < 0) || (y < 0) || (x >= spr->w) || (y >= spr->h))
		return gp_mask_conv(GP_MT_ONOFF,0,0,mt,ps); /* Transparent */
	else if ((s->f == &gp_spr_00) || (s->f == &gp_spr_10) || (s->f == &gp_spr_20))
		return gp_mask_conv(GP_MT_NONE,0,0,mt,ps); /* Solid */
	else if (s->f == &gp_spr_01)
		return gp_mask_conv(GP_MT_ONOFF,0,((short *) spr->d)[i] & 0xFF00,mt,ps);
	else if (s->f == &gp_spr_02)
		return gp_mask_conv(GP_MT_GREY,0,((unsigned short *) spr->d)[i] >> 8,mt,ps);
	else if (s->f == &gp_spr_03)
		return gp_mask_conv(GP_MT_RGB,0,((unsigned short *) spr->d)[i] >> 8,mt,ps);
	else if (s->f == &gp_spr_11)
		return gp_mask_conv(GP_MT_ONOFF,1,((unsigned short *) spr->d)[i] & 0x8000,mt,ps);
	else if (s->f == &gp_spr_12)
		return gp_mask_conv(GP_MT_GREY,1,(((unsigned int *) spr->d)[i] >> 16) & 255,mt,ps);
	else if (s->f == &gp_spr_13)
		return gp_mask_conv(GP_MT_RGB,1,((unsigned int *) spr->d)[i] >> 16,mt,ps);
	else if (s->f == &gp_spr_21)
		return gp_mask_conv(GP_MT_ONOFF,2,((unsigned int *) spr->d)[i] & 0xFF000000,mt,ps);
	else if (s->f == &gp_spr_22)
		return gp_mask_conv(GP_MT_GREY,2,((unsigned int *) spr->d)[i] >> 24,mt,ps);
	else /* gp_spr_23 */
		return gp_mask_conv(GP_MT_RGB,2,((int *) spr->d)[i*2+1],mt,ps);
}

static int gp_spr_igen_setpix(gp_spr *s,int x,int y,int ps,int c)
{
	_gp_simpspr *spr;
	int i;
	if ((s == 0) || (x < 0) || (y < 0) || (ps < 0) || (ps > 2))
		return 1; /* Fail */
	spr = s->d;
	i = x+y*spr->w;
	if ((x >= spr->w) || (y >= spr->h))
		return 1; /* Fail */
	else if (s->f == &gp_spr_00)
		((char *) spr->d)[i] = gp_col_conv(ps,c,0);
	else if ((s->f == &gp_spr_01) || (s->f == &gp_spr_02) || (s->f == &gp_spr_03))
		((char *) spr->d)[i*2] = gp_col_conv(ps,c,0);
	else if (s->f == &gp_spr_10)
		((short *) spr->d)[i] = gp_col_conv(ps,c,1);
	else if (s->f == &gp_spr_11)
		((short *) spr->d)[i] = (((short *) spr->d)[i] & 0x8000) | (gp_col_conv(ps,c,1) & 0x7FFF);
	else if ((s->f == &gp_spr_12) || (s->f == &gp_spr_13))
		((short *) spr->d)[i*2] = gp_col_conv(ps,c,1);
	else if (s->f == &gp_spr_20)
		((int *) spr->d)[i] = gp_col_conv(ps,c,2);
	else if ((s->f == &gp_spr_21) || (s->f == &gp_spr_22))
		((int *) spr->d)[i] = (((int *) spr->d)[i] & 0xFF000000) | (gp_col_conv(ps,c,2) & 0xFFFFFF);
	else /* gp_spr_23 */
		((int *) spr->d)[i*2] = gp_col_conv(ps,c,2);
	return 0;
}

static int gp_spr_igen_setmask(gp_spr *s,int x,int y,int mt,int ps,int c)
{
	_gp_simpspr *spr;
	int i;
	if ((s == 0) || (x < 0) || (y < 0) || (ps < 0) || (ps > 2))
		return 1; /* Fail */
	spr = s->d;
	i = x+y*spr->w;
	if ((x >= spr->w) || (y >= spr->h))
		return 1; /* Fail */
	else if ((s->f == &gp_spr_00) || (s->f == &gp_spr_10) || (s->f == &gp_spr_20))
		return 1; /* Fail */
	else if (s->f == &gp_spr_01)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_ONOFF,0);
		if (c)
			c = 255;
		((char *) spr->d)[i*2+1] = c;
	}
	else if (s->f == &gp_spr_02)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_GREY,0);
		((char *) spr->d)[i*2+1] = c;
	}
	else if (s->f == &gp_spr_03)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_RGB,0);
		((char *) spr->d)[i*2+1] = c;
	}
	else if (s->f == &gp_spr_11)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_ONOFF,1);
		if (c)
			c = 0x8000;
		((unsigned short *) spr->d)[i] = c | (((unsigned short *) spr->d)[i] & 0x7FFF);
	}
	else if (s->f == &gp_spr_12)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_GREY,1);
		((short *) spr->d)[i*2+1] = c; /* 2nd of the two 16bit words */
	}
	else if (s->f == &gp_spr_13)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_RGB,1);
		((short *) spr->d)[i*2+1] = c;
	}
	else if (s->f == &gp_spr_21)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_ONOFF,2);
		if (c)
			c = 0xFF000000; /* Might as well set all bits */
		((unsigned int *) spr->d)[i] = c | (((unsigned int *) spr->d)[i] & 0xFFFFFF);
	}
	else if (s->f == &gp_spr_22)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_GREY,2);
		((unsigned int *) spr->d)[i] = (c << 24) | (((unsigned int *) spr->d)[i] & 0xFFFFFF);
	}
	else /* gp_spr_23 */
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_RGB,2);
		((int *) spr->d)[i*2+1] = c;
	}
	return 0;
}

gp_screen *gp_spr_igen_toscreen(gp_spr *s,gp_screen *scr)
{
	_gp_simpspr *spr;
	if (s == 0)
		return 0;
	spr = s->d;
	if ((spr->w < 1) || (spr->h < 1))
		return 0;
	if(!scr)
		scr = malloc(sizeof(gp_screen));
	scr->width = spr->w;
	scr->height = spr->h;
	scr->ps = (s->f->getps)(s);
	scr->mt = (s->f->getmt)(s);
	scr->gap = 0;
	scr->bank0 = scr->bank1 = spr->d;
	return scr;
}

extern int gp_genplot_monkey(gp_spr *spr,int x,int y,gp_screen *scr);
extern int gp_genplot_yeknom(gp_spr *spr,int x,int y,gp_screen *scr,int l,f1616 sx,f1616 sy,f1616 dx,f1616 dy);

gp_sprfmt gp_spr_00 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_01 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_02 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_03 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_10 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_11 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_12 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_13 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_20 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_21 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_22 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_23 = {
	gp_spr_igen_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_igen_getsize, gp_spr_igen_getps, gp_spr_igen_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_igen_getpix, gp_spr_igen_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_igen_setpix, gp_spr_igen_setmask, gp_genplot_monkey, gp_spr_igen_toscreen, gp_genplot_yeknom
};

/* Preshifted sprite formats */
static gp_spr *gp_spr_ipre_create(gp_sprfmt *f,int w,int h,int ox,int oy)
{
	gp_spr *s;
	int sz,mt;
	_gp_simpspr *spr;
	if ((w < 1) || (h < 1))
		return 0;
	if ((w & 1) || ((f == &gp_spr_pre00) && (w & 2))) /* Only word aligned sprite widths for first version */
		return 0;
	s = malloc(sizeof(gp_spr));
	if (s == 0)
		return 0;
	s->f = f;
	s->d = 0;
	sz = w*h*4+4;
	spr = malloc(sizeof(_gp_simpspr)+sz);
	if (spr == 0)
	{
		free(s);
		return 0;
	}
	s->d = spr;
	spr->w = w;
	spr->h = h;
	spr->ox = ox;
	spr->oy = oy;
	if ((f == &gp_spr_pre00) || (f == &gp_spr_pre10))
	{
		memset(spr->d,0,sz);
		return s;
	}
	/* Else fill with mask data */
	if (f == &gp_spr_pre01)
		mt = 0xFF00FF00;
	else
		mt = 0x80008000;
	sz /= 4;
	while (sz--)
		((unsigned int *) spr->d)[sz] = mt;
	return s;
}

static int gp_spr_ipre_getsize(gp_spr *s)
{
	_gp_simpspr *spr;
	if (s == 0)
		return 0;
	spr = s->d;
	return sizeof(_gp_simpspr)+spr->w*spr->h*4+4;
}

static int gp_spr_ipre_getps(gp_spr *s)
{
	if (s == 0)
		return 0;
	if ((s->f == &gp_spr_pre00) || (s->f == &gp_spr_pre01))
		return 0;
	else
		return 1;
}

static int gp_spr_ipre_getmt(gp_spr *s)
{
	if (s == 0)
		return 0;
	if ((s->f == &gp_spr_pre00) || (s->f == &gp_spr_pre10)) return GP_MT_NONE;
	else return GP_MT_ONOFF;
}

static int gp_spr_ipre_getpix(gp_spr *s,int x,int y,int ps)
{
	_gp_simpspr *spr;
	int i;
	if (s == 0)
		return 0;
	spr = s->d;
	i = x+y*spr->w;
	if ((x < 0) || (x >= spr->w) || (y < 0) || (y >= spr->h))
		return 0;
	else if (s->f == &gp_spr_pre00)
		return gp_col_conv(0,((char *) spr->d)[i],ps);
	else if (s->f == &gp_spr_pre01)
	{
		x = ((short *) spr->d)[i];
		if (x & 0xFF00)
			return gp_col_conv(0,x & 255,ps);
		else
			return 0; /* Return 0 if 'off', since it technically has no colour (and means conversions to other formats work) */
	}
	else if (s->f == &gp_spr_pre10)
		return gp_col_conv(1,((short *) spr->d)[i],ps);
	else /* gp_spr_pre11 */
	{
		x = ((short *) spr->d)[i] & 0x7FFF;
		if (x & 0x8000)
			return gp_col_conv(1,x & 0x7FFF,ps);
		else
			return 0;
	}
}

static int gp_spr_ipre_getmask(gp_spr *s,int x,int y,int mt,int ps)
{
	_gp_simpspr *spr;
	int i;
	if ((s == 0) || (mt == GP_MT_NONE))
		return 0;
	spr = s->d;
	i = x+y*spr->w;
	if ((x < 0) || (y < 0) || (x >= spr->w) || (y >= spr->h))
		return gp_mask_conv(GP_MT_ONOFF,0,0,mt,ps); /* Transparent */
	else if ((s->f == &gp_spr_pre00) || (s->f == &gp_spr_pre10))
		return gp_mask_conv(GP_MT_NONE,0,0,mt,ps); /* Solid */
	else if (s->f == &gp_spr_pre01)
		return gp_mask_conv(GP_MT_ONOFF,0,((short *) spr->d)[i] & 0xFF00,mt,ps);
	else /* gp_spr_pre11 */
		return gp_mask_conv(GP_MT_ONOFF,1,((unsigned short *) spr->d)[i] & 0x8000,mt,ps);
}

static int gp_spr_ipre_setpix(gp_spr *s,int x,int y,int ps,int c)
{
	_gp_simpspr *spr;
	int i,j;
	if ((s == 0) || (x < 0) || (y < 0) || (ps < 0) || (ps > 2))
		return 1; /* Fail */
	spr = s->d;
	i = x+y*spr->w;
	j = spr->w*spr->h+1; /* Size of one preshift, in pixels */
	if ((x >= spr->w) || (y >= spr->h))
		return 1; /* Fail */
	else if (s->f == &gp_spr_pre00)
		((char *) spr->d)[i] =((char *) spr->d)[i+j] =((char *) spr->d)[i+2*j] =((char *) spr->d)[i+3*j] = gp_col_conv(ps,c,0);
	else if ((s->f == &gp_spr_pre01))
		((char *) spr->d)[i*2] = ((char *) spr->d)[(i+j)*2] = gp_col_conv(ps,c,0);
	else if (s->f == &gp_spr_pre10)
		((short *) spr->d)[i] = ((short *) spr->d)[i+j] = gp_col_conv(ps,c,1);
	else /* gp_spr_pre11 */
		((short *) spr->d)[i] = ((short *) spr->d)[i+j] = (((short *) spr->d)[i] & 0x8000) | (gp_col_conv(ps,c,1) & 0x7FFF);
	return 0;
}

static int gp_spr_ipre_setmask(gp_spr *s,int x,int y,int mt,int ps,int c)
{
	_gp_simpspr *spr;
	int i,j;
	if ((s == 0) || (x < 0) || (y < 0) || (ps < 0) || (ps > 2))
		return 1; /* Fail */
	spr = s->d;
	i = x+y*spr->w;
	j = spr->w*spr->h+1; /* Size of one preshift, in pixels */
	if ((x >= spr->w) || (y >= spr->h))
		return 1; /* Fail */
	else if ((s->f == &gp_spr_pre00) || (s->f == &gp_spr_pre10))
		return 1; /* Fail */
	else if (s->f == &gp_spr_pre01)
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_ONOFF,0);
		if (c)
			c = 255;
		((char *) spr->d)[i*2+1] = ((char *) spr->d)[(i+j)*2+1] = c;
	}
	else /* gp_spr_pre11 */
	{
		c = gp_mask_conv(mt,ps,c,GP_MT_ONOFF,1);
		if (c)
			c = 32768;
		((unsigned short *) spr->d)[i] = ((unsigned short *) spr->d)[i+j] = c | (((unsigned short *) spr->d)[i] & 0x7FFF);
	}
	return 0;
}

gp_screen *gp_spr_ipre_toscreen(gp_spr *s,gp_screen *scr)
{
	return 0;
}

extern int gp_genplot_premonkey(gp_spr *spr,int x,int y,gp_screen *scr);

gp_sprfmt gp_spr_pre00 = {
	gp_spr_ipre_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_ipre_getsize, gp_spr_ipre_getps, gp_spr_ipre_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_ipre_getpix, gp_spr_ipre_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_ipre_setpix, gp_spr_ipre_setmask, gp_genplot_premonkey, gp_spr_ipre_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_pre01 = {
	gp_spr_ipre_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_ipre_getsize, gp_spr_ipre_getps, gp_spr_ipre_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_ipre_getpix, gp_spr_ipre_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_ipre_setpix, gp_spr_ipre_setmask, gp_genplot_premonkey, gp_spr_ipre_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_pre10 = {
	gp_spr_ipre_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_ipre_getsize, gp_spr_ipre_getps, gp_spr_ipre_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_ipre_getpix, gp_spr_ipre_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_ipre_setpix, gp_spr_ipre_setmask, gp_genplot_premonkey, gp_spr_ipre_toscreen, gp_genplot_yeknom
};

gp_sprfmt gp_spr_pre11 = {
	gp_spr_ipre_create, gp_spr_gen_fromscreen, gp_spr_gen_fromspr, gp_spr_gen_delete, gp_spr_ipre_getsize, gp_spr_ipre_getps, gp_spr_ipre_getmt, gp_spr_igen_getw, gp_spr_igen_geth, gp_spr_igen_getox, gp_spr_igen_getoy, gp_spr_ipre_getpix, gp_spr_ipre_getmask, gp_spr_gen_setw, gp_spr_gen_seth, gp_spr_gen_setox, gp_spr_gen_setoy, gp_spr_ipre_setpix, gp_spr_ipre_setmask, gp_genplot_premonkey, gp_spr_ipre_toscreen, gp_genplot_yeknom
};

#endif
