/*
   Copyright 2008 Jeffrey Lee
   This file is part of WOUM.
   WOUM 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.
   WOUM 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 WOUM.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>

#include "kernel.h"
#include "swis.h"

#include "spandraw.h"
#include "vec.h"
#include "tmat.h"

#include "screen.h"
#include "WoumInclude:lib/gp/screen.h"

#include "timer.c"

#define PROF

f1616 rotx,roty,rotz;
int stop;

tmat16 mat1,mat2;

#define POINTFIVE 0x8000

void histogram(int col,void *scr,int len)
{
	char *s;
	if (len < 1)
	{
		stop = 1;
		printf("len=%d col=%d\n",len,col & 0xFF);
	}
	col = col & 0xFF;
	if ((col) || (stop == 0))
		gp_screen_hline0(col*0x1010101,scr,len);
	s = (char *) span_buf;
	if ((len >= span_lines-64) || (len < 1) || (col == 0))
		return;
	s = s + ((len+64)*span_width);
	len = span_width;
	while ((*s) && (--len)) /* Avoid running off the end of the screen */
		s++;
	*s = col;
}

#define PERCENT(x) ((double) timer_report(x)*100)/((double) (timer_report(0)+1))

vec16 tvec[4];
void *framea,*frameb,*framec;

int main(int argc,char **argv)
{
#define I 0x10000
	vec16 vecs[] = {{0,0,0},{I,0,0},{I,I,0},{0,I,0}, // Front face
			{0,I,0},{I,I,0},{I,I,I},{0,I,I}, // Top
			{0,0,I},{0,0,0},{0,I,0},{0,I,I}, // Left side
			{I,0,I},{0,0,I},{0,I,I},{I,I,I}, // Back
			{0,0,I},{I,0,I},{I,0,0},{0,0,0}, // Bottom
			{I,0,0},{I,0,I},{I,I,I},{I,I,0}}; // Right
#undef I
	int side,frames;
	_kernel_swi_regs regs;
	f1616 dist;
	vec16 *ar[4];
	dist = f1616_FromInt(3);
	screen_oldmode(28);
	screen_createbanks(2);
	screen_setvdu(1); /* Set up banks */
	screen_setdisplay(2);
	screen_getdata();
	span_lines = screen.height+1;
	span_width = screen.width+1;
	span_ps = 0;
	span_gap = 0;
	frames=0;
	do {
		timer_start(0);
#ifdef PROF
		timer_start(4);
#endif
		screen_vsync();
#ifdef PROF
		timer_stop(4);
		timer_start(5);
#endif
		screen_swap();
		screen_getdata();
		_kernel_swi(0x100+31,&regs,&regs); /* Reposition cursor */
		_kernel_swi(0x100,&regs,&regs);
		_kernel_swi(0x100,&regs,&regs);
		span_buf = (void *) screen.vdu;
		span_init(0);
#ifdef PROF
		timer_stop(5);
		timer_start(1);
#endif
		/* Set up matrix */
		tmat16_ident(&mat1);
		tvec[0].x = tvec[0].y = tvec[0].z = -POINTFIVE;
		tmat16_translate(&mat1,&mat2,&tvec[0]);
		tmat16_rotx(&mat2,&mat1,rotx);
		tmat16_roty(&mat1,&mat2,roty);
		tmat16_rotz(&mat2,&mat1,rotz);
		tvec[0].x = tvec[0].y = 0;
		tvec[0].z = dist;
		tmat16_translate(&mat1,&mat2,&tvec[0]);
		tvec[0].x = tvec[0].z = 0x10000;
		tvec[0].y = f1616_div(f1616_FromInt(span_width),f1616_FromInt(span_lines));
		tmat16_scale(&mat2,&mat1,&tvec[0]); /* Account for aspect ratio */
#ifdef PROF
		timer_stop(1);
		timer_start(3);
#endif
		for (side=0;side<6;side++)
		{
			ar[0] = &(vecs[side*4]);
			ar[1] = &(vecs[side*4+1]);
			ar[2] = &(vecs[side*4+2]);
			ar[3] = &(vecs[side*4+3]);
			span_addpoly(4,ar,0x10101010*(side+1),&mat1);
		}
#ifdef PROF
		timer_stop(3);
		timer_start(2);
#endif
	/*	span_do2(gp_screen_hline0);*/
	/*	span_do2(histogram);*/
		if (framea)
		{
			span_swapset(framea);
			span_addrect(0,span_width-1,0,64,0,1); /* Overwrite the text at the top of the screen */
			span_swapset(framea);
		}
		framea = span_do3(gp_screen_hline0,framea);
		/* Swap a and b */
		framec = frameb;
		frameb = framea;
		framea = framec;
#ifdef PROF
		timer_stop(2);
		timer_start(5);
#endif
		span_free(0);
		if (!stop)
		{
			rotx += f1616_FromFloat(0.5);
			roty += f1616_FromFloat(0.25);
			rotz += f1616_FromFloat(0.125);
		}
#ifdef PROF
		timer_stop(5);
#endif
		timer_stop(0);
		frames++;
		printf("frames %d; average %.2ffps\n",frames,(double) (100*frames)/(timer_report(0)+1));
#ifdef PROF
		printf("ext poly add=%.2f%% int poly add=%.2f%% screen draw=%.2f%% vsync=%.2f%% misc=%.2f%%\n",PERCENT(1),PERCENT(3),PERCENT(2),PERCENT(4),PERCENT(5));
#endif
		_kernel_swi(OS_Mouse,&regs,&regs);
		if (regs.r[2] & 4)
			dist -= 0x1000; /* one 16th */
		if (regs.r[2] & 1)
			dist += 0x1000;
#ifdef PROF
		if (regs.r[2] & 2)
		{
			timer_reset(0); /* Reset timers to allow more accurate timings during long runs */
			timer_reset(1);
			timer_reset(2);
			timer_reset(3);
			timer_reset(4);
			timer_reset(5);
			frames = 0;
		}
#endif
	} while (1);
	return 0;
}


