begin process at 2012 05 27 16:32:31
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Graphique

 > GENERATEUR DE FRACTAL PERSONNALISE [VESA] [DJGPP]

GENERATEUR DE FRACTAL PERSONNALISE [VESA] [DJGPP]


 Information sur la source

Note :
9 / 10 - par 1 personne
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Graphique Niveau :Initié Date de création :05/08/2004 Vu / téléchargé :6 300 / 176

Auteur : gorgonzola

Ecrire un message privé
Site perso
Commentaire sur cette source (17)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Un generateur de fractal assez spécial, où l'utilisateur dessine a la souris plusieurs 'segments', puis une forme (la aussi avec des segments), et le programme va se charger de repeter les premiers segments sur chaques segments de la forme dessinee. Ça fonctionne avec des listes chainees et le mode graphique VESA 105h.

Source

  • #include <assert.h>
  • #include <conio.h>
  • #include <dpmi.h>
  • #include <go32.h>
  • #include <math.h>
  • #include <pc.h>
  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <string.h>
  • #include <sys/farptr.h>
  • #include <sys/movedata.h>
  • #include <unistd.h>
  • #define BLACK 0
  • #define RED 1
  • #define WHITE 2
  • #define ENTER 13
  • #define ESCAPE 27
  • #define SPACE 32
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • typedef struct VERTEX
  • {
  • double x;
  • double y;
  • struct VERTEX* n;
  • } VERTEX;
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • char ascii[2048];
  • char* buffer;
  • double SIN[360];
  • double COS[360];
  • __dpmi_regs regs;
  • VERTEX* f;
  • VERTEX* fh;
  • VERTEX* m;
  • VERTEX* mh;
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • int mouse(int* cx,int* cy,int lx,int ly);
  • int build(VERTEX* v);
  • void display();
  • void draw(VERTEX* v,char color);
  • void erase();
  • void free_fractal();
  • void generation();
  • void initVESA();
  • void line(int fx,int fy,int lx,int ly,char color);
  • void pcx();
  • void stopVESA();
  • void text(char* t,int c,int x,int y);
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • int main()
  • {
  • char key;
  • char segs[30];
  • int i;
  • int fi;
  • int mi;
  • initVESA();
  • mi=build(m);
  • if (mi==-1) { stopVESA(); return 0; }
  • fi=build(f);
  • if (fi==-1) { stopVESA(); return 0; }
  • draw(f,BLACK);
  • i=0;
  • while (1)
  • {
  • sprintf(segs,"%d segments ",(int)(fi*pow(mi,i++)));
  • text(segs,WHITE,1,10);
  • display();
  • do key=getch(); while ((key!=ENTER)&&(key!='P')&&(key!=ESCAPE));
  • if (key==ESCAPE) break;
  • else if (key=='P') pcx();
  • erase();
  • generation();
  • };
  • stopVESA();
  • return 0;
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • int mouse(int* cx,int* cy,int lx,int ly)
  • {
  • int button=0;
  • do
  • {
  • regs.x.ax=0x03; // MOV AX,00h
  • __dpmi_int(0x33,&regs); // INT 33h
  • button=(button&2)|(regs.x.bx&1);
  • if (button==1)
  • {
  • (*cx)+=regs.x.cx-lx; // augmente cx du nombre de pixel dont la souris a bouge
  • (*cy)-=regs.x.dx-ly; // diminue cy du nombre de pixel dont la souris a bouge
  • button|=2;
  • }
  • } while (button&1); // continue tant qu'un bouton est presse
  • if (!button)
  • {
  • (*cx)+=regs.x.cx-lx; // augmente cx du nombre de pixel dont la souris a bouge
  • (*cy)-=regs.x.dx-ly; // diminue cy du nombre de pixel dont la souris a bouge
  • }
  • if ((*cx)>350) (*cx)=350; // pour eviter les debordements
  • else if ((*cx)<-349) (*cx)=-349;
  • if ((*cy)>350) (*cy)=350; // pour eviter les debordements
  • else if ((*cy)<-349) (*cy)=-349;
  • regs.x.ax=0x04; // MOV AX,00h
  • regs.x.cx=lx; // MOV CX,[lx]
  • regs.x.dx=ly; // MOV DX,[ly]
  • __dpmi_int(0x33,&regs); // INT 33h
  • return button;
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • int build(VERTEX* v)
  • {
  • int cx=0;
  • int cy=0;
  • int lx;
  • int ly;
  • int i=1;
  • char key;
  • char pos[5];
  • double deg;
  • VERTEX* p;
  • VERTEX* h;
  • text("X : ",WHITE,1,10);
  • text("Y : ",WHITE,1,11);
  • text("angle : ",WHITE,1,12);
  • regs.x.ax=0x03; // MOV AX,00h
  • __dpmi_int(0x33,&regs); // INT 33h
  • lx=regs.x.cx; // position X actuelle de la souris
  • ly=regs.x.dx; // position Y actuelle de la souris
  • h=v; // sauve l'adresse du debut de la liste
  • if (v->n==NULL) // si l'utilisateur doit choisir le premier et le dernier vertex
  • {
  • while (1) // boucle infinie
  • {
  • // efface l'ancien curseur
  • if (cy==350) buffer[cx+510+((382-cy)<<10)]=BLACK; else buffer[cx+510+((382-cy)<<10)]=WHITE;
  • if (cx==350) buffer[cx+511+((383-cy)<<10)]=BLACK; else buffer[cx+511+((383-cy)<<10)]=WHITE;
  • if (cy==-349) buffer[cx+510+((384-cy)<<10)]=BLACK; else buffer[cx+510+((384-cy)<<10)]=WHITE;
  • if (cx==-349) buffer[cx+509+((383-cy)<<10)]=BLACK; else buffer[cx+509+((383-cy)<<10)]=WHITE;
  • buffer[cx+510+((383-cy)<<10)]=WHITE;
  • if (mouse(&cx,&cy,lx,ly))
  • {
  • v->x=(double)cx;
  • v->y=(double)cy;
  • if (v->n==NULL) // si l'utilisateur a choisi le premier vertex
  • {
  • v->n=(VERTEX*)malloc(sizeof(VERTEX));
  • v=v->n;
  • v->n=(VERTEX*)1; // flag
  • }
  • else break; // quitte la boucle infinie si le dernier vertex a ete choisi
  • }
  • // gestion du clavier
  • if (kbhit())
  • {
  • key=getch();
  • if (key==ESCAPE)
  • {
  • v->n=NULL;
  • return -1;
  • }
  • }
  • // affiche la position du curseur
  • sprintf(pos,"%4d",cx);
  • text(pos,WHITE,5,10);
  • sprintf(pos,"%4d",cy);
  • text(pos,WHITE,5,11);
  • // dessine le nouveau curseur
  • buffer[cx+510+((382-cy)<<10)]=RED;
  • buffer[cx+511+((383-cy)<<10)]=RED;
  • buffer[cx+510+((384-cy)<<10)]=RED;
  • buffer[cx+509+((383-cy)<<10)]=RED;
  • buffer[cx+510+((383-cy)<<10)]=RED;
  • // si le premier vertex est deja choisi
  • if (v->n)
  • {
  • line(h->x,h->y,cx,cy,BLACK);
  • buffer[(int)h->x+510+((int)(382-h->y)<<10)]=BLACK;
  • buffer[(int)h->x+511+((int)(383-h->y)<<10)]=BLACK;
  • buffer[(int)h->x+510+((int)(384-h->y)<<10)]=BLACK;
  • buffer[(int)h->x+509+((int)(383-h->y)<<10)]=BLACK;
  • buffer[(int)h->x+510+((int)(383-h->y)<<10)]=BLACK;
  • // affiche l'amplitude
  • if ((cx-h->x==0.0)&&(cy-h->y>=0.0)) deg=90.0;
  • else if ((cx-h->x==0.0)&&(cy-h->y<=0.0)) deg=270.0;
  • else if ((cx-h->x>=0.0)&&(cy-h->y>=0.0)) deg=180.0/PI*atan((cy-h->y)/(cx-h->x));
  • else if ((cx-h->x<=0.0)&&(cy-h->y>=0.0)) deg=180.0-180.0/PI*atan(-(cy-h->y)/(cx-h->x));
  • else if ((cx-h->x<=0.0)&&(cy-h->y<=0.0)) deg=180.0+180.0/PI*atan((cy-h->y)/(cx-h->x));
  • else deg=360.0-180.0/PI*atan(-(cy-h->y)/(cx-h->x));
  • sprintf(pos,"%3.0f",deg);
  • text(pos,WHITE,9,12);
  • }
  • display();
  • line(h->x,h->y,cx,cy,WHITE);
  • }
  • v->n=NULL; // ferme la liste chainee
  • v=h; // revient au debut de la liste chainee
  • // efface le premier vertex
  • if (h->y==350) buffer[(int)h->x+510+((int)(382-h->y)<<10)]=BLACK; else buffer[(int)h->x+510+((int)(382-h->y)<<10)]=WHITE;
  • if (cx==350) buffer[(int)h->x+511+((int)(383-h->y)<<10)]=BLACK; else buffer[(int)h->x+511+((int)(383-h->y)<<10)]=WHITE;
  • if (h->y==-349) buffer[(int)h->x+510+((int)(384-h->y)<<10)]=BLACK; else buffer[(int)h->x+510+((int)(384-h->y)<<10)]=WHITE;
  • if (cx==-349) buffer[(int)h->x+509+((int)(383-h->y)<<10)]=BLACK; else buffer[(int)h->x+509+((int)(383-h->y)<<10)]=WHITE;
  • buffer[(int)h->x+510+((int)(383-h->y)<<10)]=WHITE;
  • }
  • p=v->n; // sauve l'adresse de l'element suivant
  • v->n=(VERTEX*)malloc(sizeof(VERTEX)); // nouvel element suivant
  • v->n->n=p; // positionne le nouvel element juste avant l'ancien element
  • p=v; // sauve l'adresse de l'element actuel
  • v=v->n;
  • do
  • {
  • while (!kbhit()) // tant qu'aucune touche n'est pressee
  • {
  • // efface l'ancien curseur
  • if (cy==350) buffer[cx+510+((382-cy)<<10)]=BLACK; else buffer[cx+510+((382-cy)<<10)]=WHITE;
  • if (cx==350) buffer[cx+511+((383-cy)<<10)]=BLACK; else buffer[cx+511+((383-cy)<<10)]=WHITE;
  • if (cy==-349) buffer[cx+510+((384-cy)<<10)]=BLACK; else buffer[cx+510+((384-cy)<<10)]=WHITE;
  • if (cx==-349) buffer[cx+509+((383-cy)<<10)]=BLACK; else buffer[cx+509+((383-cy)<<10)]=WHITE;
  • buffer[cx+510+((383-cy)<<10)]=WHITE;
  • if (mouse(&cx,&cy,lx,ly))
  • {
  • i++; // augmente le nombre de segments
  • erase();
  • v->x=(double)cx;
  • v->y=(double)cy;
  • p=v->n;
  • v->n=(VERTEX*)malloc(sizeof(VERTEX));
  • v->n->n=p;
  • p=v;
  • v=v->n;
  • // le nouveau vertex est maintenant enregistre
  • // et on passe au vertex suivant
  • }
  • else erase(); // efface l'ancien fractal
  • v->x=(double)cx; // nouvelle position X du point
  • v->y=(double)cy; // nouvelle position Y du point
  • draw(h,RED); // dessine le nouveau fractal
  • // affiche la position du curseur
  • sprintf(pos,"%4d",cx);
  • text(pos,WHITE,5,10);
  • sprintf(pos,"%4d",cy);
  • text(pos,WHITE,5,11);
  • // affiche l'amplitude
  • if ((cx-p->x==0.0)&&(cy-p->y>=0.0)) deg=90.0;
  • else if ((cx-p->x==0.0)&&(cy-p->y<=0.0)) deg=270.0;
  • else if ((cx-p->x>=0.0)&&(cy-p->y>=0.0)) deg=180.0/PI*atan((cy-p->y)/(cx-p->x));
  • else if ((cx-p->x<=0.0)&&(cy-p->y>=0.0)) deg=180.0-180.0/PI*atan(-(cy-p->y)/(cx-p->x));
  • else if ((cx-p->x<=0.0)&&(cy-p->y<=0.0)) deg=180.0+180.0/PI*atan((cy-p->y)/(cx-p->x));
  • else deg=360.0-180.0/PI*atan(-(cy-p->y)/(cx-p->x));
  • sprintf(pos,"%3.0f",deg);
  • text(pos,WHITE,9,12);
  • // dessine le nouveau curseur
  • buffer[cx+510+((382-cy)<<10)]=BLACK;
  • buffer[cx+511+((383-cy)<<10)]=BLACK;
  • buffer[cx+510+((384-cy)<<10)]=BLACK;
  • buffer[cx+509+((383-cy)<<10)]=BLACK;
  • buffer[cx+510+((383-cy)<<10)]=BLACK;
  • display(); // affichage
  • }
  • // gestion du clavier
  • key=getch();
  • if (key==ESCAPE)
  • {
  • v->n=NULL;
  • return -1;
  • }
  • } while (key!=ENTER); // recommence si ENTER n'a pas ete presse
  • erase(); // efface le fractal
  • text(" ",WHITE,1,10);
  • text(" ",WHITE,1,11);
  • text(" ",WHITE,1,12);
  • display();
  • v=h;
  • while (v->n->n) // cherche l'avant-dernier vertex
  • {
  • p=v; // sauve l'adresse de l'element actuel
  • v=v->n; // et passe a l'element suivant
  • }
  • p->n=v->n; // efface l'element actuel
  • free(v); // libere la memoire
  • return i; // renvoie le nombre de segments
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void display()
  • {
  • int bank;
  • while (!(inportw(0x03DA)&8)); // synchronisation avec l'ecran
  • while (inportw(0x03DA)&8);
  • for (bank=0 ; bank<12 ; bank++) // 12 banques
  • {
  • regs.x.ax=0x4F05; // fonction 4F05h
  • regs.x.bx=0; // fenetre A
  • regs.x.dx=bank; // numero de la banque
  • __dpmi_int(0x10,&regs); // INT 10h
  • dosmemput(buffer+(bank<<16),65536L,0xA0000); // affichage
  • }
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void draw(VERTEX* v,char color)
  • {
  • while (v->n)
  • {
  • line(v->x,v->y,v->n->x,v->n->y,color);
  • v=v->n;
  • }
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void erase()
  • {
  • unsigned long i;
  • i=161+33*1024; // position 161:33
  • while (i<=860+732*1024) // tant qu'on est pas a la position 860:732
  • {
  • buffer[i]=WHITE; // pixel blanc
  • i++; // augmente i
  • if ((i%1024)>860) i+=163+161; // si X > 860
  • } // on vient d'effacer le carre blanc de 700x700 pixels
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void free_fractal()
  • {
  • f=fh; // revient au debut de la liste
  • while (f->n) // on efface chaque element jusqu'a ce
  • { // qu'on soit arrive au dernier element
  • fh=f; // on retient l'adresse de l'element actuel
  • f=f->n; // on va a l'element suivant
  • free(fh); // et on efface l'element de l'adresse retenue
  • } // on recommence tant qu'il reste des elements
  • free(f); // et on efface le tout dernier element
  • m=mh; // on fait exactement la meme chose pour l'autre liste chainee
  • while (m->n)
  • {
  • mh=m;
  • m=m->n;
  • free(mh);
  • }
  • free(m);
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void generation()
  • {
  • double deg;
  • double fl;
  • double fx;
  • double fy;
  • double fdeg;
  • double ml;
  • double mx;
  • double my;
  • double mdeg;
  • VERTEX* p;
  • f=fh;
  • draw(f,BLACK);
  • display();
  • while (f->n)
  • {
  • // calcule l'amplitude et la longueur du segment
  • fx=f->n->x-f->x;
  • fy=f->n->y-f->y;
  • fl=sqrt(fx*fx+fy*fy);
  • if ((fx==0.0)&&(fy>=0.0)) fdeg=90.0;
  • else if ((fx==0.0)&&(fy<=0.0)) fdeg=270.0;
  • else if ((fx>=0.0)&&(fy>=0.0)) fdeg=180.0/PI*atan(fy/fx);
  • else if ((fx<=0.0)&&(fy>=0.0)) fdeg=180.0-180.0/PI*atan(-fy/fx);
  • else if ((fx<=0.0)&&(fy<=0.0)) fdeg=180.0+180.0/PI*atan(fy/fx);
  • else fdeg=360.0-180.0/PI*atan(-fy/fx);
  • m=mh;
  • while (m->n->n)
  • {
  • // efface l'ancien segment
  • line(f->x,f->y,f->n->x,f->n->y,WHITE);
  • // calcule l'amplitude et la longueur du segment
  • mx=m->n->x-m->x;
  • my=m->n->y-m->y;
  • ml=sqrt(mx*mx+my*my);
  • if ((mx==0.0)&&(my>=0.0)) mdeg=90.0;
  • else if ((mx==0.0)&&(my<=0.0)) mdeg=270.0;
  • else if ((mx>=0.0)&&(my>=0.0)) mdeg=180.0/PI*atan(my/mx);
  • else if ((mx<=0.0)&&(my>=0.0)) mdeg=180.0-180.0/PI*atan(-my/mx);
  • else if ((mx<=0.0)&&(my<=0.0)) mdeg=180.0+180.0/PI*atan(my/mx);
  • else mdeg=360.0-180.0/PI*atan(-my/mx);
  • // insere un nouveau vertex
  • p=f->n;
  • f->n=(VERTEX*)malloc(sizeof(VERTEX));
  • f->n->n=p;
  • p=f;
  • f=f->n;
  • // positionne le nouveau vertex
  • deg=fdeg+mdeg;
  • if (deg>=360.0) deg-=360.0;
  • ml=fl*ml/700.0;
  • f->x=p->x+COS[(int)deg]*ml;
  • f->y=p->y+SIN[(int)deg]*ml;
  • // affiche le nouveau segment en rouge
  • line(p->x,p->y,f->x,f->y,RED);
  • display();
  • m=m->n;
  • }
  • line(f->x,f->y,f->n->x,f->n->y,RED);
  • f=f->n;
  • }
  • m=mh;
  • f=fh;
  • erase();
  • draw(f,BLACK);
  • display();
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void initVESA()
  • {
  • unsigned long i;
  • regs.x.ax=0x4F02; // fonction 4F02h
  • regs.x.bx=0x105; // mode 105h - 1024x768 256 couleurs
  • __dpmi_int(0x10,&regs); // INT 10h
  • buffer=(char*)malloc(1024*768); // alloue de la memoire pour le buffer
  • outportb(0x03C8,BLACK); // noir
  • outportb(0x03C9,0);
  • outportb(0x03C9,0);
  • outportb(0x03C9,0);
  • outportb(0x03C8,RED); // rouge
  • outportb(0x03C9,63);
  • outportb(0x03C9,0);
  • outportb(0x03C9,0);
  • outportb(0x03C8,WHITE); // blanc
  • outportb(0x03C9,63);
  • outportb(0x03C9,63);
  • outportb(0x03C9,63);
  • for (i=0 ; i<1024*768 ; i++) buffer[i]=BLACK; // ecran noir
  • erase(); // dessine un carre blanc de 700x700 pixels
  • f=(VERTEX*)malloc(sizeof(VERTEX)); // creation du premier element
  • fh=f; // sauve l'adresse du debut
  • f->n=NULL; // on ferme la liste chainee
  • m=(VERTEX*)malloc(sizeof(VERTEX)); // creation des deux premiers vertex
  • mh=m; // sauve l'adresse du debut
  • m->x=-349.0; // premier vertex au centre
  • m->y=0.0; // et tout a gauche
  • m->n=(VERTEX*)malloc(sizeof(VERTEX)); // vertex suivant
  • m=m->n;
  • m->x=350.0; // second vertex au centre
  • m->y=0.0; // et tout a droite
  • m->n=NULL; // on ferme la liste chainee
  • m=mh; // on revient au debut de la liste chainee
  • // initialisation de la souris
  • regs.x.ax=0x00; // MOV AX,00h
  • __dpmi_int(0x33,&regs); // INT 33h
  • regs.x.ax=0x02; // MOV AX,02h
  • __dpmi_int(0x33,&regs); // INT 33h
  • // precalcul des nombres trigonometriques
  • for (i=0 ; i<360 ; i++)
  • {
  • SIN[i]=sin(i*PI/180.0);
  • COS[i]=cos(i*PI/180.0);
  • }
  • // initialisation texte
  • dosmemget(0x000FFA6E,2048L,ascii);
  • text("GENERATEUR DE FRACTAL - par Boes Olivier\r\n",RED,41,1);
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void line(int fx,int fy,int lx,int ly,char color)
  • {
  • int x1;
  • int y1;
  • int x2;
  • int y2;
  • int dx;
  • int dy;
  • int sub;
  • int remain;
  • int error;
  • int inc1;
  • int inc2;
  • fx+=510;
  • fy=383-fy;
  • lx+=510;
  • ly=383-ly;
  • if (fx>lx)
  • {
  • x1=lx;
  • x2=fx;
  • y1=ly;
  • y2=fy;
  • }
  • else
  • {
  • x1=fx;
  • x2=lx;
  • y1=fy;
  • y2=ly;
  • }
  • dx=x2-x1;
  • dy=y2-y1;
  • if ((!dx)&&(!dy)) return;
  • if (dy<0)
  • {
  • dy=-dy;
  • inc1=-1;
  • inc2=1;
  • }
  • else
  • {
  • inc1=1;
  • inc2=1;
  • }
  • if (dx>dy)
  • {
  • sub=dx-dy;
  • error=dy-(dx>>1);
  • remain=(dx+1)>>1;
  • do
  • {
  • if ((x1>160)&&(x1<861)&&(y1>32)&&(y1<733)) buffer[x1+(y1<<10)]=color;
  • if ((x2>160)&&(x2<861)&&(y2>32)&&(y2<733)) buffer[x2+(y2<<10)]=color;
  • x1+=inc2;
  • x2-=inc2;
  • if (error>=0)
  • {
  • y1+=inc1;
  • y2-=inc1;
  • error-=sub;
  • }
  • else error+=dy;
  • } while (--remain>0);
  • if ((!(dx&1))&&((x1>160)&&(x1<861)&&(y1>32)&&(y1<733))) buffer[x1+(y1<<10)]=color;
  • }
  • else
  • {
  • sub=dy-dx;
  • error=dx-(dy>>1);
  • remain=(dy+1)>>1;
  • do
  • {
  • if ((x1>160)&&(x1<861)&&(y1>32)&&(y1<733)) buffer[x1+(y1<<10)]=color;
  • if ((x2>160)&&(x2<861)&&(y2>32)&&(y2<733)) buffer[x2+(y2<<10)]=color;
  • y1+=inc1;
  • y2-=inc1;
  • if (error>=0)
  • {
  • x1+=inc2;
  • x2-=inc2;
  • error-=sub;
  • }
  • else error+=dx;
  • } while (--remain>0);
  • if ((!(dy&1))&&((x1>160)&&(x1<861)&&(y1>32)&&(y1<733))) buffer[x1+(y1<<10)]=color;
  • }
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void pcx()
  • {
  • char header[128];
  • char c;
  • char n;
  • char name[11];
  • char* img;
  • FILE* file;
  • unsigned char pal[768];
  • unsigned int width=(700+(700&1));
  • unsigned long max=700*700;
  • unsigned long i;
  • unsigned long i2;
  • /* --- CREATION DU PCX --- */
  • strcpy(name,"ecran0.pcx");
  • while ((__file_exists(name))&&(name[5]<='9')) name[5]++;
  • if (name[5]>'9') return;
  • file=fopen(name,"wb");
  • img=(char*)malloc(700*700*sizeof(char));
  • i=161+33*1024; // position 161:33
  • i2=0;
  • while (i<=860+732*1024) // tant qu'on est pas a la position 860:732
  • {
  • img[i2++]=buffer[i];
  • i++; // augmente i
  • if ((i%1024)>860) i+=163+161; // si X > 860
  • }
  • /* --- EN-TETE --- */
  • header[0]=10; /* octet PCX */
  • header[1]=5; /* version de PCX */
  • header[2]=1; /* RLE active */
  • header[3]=8; /* 8 bits pour un pixel */
  • header[4]=0; /* Xmin */
  • header[5]=0; /* Xmin */
  • header[6]=0; /* Ymin */
  • header[7]=0; /* Ymin */
  • header[8]=(700-1)&0x00FF; /* Xmax */
  • header[9]=((700-1)&0xFF00)>>8; /* Xmax */
  • header[10]=(700-1)&0x00FF; /* Ymax */
  • header[11]=((700-1)&0xFF00)>>8; /* Ymax */
  • header[12]=72; /* resolution horizontale */
  • header[13]=0; /* resolution horizontale */
  • header[14]=72; /* resolution verticale */
  • header[15]=0; /* resolution verticale */
  • for (i=0 ; i<16 ; i++) /* palette 16 couleurs */
  • {
  • header[i*3+16]=15-i;
  • header[i*3+17]=15-i;
  • header[i*3+18]=15-i;
  • }
  • header[64]=0; /* toujours 0 */
  • header[65]=1; /* toujours 1 */
  • header[66]=width&0x00FF; /* largeur, doit etre un nombre pair */
  • header[67]=(width&0xFF00)>>8; /* largeur, doit etre un nombre pair */
  • header[68]=1; /* 1 = couleurs, 2 = noir et blanc */
  • for (i=69 ; i<128 ; i++) header[i]=0; /* tout le reste c'est 0 */
  • fwrite(header,sizeof(char),128,file); /* on ecrit l'en-tete */
  • /* --- IMAGE --- */
  • i=0;
  • do
  • {
  • c=img[i];
  • i++;
  • n=1;
  • if (i!=max) while (img[i]==c)
  • {
  • if ((n<63)&&(i%700)) n++;
  • else break;
  • i++;
  • if (i==max) break;
  • }
  • if ((n==1)&&((c&0xC0)!=0xC0)) fwrite(&c,sizeof(char),1,file);
  • else
  • {
  • if ((i%700==0)&&(700!=width)&&(c==(char)(255)))
  • {
  • n++;
  • width=0;
  • }
  • n|=0xC0;
  • fwrite(&n,sizeof(char),1,file);
  • fwrite(&c,sizeof(char),1,file);
  • }
  • if (!width) width=700+1;
  • else if ((i%700==0)&&(700!=width)) fwrite("\xC1\xFF",sizeof(char),2,file);
  • } while (i!=max);
  • /* --- PALETTE --- */
  • c=12;
  • fwrite(&c,sizeof(char),1,file);
  • pal[0]=0; pal[1]=0; pal[2]=0;
  • pal[3]=255; pal[4]=0; pal[5]=0;
  • pal[6]=255; pal[7]=255; pal[8]=255;
  • for (i=9 ; i<768 ; i++) pal[i]=0;
  • fwrite(pal,sizeof(char),768,file);
  • fclose(file);
  • free(img);
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void stopVESA()
  • {
  • regs.h.ah=0x00; // fonction 00h
  • regs.h.al=0x03; // mode 03h - mode texte normal
  • __dpmi_int(0x10,&regs); // INT 10h
  • free(buffer); // on libere la memoire du buffer
  • free_fractal(); // on libere la memoire des listes chainees
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void text(char* t,int c,int x,int y)
  • {
  • unsigned int i;
  • unsigned int i2;
  • unsigned int pos1;
  • unsigned int pos2;
  • pos1=(x<<3)+(y<<13); // convertit les positions
  • for (i=0 ; t[i] ; i++) // tant que le texte n'est pas fini
  • {
  • if (t[i]=='\n') // passe une ligne
  • {
  • pos1+=1024*8;
  • continue;
  • }
  • if (t[i]=='\r') // retour a gauche
  • {
  • pos1=(pos1&0xFFC00)+(x<<3);
  • continue;
  • }
  • pos2=t[i]<<3; // va au caractere demande
  • for (i2=0 ; i2<8 ; i2++) // 8 lignes par caracteres
  • {
  • if (ascii[pos2]&0x80) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x40) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x20) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x10) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x08) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x04) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x02) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x01) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • pos1+=1024-8;
  • pos2++;
  • }
  • pos1-=1024*8-8;
  • }
  • }
  • #include <assert.h>
  • #include <conio.h>
  • #include <dpmi.h>
  • #include <go32.h>
  • #include <math.h>
  • #include <pc.h>
  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <string.h>
  • #include <sys/farptr.h>
  • #include <sys/movedata.h>
  • #include <unistd.h>
  • #define BLACK 0
  • #define RED 1
  • #define WHITE 2
  • #define ENTER 13
  • #define ESCAPE 27
  • #define SPACE 32
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • typedef struct VERTEX
  • {
  • double x;
  • double y;
  • struct VERTEX* n;
  • } VERTEX;
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • char ascii[2048];
  • char* buffer;
  • double SIN[360];
  • double COS[360];
  • __dpmi_regs regs;
  • VERTEX* f;
  • VERTEX* fh;
  • VERTEX* m;
  • VERTEX* mh;
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • int mouse(int* cx,int* cy,int lx,int ly);
  • int build(VERTEX* v);
  • void display();
  • void draw(VERTEX* v,char color);
  • void erase();
  • void free_fractal();
  • void generation();
  • void initVESA();
  • void line(int fx,int fy,int lx,int ly,char color);
  • void pcx();
  • void stopVESA();
  • void text(char* t,int c,int x,int y);
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • int main()
  • {
  • char key;
  • char segs[30];
  • int i;
  • int fi;
  • int mi;
  • initVESA();
  • mi=build(m);
  • if (mi==-1) { stopVESA(); return 0; }
  • fi=build(f);
  • if (fi==-1) { stopVESA(); return 0; }
  • draw(f,BLACK);
  • i=0;
  • while (1)
  • {
  • sprintf(segs,"%d segments ",(int)(fi*pow(mi,i++)));
  • text(segs,WHITE,1,10);
  • display();
  • do key=getch(); while ((key!=ENTER)&&(key!='P')&&(key!=ESCAPE));
  • if (key==ESCAPE) break;
  • else if (key=='P') pcx();
  • erase();
  • generation();
  • };
  • stopVESA();
  • return 0;
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • int mouse(int* cx,int* cy,int lx,int ly)
  • {
  • int button=0;
  • do
  • {
  • regs.x.ax=0x03; // MOV AX,00h
  • __dpmi_int(0x33,&regs); // INT 33h
  • button=(button&2)|(regs.x.bx&1);
  • if (button==1)
  • {
  • (*cx)+=regs.x.cx-lx; // augmente cx du nombre de pixel dont la souris a bouge
  • (*cy)-=regs.x.dx-ly; // diminue cy du nombre de pixel dont la souris a bouge
  • button|=2;
  • }
  • } while (button&1); // continue tant qu'un bouton est presse
  • if (!button)
  • {
  • (*cx)+=regs.x.cx-lx; // augmente cx du nombre de pixel dont la souris a bouge
  • (*cy)-=regs.x.dx-ly; // diminue cy du nombre de pixel dont la souris a bouge
  • }
  • if ((*cx)>350) (*cx)=350; // pour eviter les debordements
  • else if ((*cx)<-349) (*cx)=-349;
  • if ((*cy)>350) (*cy)=350; // pour eviter les debordements
  • else if ((*cy)<-349) (*cy)=-349;
  • regs.x.ax=0x04; // MOV AX,00h
  • regs.x.cx=lx; // MOV CX,[lx]
  • regs.x.dx=ly; // MOV DX,[ly]
  • __dpmi_int(0x33,&regs); // INT 33h
  • return button;
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • int build(VERTEX* v)
  • {
  • int cx=0;
  • int cy=0;
  • int lx;
  • int ly;
  • int i=1;
  • char key;
  • char pos[5];
  • double deg;
  • VERTEX* p;
  • VERTEX* h;
  • text("X : ",WHITE,1,10);
  • text("Y : ",WHITE,1,11);
  • text("angle : ",WHITE,1,12);
  • regs.x.ax=0x03; // MOV AX,00h
  • __dpmi_int(0x33,&regs); // INT 33h
  • lx=regs.x.cx; // position X actuelle de la souris
  • ly=regs.x.dx; // position Y actuelle de la souris
  • h=v; // sauve l'adresse du debut de la liste
  • if (v->n==NULL) // si l'utilisateur doit choisir le premier et le dernier vertex
  • {
  • while (1) // boucle infinie
  • {
  • // efface l'ancien curseur
  • if (cy==350) buffer[cx+510+((382-cy)<<10)]=BLACK; else buffer[cx+510+((382-cy)<<10)]=WHITE;
  • if (cx==350) buffer[cx+511+((383-cy)<<10)]=BLACK; else buffer[cx+511+((383-cy)<<10)]=WHITE;
  • if (cy==-349) buffer[cx+510+((384-cy)<<10)]=BLACK; else buffer[cx+510+((384-cy)<<10)]=WHITE;
  • if (cx==-349) buffer[cx+509+((383-cy)<<10)]=BLACK; else buffer[cx+509+((383-cy)<<10)]=WHITE;
  • buffer[cx+510+((383-cy)<<10)]=WHITE;
  • if (mouse(&cx,&cy,lx,ly))
  • {
  • v->x=(double)cx;
  • v->y=(double)cy;
  • if (v->n==NULL) // si l'utilisateur a choisi le premier vertex
  • {
  • v->n=(VERTEX*)malloc(sizeof(VERTEX));
  • v=v->n;
  • v->n=(VERTEX*)1; // flag
  • }
  • else break; // quitte la boucle infinie si le dernier vertex a ete choisi
  • }
  • // gestion du clavier
  • if (kbhit())
  • {
  • key=getch();
  • if (key==ESCAPE)
  • {
  • v->n=NULL;
  • return -1;
  • }
  • }
  • // affiche la position du curseur
  • sprintf(pos,"%4d",cx);
  • text(pos,WHITE,5,10);
  • sprintf(pos,"%4d",cy);
  • text(pos,WHITE,5,11);
  • // dessine le nouveau curseur
  • buffer[cx+510+((382-cy)<<10)]=RED;
  • buffer[cx+511+((383-cy)<<10)]=RED;
  • buffer[cx+510+((384-cy)<<10)]=RED;
  • buffer[cx+509+((383-cy)<<10)]=RED;
  • buffer[cx+510+((383-cy)<<10)]=RED;
  • // si le premier vertex est deja choisi
  • if (v->n)
  • {
  • line(h->x,h->y,cx,cy,BLACK);
  • buffer[(int)h->x+510+((int)(382-h->y)<<10)]=BLACK;
  • buffer[(int)h->x+511+((int)(383-h->y)<<10)]=BLACK;
  • buffer[(int)h->x+510+((int)(384-h->y)<<10)]=BLACK;
  • buffer[(int)h->x+509+((int)(383-h->y)<<10)]=BLACK;
  • buffer[(int)h->x+510+((int)(383-h->y)<<10)]=BLACK;
  • // affiche l'amplitude
  • if ((cx-h->x==0.0)&&(cy-h->y>=0.0)) deg=90.0;
  • else if ((cx-h->x==0.0)&&(cy-h->y<=0.0)) deg=270.0;
  • else if ((cx-h->x>=0.0)&&(cy-h->y>=0.0)) deg=180.0/PI*atan((cy-h->y)/(cx-h->x));
  • else if ((cx-h->x<=0.0)&&(cy-h->y>=0.0)) deg=180.0-180.0/PI*atan(-(cy-h->y)/(cx-h->x));
  • else if ((cx-h->x<=0.0)&&(cy-h->y<=0.0)) deg=180.0+180.0/PI*atan((cy-h->y)/(cx-h->x));
  • else deg=360.0-180.0/PI*atan(-(cy-h->y)/(cx-h->x));
  • sprintf(pos,"%3.0f",deg);
  • text(pos,WHITE,9,12);
  • }
  • display();
  • line(h->x,h->y,cx,cy,WHITE);
  • }
  • v->n=NULL; // ferme la liste chainee
  • v=h; // revient au debut de la liste chainee
  • // efface le premier vertex
  • if (h->y==350) buffer[(int)h->x+510+((int)(382-h->y)<<10)]=BLACK; else buffer[(int)h->x+510+((int)(382-h->y)<<10)]=WHITE;
  • if (cx==350) buffer[(int)h->x+511+((int)(383-h->y)<<10)]=BLACK; else buffer[(int)h->x+511+((int)(383-h->y)<<10)]=WHITE;
  • if (h->y==-349) buffer[(int)h->x+510+((int)(384-h->y)<<10)]=BLACK; else buffer[(int)h->x+510+((int)(384-h->y)<<10)]=WHITE;
  • if (cx==-349) buffer[(int)h->x+509+((int)(383-h->y)<<10)]=BLACK; else buffer[(int)h->x+509+((int)(383-h->y)<<10)]=WHITE;
  • buffer[(int)h->x+510+((int)(383-h->y)<<10)]=WHITE;
  • }
  • p=v->n; // sauve l'adresse de l'element suivant
  • v->n=(VERTEX*)malloc(sizeof(VERTEX)); // nouvel element suivant
  • v->n->n=p; // positionne le nouvel element juste avant l'ancien element
  • p=v; // sauve l'adresse de l'element actuel
  • v=v->n;
  • do
  • {
  • while (!kbhit()) // tant qu'aucune touche n'est pressee
  • {
  • // efface l'ancien curseur
  • if (cy==350) buffer[cx+510+((382-cy)<<10)]=BLACK; else buffer[cx+510+((382-cy)<<10)]=WHITE;
  • if (cx==350) buffer[cx+511+((383-cy)<<10)]=BLACK; else buffer[cx+511+((383-cy)<<10)]=WHITE;
  • if (cy==-349) buffer[cx+510+((384-cy)<<10)]=BLACK; else buffer[cx+510+((384-cy)<<10)]=WHITE;
  • if (cx==-349) buffer[cx+509+((383-cy)<<10)]=BLACK; else buffer[cx+509+((383-cy)<<10)]=WHITE;
  • buffer[cx+510+((383-cy)<<10)]=WHITE;
  • if (mouse(&cx,&cy,lx,ly))
  • {
  • i++; // augmente le nombre de segments
  • erase();
  • v->x=(double)cx;
  • v->y=(double)cy;
  • p=v->n;
  • v->n=(VERTEX*)malloc(sizeof(VERTEX));
  • v->n->n=p;
  • p=v;
  • v=v->n;
  • // le nouveau vertex est maintenant enregistre
  • // et on passe au vertex suivant
  • }
  • else erase(); // efface l'ancien fractal
  • v->x=(double)cx; // nouvelle position X du point
  • v->y=(double)cy; // nouvelle position Y du point
  • draw(h,RED); // dessine le nouveau fractal
  • // affiche la position du curseur
  • sprintf(pos,"%4d",cx);
  • text(pos,WHITE,5,10);
  • sprintf(pos,"%4d",cy);
  • text(pos,WHITE,5,11);
  • // affiche l'amplitude
  • if ((cx-p->x==0.0)&&(cy-p->y>=0.0)) deg=90.0;
  • else if ((cx-p->x==0.0)&&(cy-p->y<=0.0)) deg=270.0;
  • else if ((cx-p->x>=0.0)&&(cy-p->y>=0.0)) deg=180.0/PI*atan((cy-p->y)/(cx-p->x));
  • else if ((cx-p->x<=0.0)&&(cy-p->y>=0.0)) deg=180.0-180.0/PI*atan(-(cy-p->y)/(cx-p->x));
  • else if ((cx-p->x<=0.0)&&(cy-p->y<=0.0)) deg=180.0+180.0/PI*atan((cy-p->y)/(cx-p->x));
  • else deg=360.0-180.0/PI*atan(-(cy-p->y)/(cx-p->x));
  • sprintf(pos,"%3.0f",deg);
  • text(pos,WHITE,9,12);
  • // dessine le nouveau curseur
  • buffer[cx+510+((382-cy)<<10)]=BLACK;
  • buffer[cx+511+((383-cy)<<10)]=BLACK;
  • buffer[cx+510+((384-cy)<<10)]=BLACK;
  • buffer[cx+509+((383-cy)<<10)]=BLACK;
  • buffer[cx+510+((383-cy)<<10)]=BLACK;
  • display(); // affichage
  • }
  • // gestion du clavier
  • key=getch();
  • if (key==ESCAPE)
  • {
  • v->n=NULL;
  • return -1;
  • }
  • } while (key!=ENTER); // recommence si ENTER n'a pas ete presse
  • erase(); // efface le fractal
  • text(" ",WHITE,1,10);
  • text(" ",WHITE,1,11);
  • text(" ",WHITE,1,12);
  • display();
  • v=h;
  • while (v->n->n) // cherche l'avant-dernier vertex
  • {
  • p=v; // sauve l'adresse de l'element actuel
  • v=v->n; // et passe a l'element suivant
  • }
  • p->n=v->n; // efface l'element actuel
  • free(v); // libere la memoire
  • return i; // renvoie le nombre de segments
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void display()
  • {
  • int bank;
  • while (!(inportw(0x03DA)&8)); // synchronisation avec l'ecran
  • while (inportw(0x03DA)&8);
  • for (bank=0 ; bank<12 ; bank++) // 12 banques
  • {
  • regs.x.ax=0x4F05; // fonction 4F05h
  • regs.x.bx=0; // fenetre A
  • regs.x.dx=bank; // numero de la banque
  • __dpmi_int(0x10,&regs); // INT 10h
  • dosmemput(buffer+(bank<<16),65536L,0xA0000); // affichage
  • }
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void draw(VERTEX* v,char color)
  • {
  • while (v->n)
  • {
  • line(v->x,v->y,v->n->x,v->n->y,color);
  • v=v->n;
  • }
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void erase()
  • {
  • unsigned long i;
  • i=161+33*1024; // position 161:33
  • while (i<=860+732*1024) // tant qu'on est pas a la position 860:732
  • {
  • buffer[i]=WHITE; // pixel blanc
  • i++; // augmente i
  • if ((i%1024)>860) i+=163+161; // si X > 860
  • } // on vient d'effacer le carre blanc de 700x700 pixels
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void free_fractal()
  • {
  • f=fh; // revient au debut de la liste
  • while (f->n) // on efface chaque element jusqu'a ce
  • { // qu'on soit arrive au dernier element
  • fh=f; // on retient l'adresse de l'element actuel
  • f=f->n; // on va a l'element suivant
  • free(fh); // et on efface l'element de l'adresse retenue
  • } // on recommence tant qu'il reste des elements
  • free(f); // et on efface le tout dernier element
  • m=mh; // on fait exactement la meme chose pour l'autre liste chainee
  • while (m->n)
  • {
  • mh=m;
  • m=m->n;
  • free(mh);
  • }
  • free(m);
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void generation()
  • {
  • double deg;
  • double fl;
  • double fx;
  • double fy;
  • double fdeg;
  • double ml;
  • double mx;
  • double my;
  • double mdeg;
  • VERTEX* p;
  • f=fh;
  • draw(f,BLACK);
  • display();
  • while (f->n)
  • {
  • // calcule l'amplitude et la longueur du segment
  • fx=f->n->x-f->x;
  • fy=f->n->y-f->y;
  • fl=sqrt(fx*fx+fy*fy);
  • if ((fx==0.0)&&(fy>=0.0)) fdeg=90.0;
  • else if ((fx==0.0)&&(fy<=0.0)) fdeg=270.0;
  • else if ((fx>=0.0)&&(fy>=0.0)) fdeg=180.0/PI*atan(fy/fx);
  • else if ((fx<=0.0)&&(fy>=0.0)) fdeg=180.0-180.0/PI*atan(-fy/fx);
  • else if ((fx<=0.0)&&(fy<=0.0)) fdeg=180.0+180.0/PI*atan(fy/fx);
  • else fdeg=360.0-180.0/PI*atan(-fy/fx);
  • m=mh;
  • while (m->n->n)
  • {
  • // efface l'ancien segment
  • line(f->x,f->y,f->n->x,f->n->y,WHITE);
  • // calcule l'amplitude et la longueur du segment
  • mx=m->n->x-m->x;
  • my=m->n->y-m->y;
  • ml=sqrt(mx*mx+my*my);
  • if ((mx==0.0)&&(my>=0.0)) mdeg=90.0;
  • else if ((mx==0.0)&&(my<=0.0)) mdeg=270.0;
  • else if ((mx>=0.0)&&(my>=0.0)) mdeg=180.0/PI*atan(my/mx);
  • else if ((mx<=0.0)&&(my>=0.0)) mdeg=180.0-180.0/PI*atan(-my/mx);
  • else if ((mx<=0.0)&&(my<=0.0)) mdeg=180.0+180.0/PI*atan(my/mx);
  • else mdeg=360.0-180.0/PI*atan(-my/mx);
  • // insere un nouveau vertex
  • p=f->n;
  • f->n=(VERTEX*)malloc(sizeof(VERTEX));
  • f->n->n=p;
  • p=f;
  • f=f->n;
  • // positionne le nouveau vertex
  • deg=fdeg+mdeg;
  • if (deg>=360.0) deg-=360.0;
  • ml=fl*ml/700.0;
  • f->x=p->x+COS[(int)deg]*ml;
  • f->y=p->y+SIN[(int)deg]*ml;
  • // affiche le nouveau segment en rouge
  • line(p->x,p->y,f->x,f->y,RED);
  • display();
  • m=m->n;
  • }
  • line(f->x,f->y,f->n->x,f->n->y,RED);
  • f=f->n;
  • }
  • m=mh;
  • f=fh;
  • erase();
  • draw(f,BLACK);
  • display();
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void initVESA()
  • {
  • unsigned long i;
  • regs.x.ax=0x4F02; // fonction 4F02h
  • regs.x.bx=0x105; // mode 105h - 1024x768 256 couleurs
  • __dpmi_int(0x10,&regs); // INT 10h
  • buffer=(char*)malloc(1024*768); // alloue de la memoire pour le buffer
  • outportb(0x03C8,BLACK); // noir
  • outportb(0x03C9,0);
  • outportb(0x03C9,0);
  • outportb(0x03C9,0);
  • outportb(0x03C8,RED); // rouge
  • outportb(0x03C9,63);
  • outportb(0x03C9,0);
  • outportb(0x03C9,0);
  • outportb(0x03C8,WHITE); // blanc
  • outportb(0x03C9,63);
  • outportb(0x03C9,63);
  • outportb(0x03C9,63);
  • for (i=0 ; i<1024*768 ; i++) buffer[i]=BLACK; // ecran noir
  • erase(); // dessine un carre blanc de 700x700 pixels
  • f=(VERTEX*)malloc(sizeof(VERTEX)); // creation du premier element
  • fh=f; // sauve l'adresse du debut
  • f->n=NULL; // on ferme la liste chainee
  • m=(VERTEX*)malloc(sizeof(VERTEX)); // creation des deux premiers vertex
  • mh=m; // sauve l'adresse du debut
  • m->x=-349.0; // premier vertex au centre
  • m->y=0.0; // et tout a gauche
  • m->n=(VERTEX*)malloc(sizeof(VERTEX)); // vertex suivant
  • m=m->n;
  • m->x=350.0; // second vertex au centre
  • m->y=0.0; // et tout a droite
  • m->n=NULL; // on ferme la liste chainee
  • m=mh; // on revient au debut de la liste chainee
  • // initialisation de la souris
  • regs.x.ax=0x00; // MOV AX,00h
  • __dpmi_int(0x33,&regs); // INT 33h
  • regs.x.ax=0x02; // MOV AX,02h
  • __dpmi_int(0x33,&regs); // INT 33h
  • // precalcul des nombres trigonometriques
  • for (i=0 ; i<360 ; i++)
  • {
  • SIN[i]=sin(i*PI/180.0);
  • COS[i]=cos(i*PI/180.0);
  • }
  • // initialisation texte
  • dosmemget(0x000FFA6E,2048L,ascii);
  • text("GENERATEUR DE FRACTAL - par Boes Olivier\r\n",RED,41,1);
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void line(int fx,int fy,int lx,int ly,char color)
  • {
  • int x1;
  • int y1;
  • int x2;
  • int y2;
  • int dx;
  • int dy;
  • int sub;
  • int remain;
  • int error;
  • int inc1;
  • int inc2;
  • fx+=510;
  • fy=383-fy;
  • lx+=510;
  • ly=383-ly;
  • if (fx>lx)
  • {
  • x1=lx;
  • x2=fx;
  • y1=ly;
  • y2=fy;
  • }
  • else
  • {
  • x1=fx;
  • x2=lx;
  • y1=fy;
  • y2=ly;
  • }
  • dx=x2-x1;
  • dy=y2-y1;
  • if ((!dx)&&(!dy)) return;
  • if (dy<0)
  • {
  • dy=-dy;
  • inc1=-1;
  • inc2=1;
  • }
  • else
  • {
  • inc1=1;
  • inc2=1;
  • }
  • if (dx>dy)
  • {
  • sub=dx-dy;
  • error=dy-(dx>>1);
  • remain=(dx+1)>>1;
  • do
  • {
  • if ((x1>160)&&(x1<861)&&(y1>32)&&(y1<733)) buffer[x1+(y1<<10)]=color;
  • if ((x2>160)&&(x2<861)&&(y2>32)&&(y2<733)) buffer[x2+(y2<<10)]=color;
  • x1+=inc2;
  • x2-=inc2;
  • if (error>=0)
  • {
  • y1+=inc1;
  • y2-=inc1;
  • error-=sub;
  • }
  • else error+=dy;
  • } while (--remain>0);
  • if ((!(dx&1))&&((x1>160)&&(x1<861)&&(y1>32)&&(y1<733))) buffer[x1+(y1<<10)]=color;
  • }
  • else
  • {
  • sub=dy-dx;
  • error=dx-(dy>>1);
  • remain=(dy+1)>>1;
  • do
  • {
  • if ((x1>160)&&(x1<861)&&(y1>32)&&(y1<733)) buffer[x1+(y1<<10)]=color;
  • if ((x2>160)&&(x2<861)&&(y2>32)&&(y2<733)) buffer[x2+(y2<<10)]=color;
  • y1+=inc1;
  • y2-=inc1;
  • if (error>=0)
  • {
  • x1+=inc2;
  • x2-=inc2;
  • error-=sub;
  • }
  • else error+=dx;
  • } while (--remain>0);
  • if ((!(dy&1))&&((x1>160)&&(x1<861)&&(y1>32)&&(y1<733))) buffer[x1+(y1<<10)]=color;
  • }
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void pcx()
  • {
  • char header[128];
  • char c;
  • char n;
  • char name[11];
  • char* img;
  • FILE* file;
  • unsigned char pal[768];
  • unsigned int width=(700+(700&1));
  • unsigned long max=700*700;
  • unsigned long i;
  • unsigned long i2;
  • /* --- CREATION DU PCX --- */
  • strcpy(name,"ecran0.pcx");
  • while ((__file_exists(name))&&(name[5]<='9')) name[5]++;
  • if (name[5]>'9') return;
  • file=fopen(name,"wb");
  • img=(char*)malloc(700*700*sizeof(char));
  • i=161+33*1024; // position 161:33
  • i2=0;
  • while (i<=860+732*1024) // tant qu'on est pas a la position 860:732
  • {
  • img[i2++]=buffer[i];
  • i++; // augmente i
  • if ((i%1024)>860) i+=163+161; // si X > 860
  • }
  • /* --- EN-TETE --- */
  • header[0]=10; /* octet PCX */
  • header[1]=5; /* version de PCX */
  • header[2]=1; /* RLE active */
  • header[3]=8; /* 8 bits pour un pixel */
  • header[4]=0; /* Xmin */
  • header[5]=0; /* Xmin */
  • header[6]=0; /* Ymin */
  • header[7]=0; /* Ymin */
  • header[8]=(700-1)&0x00FF; /* Xmax */
  • header[9]=((700-1)&0xFF00)>>8; /* Xmax */
  • header[10]=(700-1)&0x00FF; /* Ymax */
  • header[11]=((700-1)&0xFF00)>>8; /* Ymax */
  • header[12]=72; /* resolution horizontale */
  • header[13]=0; /* resolution horizontale */
  • header[14]=72; /* resolution verticale */
  • header[15]=0; /* resolution verticale */
  • for (i=0 ; i<16 ; i++) /* palette 16 couleurs */
  • {
  • header[i*3+16]=15-i;
  • header[i*3+17]=15-i;
  • header[i*3+18]=15-i;
  • }
  • header[64]=0; /* toujours 0 */
  • header[65]=1; /* toujours 1 */
  • header[66]=width&0x00FF; /* largeur, doit etre un nombre pair */
  • header[67]=(width&0xFF00)>>8; /* largeur, doit etre un nombre pair */
  • header[68]=1; /* 1 = couleurs, 2 = noir et blanc */
  • for (i=69 ; i<128 ; i++) header[i]=0; /* tout le reste c'est 0 */
  • fwrite(header,sizeof(char),128,file); /* on ecrit l'en-tete */
  • /* --- IMAGE --- */
  • i=0;
  • do
  • {
  • c=img[i];
  • i++;
  • n=1;
  • if (i!=max) while (img[i]==c)
  • {
  • if ((n<63)&&(i%700)) n++;
  • else break;
  • i++;
  • if (i==max) break;
  • }
  • if ((n==1)&&((c&0xC0)!=0xC0)) fwrite(&c,sizeof(char),1,file);
  • else
  • {
  • if ((i%700==0)&&(700!=width)&&(c==(char)(255)))
  • {
  • n++;
  • width=0;
  • }
  • n|=0xC0;
  • fwrite(&n,sizeof(char),1,file);
  • fwrite(&c,sizeof(char),1,file);
  • }
  • if (!width) width=700+1;
  • else if ((i%700==0)&&(700!=width)) fwrite("\xC1\xFF",sizeof(char),2,file);
  • } while (i!=max);
  • /* --- PALETTE --- */
  • c=12;
  • fwrite(&c,sizeof(char),1,file);
  • pal[0]=0; pal[1]=0; pal[2]=0;
  • pal[3]=255; pal[4]=0; pal[5]=0;
  • pal[6]=255; pal[7]=255; pal[8]=255;
  • for (i=9 ; i<768 ; i++) pal[i]=0;
  • fwrite(pal,sizeof(char),768,file);
  • fclose(file);
  • free(img);
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void stopVESA()
  • {
  • regs.h.ah=0x00; // fonction 00h
  • regs.h.al=0x03; // mode 03h - mode texte normal
  • __dpmi_int(0x10,&regs); // INT 10h
  • free(buffer); // on libere la memoire du buffer
  • free_fractal(); // on libere la memoire des listes chainees
  • }
  • ////////////////////////////////////////////////////////////////////////////////////////////////////
  • void text(char* t,int c,int x,int y)
  • {
  • unsigned int i;
  • unsigned int i2;
  • unsigned int pos1;
  • unsigned int pos2;
  • pos1=(x<<3)+(y<<13); // convertit les positions
  • for (i=0 ; t[i] ; i++) // tant que le texte n'est pas fini
  • {
  • if (t[i]=='\n') // passe une ligne
  • {
  • pos1+=1024*8;
  • continue;
  • }
  • if (t[i]=='\r') // retour a gauche
  • {
  • pos1=(pos1&0xFFC00)+(x<<3);
  • continue;
  • }
  • pos2=t[i]<<3; // va au caractere demande
  • for (i2=0 ; i2<8 ; i2++) // 8 lignes par caracteres
  • {
  • if (ascii[pos2]&0x80) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x40) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x20) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x10) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x08) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x04) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x02) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • if (ascii[pos2]&0x01) buffer[pos1++]=c&0x00FF;
  • else buffer[pos1++]=(c&0xFF00)>>8;
  • pos1+=1024-8;
  • pos2++;
  • }
  • pos1-=1024*8-8;
  • }
  • }
#include			<assert.h>
#include			<conio.h>
#include			<dpmi.h>
#include			<go32.h>
#include			<math.h>
#include			<pc.h>
#include			<stdio.h>
#include			<stdlib.h>
#include			<string.h>
#include			<sys/farptr.h>
#include			<sys/movedata.h>
#include			<unistd.h>

#define				BLACK		0
#define				RED		1
#define				WHITE		2
#define				ENTER		13
#define				ESCAPE		27
#define				SPACE		32

////////////////////////////////////////////////////////////////////////////////////////////////////

typedef struct VERTEX
{
	double			x;
	double			y;
	struct VERTEX*		n;
} VERTEX;

////////////////////////////////////////////////////////////////////////////////////////////////////

char				ascii[2048];
char*				buffer;
double				SIN[360];
double				COS[360];
__dpmi_regs			regs;
VERTEX*				f;
VERTEX*				fh;
VERTEX*				m;
VERTEX*				mh;

////////////////////////////////////////////////////////////////////////////////////////////////////

int				mouse(int* cx,int* cy,int lx,int ly);
int				build(VERTEX* v);
void				display();
void				draw(VERTEX* v,char color);
void				erase();
void				free_fractal();
void				generation();
void				initVESA();
void				line(int fx,int fy,int lx,int ly,char color);
void				pcx();
void				stopVESA();
void				text(char* t,int c,int x,int y);

////////////////////////////////////////////////////////////////////////////////////////////////////

int				main()
{
	char			key;
	char			segs[30];
	int			i;
	int			fi;
	int			mi;

	initVESA();

	mi=build(m);
	if (mi==-1) { stopVESA(); return 0; }
	fi=build(f);
	if (fi==-1) { stopVESA(); return 0; }
	draw(f,BLACK);
	i=0;
	while (1)
	{
		sprintf(segs,"%d segments    ",(int)(fi*pow(mi,i++)));
		text(segs,WHITE,1,10);
		display();
		do key=getch(); while ((key!=ENTER)&&(key!='P')&&(key!=ESCAPE));
		if (key==ESCAPE) break;
		else if (key=='P') pcx();
		erase();
		generation();
	};

	stopVESA();
	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int				mouse(int* cx,int* cy,int lx,int ly)
{
	int			button=0;

	do
	{
		regs.x.ax=0x03;		// MOV AX,00h
		__dpmi_int(0x33,&regs);	// INT 33h
		button=(button&2)|(regs.x.bx&1);
		if (button==1)
		{
			(*cx)+=regs.x.cx-lx;	// augmente cx du nombre de pixel dont la souris a bouge
			(*cy)-=regs.x.dx-ly;	// diminue cy du nombre de pixel dont la souris a bouge
			button|=2;
		}
	} while (button&1);	// continue tant qu'un bouton est presse

	if (!button)
	{
		(*cx)+=regs.x.cx-lx;	// augmente cx du nombre de pixel dont la souris a bouge
		(*cy)-=regs.x.dx-ly;	// diminue cy du nombre de pixel dont la souris a bouge
	}
	if ((*cx)>350) (*cx)=350;	// pour eviter les debordements
	else if ((*cx)<-349) (*cx)=-349;
	if ((*cy)>350) (*cy)=350;	// pour eviter les debordements
	else if ((*cy)<-349) (*cy)=-349;

	regs.x.ax=0x04;		// MOV AX,00h
	regs.x.cx=lx;		// MOV CX,[lx]
	regs.x.dx=ly;		// MOV DX,[ly]
	__dpmi_int(0x33,&regs);	// INT 33h

	return button;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int				build(VERTEX* v)
{
	int			cx=0;
	int			cy=0;
	int			lx;
	int			ly;
	int			i=1;
	char			key;
	char			pos[5];
	double			deg;
	VERTEX*			p;
	VERTEX*			h;

	text("X : ",WHITE,1,10);
	text("Y : ",WHITE,1,11);
	text("angle : ",WHITE,1,12);

	regs.x.ax=0x03;		// MOV AX,00h
	__dpmi_int(0x33,&regs);	// INT 33h
	lx=regs.x.cx;	// position X actuelle de la souris
	ly=regs.x.dx;	// position Y actuelle de la souris

	h=v;	// sauve l'adresse du debut de la liste
	if (v->n==NULL)	// si l'utilisateur doit choisir le premier et le dernier vertex
	{
		while (1)	// boucle infinie
		{
			// efface l'ancien curseur
			if (cy==350)	buffer[cx+510+((382-cy)<<10)]=BLACK; else buffer[cx+510+((382-cy)<<10)]=WHITE;
			if (cx==350)	buffer[cx+511+((383-cy)<<10)]=BLACK; else buffer[cx+511+((383-cy)<<10)]=WHITE;
			if (cy==-349)	buffer[cx+510+((384-cy)<<10)]=BLACK; else buffer[cx+510+((384-cy)<<10)]=WHITE;
			if (cx==-349)	buffer[cx+509+((383-cy)<<10)]=BLACK; else buffer[cx+509+((383-cy)<<10)]=WHITE;
			buffer[cx+510+((383-cy)<<10)]=WHITE;

			if (mouse(&cx,&cy,lx,ly))
			{
				v->x=(double)cx;
				v->y=(double)cy;
				if (v->n==NULL) // si l'utilisateur a choisi le premier vertex
				{
					v->n=(VERTEX*)malloc(sizeof(VERTEX));
					v=v->n;
					v->n=(VERTEX*)1;	// flag
				}
				else break;	// quitte la boucle infinie si le dernier vertex a ete choisi
			}

			// gestion du clavier
			if (kbhit())
			{
				key=getch();
				if (key==ESCAPE)
				{
					v->n=NULL;
					return -1;
				}
			}

			// affiche la position du curseur
			sprintf(pos,"%4d",cx);
			text(pos,WHITE,5,10);
			sprintf(pos,"%4d",cy);
			text(pos,WHITE,5,11);

			// dessine le nouveau curseur
			buffer[cx+510+((382-cy)<<10)]=RED;
			buffer[cx+511+((383-cy)<<10)]=RED;
			buffer[cx+510+((384-cy)<<10)]=RED;
			buffer[cx+509+((383-cy)<<10)]=RED;
			buffer[cx+510+((383-cy)<<10)]=RED;

			// si le premier vertex est deja choisi
			if (v->n)
			{
				line(h->x,h->y,cx,cy,BLACK);
				buffer[(int)h->x+510+((int)(382-h->y)<<10)]=BLACK;
				buffer[(int)h->x+511+((int)(383-h->y)<<10)]=BLACK;
				buffer[(int)h->x+510+((int)(384-h->y)<<10)]=BLACK;
				buffer[(int)h->x+509+((int)(383-h->y)<<10)]=BLACK;
				buffer[(int)h->x+510+((int)(383-h->y)<<10)]=BLACK;

				// affiche l'amplitude
				if ((cx-h->x==0.0)&&(cy-h->y>=0.0)) deg=90.0;
				else if ((cx-h->x==0.0)&&(cy-h->y<=0.0)) deg=270.0;
				else if ((cx-h->x>=0.0)&&(cy-h->y>=0.0)) deg=180.0/PI*atan((cy-h->y)/(cx-h->x));
				else if ((cx-h->x<=0.0)&&(cy-h->y>=0.0)) deg=180.0-180.0/PI*atan(-(cy-h->y)/(cx-h->x));
				else if ((cx-h->x<=0.0)&&(cy-h->y<=0.0)) deg=180.0+180.0/PI*atan((cy-h->y)/(cx-h->x));
				else deg=360.0-180.0/PI*atan(-(cy-h->y)/(cx-h->x));
				sprintf(pos,"%3.0f",deg);
				text(pos,WHITE,9,12);
			}
			display();
			line(h->x,h->y,cx,cy,WHITE);
		}
		v->n=NULL;	// ferme la liste chainee
		v=h;		// revient au debut de la liste chainee

		// efface le premier vertex
		if (h->y==350)	buffer[(int)h->x+510+((int)(382-h->y)<<10)]=BLACK; else buffer[(int)h->x+510+((int)(382-h->y)<<10)]=WHITE;
		if (cx==350)	buffer[(int)h->x+511+((int)(383-h->y)<<10)]=BLACK; else buffer[(int)h->x+511+((int)(383-h->y)<<10)]=WHITE;
		if (h->y==-349)	buffer[(int)h->x+510+((int)(384-h->y)<<10)]=BLACK; else buffer[(int)h->x+510+((int)(384-h->y)<<10)]=WHITE;
		if (cx==-349)	buffer[(int)h->x+509+((int)(383-h->y)<<10)]=BLACK; else buffer[(int)h->x+509+((int)(383-h->y)<<10)]=WHITE;
		buffer[(int)h->x+510+((int)(383-h->y)<<10)]=WHITE;
	}
	p=v->n;		// sauve l'adresse de l'element suivant
	v->n=(VERTEX*)malloc(sizeof(VERTEX));	// nouvel element suivant
	v->n->n=p;	// positionne le nouvel element juste avant l'ancien element
	p=v;		// sauve l'adresse de l'element actuel
	v=v->n;
	do
	{
		while (!kbhit())	// tant qu'aucune touche n'est pressee
		{
			// efface l'ancien curseur
			if (cy==350)	buffer[cx+510+((382-cy)<<10)]=BLACK; else buffer[cx+510+((382-cy)<<10)]=WHITE;
			if (cx==350)	buffer[cx+511+((383-cy)<<10)]=BLACK; else buffer[cx+511+((383-cy)<<10)]=WHITE;
			if (cy==-349)	buffer[cx+510+((384-cy)<<10)]=BLACK; else buffer[cx+510+((384-cy)<<10)]=WHITE;
			if (cx==-349)	buffer[cx+509+((383-cy)<<10)]=BLACK; else buffer[cx+509+((383-cy)<<10)]=WHITE;
			buffer[cx+510+((383-cy)<<10)]=WHITE;

			if (mouse(&cx,&cy,lx,ly))
			{
				i++;	// augmente le nombre de segments
				erase();
				v->x=(double)cx;
				v->y=(double)cy;
				p=v->n;
				v->n=(VERTEX*)malloc(sizeof(VERTEX));
				v->n->n=p;
				p=v;
				v=v->n;
				// le nouveau vertex est maintenant enregistre
				// et on passe au vertex suivant
			}
			else erase();		// efface l'ancien fractal

			v->x=(double)cx;	// nouvelle position X du point
			v->y=(double)cy;	// nouvelle position Y du point
			draw(h,RED);		// dessine le nouveau fractal

			// affiche la position du curseur
			sprintf(pos,"%4d",cx);
			text(pos,WHITE,5,10);
			sprintf(pos,"%4d",cy);
			text(pos,WHITE,5,11);

			// affiche l'amplitude
			if ((cx-p->x==0.0)&&(cy-p->y>=0.0)) deg=90.0;
			else if ((cx-p->x==0.0)&&(cy-p->y<=0.0)) deg=270.0;
			else if ((cx-p->x>=0.0)&&(cy-p->y>=0.0)) deg=180.0/PI*atan((cy-p->y)/(cx-p->x));
			else if ((cx-p->x<=0.0)&&(cy-p->y>=0.0)) deg=180.0-180.0/PI*atan(-(cy-p->y)/(cx-p->x));
			else if ((cx-p->x<=0.0)&&(cy-p->y<=0.0)) deg=180.0+180.0/PI*atan((cy-p->y)/(cx-p->x));
			else deg=360.0-180.0/PI*atan(-(cy-p->y)/(cx-p->x));
			sprintf(pos,"%3.0f",deg);
			text(pos,WHITE,9,12);

			// dessine le nouveau curseur
			buffer[cx+510+((382-cy)<<10)]=BLACK;
			buffer[cx+511+((383-cy)<<10)]=BLACK;
			buffer[cx+510+((384-cy)<<10)]=BLACK;
			buffer[cx+509+((383-cy)<<10)]=BLACK;
			buffer[cx+510+((383-cy)<<10)]=BLACK;

			display();		// affichage
		}

		// gestion du clavier
		key=getch();
		if (key==ESCAPE)
		{
			v->n=NULL;
			return -1;
		}

	} while (key!=ENTER);	// recommence si ENTER n'a pas ete presse
	erase();				// efface le fractal
	text("              ",WHITE,1,10);
	text("              ",WHITE,1,11);
	text("              ",WHITE,1,12);
	display();
	v=h;
	while (v->n->n) // cherche l'avant-dernier vertex
	{
		p=v;	// sauve l'adresse de l'element actuel
		v=v->n;	// et passe a l'element suivant
	}
	p->n=v->n;	// efface l'element actuel
	free(v);	// libere la memoire

	return i;	// renvoie le nombre de segments
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				display()
{
	int			bank;

	while (!(inportw(0x03DA)&8));	// synchronisation avec l'ecran
	while (inportw(0x03DA)&8);
	for (bank=0 ; bank<12 ; bank++)	// 12 banques
	{
		regs.x.ax=0x4F05;	// fonction 4F05h
		regs.x.bx=0;		// fenetre A
		regs.x.dx=bank;	// numero de la banque
		__dpmi_int(0x10,&regs);	// INT 10h
		dosmemput(buffer+(bank<<16),65536L,0xA0000);	// affichage
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				draw(VERTEX* v,char color)
{
	while (v->n)
	{
		line(v->x,v->y,v->n->x,v->n->y,color);
		v=v->n;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				erase()
{
	unsigned long		i;

	i=161+33*1024;	// position 161:33
	while (i<=860+732*1024)	// tant qu'on est pas a la position 860:732
	{
		buffer[i]=WHITE;		// pixel blanc
		i++;				// augmente i
		if ((i%1024)>860) i+=163+161;	// si X > 860
	}	// on vient d'effacer le carre blanc de 700x700 pixels

}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				free_fractal()
{
	f=fh;			// revient au debut de la liste
	while (f->n)		// on efface chaque element jusqu'a ce
	{			// qu'on soit arrive au dernier element
		fh=f;		// on retient l'adresse de l'element actuel
		f=f->n;		// on va a l'element suivant
		free(fh);	// et on efface l'element de l'adresse retenue
	}			// on recommence tant qu'il reste des elements
	free(f);		// et on efface le tout dernier element
	m=mh;		// on fait exactement la meme chose pour l'autre liste chainee
	while (m->n)
	{
		mh=m;
		m=m->n;
		free(mh);
	}
	free(m);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				generation()
{
	double			deg;
	double			fl;
	double			fx;
	double			fy;
	double			fdeg;
	double			ml;
	double			mx;
	double			my;
	double			mdeg;
	VERTEX*			p;

	
	f=fh;
	draw(f,BLACK);
	display();
	while (f->n)
	{
		// calcule l'amplitude et la longueur du segment
		fx=f->n->x-f->x;
		fy=f->n->y-f->y;
		fl=sqrt(fx*fx+fy*fy);
		if ((fx==0.0)&&(fy>=0.0)) fdeg=90.0;
		else if ((fx==0.0)&&(fy<=0.0)) fdeg=270.0;
		else if ((fx>=0.0)&&(fy>=0.0)) fdeg=180.0/PI*atan(fy/fx);
		else if ((fx<=0.0)&&(fy>=0.0)) fdeg=180.0-180.0/PI*atan(-fy/fx);
		else if ((fx<=0.0)&&(fy<=0.0)) fdeg=180.0+180.0/PI*atan(fy/fx);
		else fdeg=360.0-180.0/PI*atan(-fy/fx);
		m=mh;
		while (m->n->n)
		{
			// efface l'ancien segment
			line(f->x,f->y,f->n->x,f->n->y,WHITE);

			// calcule l'amplitude et la longueur du segment
			mx=m->n->x-m->x;
			my=m->n->y-m->y;
			ml=sqrt(mx*mx+my*my);
			if ((mx==0.0)&&(my>=0.0)) mdeg=90.0;
			else if ((mx==0.0)&&(my<=0.0)) mdeg=270.0;
			else if ((mx>=0.0)&&(my>=0.0)) mdeg=180.0/PI*atan(my/mx);
			else if ((mx<=0.0)&&(my>=0.0)) mdeg=180.0-180.0/PI*atan(-my/mx);
			else if ((mx<=0.0)&&(my<=0.0)) mdeg=180.0+180.0/PI*atan(my/mx);
			else mdeg=360.0-180.0/PI*atan(-my/mx);

			// insere un nouveau vertex
			p=f->n;
			f->n=(VERTEX*)malloc(sizeof(VERTEX));
			f->n->n=p;
			p=f;
			f=f->n;

			// positionne le nouveau vertex
			deg=fdeg+mdeg;
			if (deg>=360.0) deg-=360.0;
			ml=fl*ml/700.0;
			f->x=p->x+COS[(int)deg]*ml;
			f->y=p->y+SIN[(int)deg]*ml;

			// affiche le nouveau segment en rouge
			line(p->x,p->y,f->x,f->y,RED);
			display();

			m=m->n;
		}
		line(f->x,f->y,f->n->x,f->n->y,RED);
		f=f->n;
	}
	m=mh;
	f=fh;
	erase();
	draw(f,BLACK);
	display();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				initVESA()
{
	unsigned long		i;

	regs.x.ax=0x4F02;		// fonction 4F02h
	regs.x.bx=0x105;		// mode 105h - 1024x768 256 couleurs
	__dpmi_int(0x10,&regs);		// INT 10h
	buffer=(char*)malloc(1024*768);	// alloue de la memoire pour le buffer

	outportb(0x03C8,BLACK);		// noir
	outportb(0x03C9,0);
	outportb(0x03C9,0);
	outportb(0x03C9,0);
	outportb(0x03C8,RED);		// rouge
	outportb(0x03C9,63);
	outportb(0x03C9,0);
	outportb(0x03C9,0);
	outportb(0x03C8,WHITE);		// blanc
	outportb(0x03C9,63);
	outportb(0x03C9,63);
	outportb(0x03C9,63);

	for (i=0 ; i<1024*768 ; i++) buffer[i]=BLACK;	// ecran noir
	erase();	// dessine un carre blanc de 700x700 pixels

	f=(VERTEX*)malloc(sizeof(VERTEX));	// creation du premier element
	fh=f;					// sauve l'adresse du debut
	f->n=NULL;				// on ferme la liste chainee

	m=(VERTEX*)malloc(sizeof(VERTEX));	// creation des deux premiers vertex
	mh=m;					// sauve l'adresse du debut
	m->x=-349.0;	// premier vertex au centre
	m->y=0.0;	// et tout a gauche
	m->n=(VERTEX*)malloc(sizeof(VERTEX));	// vertex suivant
	m=m->n;
	m->x=350.0;	// second vertex au centre
	m->y=0.0;	// et tout a droite
	m->n=NULL;	// on ferme la liste chainee
	m=mh;		// on revient au debut de la liste chainee

	// initialisation de la souris
	regs.x.ax=0x00;		// MOV AX,00h
	__dpmi_int(0x33,&regs);	// INT 33h
	regs.x.ax=0x02;		// MOV AX,02h
	__dpmi_int(0x33,&regs);	// INT 33h

	// precalcul des nombres trigonometriques
	for (i=0 ; i<360 ; i++)
	{
		SIN[i]=sin(i*PI/180.0);
		COS[i]=cos(i*PI/180.0);
	}

	// initialisation texte
	dosmemget(0x000FFA6E,2048L,ascii);
	text("GENERATEUR DE FRACTAL - par Boes Olivier\r\n",RED,41,1);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				line(int fx,int fy,int lx,int ly,char color)
{
	int			x1;
	int			y1;
	int			x2;
	int			y2;
	int			dx;
	int			dy;
	int			sub;
	int			remain;
	int			error;
	int			inc1;
	int			inc2;

	fx+=510;
	fy=383-fy;
	lx+=510;
	ly=383-ly;
	if (fx>lx)
	{
		x1=lx;
		x2=fx;
		y1=ly;
		y2=fy;
	}
	else
	{
		x1=fx;
		x2=lx;
		y1=fy;
		y2=ly;
	}
	dx=x2-x1;
	dy=y2-y1;
	if ((!dx)&&(!dy)) return;
	if (dy<0) 
	{
		dy=-dy;
		inc1=-1;
		inc2=1;
	}
	else 
	{
		inc1=1;
		inc2=1;
	}
	if (dx>dy)
	{	
		sub=dx-dy;
		error=dy-(dx>>1);
		remain=(dx+1)>>1;

		do
		{
			if ((x1>160)&&(x1<861)&&(y1>32)&&(y1<733)) buffer[x1+(y1<<10)]=color;
			if ((x2>160)&&(x2<861)&&(y2>32)&&(y2<733)) buffer[x2+(y2<<10)]=color;
			x1+=inc2;
			x2-=inc2;
			if (error>=0)
			{
				y1+=inc1;
				y2-=inc1;
				error-=sub;
			}
			else error+=dy;
		} while (--remain>0);
		if ((!(dx&1))&&((x1>160)&&(x1<861)&&(y1>32)&&(y1<733))) buffer[x1+(y1<<10)]=color;
	}
	else
	{	
		sub=dy-dx;
		error=dx-(dy>>1);
		remain=(dy+1)>>1;

		do
		{
			if ((x1>160)&&(x1<861)&&(y1>32)&&(y1<733)) buffer[x1+(y1<<10)]=color;
			if ((x2>160)&&(x2<861)&&(y2>32)&&(y2<733)) buffer[x2+(y2<<10)]=color;
			y1+=inc1;
			y2-=inc1;
			if (error>=0)
			{
				x1+=inc2;
				x2-=inc2;
				error-=sub;
			}
			else error+=dx;
		} while (--remain>0);
		if ((!(dy&1))&&((x1>160)&&(x1<861)&&(y1>32)&&(y1<733))) buffer[x1+(y1<<10)]=color;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void					pcx()
{
	char				header[128];
	char				c;
	char				n;
	char				name[11];
	char*				img;
	FILE*				file;
	unsigned char			pal[768];
	unsigned int			width=(700+(700&1));
	unsigned long			max=700*700;
	unsigned long			i;
	unsigned long			i2;

	/* --- CREATION DU PCX --- */
	strcpy(name,"ecran0.pcx");
	while ((__file_exists(name))&&(name[5]<='9')) name[5]++;
	if (name[5]>'9') return;
	file=fopen(name,"wb");
	img=(char*)malloc(700*700*sizeof(char));
	i=161+33*1024;	// position 161:33
	i2=0;
	while (i<=860+732*1024)	// tant qu'on est pas a la position 860:732
	{
		img[i2++]=buffer[i];
		i++;				// augmente i
		if ((i%1024)>860) i+=163+161;	// si X > 860
	}

	/* --- EN-TETE --- */
	header[0]=10;				/* octet PCX */
	header[1]=5;				/* version de PCX */
	header[2]=1;				/* RLE active */
	header[3]=8;				/* 8 bits pour un pixel */
	header[4]=0;				/* Xmin */
	header[5]=0;				/* Xmin */
	header[6]=0;				/* Ymin */
	header[7]=0;				/* Ymin */
	header[8]=(700-1)&0x00FF;			/* Xmax */
	header[9]=((700-1)&0xFF00)>>8;		/* Xmax */
	header[10]=(700-1)&0x00FF;		/* Ymax */
	header[11]=((700-1)&0xFF00)>>8;		/* Ymax */
	header[12]=72;				/* resolution horizontale */
	header[13]=0;				/* resolution horizontale */
	header[14]=72;				/* resolution verticale */
	header[15]=0;				/* resolution verticale */
	for (i=0 ; i<16 ; i++)			/* palette 16 couleurs */
	{
		header[i*3+16]=15-i;
		header[i*3+17]=15-i;
		header[i*3+18]=15-i;
	}
	header[64]=0;				/* toujours 0 */
	header[65]=1;				/* toujours 1 */
	header[66]=width&0x00FF;		/* largeur, doit etre un nombre pair */
	header[67]=(width&0xFF00)>>8;		/* largeur, doit etre un nombre pair */
	header[68]=1;				/* 1 = couleurs, 2 = noir et blanc */
	for (i=69 ; i<128 ; i++) header[i]=0;	/* tout le reste c'est 0 */

	fwrite(header,sizeof(char),128,file);	/* on ecrit l'en-tete */

	/* --- IMAGE --- */
	i=0;
	do
	{
		c=img[i];
		i++;
		n=1;
		if (i!=max) while (img[i]==c)
		{
			if ((n<63)&&(i%700)) n++;
			else break;
			i++;
			if (i==max) break;
		}
		if ((n==1)&&((c&0xC0)!=0xC0)) fwrite(&c,sizeof(char),1,file);
		else
		{
			if ((i%700==0)&&(700!=width)&&(c==(char)(255)))
			{
				n++;
				width=0;
			}
			n|=0xC0;
			fwrite(&n,sizeof(char),1,file);
			fwrite(&c,sizeof(char),1,file);
		}
		if (!width) width=700+1;
		else if ((i%700==0)&&(700!=width)) fwrite("\xC1\xFF",sizeof(char),2,file);
	} while (i!=max);
	
	/* --- PALETTE --- */
	c=12;
	fwrite(&c,sizeof(char),1,file);
	pal[0]=0;	pal[1]=0;	pal[2]=0;
	pal[3]=255;	pal[4]=0;	pal[5]=0;
	pal[6]=255;	pal[7]=255;	pal[8]=255;
	for (i=9 ; i<768 ; i++) pal[i]=0;
	fwrite(pal,sizeof(char),768,file);
	fclose(file);
	free(img);
}


////////////////////////////////////////////////////////////////////////////////////////////////////

void				stopVESA()
{
	regs.h.ah=0x00;		// fonction 00h
	regs.h.al=0x03;		// mode 03h - mode texte normal
	__dpmi_int(0x10,&regs);	// INT 10h
	free(buffer);		// on libere la memoire du buffer
	free_fractal();		// on libere la memoire des listes chainees
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				text(char* t,int c,int x,int y)
{
	unsigned int		i;
	unsigned int		i2;
	unsigned int		pos1;
	unsigned int		pos2;

	pos1=(x<<3)+(y<<13);	// convertit les positions
	for (i=0 ; t[i] ; i++)	// tant que le texte n'est pas fini
	{
		if (t[i]=='\n')	// passe une ligne
		{
			pos1+=1024*8;
			continue;
		}
		if (t[i]=='\r')	// retour a gauche
		{
			pos1=(pos1&0xFFC00)+(x<<3);
			continue;
		}
		pos2=t[i]<<3;	// va au caractere demande
		for (i2=0 ; i2<8 ; i2++)	// 8 lignes par caracteres
		{
			if (ascii[pos2]&0x80) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x40) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x20) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x10) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x08) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x04) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x02) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x01) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			pos1+=1024-8;
			pos2++;
		}
		pos1-=1024*8-8;
	}
}
#include			<assert.h>
#include			<conio.h>
#include			<dpmi.h>
#include			<go32.h>
#include			<math.h>
#include			<pc.h>
#include			<stdio.h>
#include			<stdlib.h>
#include			<string.h>
#include			<sys/farptr.h>
#include			<sys/movedata.h>
#include			<unistd.h>

#define				BLACK		0
#define				RED		1
#define				WHITE		2
#define				ENTER		13
#define				ESCAPE		27
#define				SPACE		32

////////////////////////////////////////////////////////////////////////////////////////////////////

typedef struct VERTEX
{
	double			x;
	double			y;
	struct VERTEX*		n;
} VERTEX;

////////////////////////////////////////////////////////////////////////////////////////////////////

char				ascii[2048];
char*				buffer;
double				SIN[360];
double				COS[360];
__dpmi_regs			regs;
VERTEX*				f;
VERTEX*				fh;
VERTEX*				m;
VERTEX*				mh;

////////////////////////////////////////////////////////////////////////////////////////////////////

int				mouse(int* cx,int* cy,int lx,int ly);
int				build(VERTEX* v);
void				display();
void				draw(VERTEX* v,char color);
void				erase();
void				free_fractal();
void				generation();
void				initVESA();
void				line(int fx,int fy,int lx,int ly,char color);
void				pcx();
void				stopVESA();
void				text(char* t,int c,int x,int y);

////////////////////////////////////////////////////////////////////////////////////////////////////

int				main()
{
	char			key;
	char			segs[30];
	int			i;
	int			fi;
	int			mi;

	initVESA();

	mi=build(m);
	if (mi==-1) { stopVESA(); return 0; }
	fi=build(f);
	if (fi==-1) { stopVESA(); return 0; }
	draw(f,BLACK);
	i=0;
	while (1)
	{
		sprintf(segs,"%d segments    ",(int)(fi*pow(mi,i++)));
		text(segs,WHITE,1,10);
		display();
		do key=getch(); while ((key!=ENTER)&&(key!='P')&&(key!=ESCAPE));
		if (key==ESCAPE) break;
		else if (key=='P') pcx();
		erase();
		generation();
	};

	stopVESA();
	return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int				mouse(int* cx,int* cy,int lx,int ly)
{
	int			button=0;

	do
	{
		regs.x.ax=0x03;		// MOV AX,00h
		__dpmi_int(0x33,&regs);	// INT 33h
		button=(button&2)|(regs.x.bx&1);
		if (button==1)
		{
			(*cx)+=regs.x.cx-lx;	// augmente cx du nombre de pixel dont la souris a bouge
			(*cy)-=regs.x.dx-ly;	// diminue cy du nombre de pixel dont la souris a bouge
			button|=2;
		}
	} while (button&1);	// continue tant qu'un bouton est presse

	if (!button)
	{
		(*cx)+=regs.x.cx-lx;	// augmente cx du nombre de pixel dont la souris a bouge
		(*cy)-=regs.x.dx-ly;	// diminue cy du nombre de pixel dont la souris a bouge
	}
	if ((*cx)>350) (*cx)=350;	// pour eviter les debordements
	else if ((*cx)<-349) (*cx)=-349;
	if ((*cy)>350) (*cy)=350;	// pour eviter les debordements
	else if ((*cy)<-349) (*cy)=-349;

	regs.x.ax=0x04;		// MOV AX,00h
	regs.x.cx=lx;		// MOV CX,[lx]
	regs.x.dx=ly;		// MOV DX,[ly]
	__dpmi_int(0x33,&regs);	// INT 33h

	return button;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

int				build(VERTEX* v)
{
	int			cx=0;
	int			cy=0;
	int			lx;
	int			ly;
	int			i=1;
	char			key;
	char			pos[5];
	double			deg;
	VERTEX*			p;
	VERTEX*			h;

	text("X : ",WHITE,1,10);
	text("Y : ",WHITE,1,11);
	text("angle : ",WHITE,1,12);

	regs.x.ax=0x03;		// MOV AX,00h
	__dpmi_int(0x33,&regs);	// INT 33h
	lx=regs.x.cx;	// position X actuelle de la souris
	ly=regs.x.dx;	// position Y actuelle de la souris

	h=v;	// sauve l'adresse du debut de la liste
	if (v->n==NULL)	// si l'utilisateur doit choisir le premier et le dernier vertex
	{
		while (1)	// boucle infinie
		{
			// efface l'ancien curseur
			if (cy==350)	buffer[cx+510+((382-cy)<<10)]=BLACK; else buffer[cx+510+((382-cy)<<10)]=WHITE;
			if (cx==350)	buffer[cx+511+((383-cy)<<10)]=BLACK; else buffer[cx+511+((383-cy)<<10)]=WHITE;
			if (cy==-349)	buffer[cx+510+((384-cy)<<10)]=BLACK; else buffer[cx+510+((384-cy)<<10)]=WHITE;
			if (cx==-349)	buffer[cx+509+((383-cy)<<10)]=BLACK; else buffer[cx+509+((383-cy)<<10)]=WHITE;
			buffer[cx+510+((383-cy)<<10)]=WHITE;

			if (mouse(&cx,&cy,lx,ly))
			{
				v->x=(double)cx;
				v->y=(double)cy;
				if (v->n==NULL) // si l'utilisateur a choisi le premier vertex
				{
					v->n=(VERTEX*)malloc(sizeof(VERTEX));
					v=v->n;
					v->n=(VERTEX*)1;	// flag
				}
				else break;	// quitte la boucle infinie si le dernier vertex a ete choisi
			}

			// gestion du clavier
			if (kbhit())
			{
				key=getch();
				if (key==ESCAPE)
				{
					v->n=NULL;
					return -1;
				}
			}

			// affiche la position du curseur
			sprintf(pos,"%4d",cx);
			text(pos,WHITE,5,10);
			sprintf(pos,"%4d",cy);
			text(pos,WHITE,5,11);

			// dessine le nouveau curseur
			buffer[cx+510+((382-cy)<<10)]=RED;
			buffer[cx+511+((383-cy)<<10)]=RED;
			buffer[cx+510+((384-cy)<<10)]=RED;
			buffer[cx+509+((383-cy)<<10)]=RED;
			buffer[cx+510+((383-cy)<<10)]=RED;

			// si le premier vertex est deja choisi
			if (v->n)
			{
				line(h->x,h->y,cx,cy,BLACK);
				buffer[(int)h->x+510+((int)(382-h->y)<<10)]=BLACK;
				buffer[(int)h->x+511+((int)(383-h->y)<<10)]=BLACK;
				buffer[(int)h->x+510+((int)(384-h->y)<<10)]=BLACK;
				buffer[(int)h->x+509+((int)(383-h->y)<<10)]=BLACK;
				buffer[(int)h->x+510+((int)(383-h->y)<<10)]=BLACK;

				// affiche l'amplitude
				if ((cx-h->x==0.0)&&(cy-h->y>=0.0)) deg=90.0;
				else if ((cx-h->x==0.0)&&(cy-h->y<=0.0)) deg=270.0;
				else if ((cx-h->x>=0.0)&&(cy-h->y>=0.0)) deg=180.0/PI*atan((cy-h->y)/(cx-h->x));
				else if ((cx-h->x<=0.0)&&(cy-h->y>=0.0)) deg=180.0-180.0/PI*atan(-(cy-h->y)/(cx-h->x));
				else if ((cx-h->x<=0.0)&&(cy-h->y<=0.0)) deg=180.0+180.0/PI*atan((cy-h->y)/(cx-h->x));
				else deg=360.0-180.0/PI*atan(-(cy-h->y)/(cx-h->x));
				sprintf(pos,"%3.0f",deg);
				text(pos,WHITE,9,12);
			}
			display();
			line(h->x,h->y,cx,cy,WHITE);
		}
		v->n=NULL;	// ferme la liste chainee
		v=h;		// revient au debut de la liste chainee

		// efface le premier vertex
		if (h->y==350)	buffer[(int)h->x+510+((int)(382-h->y)<<10)]=BLACK; else buffer[(int)h->x+510+((int)(382-h->y)<<10)]=WHITE;
		if (cx==350)	buffer[(int)h->x+511+((int)(383-h->y)<<10)]=BLACK; else buffer[(int)h->x+511+((int)(383-h->y)<<10)]=WHITE;
		if (h->y==-349)	buffer[(int)h->x+510+((int)(384-h->y)<<10)]=BLACK; else buffer[(int)h->x+510+((int)(384-h->y)<<10)]=WHITE;
		if (cx==-349)	buffer[(int)h->x+509+((int)(383-h->y)<<10)]=BLACK; else buffer[(int)h->x+509+((int)(383-h->y)<<10)]=WHITE;
		buffer[(int)h->x+510+((int)(383-h->y)<<10)]=WHITE;
	}
	p=v->n;		// sauve l'adresse de l'element suivant
	v->n=(VERTEX*)malloc(sizeof(VERTEX));	// nouvel element suivant
	v->n->n=p;	// positionne le nouvel element juste avant l'ancien element
	p=v;		// sauve l'adresse de l'element actuel
	v=v->n;
	do
	{
		while (!kbhit())	// tant qu'aucune touche n'est pressee
		{
			// efface l'ancien curseur
			if (cy==350)	buffer[cx+510+((382-cy)<<10)]=BLACK; else buffer[cx+510+((382-cy)<<10)]=WHITE;
			if (cx==350)	buffer[cx+511+((383-cy)<<10)]=BLACK; else buffer[cx+511+((383-cy)<<10)]=WHITE;
			if (cy==-349)	buffer[cx+510+((384-cy)<<10)]=BLACK; else buffer[cx+510+((384-cy)<<10)]=WHITE;
			if (cx==-349)	buffer[cx+509+((383-cy)<<10)]=BLACK; else buffer[cx+509+((383-cy)<<10)]=WHITE;
			buffer[cx+510+((383-cy)<<10)]=WHITE;

			if (mouse(&cx,&cy,lx,ly))
			{
				i++;	// augmente le nombre de segments
				erase();
				v->x=(double)cx;
				v->y=(double)cy;
				p=v->n;
				v->n=(VERTEX*)malloc(sizeof(VERTEX));
				v->n->n=p;
				p=v;
				v=v->n;
				// le nouveau vertex est maintenant enregistre
				// et on passe au vertex suivant
			}
			else erase();		// efface l'ancien fractal

			v->x=(double)cx;	// nouvelle position X du point
			v->y=(double)cy;	// nouvelle position Y du point
			draw(h,RED);		// dessine le nouveau fractal

			// affiche la position du curseur
			sprintf(pos,"%4d",cx);
			text(pos,WHITE,5,10);
			sprintf(pos,"%4d",cy);
			text(pos,WHITE,5,11);

			// affiche l'amplitude
			if ((cx-p->x==0.0)&&(cy-p->y>=0.0)) deg=90.0;
			else if ((cx-p->x==0.0)&&(cy-p->y<=0.0)) deg=270.0;
			else if ((cx-p->x>=0.0)&&(cy-p->y>=0.0)) deg=180.0/PI*atan((cy-p->y)/(cx-p->x));
			else if ((cx-p->x<=0.0)&&(cy-p->y>=0.0)) deg=180.0-180.0/PI*atan(-(cy-p->y)/(cx-p->x));
			else if ((cx-p->x<=0.0)&&(cy-p->y<=0.0)) deg=180.0+180.0/PI*atan((cy-p->y)/(cx-p->x));
			else deg=360.0-180.0/PI*atan(-(cy-p->y)/(cx-p->x));
			sprintf(pos,"%3.0f",deg);
			text(pos,WHITE,9,12);

			// dessine le nouveau curseur
			buffer[cx+510+((382-cy)<<10)]=BLACK;
			buffer[cx+511+((383-cy)<<10)]=BLACK;
			buffer[cx+510+((384-cy)<<10)]=BLACK;
			buffer[cx+509+((383-cy)<<10)]=BLACK;
			buffer[cx+510+((383-cy)<<10)]=BLACK;

			display();		// affichage
		}

		// gestion du clavier
		key=getch();
		if (key==ESCAPE)
		{
			v->n=NULL;
			return -1;
		}

	} while (key!=ENTER);	// recommence si ENTER n'a pas ete presse
	erase();				// efface le fractal
	text("              ",WHITE,1,10);
	text("              ",WHITE,1,11);
	text("              ",WHITE,1,12);
	display();
	v=h;
	while (v->n->n) // cherche l'avant-dernier vertex
	{
		p=v;	// sauve l'adresse de l'element actuel
		v=v->n;	// et passe a l'element suivant
	}
	p->n=v->n;	// efface l'element actuel
	free(v);	// libere la memoire

	return i;	// renvoie le nombre de segments
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				display()
{
	int			bank;

	while (!(inportw(0x03DA)&8));	// synchronisation avec l'ecran
	while (inportw(0x03DA)&8);
	for (bank=0 ; bank<12 ; bank++)	// 12 banques
	{
		regs.x.ax=0x4F05;	// fonction 4F05h
		regs.x.bx=0;		// fenetre A
		regs.x.dx=bank;	// numero de la banque
		__dpmi_int(0x10,&regs);	// INT 10h
		dosmemput(buffer+(bank<<16),65536L,0xA0000);	// affichage
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				draw(VERTEX* v,char color)
{
	while (v->n)
	{
		line(v->x,v->y,v->n->x,v->n->y,color);
		v=v->n;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				erase()
{
	unsigned long		i;

	i=161+33*1024;	// position 161:33
	while (i<=860+732*1024)	// tant qu'on est pas a la position 860:732
	{
		buffer[i]=WHITE;		// pixel blanc
		i++;				// augmente i
		if ((i%1024)>860) i+=163+161;	// si X > 860
	}	// on vient d'effacer le carre blanc de 700x700 pixels

}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				free_fractal()
{
	f=fh;			// revient au debut de la liste
	while (f->n)		// on efface chaque element jusqu'a ce
	{			// qu'on soit arrive au dernier element
		fh=f;		// on retient l'adresse de l'element actuel
		f=f->n;		// on va a l'element suivant
		free(fh);	// et on efface l'element de l'adresse retenue
	}			// on recommence tant qu'il reste des elements
	free(f);		// et on efface le tout dernier element
	m=mh;		// on fait exactement la meme chose pour l'autre liste chainee
	while (m->n)
	{
		mh=m;
		m=m->n;
		free(mh);
	}
	free(m);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				generation()
{
	double			deg;
	double			fl;
	double			fx;
	double			fy;
	double			fdeg;
	double			ml;
	double			mx;
	double			my;
	double			mdeg;
	VERTEX*			p;

	
	f=fh;
	draw(f,BLACK);
	display();
	while (f->n)
	{
		// calcule l'amplitude et la longueur du segment
		fx=f->n->x-f->x;
		fy=f->n->y-f->y;
		fl=sqrt(fx*fx+fy*fy);
		if ((fx==0.0)&&(fy>=0.0)) fdeg=90.0;
		else if ((fx==0.0)&&(fy<=0.0)) fdeg=270.0;
		else if ((fx>=0.0)&&(fy>=0.0)) fdeg=180.0/PI*atan(fy/fx);
		else if ((fx<=0.0)&&(fy>=0.0)) fdeg=180.0-180.0/PI*atan(-fy/fx);
		else if ((fx<=0.0)&&(fy<=0.0)) fdeg=180.0+180.0/PI*atan(fy/fx);
		else fdeg=360.0-180.0/PI*atan(-fy/fx);
		m=mh;
		while (m->n->n)
		{
			// efface l'ancien segment
			line(f->x,f->y,f->n->x,f->n->y,WHITE);

			// calcule l'amplitude et la longueur du segment
			mx=m->n->x-m->x;
			my=m->n->y-m->y;
			ml=sqrt(mx*mx+my*my);
			if ((mx==0.0)&&(my>=0.0)) mdeg=90.0;
			else if ((mx==0.0)&&(my<=0.0)) mdeg=270.0;
			else if ((mx>=0.0)&&(my>=0.0)) mdeg=180.0/PI*atan(my/mx);
			else if ((mx<=0.0)&&(my>=0.0)) mdeg=180.0-180.0/PI*atan(-my/mx);
			else if ((mx<=0.0)&&(my<=0.0)) mdeg=180.0+180.0/PI*atan(my/mx);
			else mdeg=360.0-180.0/PI*atan(-my/mx);

			// insere un nouveau vertex
			p=f->n;
			f->n=(VERTEX*)malloc(sizeof(VERTEX));
			f->n->n=p;
			p=f;
			f=f->n;

			// positionne le nouveau vertex
			deg=fdeg+mdeg;
			if (deg>=360.0) deg-=360.0;
			ml=fl*ml/700.0;
			f->x=p->x+COS[(int)deg]*ml;
			f->y=p->y+SIN[(int)deg]*ml;

			// affiche le nouveau segment en rouge
			line(p->x,p->y,f->x,f->y,RED);
			display();

			m=m->n;
		}
		line(f->x,f->y,f->n->x,f->n->y,RED);
		f=f->n;
	}
	m=mh;
	f=fh;
	erase();
	draw(f,BLACK);
	display();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				initVESA()
{
	unsigned long		i;

	regs.x.ax=0x4F02;		// fonction 4F02h
	regs.x.bx=0x105;		// mode 105h - 1024x768 256 couleurs
	__dpmi_int(0x10,&regs);		// INT 10h
	buffer=(char*)malloc(1024*768);	// alloue de la memoire pour le buffer

	outportb(0x03C8,BLACK);		// noir
	outportb(0x03C9,0);
	outportb(0x03C9,0);
	outportb(0x03C9,0);
	outportb(0x03C8,RED);		// rouge
	outportb(0x03C9,63);
	outportb(0x03C9,0);
	outportb(0x03C9,0);
	outportb(0x03C8,WHITE);		// blanc
	outportb(0x03C9,63);
	outportb(0x03C9,63);
	outportb(0x03C9,63);

	for (i=0 ; i<1024*768 ; i++) buffer[i]=BLACK;	// ecran noir
	erase();	// dessine un carre blanc de 700x700 pixels

	f=(VERTEX*)malloc(sizeof(VERTEX));	// creation du premier element
	fh=f;					// sauve l'adresse du debut
	f->n=NULL;				// on ferme la liste chainee

	m=(VERTEX*)malloc(sizeof(VERTEX));	// creation des deux premiers vertex
	mh=m;					// sauve l'adresse du debut
	m->x=-349.0;	// premier vertex au centre
	m->y=0.0;	// et tout a gauche
	m->n=(VERTEX*)malloc(sizeof(VERTEX));	// vertex suivant
	m=m->n;
	m->x=350.0;	// second vertex au centre
	m->y=0.0;	// et tout a droite
	m->n=NULL;	// on ferme la liste chainee
	m=mh;		// on revient au debut de la liste chainee

	// initialisation de la souris
	regs.x.ax=0x00;		// MOV AX,00h
	__dpmi_int(0x33,&regs);	// INT 33h
	regs.x.ax=0x02;		// MOV AX,02h
	__dpmi_int(0x33,&regs);	// INT 33h

	// precalcul des nombres trigonometriques
	for (i=0 ; i<360 ; i++)
	{
		SIN[i]=sin(i*PI/180.0);
		COS[i]=cos(i*PI/180.0);
	}

	// initialisation texte
	dosmemget(0x000FFA6E,2048L,ascii);
	text("GENERATEUR DE FRACTAL - par Boes Olivier\r\n",RED,41,1);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				line(int fx,int fy,int lx,int ly,char color)
{
	int			x1;
	int			y1;
	int			x2;
	int			y2;
	int			dx;
	int			dy;
	int			sub;
	int			remain;
	int			error;
	int			inc1;
	int			inc2;

	fx+=510;
	fy=383-fy;
	lx+=510;
	ly=383-ly;
	if (fx>lx)
	{
		x1=lx;
		x2=fx;
		y1=ly;
		y2=fy;
	}
	else
	{
		x1=fx;
		x2=lx;
		y1=fy;
		y2=ly;
	}
	dx=x2-x1;
	dy=y2-y1;
	if ((!dx)&&(!dy)) return;
	if (dy<0) 
	{
		dy=-dy;
		inc1=-1;
		inc2=1;
	}
	else 
	{
		inc1=1;
		inc2=1;
	}
	if (dx>dy)
	{	
		sub=dx-dy;
		error=dy-(dx>>1);
		remain=(dx+1)>>1;

		do
		{
			if ((x1>160)&&(x1<861)&&(y1>32)&&(y1<733)) buffer[x1+(y1<<10)]=color;
			if ((x2>160)&&(x2<861)&&(y2>32)&&(y2<733)) buffer[x2+(y2<<10)]=color;
			x1+=inc2;
			x2-=inc2;
			if (error>=0)
			{
				y1+=inc1;
				y2-=inc1;
				error-=sub;
			}
			else error+=dy;
		} while (--remain>0);
		if ((!(dx&1))&&((x1>160)&&(x1<861)&&(y1>32)&&(y1<733))) buffer[x1+(y1<<10)]=color;
	}
	else
	{	
		sub=dy-dx;
		error=dx-(dy>>1);
		remain=(dy+1)>>1;

		do
		{
			if ((x1>160)&&(x1<861)&&(y1>32)&&(y1<733)) buffer[x1+(y1<<10)]=color;
			if ((x2>160)&&(x2<861)&&(y2>32)&&(y2<733)) buffer[x2+(y2<<10)]=color;
			y1+=inc1;
			y2-=inc1;
			if (error>=0)
			{
				x1+=inc2;
				x2-=inc2;
				error-=sub;
			}
			else error+=dx;
		} while (--remain>0);
		if ((!(dy&1))&&((x1>160)&&(x1<861)&&(y1>32)&&(y1<733))) buffer[x1+(y1<<10)]=color;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void					pcx()
{
	char				header[128];
	char				c;
	char				n;
	char				name[11];
	char*				img;
	FILE*				file;
	unsigned char			pal[768];
	unsigned int			width=(700+(700&1));
	unsigned long			max=700*700;
	unsigned long			i;
	unsigned long			i2;

	/* --- CREATION DU PCX --- */
	strcpy(name,"ecran0.pcx");
	while ((__file_exists(name))&&(name[5]<='9')) name[5]++;
	if (name[5]>'9') return;
	file=fopen(name,"wb");
	img=(char*)malloc(700*700*sizeof(char));
	i=161+33*1024;	// position 161:33
	i2=0;
	while (i<=860+732*1024)	// tant qu'on est pas a la position 860:732
	{
		img[i2++]=buffer[i];
		i++;				// augmente i
		if ((i%1024)>860) i+=163+161;	// si X > 860
	}

	/* --- EN-TETE --- */
	header[0]=10;				/* octet PCX */
	header[1]=5;				/* version de PCX */
	header[2]=1;				/* RLE active */
	header[3]=8;				/* 8 bits pour un pixel */
	header[4]=0;				/* Xmin */
	header[5]=0;				/* Xmin */
	header[6]=0;				/* Ymin */
	header[7]=0;				/* Ymin */
	header[8]=(700-1)&0x00FF;			/* Xmax */
	header[9]=((700-1)&0xFF00)>>8;		/* Xmax */
	header[10]=(700-1)&0x00FF;		/* Ymax */
	header[11]=((700-1)&0xFF00)>>8;		/* Ymax */
	header[12]=72;				/* resolution horizontale */
	header[13]=0;				/* resolution horizontale */
	header[14]=72;				/* resolution verticale */
	header[15]=0;				/* resolution verticale */
	for (i=0 ; i<16 ; i++)			/* palette 16 couleurs */
	{
		header[i*3+16]=15-i;
		header[i*3+17]=15-i;
		header[i*3+18]=15-i;
	}
	header[64]=0;				/* toujours 0 */
	header[65]=1;				/* toujours 1 */
	header[66]=width&0x00FF;		/* largeur, doit etre un nombre pair */
	header[67]=(width&0xFF00)>>8;		/* largeur, doit etre un nombre pair */
	header[68]=1;				/* 1 = couleurs, 2 = noir et blanc */
	for (i=69 ; i<128 ; i++) header[i]=0;	/* tout le reste c'est 0 */

	fwrite(header,sizeof(char),128,file);	/* on ecrit l'en-tete */

	/* --- IMAGE --- */
	i=0;
	do
	{
		c=img[i];
		i++;
		n=1;
		if (i!=max) while (img[i]==c)
		{
			if ((n<63)&&(i%700)) n++;
			else break;
			i++;
			if (i==max) break;
		}
		if ((n==1)&&((c&0xC0)!=0xC0)) fwrite(&c,sizeof(char),1,file);
		else
		{
			if ((i%700==0)&&(700!=width)&&(c==(char)(255)))
			{
				n++;
				width=0;
			}
			n|=0xC0;
			fwrite(&n,sizeof(char),1,file);
			fwrite(&c,sizeof(char),1,file);
		}
		if (!width) width=700+1;
		else if ((i%700==0)&&(700!=width)) fwrite("\xC1\xFF",sizeof(char),2,file);
	} while (i!=max);
	
	/* --- PALETTE --- */
	c=12;
	fwrite(&c,sizeof(char),1,file);
	pal[0]=0;	pal[1]=0;	pal[2]=0;
	pal[3]=255;	pal[4]=0;	pal[5]=0;
	pal[6]=255;	pal[7]=255;	pal[8]=255;
	for (i=9 ; i<768 ; i++) pal[i]=0;
	fwrite(pal,sizeof(char),768,file);
	fclose(file);
	free(img);
}


////////////////////////////////////////////////////////////////////////////////////////////////////

void				stopVESA()
{
	regs.h.ah=0x00;		// fonction 00h
	regs.h.al=0x03;		// mode 03h - mode texte normal
	__dpmi_int(0x10,&regs);	// INT 10h
	free(buffer);		// on libere la memoire du buffer
	free_fractal();		// on libere la memoire des listes chainees
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void				text(char* t,int c,int x,int y)
{
	unsigned int		i;
	unsigned int		i2;
	unsigned int		pos1;
	unsigned int		pos2;

	pos1=(x<<3)+(y<<13);	// convertit les positions
	for (i=0 ; t[i] ; i++)	// tant que le texte n'est pas fini
	{
		if (t[i]=='\n')	// passe une ligne
		{
			pos1+=1024*8;
			continue;
		}
		if (t[i]=='\r')	// retour a gauche
		{
			pos1=(pos1&0xFFC00)+(x<<3);
			continue;
		}
		pos2=t[i]<<3;	// va au caractere demande
		for (i2=0 ; i2<8 ; i2++)	// 8 lignes par caracteres
		{
			if (ascii[pos2]&0x80) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x40) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x20) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x10) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x08) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x04) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x02) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			if (ascii[pos2]&0x01) buffer[pos1++]=c&0x00FF;
			else buffer[pos1++]=(c&0xFF00)>>8;
			pos1+=1024-8;
			pos2++;
		}
		pos1-=1024*8-8;
	}
}

 Conclusion

J'ai hésité à mettre la source dans 'Algorythme' ou 'Graphique', finalement c'est ce dernier que j'ai choisi.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Sources du même auteur

Source avec Zip Source avec une capture RESOLUTION D'EQUATIONS (JUSQU'AU 3EME DEGRE) + CLASSE POUR M...
Source avec Zip DESSINER A LA MAIN UNE STRUCTURE FRACTALE [DJGPP] [VGA 13H]
Source avec Zip JEU DE LA VIE EN MODE VGA 11H [DJGPP]
Source avec Zip MODE VESA HAUTE RESOLUTION [DJGPP]
Source avec Zip Source avec une capture CUBE 3D EN ROTATION / MODE GRAPHIQUE VGA 13H / DJGPP

 Sources de la même categorie

Source avec Zip Source avec une capture PLANNING D'EQUIPE par grephit
Source avec Zip APPLICATION DE DESSIN DE QUELQUES FIGURES par laguchori
Source avec Zip Source avec une capture HDR EXPOSURE FUSION par mecrosoft
Source avec Zip Source avec une capture IRC CLIENT MULTISERVEUR EN MFC (TXIRC) par TeniX
Source avec Zip ENTETE DU FICHIER BMP (BIPMAP) par k.Lutchi

Commentaires et avis

Commentaire de AlexMAN le 05/08/2004 17:56:27

D'apres la capture, bravo, ca a l'air bien beau tt ca, mais dommage ke l'on puisse pas compiler sans DJGPP, a kan la version win32 ?

++

Commentaire de tibur le 05/08/2004 18:44:45

Je suis d'accord avec toi, AlexMAN. Pourquoi ne pas tester OpenGL ? Sauf erreur de ma part, ca doit etre impossible de faire fonctionner le mode VESA 105h sous Windows 2000 ou WinXP, non ?

Commentaire de gorgonzola le 05/08/2004 18:52:37

ça compile sans probleme avec DJGPP sous WinXP chez moi
mais si j'avais voulu faire la même chose en ASM ou avec un compilo 16 bits ça aurait surement foiré

Commentaire de MiTcH37 le 06/08/2004 09:54:13

Un exécutable aurait été le bien venu !
Car ça a l'air vraiment bien, chapeau !

Commentaire de gorgonzola le 06/08/2004 16:25:58

pour ceux que ça intéresse :

executable : http://gcheese.free.fr/fractal.exe
(on ne peut pas mettre d'executables dans le zip)
escape pour quitter

Commentaire de AlexMAN le 07/08/2004 00:54:04

Foire karément chez moi (winXP), "pas de signal d'entrée RGB"...

Commentaire de BruNews le 07/08/2004 01:02:14 administrateur CS

Sur XP SP1, met le moniteur en veille, au moins un resultat.

Commentaire de AlexMAN le 07/08/2004 09:58:25

marche pas ton idée Brunews...

Commentaire de BruNews le 07/08/2004 10:30:44 administrateur CS

C'est pas mon idee, je dis ce que fait cet exe sur le PC ou je l'ai lance.
Si mon idee etait d'eteindre le moniteur, ça se fait en 2 lignes, alors....

Commentaire de AlexMAN le 07/08/2004 10:35:19

Ah d'accord, pardon, j'avais pris ca comme un conseil, c exactement ski se passe chez moi oci..

Commentaire de gorgonzola le 07/08/2004 14:00:19

pige pas :-/ chez moi ça marche sans problème

Commentaire de BruNews le 07/08/2004 14:12:11 administrateur CS

Je viens de tester sur Server 2003, la c'est carrement le gestionnaire d'ecran qui dit 'OUT OF RANGE'.

Sur quel systeme as-tu teste ?

Dans tous les cas, absolument abandonner le 16 bits, devrait etre fait depuis 10 ans. Penser a ecrire portable 64 bits qui est pour tres bientot.

Commentaire de gorgonzola le 09/08/2004 13:53:07

bah oui mais je programme pour mon plaisir moi lol, je sais bien que le 16 bits c'est fini
je comprend pas pourquoi ça ne marche pas, chez moi sur WinXP ya aucun probleme

Commentaire de BruNews le 09/08/2004 14:10:04 administrateur CS

Je comprends bien mais c'est dommage de voir des competences qui vont se perdre. Faut penser que le 16 bits ne pourra bientot meme plus etre lance, il ne demarrera plus du tout.

Commentaire de MiTcH37 le 09/08/2004 20:26:26

moi sur xp,ça marche...bon ça détruit mon parasite mon affichage après mais ça marche.
D'où tire-tu toutes ces idées de programme ???

Commentaire de gorgonzola le 27/08/2004 21:35:29

qu'est-ce que tu veux dire par 'ça détruit parasite mon affichage' ? je suis désolé que ça foire sur tant de machines, chez moi ça marche sans aucun problème. Je me doutais que ça ne serait pas très portable mais je sais pas faire mieux, je suis vraiment nul pour tout ce qui est de bas niveau. Sinon bah là je me faisais chier alors j'ai fait ce petit programme pour m'amuser lol.

Commentaire de ccgousset le 05/07/2011 10:31:49

Ta raison fromage ecoute pas ces vieilles femmes. Ki peut en 64 peut certainement en 16. Y son ka se creuser les menages ...

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,530 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales