/*

DS glOrtho Test
Relminator 2010 
Richard Eric M. Lope BSN RN

http://rel.betterwebber.com

Just a proof of concept of using the 3d core to render 2d stuff


Notes:
*/


#include <nds.h>
#include <stdio.h>

/*
  These enums are bits for flipping the sprites
  You can "|" (or) GL_FLIP_V and GL_FLIP_H to flip 
  both ways. 
*/
typedef enum
{

	GL_FLIP_NONE 	= 1 << 0,
	GL_FLIP_V 		= 1 << 1,
	GL_FLIP_H 		= 1 << 2,
	
} GL_FLIP_MODE;


/*
  This is our struct to hold our image
  attributes. You don't need to worry about this 
  if you use the texture packer.
  
  width -> image width
  height -> image height
  u_off and -> ST/XY/UV texture offsets
  textureID -> the texture handle in VRAM (returned by glGenTextures())
               ie. This references the actual texture stored in VRAM
*/
typedef struct glImage
{

	int		width;
	int 	height;
	int 	u_off;
	int 	v_off;
	int		textureID;

} glImage;


/******************************************************************************
	Direct copy of glVertex3v16()
	I made this since VideoGL don't have a
	glVertexni() wrappers
******************************************************/
static inline void glVertex3i(v16 x, v16 y, v16 z)
{
	GFX_VERTEX16 = (y << 16) | (x & 0xFFFF);
	GFX_VERTEX16 = ((uint32)(uint16)z);
}

/******************************************************************************
	Again no glVertex2i() in the videoGL header
	This is used for optimizing vertex calls
******************************************************/
static inline void glVertex2i(v16 x, v16 y)
{
	GFX_VERTEX_XY = (y << 16) | (x & 0xFFFF);	
}

/******************************************************************************
	Almost a direct copy of TEXTURE_PACK except that
	UV coords are shifted left by 4 bits.
	U and V are shifted left by 4 bits
	since GFX_TEX_COORD expects 12.4 Fixed point values
******************************************************/
static inline void glTexcoord2i(t16 u, t16 v)
{
	GFX_TEX_COORD = (v << 20) | ( (u << 4) & 0xFFFF );
}


/******************************************************************************
    I made this since the scale wrappers are either the 
	vectorized mode or does not permit you to scale only
	the axes you want to scale. Needed for sprite scaling.
******************************************************************************/
static inline void glScale(s32 x, s32 y, s32 z)
{
	MATRIX_SCALE = x;
	MATRIX_SCALE = y;
	MATRIX_SCALE = z;
}

/*
  Our static global variable used for
  Depth values since we cannot disable 
  depth testing in the DS hardware
  This value is incremented for every draw call
*/
static v16 g_depth = 0;



/******************************************************************************
	Initializes GL in 3d mode 
	I initialized in 3d mode so that we could combine 2d and 3d later
	Almost a direct copy from the example files
******************************************************************************/
void glInitScreen()
{
		
	// initialize gl
	glInit();
	
	//enable textures
	glEnable(GL_TEXTURE_2D);
	
	// enable antialiasing
	glEnable(GL_ANTIALIAS);
		
	// setup the rear plane
	glClearColor(0,0,0,31); // BG must be opaque for AA to work
	glClearPolyID(63); // BG must have a unique polygon ID for AA to work
	
	glClearDepth(GL_MAX_DEPTH);

	//this should work the same as the normal gl call
	glViewport(0,0,255,191);
	
	
	//any floating point gl call is being converted to fixed prior to being implemented
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(70, 256.0 / 192.0, 1, 200);
	
	gluLookAt(	0.0, 0.0, 1.0,		//camera possition 
				0.0, 0.0, 0.0,		//look at
				0.0, 1.0, 0.0);		//up

	glMaterialf(GL_AMBIENT, RGB15(31,31,31));
	glMaterialf(GL_DIFFUSE, RGB15(31,31,31));
	glMaterialf(GL_SPECULAR, BIT(15) | RGB15(31,31,31));
	glMaterialf(GL_EMISSION, RGB15(31,31,31));

	//ds uses a table for shinyness..this generates a half-ass one
	glMaterialShinyness();

	//not a real gl function and will likely change
	glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK);
	
}

