Accueil > > > GENERATEUR DE FRACTAL PERSONNALISE [VESA] [DJGPP]
GENERATEUR DE FRACTAL PERSONNALISE [VESA] [DJGPP]
Information sur la source
Description
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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // INT 33h
- regs.x.ax=0x02; // MOV AX,02h
- __dpmi_int(0x33,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // INT 33h
- regs.x.ax=0x02; // MOV AX,02h
- __dpmi_int(0x33,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // INT 33h
regs.x.ax=0x02; // MOV AX,02h
__dpmi_int(0x33,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // 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,®s); // INT 33h
regs.x.ax=0x02; // MOV AX,02h
__dpmi_int(0x33,®s); // 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,®s); // 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.
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc REACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITERREACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITER par Groc
Une mauvaise utilisation de rx lors de l'écriture d'une couche d'accès à des services peut conduire à des cas embarassants avec des erreurs mal gérées, des appels qui ne partent lorsqu'ils le devraient, et même des résultats incorrects . le tout nuis...
Cliquez pour lire la suite de l'article par Groc SHAREPOINT BLOG SITE, PROBLèME D'ARCHIVESSHAREPOINT BLOG SITE, PROBLèME D'ARCHIVES par junarnoalg
Dernièrement, nous avons migré le site
myTIC
vers un nouveau serveur SharePoint 2010. Dans les contenus que nous vouloins récupérer, nous avions un certain nombre de blogs.
Nous avons utilisé les commandes Power...
Cliquez pour lire la suite de l'article par junarnoalg
Forum
MATRICE TEMPLATEMATRICE TEMPLATE par hjr2610
Cliquez pour lire la suite par hjr2610 RE : SAC A DOS RE : SAC A DOS par hadjkaddour
Cliquez pour lire la suite par hadjkaddour
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|