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 / Exemple :
#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.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.