/******************************************************************************
	Set orthographic projection
	at 1:1 correspondence to screen coords
	glOrtho expects f32 values but if we use the
	standard f32 values, we need to rescale either
	every vert or the modelview matrix by the same
	amount to make it work.  That's gonna give us
	lots of overflows and headaches.  So we "scale down"
	and use an all integer value.
******************************************************************************/
void glSetOrtho()		
{

	glMatrixMode(GL_PROJECTION);     // set matrixmode to projection
	glLoadIdentity();				 // reset
	glOrthof32(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1 << 12, 1 << 12);  // downscale projection matrix
	
}


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


******************************************************************************/
void glStart2D()
{

	
	// save 3d perpective projection matrix
	glMatrixMode(GL_PROJECTION);   
    glPushMatrix();
	
	// save 3d modelview matrix for safety
	glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
	
	
	//what?!! No glDisable(GL_DEPTH_TEST)?!!!!!!
	glEnable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_ANTIALIAS);		// disable AA
	glDisable(GL_OUTLINE);			// disable edge-marking

	glColor(0x7FFF); 				// max color
	
	glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);  // no culling

	glSetOrtho();
	
	glMatrixMode(GL_TEXTURE);      	// reset texture matrix just in case we did some funky stuff with it
	glLoadIdentity();
	
	glMatrixMode(GL_MODELVIEW);		// reset modelview matrix. No need to scale up by << 12
	glLoadIdentity();

	
	g_depth = 0; 	// set depth to 0. We need this var since we cannot disable depth testing

}


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

	Issue this after drawing 2d so that we don't mess the matrix stack

******************************************************************************/
void glEnd2D()
{

	// restore 3d matrices and set current matrix to modelview
	glMatrixMode(GL_PROJECTION);    
    glPopMatrix(1);
	glMatrixMode(GL_MODELVIEW);
    glPopMatrix(1);

}

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

	draws a line
	
******************************************************************************/
void glLine(int x1, int y1, int x2, int y2, int color)
{

	glBindTexture(0,0);
	glColor(color);
	glBegin(GL_TRIANGLES);
		glVertex3i(x1,y1,g_depth);
		glVertex2i(x2,y2);
		glVertex2i(x2,y2);
	glEnd();
	glColor(0x7FFF);
	g_depth++;
	
}


/******************************************************************************
    
	draws a box

******************************************************************************/
void glBox(int x1, int y1, int x2, int y2, int color)
{
	
	glBindTexture(0,0);
	glColor(color);
	glBegin(GL_TRIANGLES);
	
		glVertex3i(x1,y1,g_depth);
		glVertex2i(x2,y1);
		glVertex2i(x2,y1);

		glVertex2i(x2,y1);
		glVertex2i(x2,y2);
		glVertex2i(x2,y2);

		glVertex2i(++x2,y2);  // bug fix for lower-right corner disappearing pixel
		glVertex2i(x1,y2);
		glVertex2i(x1,y2);

		glVertex2i(x1,y2);
		glVertex2i(x1,y1);
		glVertex2i(x1,y1);
		
	glEnd();
	glColor(0x7FFF);
	g_depth++;

}

/******************************************************************************
   
   draws a filled box

******************************************************************************/
void glBoxFilled(int x1, int y1, int x2, int y2, int color)
{

	glBindTexture(0,0);
	glColor(color);
	glBegin(GL_QUADS);
		glVertex3i(x1,y1,g_depth);		// use 3i for first vertex so that we increment HW depth
		glVertex2i(x1,y2);				// no need for 3 vertices as 2i would share last depth call
		glVertex2i(x2,y2);
		glVertex2i(x2,y1);
	glEnd();
	glColor(0x7FFF);
	g_depth++;

}


/******************************************************************************
   
   draws a filled box in gradient colors

******************************************************************************/
void glBoxFilledGradient(int x1, int y1, int x2, int y2, int color1, int color2, int color3, int color4)
{

	glBindTexture(0,0);
	glBegin(GL_QUADS);
		glColor(color1); glVertex3i(x1,y1,g_depth);		// use 3i for first vertex so that we increment HW depth
		glColor(color2); glVertex2i(x1,y2);				// no need for 3 vertices as 2i would share last depth call
		glColor(color3); glVertex2i(x2,y2);
		glColor(color4); glVertex2i(x2,y1);
	glEnd();
	glColor(0x7FFF);
	g_depth++;

}



