#include "header.h"

void set_mode(int mode);
void get_modeinfo(int mode);
     
int width=WIDTH;
int height=HEIGHT;
int bpp=3;

unsigned char *video; /* c'est là qu'on va écrire */

/* ecriture d'un pixel bien placé */
void set_pix(int x, int y, int r, int g, int b)
{
	/* on calcule la position sur l'écran et on met des limites */
	int pos = bpp*(x + y*width);
	if(x<0 || x>=width) return;
	if(y<0 || y>=height)  return;
	/* et on ecrit directement en mémoire vidéo */
	video[pos] = r;
	video[pos+1] = g;
	video[pos+2] = b;
}

/* definitioture d'un pixel avec une palette */
void set_pix_palette(int x, int y, int pos)
{
	int r,g,b;
	/* on garde l'intérieur en noir */
	if(pos == 0) return;
	/* on essaie de faire joli ... coloré quoi */
	if(pos < 64) {
		r = g = b = pos*2;
	} else if(pos < 128) {
		b = 128 + 2*(pos-64);
		g = 128 - 2*(pos-64);
		r = 128 - 2*(pos-64);
	} else {
		b = 256 - 2*(pos - 128);
		g = 0; 
		r = (pos - 128);
	}
	set_pix(x,y,r,g,b);
}

/* conversion en coordonnées flotantes */
void convert_i2d(int x, int y, double*ppx, double *ppy)
{
        /* on centre a droite pour optimiser la place */
        *ppx = (double)(x-height) / (height/2);
        *ppy = (double)(y-height/2) / (height/2);
}


/* une itération du calcul fractal pour un pixel */
double iteration(double cx, double cy, double *ppx, double *ppy)
{
        double tx,ty;
        /* p = p^2 + C */
        tx = (*ppx)*(*ppx) - (*ppy)*(*ppy) + cx;
        ty = 2*(*ppx)*(*ppy) + cy;
        *ppx = tx;
        *ppy = ty;
        /* |p| */
        return (tx*tx+ty*ty);
}

/* affichage complet de la fractale */
void display()
{
        int x,y;
        int i;
        double cx,cy;
        double px,py;
        double radius;
       /* on parcourt l'écran */
        for(x=0;x<1024;x++) {
                for(y=0;y<768;y++) {
                        convert_i2d(x,y,&cx,&cy);
                        px=cx;
                        py=cy;
                        /* on compte le nombre d'itération pour la couleur, plus joli */
                        for(i=0;i<255;i++) {
                                radius = iteration(cx,cy,&px,&py);
                                if(radius > 8.)
                                        break;
                        }
			set_pix_palette(x,y,255-i);
                }
        }
}

/* notre noyal */
void cmain ()
{
	unsigned int data;

	/* on récupère les infos sur le mode qui nous intéresse */
	get_modeinfo(0x118);
	data = (MODEINFO_SEG << 4)+MODEINFO_OFF;
	/* on joue sur les converstions pour la lecture du bon nombre d'octets en ram */
	video = (unsigned char*) *(unsigned int*)(data + 0x28);
	width = (int) *(unsigned short*)(data + 0x12);
	height = (int) *(unsigned short*)(data + 0x14);
	bpp = (int) *(unsigned char*)(data + 0x19);
	bpp /= 8;

	/* etc'est parti */
	set_mode(0x118);
	display();
}
 

