#include <stdio.h>
#include <sys/time.h>	 
#include <unistd.h>
#include <stdlib.h>
#include <vga.h>
#include <vgagl.h>
#include "memtype.h"
#include "atari.h"
#include "6502.h"
#include "rgb.h"
#include "keyboard.h"


/* Atari interface for SVGA
 *  by Frank Barrus
 */

static int framecount = 1;



#define GMODE	G320x240x256
#define VWID	320
#define VHGT	240
#define VOFS	16
#define HOFS	32
#define SCBOT	240



char *interface_name = "SVGAlib interface v0.01 by Frank Barrus";



static inline byte in_portb(word p) {
volatile byte v;
	asm("inb %%dx,%%al":"a="(v):"d"(p));
	return (byte)v;
}

static inline byte out_portb(byte v, word p) {
	asm("outb %%al,%%dx"::"a"(v),"d"(p));
}




typedef struct timeval timedelta;


static int time_delta(timedelta *tlast)
{
struct timeval tv;
int tdif;
	gettimeofday(&tv,NULL);
	tdif = (tv.tv_sec-tlast->tv_sec)*1000000
		+(tv.tv_usec-tlast->tv_usec);
	*tlast = tv;
	return(tdif);
}



void interface_screen_update(void)
{
char buf[80];
static timedelta td;
static int fsec;
int fcount;
static int oldfcount;
int start;
int n,skip;
int skipmax;
static int frame = 0;
	if(++frame < framecount)
		return;
	frame = 0;
	if(sys.scale)
		skipmax = 0;
	else
		skipmax = 4;
	start = VOFS;
	while(start < SCHGT && !sys.scan[start].redraw)
		start++;
	n = start;
	while(1) {
		if(n >= SCBOT)
			break;
		while(n < SCHGT && sys.scan[n].redraw) {
			sys.scan[n].redraw = False;
			n++;
		}
		skip = n;
		while(skip < SCHGT && !sys.scan[skip].redraw)
			skip++;
		if(skip-n >= skipmax || skip >= SCBOT)  {
			vga_copytoplanar256(sys.screen+(SCWID*start)+HOFS,SCWID,
					VWID/4*(start-VOFS),VWID/4,VWID,n-start+1); 
			start = skip;
			n = skip;
		} else
			n = skip;
	}
/*
	fcount = sys.fcount%NFRAMES;
	sprintf(buf, "frame: %5d.%2d  f/sec=%3d  eff=%3d%%",
		sys.fcount/NFRAMES, fcount, fsec, 100*fsec/NFRAMES);
	t.chars = buf;
	t.nchars = strlen(t.chars);
	t.delta = 1;
	t.font = None;
	XDrawText(xatari.display, xatari.window, xatari.gc[15],
		  0, SCHGT-1, &t, 1);
	if(fcount < oldfcount) 
		fsec = NFRAMES*1000000/time_delta(&td);
*/
	oldfcount = fcount;
}



void pc_speaker_tone(int freq)
{
int n;
int oldkb;
	n = 1193182/freq;
	out_portb(0xb6, 0x43);
	out_portb(n&0xff, 0x42);
	out_portb(n>>8, 0x42);
	oldkb = in_portb(0x61);
	out_portb(oldkb|3, 0x61);
}

void pc_speaker_off(void)
{
int oldkb;
	oldkb = in_portb(0x61);
	out_portb(oldkb&~1, 0x61);
}


void interface_click(int n)
{
int oldkb;
	oldkb = in_portb(0x61);
	if(n)
		out_portb((oldkb&~3)|2, 0x61);
	else
		out_portb(oldkb&~3, 0x61);
	if(oldkb&1)
		out_portb(oldkb, 0x61);
}

void interface_sound_update(void)
{
int i;
int x,v,mv;
static last = -1;
static lastf = 0;

/*
	for(i=0; i<4; i++) {
		x = SCWID-sys.audf[i]-1;
		v = sys.audc[i]&15;
		XFillRectangle(xatari.display, xatari.window,
			xatari.gc[i*64+16+(sys.audc[i]>>4)],x,SCHGT-v,1,v);
	}
	if(!(sys.speaker&8))
		XFillRectangle(xatari.display, xatari.window, xatari.gc[15],
				0, SCHGT-8, 8,8);
*/
	x = -1;
	mv = 0;
	for(i=0; i<4; i++) {
		v = sys.audc[i]&0xf;
		if(v >= mv && (sys.audc[i]&0xf0) == 0xa0) {
			x = i;
			mv = v;
		}
	}
	if(mv > 0) {
		if((sys.audctl & 0x08) && (x&1)) 
			i = sys.clock[x]/(WORD(sys.audf[x],sys.audf[x-1])+1);
		else
			i = sys.clock[x]/(sys.audf[x]+1);
		if(last != x || lastf != i)
			pc_speaker_tone(i);
		last = x;
		lastf = i;
	} else {
		if(last >= 0)
			pc_speaker_off();
		last = -1;
	}
}




static void init_controls(void)
{
}



void interface_control_update(void)
{
int k;
	k = vga_getkey();
	if(k > 0)
		keyboard_press_ascii(k);
}



void interface_open(void)
{
int col,lum,n, red, green, blue;
int i;
	vga_setmode(GMODE);
	vga_setmodeX();
	gl_setcontextvga(GMODE);
	for(i=0; i<256; i++) {
		col = i/16;
		lum = i&15;
		if(col==0) 
			n = 3800;
		else
			n = 2125;
		red = (color[col].red*(lum+7)*6)+n*lum;
		green = (color[col].green*(lum+7)*6)+n*lum;
		blue = (color[col].blue*(lum+7)*6)+n*lum;
		gl_setpalettecolor(i, red/1024, green/1024, blue/1024);	
		sys.pixel[i] = i;
	}
	vga_copytoplanar256(sys.screen+(SCWID*VOFS)+HOFS,SCWID,
				 0,VWID/4,VWID,VHGT); 
}


void interface_close(void)
{
	vga_setmode(TEXT);
}


int interface_init(int argc, char **argv)
{
static int init = True;
int narg = 0;
char **argp = argv;

	while(argc--) {
		if(!strcmp(*argv,"-frame"))  {
			framecount = atoi(*(++argv));
			argc--;
			continue;
		} else {
			*argp++ = *argv; narg++;
		}
		if(!strcmp(*argv++,"-h")) {
			printf("SVGAlib interface options:\n");
			if(init) {
			}
			printf("\t-frame <n>\t\trefresh every <n>th frame\n");
			return narg;
		}
	}
	if(!init)
		return narg;
	init = False;

	ioperm(0,0x3ff,1); 
	vga_init();
	vga_unlockvc();
	init_controls();
	keyboard_init("console.key");
	return narg;
}


void interface_end(void)
{
	vga_setmode(TEXT);
	printf("\n");
}



void	interface_map_update(uint base, int len, uint adr, int type)
{
}

void	interface_device_cmd(char type, int uint, char *cmd)
{
}

void	interface_device_param(char type, int uint, char *cmd, char *param)
{
}