/******************************************************************************
    
	draws a Triangle

******************************************************************************/
void glTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color)
{
	
	glBindTexture(0,0);
	glColor(color);
	glBegin(GL_TRIANGLES);
	
		glVertex3i(x1,y1,g_depth);
		glVertex2i(x2,y2);
		glVertex2i(x2,y2);

		glVertex2i(x2,y2);
		glVertex2i(x3,y3);
		glVertex2i(x3,y3);

		glVertex2i(x3,y3);  
		glVertex2i(x1,y1);
		glVertex2i(x1,y1);
		
	glEnd();
	glColor(0x7FFF);
	g_depth++;

}

/******************************************************************************
   
   draws a filled triangle

******************************************************************************/
void glTriangleFilled(int x1, int y1, int x2, int y2, int x3, int y3, int color)
{

	glBindTexture(0,0);
	glColor(color);
	glBegin(GL_TRIANGLES);
		glVertex3i(x1,y1,g_depth);		// use 3i for first vertex so that we increment HW depth
		glVertex2i(x2,y2);				// no need for 3 vertices as 2i would share last depth call
		glVertex2i(x3,y3);
	glEnd();
	glColor(0x7FFF);
	g_depth++;

}


/******************************************************************************
   
   draws a filled Triangle in gradient colors

******************************************************************************/
void glTriangleFilledGradient(int x1, int y1, int x2, int y2, int x3, int y3, int color1, int color2, int color3)
{

	glBindTexture(0,0);
	glBegin(GL_TRIANGLES);
		glColor(color1); glVertex3i(x1,y1,g_depth);		// use 3i for first vertex so that we increment HW depth
		glColor(color2); glVertex2i(x2,y2);				// no need for 3 vertices as 2i would share last depth call
		glColor(color3); glVertex2i(x3,y3);
	glEnd();
	glColor(0x7FFF);
	g_depth++;

}


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

    Draws a sprite
	Parameters:
       x 		-> x position of the sprite
	   y 		-> y position of the sprite
	   flipmode -> mode for flipping (see GL_FLIP_MODE enum)
	   *spr 	-> pointer to a glImage

******************************************************************************/
void glSprite(int x, int y, GL_FLIP_MODE flipmode, glImage *spr)
{
	int x1 = x;
	int y1 = y;
	int x2 = x + spr->width;
	int y2 = y + spr->height;

	int	u1 = (flipmode  & GL_FLIP_H) ? spr->u_off + spr->width - 1  : spr->u_off;
 	int	u2 = (flipmode  & GL_FLIP_H) ? spr->u_off 			        : spr->u_off + spr->width;
	int v1 = (flipmode  & GL_FLIP_V) ? spr->v_off + spr->height - 1 : spr->v_off;
 	int v2 = (flipmode  & GL_FLIP_V) ? spr->v_off 				    : spr->v_off + spr->height;
 	
 
	glBindTexture(0, spr->textureID);	
	glBegin(GL_QUADS);
		
		glTexcoord2i(u1, v1); glVertex3i(x1, y1, g_depth);	
		glTexcoord2i(u1, v2); glVertex2i(x1, y2);
		glTexcoord2i(u2, v2); glVertex2i(x2, y2);
		glTexcoord2i(u2, v1); glVertex2i(x2, y1);
		
	glEnd();
	
	g_depth++;

}

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

    Draws a center rotated sprite
	Parameters:
       x 		-> x position of the sprite center
	   y 		-> y position of the sprite center
	   angle    -> is the angle to rotated (-32768 to 32767)
	   flipmode -> mode for flipping (see GL_FLIP_MODE enum)
	   *spr 	-> pointer to a glImage

