/*
	r_sky.c

	(description)

	Copyright (C) 1996-1997  Id Software, Inc.

	This program 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 2
	of the License, or (at your option) any later version.

	This program 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 this program; if not, write to:

		Free Software Foundation, Inc.
		59 Temple Place - Suite 330
		Boston, MA  02111-1307, USA

*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "QF/render.h"

#include "r_internal.h"


static int         iskyspeed = 8;
static int         iskyspeed2 = 2;
static float r_skyperiod;
float       r_skyspeed;

float       r_skytime;

byte       *r_skysource;

int         r_skymade;

// TODO: clean up these routines

byte        bottomsky[128 * 131];
byte        bottommask[128 * 131];
byte        newsky[128 * 256];	// newsky and topsky both pack in here, 128
								// bytes of newsky on the left of each scan,
								// 128 bytes of topsky on the right, because
								// the low-level drawers need 256-byte widths


/*
	R_InitSky

	A sky texture is 256*128, with the right side being a masked overlay
*/
void
R_InitSky (texture_t *mt)
{
	int         i, j;
	byte       *src;

	int         g = GreatestCommonDivisor (iskyspeed, iskyspeed2);
	int         s1 = iskyspeed / g;
	int         s2 = iskyspeed2 / g;
	r_skyperiod = SKYSIZE * s1 * s2;

	r_skyspeed = iskyspeed;

	src = (byte *) mt + mt->offsets[0];

	for (i = 0; i < 128; i++) {
		for (j = 0; j < 128; j++) {
			newsky[(i * 256) + j + 128] = src[i * 256 + j + 128];
		}
	}

	for (i = 0; i < 128; i++) {
		for (j = 0; j < 131; j++) {
			if (src[i * 256 + (j & 0x7F)]) {
				bottomsky[(i * 131) + j] = src[i * 256 + (j & 0x7F)];
				bottommask[(i * 131) + j] = 0;
			} else {
				bottomsky[(i * 131) + j] = 0;
				bottommask[(i * 131) + j] = 0xff;
			}
		}
	}

	r_skysource = newsky;
}


void
R_MakeSky (void)
{
	int         x, y;
	int         ofs, baseofs;
	int         xshift, yshift;
	byte       *pnewsky;
	static int  xlast = -1, ylast = -1;

	xshift = r_skytime * r_skyspeed;
	yshift = r_skytime * r_skyspeed;

	if ((xshift == xlast) && (yshift == ylast))
		return;

	xlast = xshift;
	ylast = yshift;

	pnewsky = &newsky[0];

	for (y = 0; y < SKYSIZE; y++) {
		baseofs = ((y + yshift) & SKYMASK) * 131;
		for (x = 0; x < SKYSIZE; x++) {
			ofs = baseofs + ((x + xshift) & SKYMASK);

			*pnewsky = (*(pnewsky + 128) & bottommask[ofs]) | bottomsky[ofs];
			pnewsky = pnewsky + 1;
		}
		pnewsky += 128;
	}

	r_skymade = 1;
}


void
R_GenSkyTile (void *pdest)
{
	int         x, y;
	int         ofs, baseofs;
	int         xshift, yshift;
	unsigned int *pnewsky;
	unsigned int *pd;

	xshift = r_skytime * r_skyspeed;
	yshift = r_skytime * r_skyspeed;

	pnewsky = (unsigned int *) &newsky[0];
	pd = (unsigned int *) pdest;

	for (y = 0; y < SKYSIZE; y++) {
		baseofs = ((y + yshift) & SKYMASK) * 131;

// FIXME: clean this up
#if UNALIGNED_OK
		for (x = 0; x < SKYSIZE; x += 4) {
			ofs = baseofs + ((x + xshift) & SKYMASK);

			// PORT: unaligned dword access to bottommask and bottomsky

			*pd = (*(pnewsky + (128 / sizeof (unsigned int))) &
				   *(unsigned int *) &bottommask[ofs]) |
				*(unsigned int *) &bottomsky[ofs];

			pnewsky++;
			pd++;
		}
#else
		for (x = 0; x < SKYSIZE; x++) {
			ofs = baseofs + ((x + xshift) & SKYMASK);

			*(byte *) pd = (*((byte *) pnewsky + 128) &
							*(byte *) & bottommask[ofs]) |
				*(byte *) & bottomsky[ofs];
			pnewsky = (unsigned int *) ((byte *) pnewsky + 1);
			pd = (unsigned int *) ((byte *) pd + 1);
		}
#endif
		pnewsky += 128 / sizeof (unsigned int);
	}
}


void
R_SetSkyFrame (void)
{
	r_skytime = vr_data.realtime;
	r_skytime -= trunc (vr_data.realtime / r_skyperiod) * r_skyperiod;

	r_skymade = 0;
}


/*
   Stub function for loading a skybox.  Currently we have support for
   skyboxes only in GL targets, so we just do nothing here.  --KB
*/
void
R_LoadSkys (const char *name)
{
}