|
25 Years of Programming
An open source source for C, C++, OWL, BASIC, MDB, XLS, DOT, and more... |
Home Projects Up Sitemap Search Blog Forum+Chat About Us Privacy Terms of Use Feedback FAQ Images Services Ads Donate Humor |
Use Search Site at bottom of page to find the other Mandelbrot programs on this website.
/* mbrot.c 1-3-06
Copyright (C)1993, 2006 Steven Whitney.
DeSmet C 3.03 version for H100 computer.
Calculates and displays regions of the Mandelbrot set.
Uses .PIC format: width,height (width * height chars),
which appears to be compatible with Winbrot.cpp's format
even though it's not identical.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
Version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
The program requires several of the functions from my function libraries.
The special bind command allows using exec(). pcio.o provides the IBM screen fns.
bind with: bind exec mbrot mylib.s (or your library module) -ombrot
For IBM: bind exec mbrot mylib.s (or your library module) pcio -ombrot
*/
#include "stdio.h"
#include "math.h" /* no longer required unless you use any double math fns */
/*--------------------------------------------------------------------------*/
#define H100 1 /* 1 = Heathkit H100 (NORMAL USE), 0 = IBM compatible */
/* Graphics display is not possible for IBM */
/* unless you supply some missing graphics routines */
/* and do some other customization. It can do the calculations, though. */
/* This #define was only used to allow testing the program */
/* *without* its graphics on an IBM compatible, */
/* to determine if everything else works ok. */
#define WIDTH 640 /* H100 display */
#define HEIGHT 225 /* H100 draws each scan line twice(?), so pixels are 2x their real height, */
/* giving an "effective" height of 450. */
#define ASPECT (0.75) /* but the aspect ratio of Zenith ZVM-135 monitor = 7.5"/10" */
/* Anyway, .75 is the value I had to use to make it look right. */
/* You may need to adjust it if the Mbrot regions look squished. */
#define MAXITERATIONS 10 /* MUST be <= 256 so result (0-255) fits in a char */
/* 256 is best, but takes HOURS to draw on a 4MHz CPU */
/* 10 shows no detail, but at least it's fast, */
/* so that's why it's the distribution default. */
int colors[MAXITERATIONS]; /* color map */
/* ----------------------------------------------------------------------- */
/* LOCATE(LINE,COLUMN) 1-3-06 */
/* Emulates the Basic LOCATE command */
/* returns 0 and does nothing if coordinates out of range */
/* returns 1 if ok */
/* ----------------------------------------------------------------------- */
int locate(line, column)
int line, column;
{
if((line < 1) || (line > 25) || (column < 1) || (column > 80))
return(0);
#if (H100)
if(line == 25) /* automatically enable line 25 if requested */
puts("\033x1");
puts("\033Y");
putchar(line + 31);
putchar(column + 31);
#else
scr_rowcol(line - 1, column - 1); /* IBM origin seems to be 0,0 */
#endif
return(1);
}
/*--------------------------------------------------------------------------*/
/* Clear screen */
void cls()
{
#if (H100)
locate(1,1);
puts("\033E");
#else
scr_clr();
#endif
}
/*--------------------------------------------------------------------------*/
/* color map file structure: color<cr>color<cr>... */
/* # lines in file must be at least MAXITERATIONS */
/* *EACH* possible iteration count has an associated color */
/* colors[MAXITERATIONS-1] should be 0 (black) */
/* Each iteration value maps to a color. The file provided to this function */
/* should be a text file of 255 lines, with one number on each line. */
/* Each number is the number of the color to use when plotting the */
/* iteration count corresponding to that line number in the file. */
/* Remember that the H100 only has 8 colors available, numbered 0-7. */
/* EXAMPLE: */
/* 1 <-- ESCAPE TIME OF 0 MAPS TO COLOR 1 */
/* 4 <-- ESCAPE TIME OF 1 MAPS TO COLOR 4 */
/* 5 <-- ESCAPE TIME OF 2 MAPS TO COLOR 5 */
/* ETC. */
/* See the end of this page for an example colors file. */
void loadcolors()
{
int i;
char filename[80];
FILE *infile;
puts(".COL (color) file to load: ");
gets(filename);
if(!(infile = fopen(filename,"r")))
abort("Input file not found.");
for(i = 0 ; i < MAXITERATIONS ; i++)
if(fscanf(infile,"%d\n",&(colors[i])) != 1)
abort(".COL file corrupt. Repair and rerun.");
fclose(infile);
}
/*--------------------------------------------------------------------------*/
void calcmbrot()
{
int i, row, column;
char ch;
char buf[1024];
double lowx, highx, lowy, highy;
double dx, dy;
double zreal, zimag, oldzreal;
double creal, cimag;
char filename[80];
FILE *outfile;
loadcolors();
puts("\nNote that the output file will be 144,000 bytes, plus the .ZED is 54000.\n\n");
puts("Name of .PIC file to create (omit .PIC): ");
gets(filename);
puts("\n");
puts("Enter X (REAL) Low : ");
scanf("%lf",&lowx);
puts("Enter X (REAL) High : ");
scanf("%lf",&highx);
puts("\nFor proper aspect ratio, the Y range (high - low) should be: \n");
printf("%lf\n\n",ASPECT * (highx - lowx));
puts("Enter Y (IMAGINARY) Low : ");
scanf("%lf",&lowy);
puts("Enter Y (IMAGINARY) High: ");
scanf("%lf",&highy);
puts("\n");
strupr(filename);
strcpy(buf,filename);
strcat(buf,".INF");
if(!(outfile = fopen(buf,"w")))
abort("File creation error.");
sprintf(buf,"X Axis REAL = %.13lf %.13lf\n", lowx, highx);
puts(buf);
fputs(buf, outfile);
sprintf(buf,"Y Axis IMAGINARY = %.13lf %.13lf\n\n", lowy, highy);
puts(buf);
fputs(buf, outfile);
fclose(outfile);
locate(25,1);
puts("ESC = Pause (run 2nd command.com), ^C = abort.");
locate(24,1); /* leave cursor here for when pgm ends */
puts("Working...");
strcat(filename,".PIC");
if(!(outfile = fopen(filename,"w")))
abort("File creation error.");
/* must use a trailing space; a \n writes CR+LF, NOT ok! */
/* strangely, these files can be read by Winbrot.cpp, which expects a \n there, */
/* so maybe any single whitespace char will do. */
fprintf(outfile,"%d,%d ",WIDTH,HEIGHT);
dx = (highx - lowx) / (double)(WIDTH - 1);
dy = (highy - lowy) / (double)(HEIGHT - 1);
cimag = highy;
for(row = 0 ; row < HEIGHT ; row++, cimag -= dy)
{
creal = lowx;
for(column = 0 ; column < WIDTH ; column++, creal += dx)
{
/* Calculate Z = Z*Z + C until the iteration count reaches MAXITERATIONS */
/* or until we can be certain it is heading to infinity. */
/* Remember the Min result = 1, Max result = MAXITERATIONS */
/* 12/31/05 This should be compiled to assembler and optimized. */
zreal = zimag = 0.;
for(i = 1 ; i < MAXITERATIONS ; i++)
{
oldzreal = zreal;
zreal = zreal * zreal - zimag * zimag + creal;
zimag = 2.0 * oldzreal * zimag + cimag;
if((zreal * zreal + zimag * zimag) > 4.) /* norm(), magnitude */
break;
}
/* the real i has a minimum value of 1 and a maximum of 256, but char(256) == (char)0 */
/* i-- maps the range down to 0-255 and allows using all 256 colors. */
i--;
#if (H100)
pset(column,row,colors[i]);
#endif
if(fputc((char)i, outfile) == ERR)
{
#if (H100)
zedsave();
#endif
abort(".PIC file write error.");
}
if(csts())
{
ch = ci();
switch(ch)
{
case 3: /* ^C saves partial & aborts */
fclose(outfile);
#if (H100)
zedsave();
puts("\033z");
#endif
exit(0);
/* It takes hours to create one image. */
/* This option allows you to temporarily suspend calculation, */
/* so you can do something else on your computer. */
case 27: /* ESC key runs command.com */
#if (H100)
zedsave(); /* save screen so far */
puts("\033z"); /* reset terminal */
#endif
exec("command.com",""); /* shell to command.com */
#if (H100)
puts("\033z\033x1\033x5"); /* on return, restore terminal as we want */
_outb(0x78,0xd8);
zedload("screen.zed"); /* reload saved screen to resume */
#endif
break;
default:
break;
} /* end switch */
} /* end if(csts()) */
} /* end for(columns) */
} /* end for(rows) */
fclose(outfile);
#if (H100)
zedsave();
#endif
}
/*--------------------------------------------------------------------------*/
/* if the PIC's dimensions exceed 640x225, its upper left quadrant is displayed */
void LoadPIC()
{
int i, row, column, color, width, height, filewidth, fileheight;
char filename[80];
char buf[4096];
FILE *infile;
puts(".PIC file to read (omit .PIC): ");
gets(filename);
strcat(filename,".PIC");
if(!(infile = fopen(filename,"r")))
abort("Input file not found.");
loadcolors();
if(fscanf(infile,"%d,%d ",&filewidth,&fileheight) != 2)
abort(".PIC file corrupt.");
if(filewidth > 4096)
abort("Specified PIC is too wide to display. Revise program source.");
width = filewidth;
height = fileheight;
if(width > WIDTH)
width = WIDTH;
if(height > HEIGHT)
height = HEIGHT;
for(row = 0 ; row < height ; row++) /* if file has extra rows, it just won't read them */
{
if(fread(buf, sizeof(char), filewidth, infile) != filewidth)
abort(".PIC file corrupt.");
for(column = 0 ; column < width ; column++) /* pixels beyond right edge just aren't displayed */
#if (H100)
pset(column, row, colors[buf[column]]);
#endif
if(csts() == 3) /* allow ^C abort after each line */
break;
}
fclose(infile);
#if (H100)
zedsave();
#endif
}
/*--------------------------------------------------------------------------*/
main()
{
int i;
char choice;
FILE *infile;
if(!(infile = fopen("command.com","r")))
abort("A copy of COMMAND.COM must be in the current default directory, to allow using EXEC.");
fclose(infile);
#if (H100)
{
puts("\033z\033x1\033x5"); /* reset, enable 25th, cursor off */
_outb(0x78,0xd8); /* enable all H100 color planes */
}
#endif
cls();
do
{
locate(1,1);
puts("0 - Exit\n");
puts("1 - Calculate a Mandelbrot region with coordinates you specify\n");
puts("2 - Display an existing .PIC file\n\n");
puts("Enter choice: ");
choice = getchar(); /* no CR required */
puts("\n\n");
}
while((choice < '0') || (choice > '2'));
switch(choice)
{
case '0':
#if (H100)
puts("\033z");
#endif
exit(0);
case '1':
calcmbrot();
break;
case '2':
LoadPIC();
break;
}
#if (H100)
puts("\033z"); /* master H100 terminal reset */
#endif
exit(0);
} /* end main */
/*--------------------------------------------------------------------------*/
/*
Here is a sample colors file:
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
0
END OF COLORS FILE EXAMPLE.
*/
|
|
|
|
|
|