******************************************************************************/
void glSpriteRotate(int x, int y, s32 angle, GL_FLIP_MODE flipmode, glImage *spr)
{
	
	int s_half_x = spr->width/2;
	int	s_half_y = spr->height/2;
	
	int x1 =  -s_half_x;
	int y1 =  -s_half_y;
	
	int x2 =  s_half_x;
	int y2 =  s_half_y;
	
	
	int	u1 = (flipmode  & GL_FLIP_H) ? spr->u_off + spr->width - 1  : spr->u_off;
 	int	u2 = (flipmode  & GL_FLIP_H) ? spr->u_off 			        : spr->u_off + spr->width - 1;
	int v1 = (flipmode  & GL_FLIP_V) ? spr->v_off + spr->height - 1 : spr->v_off;
 	int v2 = (flipmode  & GL_FLIP_V) ? spr->v_off 				    : spr->v_off + spr->height - 1;
 	
	glBindTexture(0, spr->textureID);
	
	glPushMatrix();
	
		glTranslate3f32(x, y, 0);
		glRotateZi(angle);
		
		
	glBegin(GL_QUADS);
		
		glTexcoord2i(u1, v1); glVertex3i(x1, y1, g_depth);	
		glTexcoord2i(u1, v2); glVertex2i(x1, y2);
		glTexcoord2i(u2, v2); glVertex2i(x2, y2);
		glTexcoord2i(u2, v1); glVertex2i(x2, y1);
		
	glEnd();
	
	glPopMatrix(1);
		
	g_depth++;

}


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

    Draws a center rotated and scaled sprite
	Parameters:
       x 		-> x position of the sprite center
	   y 		-> y position of the sprite center
	   angle    -> is the angle to rotated (-32768 to 32767)
	   scale    -> is a 20.12 FP scale value (you can use floattof32(1.45) to scale
	               and GCC would optimize it to a constant)
	   flipmode -> mode for flipping (see GL_FLIP_MODE enum)
	   *spr 	-> pointer to a glImage

******************************************************************************/
void glSpriteRotateScale(int x, int y, s32 angle, s32 scale, GL_FLIP_MODE flipmode, glImage *spr)
{
	
	int s_half_x = spr->width/2;
	int	s_half_y = spr->height/2;
	
	int x1 =  -s_half_x;
	int y1 =  -s_half_y;
	
	int x2 =  s_half_x;
	int y2 =  s_half_y;
	
	int	u1 = (flipmode  & GL_FLIP_H) ? spr->u_off + spr->width - 1  : spr->u_off;
 	int	u2 = (flipmode  & GL_FLIP_H) ? spr->u_off 			        : spr->u_off + spr->width- 1;
	int v1 = (flipmode  & GL_FLIP_V) ? spr->v_off + spr->height - 1 : spr->v_off;
 	int v2 = (flipmode  & GL_FLIP_V) ? spr->v_off 				    : spr->v_off + spr->height - 1;
 	
	glBindTexture(0, spr->textureID);
	
	glPushMatrix();
	
		glTranslate3f32(x, y, 0);
		glScale(scale, scale, 1 << 12);
		glRotateZi(angle);
		
		
	glBegin(GL_QUADS);
		
		glTexcoord2i(u1, v1); glVertex3i(x1, y1, g_depth);	
		glTexcoord2i(u1, v2); glVertex2i(x1, y2);
		glTexcoord2i(u2, v2); glVertex2i(x2, y2);
		glTexcoord2i(u2, v1); glVertex2i(x2, y1);
		
	glEnd();
	
	glPopMatrix(1);
		
	g_depth++;

}


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

    Initializes our spriteset with Texture Packer generated UV coordinates
	Very safe and easy to use.
	Parameters:
       *spr 		-> pointer to an array of glImage
	   numframes 	-> number of frames in a spriteset (auto-generated by Texture Packer)
	   *texcoords 	-> Texture Packer auto-generated array of UV coords
	   textureID 	-> Texture handle returned by glGenTextures()

******************************************************************************/
void glInitSpriteset(glImage *sprite, int numframes, const unsigned int *texcoords, int textureID)
{

	int i;
	// init sprites texture coords and texture ID
	for ( i=0; i < numframes; i++)
	{
		int j = i * 4; // texcoords array is u_off, wid, hei
		sprite[i].textureID = textureID;
		sprite[i].u_off = texcoords[j];				// set x-coord
		sprite[i].v_off = texcoords[j+1];;			// y-coord 
		sprite[i].width = texcoords[j+2];			// don't decrease because NDS 3d core does not draw last vertical texel
		sprite[i].height = texcoords[j+3];		    // ditto
	}
	
}

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

    Initializes our spriteset (like glInitSpriteset()) but without the use of
	Texture Packer auto-generated files.
	Very rigid, not so safe and prone to human error.
	!!! Can ony be used for tilesets whose tiles are the same sizes!!!
	Parameters:
       *sprite 		-> pointer to an array of glImage
	   numframes 	-> number of frames in a spriteset (auto-generated by Texture Packer)
	   tile_wid 	-> width of each tile in the texture
	   tile_hei 	-> height of each tile in the texture
	   bmp_wid 		-> width of of the texture in VRAM
	   bmp_hei 		-> height of of the texture in VRAM
	   textureID 	-> Texture handle returned by glGenTextures()

