/* This is a port of my original 3dtest example to KOS. The big difference
   here is that the background plane is no longer used. */

#include <kos.h>

/* This is really more complicated than it needs to be in this particular
   case, but it's nice and verbose. */
int check_start() {
	uint8 mcont = 0;
	cont_cond_t cond;

	mcont = maple_first_controller();
	if (!mcont)
		return 0;

	/* Check for start on the controller */
	if (cont_get_cond(mcont, &cond) < 0)
		return 0;
		
	if (!(cond.buttons & CONT_START)) {
		printf("Pressed start\n");
		return 1;
	}

	return 0;
}



/* A little test program -- creates twelve rainbow polygons and
   moves them around over a color-shifting background. */
typedef struct {
	float	x, y, z;
	float	dx, dy;
} polyplace_t;

polyplace_t polys[12] = {
	{ 16.0f, 0.0f, 10.0f, 3.0f, 5.0f },	/* Top */
	{ 300.0f, 0.0f, 11.0f, 0.0f, 6.0f },
	{ 624.0f, 0.0f, 12.0f, -3.0f, 7.0f },
	
	{ 24.0f, 300.0f, 13.0f, 3.0f, -7.0f },	/* Bottom */
	{ 340.0f, 300.0f, 14.0f, 0.0f, -6.0f },
	{ 616.0f, 300.0f, 15.0f, -3.0f, -5.0f },
	
	{ 0.0f, 16.0f, 16.0f, 5.0f, 3.0f },	/* Left */
	{ 0.0f, 220.0f, 17.0f, 6.0f, 0.0f },
	{ 0.0f, 364.0f, 18.0f, 7.0f, -3.0f },
	
	{ 480.0f, 24.0f, 19.0f, -7.0f, 3.0f },	/* Right */
	{ 480.0f, 260.0f, 20.0f, -6.0f, 0.0f },
	{ 480.0f, 356.0f, 21.0f, -5.0f, -3.0f },
};

/* Does one frame of polygon movement */
void move_polys() {
	int i;
	polyplace_t *p;
	
	for (i=0; i<12; i++) {
		p = polys+i;
		
		p->x += p->dx;
		if (p->x < 0 || p->x > 580.0f) {
			p->dx = -p->dx;
			p->x += p->dx;
		}

		p->y += p->dy;
		if (p->y < 0 || p->y > 420.0f) {
			p->dy = -p->dy;
			p->y += p->dy;
		}
	}
}

/* Sends one polygon's worth of data to the TA */
void draw_one_poly(polyplace_t *p) {
	/* Opaque Colored vertex */
	pvr_vertex_t vert;
	
	vert.flags = PVR_CMD_VERTEX;
	vert.x = p->x + 0.0f;
	vert.y = p->y + 200.0f;
	vert.z = p->z;
	vert.u = vert.v = 0.0f;
	vert.argb = 0xff0000ff;
	vert.oargb = 0;
	pvr_prim(&vert, sizeof(vert));

	vert.y = p->y + 0.0f;
	vert.argb = 0xff00ff00;
	pvr_prim(&vert, sizeof(vert));

	vert.x = p->x + 200.0f;
	vert.y = p->y + 200.0f;
	vert.argb = 0xff000000;
	pvr_prim(&vert, sizeof(vert));

	vert.flags = PVR_CMD_VERTEX_EOL;
	vert.y = p->y + 0.0f;
	vert.argb = 0xffff0000;
	pvr_prim(&vert, sizeof(vert));
}

uint32 color = 0; int dcolor = 5;
void draw_frame() {
	pvr_poly_cxt_t	cxt;
	pvr_poly_hdr_t	poly;
	int i;

	pvr_poly_cxt_col(&cxt, PVR_LIST_OP_POLY);
	pvr_poly_compile(&poly, &cxt);

	color += dcolor;
	if (color <= 0) {
		color = 0; dcolor = -dcolor;
	}
	if (color >= 255) {
		color = 255; dcolor = -dcolor;
	}

	/* Start opaque poly list */
	pvr_wait_ready();
	pvr_scene_begin();
	pvr_list_begin(PVR_LIST_OP_POLY);

	/* Send polygon header to the TA using store queues */
	pvr_prim(&poly, sizeof(poly));

	/* Draw all polygons */
	for (i=0; i<12; i++)
		draw_one_poly(polys+i);

	/* End of opaque list */
	pvr_list_finish();

	/* Finish the frame */
	pvr_scene_finish();
	
	/* Move all polygons */
	move_polys();
}

/* Main program: init and loop drawing polygons */
pvr_init_params_t pvr_params = {
	{ PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_0, PVR_BINSIZE_0, PVR_BINSIZE_0 },
	64 * 1024
};
int main(int argc, char **argv) {
	pvr_init(&pvr_params);

	pvr_set_bg_color(1.0f, 1.0f, 1.0f);

	while (!check_start())
		draw_frame();

	/* Shutdown isn't technically neccessary, but is possible */
	pvr_shutdown();
		
	return 0;
}