******************************************************************************/
void glInitTileset(glImage *sprite, int numframes, int tile_wid, int tile_hei,
                   int bmp_wid, int bmp_hei, int textureID)
{

	int i=0;
	int x, y;
	
	// init sprites texture coords and texture ID
	for (y = 0; y < (bmp_hei/tile_hei); y++)
	{
		for (x = 0; x < (bmp_wid/tile_wid); x++) 
		{
			sprite[i].width 			= tile_wid;
			sprite[i].height 			= tile_hei;
			sprite[i].u_off				= x*tile_wid;
			sprite[i].v_off				= y*tile_hei; 
			sprite[i].textureID 		= textureID;
			i++;
		}
	}
}


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

    MAIN 

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



// background tile drawing routine
void drawBG(glImage *tiles);


// GRIT auto-genrated arrays of images
#include "tiles.h"
#include "enemies.h"

// Texture Packer auto-generated UV coords
#include "uvcoord_enemies.h"

// this imageset would use our texture packer generated coords so it's kinda
// safe and easy to use 
// ENEMIES_NUM_IMAGES is a value from "uvcoord_enemies.h"
glImage  enemies_images[ENEMIES_NUM_IMAGES];;

// this tileset won't make use of our texture packer generated coords
// messy, manual and prone to errors
glImage  tiles_images[8*8];  //BMP is 128x128 and tiles are 16x16 so.. (128/16) * (128 /16) = 8 * 8


int main(int argv, char *argc[])
{

	videoSetMode(MODE_5_3D);
	
	
	consoleDemoInit();
	
	iprintf("\x1b[1;1HSPRITEST LOADING TEST");
	iprintf("\x1b[3;1HBackground tiles are loaded");
	iprintf("\x1b[4;1H    via glInitTileset().");
	
	iprintf("\x1b[6;1HForeground sprites are loaded");
	iprintf("\x1b[7;1H    via glInitSpriteset().");
	
	iprintf("\x1b[9;1HExamples of:");
	iprintf("\x1b[11;1H1. Rotation");
	iprintf("\x1b[12;1H2. Rotation and scaling");
	iprintf("\x1b[13;1H3. POLY_ALPHA() Blending");
	iprintf("\x1b[14;1H4. Flipping and animation");
	
	iprintf("\x1b[17;1HRelminator");
	iprintf("\x1b[18;1Hhttp://rel.betterwebber.com");
	
	
	// Initialize GL in 3d mode
	glInitScreen();
	
	
	// set  Bank A to texture (128 kb)
	vramSetBankA(VRAM_A_TEXTURE);
	

	// Our texture handles for enemies and tiles
	int enemies_textureID;  
	int tiles_textureID;  
	
	// load paletted 8 bit bitmap with color index 0 as the transparent color
	glGenTextures(1, &enemies_textureID);
	glBindTexture(0, enemies_textureID);
	glTexImage2D( 0, 0, GL_RGB256, TEXTURE_SIZE_256 , TEXTURE_SIZE_256, 0, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, (u8*)enemiesBitmap );

	glGenTextures(1, &tiles_textureID);
	glBindTexture(0, tiles_textureID);
	glTexImage2D( 0, 0, GL_RGB256, TEXTURE_SIZE_128 , TEXTURE_SIZE_128, 0, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, (u8*)tilesBitmap );

	// load the palette for our 256 color BMP
	gluTexLoadPal(enemiesPal, 512,GL_RGB256);

	// initialize sprites easily by using the UV coords generated by the texture packer
	glInitSpriteset(enemies_images, ENEMIES_NUM_IMAGES, enemies_texcoords, enemies_textureID);

	// initialize rigid 16 x 16 tileset without the use of texture packer
	// very messy and prone to bugs
	glInitTileset(tiles_images, 30, 16, 16,
                  128, 128, tiles_textureID);

	int x, y;
	
	int option_frame = 0;
	int bee_frame = 0;
	int phoenix_frame = 0;
	int frame = 0;
	int rotation = 0;
	
	while(1)
	{
	
		// increment frame counter and rotation offsets
		frame++;
		rotation = (rotation + 128) & 32767;
		
		// animate some of our animated sprites
		// every 8th frame
		if ( (frame & 7) == 0 )
		{
			option_frame = (option_frame + 1) & 3;
			bee_frame = (bee_frame + 1) & 1;
			phoenix_frame++;
			if (phoenix_frame > 2) phoenix_frame = 0;
		}
		
		// draw 3d here
		
		// start of 2d drawing mode
		glStart2D();
		
			// needs to be called before texturing
			// or sprite gets blended by last glcolor call
			glColor(RGB15(31,31,31)); 
			
			// draw out BG composed of 16x16 tiles
			drawBG(tiles_images);
			
			// do some funky frame based movement
			x = 128 + ((cosLerp(frame)+sinLerp(32767/2+rotation) * 70) >> 12);
			y = 96 + ((cosLerp(frame)+cosLerp(-rotation) * 50) >> 12);
			
			// draw some rotated and/or animated sprites
			glSpriteRotate(x, 	   y,    rotation,      GL_FLIP_NONE,          &enemies_images[30+bee_frame]);
			glSpriteRotate(255-x, 191-y, rotation * 4,  GL_FLIP_H,             &enemies_images[84]);
			glSpriteRotate(255-x, y,     -rotation,     GL_FLIP_V,             &enemies_images[85]);
			glSpriteRotate(x,     191-y, -rotation * 3, GL_FLIP_H | GL_FLIP_V, &enemies_images[86]);
			
			
			// do some scaling and rotation
			// translucency is achieved by setting POLY_ALPHA and giving a unique POLY_ID
			s32 scale = sinLerp(rotation) * 3; 
			glPolyFmt(POLY_ALPHA(16) | POLY_CULL_NONE | POLY_ID(1));
			glSpriteRotateScale(128,96,rotation, scale, GL_FLIP_NONE, &enemies_images[32]);
			
			
			// Alpha blended sprite on the top-right
			glSprite(180, 0, GL_FLIP_NONE, &enemies_images[81]);
			
			
			// try some flipped and animated stuff
			glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE); 
			
			// some popcorn enemies on the left
			glSprite(10, 10,  GL_FLIP_NONE,           &enemies_images[option_frame]);
			glSprite(10, 40,  GL_FLIP_H,              &enemies_images[option_frame]);
			glSprite(10, 70,  GL_FLIP_V,              &enemies_images[option_frame]);
			glSprite(10, 100, GL_FLIP_V | GL_FLIP_H , &enemies_images[option_frame]);
			
			// some phoenix enemies on the right
			glSprite(200, 30,  GL_FLIP_NONE,           &enemies_images[87 + phoenix_frame]);
			glSprite(200, 60,  GL_FLIP_H,              &enemies_images[87 + phoenix_frame]);
			glSprite(200, 90,  GL_FLIP_V,              &enemies_images[87 + phoenix_frame]);
			glSprite(200, 130, GL_FLIP_V | GL_FLIP_H , &enemies_images[87 + phoenix_frame]);
			
			
		glEnd2D();  // end 2d mode
		
		// back to 3d mode again
		
		// draw some 3d here
		
		glFlush(0);

		swiWaitForVBlank();
	}

	return 0;
	
}


// Draw s screenful of 16x16 tiles
void drawBG(glImage *tiles)
{
	int i=0;  // index counter
	int x, y; 
	
	// tiles are 16x16 so we divide width and height by 16
	// init sprites texture coords and texture ID
	for (y = 0; y < (SCREEN_HEIGHT/16); y++)
	{
		for (x = 0; x < (SCREEN_WIDTH/16); x++) 
		{
			// snap tiles to 8x8 grid
			glSprite(x * 16, y * 16, GL_FLIP_NONE , &tiles[i]);
			i = (i + 1) & 63;
		}
	}
}