1 /*
2 FRACTINT - The Ultimate Fractal Generator
3 Main Routine
4 */
5
6 #include <string.h>
7 #include <time.h>
8 #include <signal.h>
9
10 #ifndef XFRACT
11 #include <io.h>
12 #endif
13
14 #ifndef USE_VARARGS
15 #include <stdarg.h>
16 #else
17 #include <varargs.h>
18 #endif
19
20 #include <ctype.h>
21
22 /* #include hierarchy for fractint is a follows:
23 Each module should include port.h as the first fractint specific
24 include. port.h includes <stdlib.h>, <stdio.h>, <math.h>,
25 <float.h>; and, ifndef XFRACT, <dos.h>.
26 Most modules should include prototyp.h, which incorporates by
27 direct or indirect reference the following header files:
28 mpmath.h
29 cmplx.h
30 fractint.h
31 big.h
32 biginit.h
33 helpcom.h
34 externs.h
35 Other modules may need the following, which must be included
36 separately:
37 fractype.h
38 helpdefs.h
39 lsys.y
40 targa.h
41 targa_lc.h
42 tplus.h
43 If included separately from prototyp.h, big.h includes cmplx.h
44 and biginit.h; and mpmath.h includes cmplx.h
45 */
46
47 #include "port.h"
48 #include "prototyp.h"
49 #include "fractype.h"
50 #include "helpdefs.h"
51
52 struct videoinfo videoentry;
53 int helpmode;
54
55 long timer_start,timer_interval; /* timer(...) start & total */
56 int adapter; /* Video Adapter chosen from list in ...h */
57 char *fract_dir1="", *fract_dir2="";
58
59 #ifdef __TURBOC__
60
61 /* yes, I *know* it's supposed to be compatible with Microsoft C,
62 but some of the routines need to know if the "C" code
63 has been compiled with Turbo-C. This flag is a 1 if FRACTINT.C
64 (and presumably the other routines as well) has been compiled
65 with Turbo-C. */
66 int compiled_by_turboc = 1;
67
68 /* set size to be used for overlays, a bit bigger than largest (help) */
69 unsigned _ovrbuffer = 54 * 64; /* that's 54k for overlays, counted in paragraphs */
70
71 #else
72
73 int compiled_by_turboc = 0;
74
75 #endif
76
77 /*
78 the following variables are out here only so
79 that the calcfract() and assembler routines can get at them easily
80 */
81 int active_system = 0; /* 0 for DOS, WINFRAC for Windows */
82 int dotmode; /* video access method */
83 int textsafe2; /* textsafe override from videotable */
84 int oktoprint; /* 0 if printf() won't work */
85 int sxdots,sydots; /* # of dots on the physical screen */
86 int sxoffs,syoffs; /* physical top left of logical screen */
87 int xdots, ydots; /* # of dots on the logical screen */
88 double dxsize, dysize; /* xdots-1, ydots-1 */
89 int colors = 256; /* maximum colors available */
90 long maxit; /* try this many iterations */
91 int boxcount; /* 0 if no zoom-box yet */
92 int zrotate; /* zoombox rotation */
93 double zbx,zby; /* topleft of zoombox */
94 double zwidth,zdepth,zskew; /* zoombox size & shape */
95
96 int fractype; /* if == 0, use Mandelbrot */
97 char stdcalcmode; /* '1', '2', 'g', 'b' */
98 long creal, cimag; /* real, imag'ry parts of C */
99 long delx, dely; /* screen pixel increments */
100 long delx2, dely2; /* screen pixel increments */
101 LDBL delxx, delyy; /* screen pixel increments */
102 LDBL delxx2, delyy2; /* screen pixel increments */
103 long delmin; /* for calcfrac/calcmand */
104 double ddelmin; /* same as a double */
105 double param[MAXPARAMS]; /* parameters */
106 double potparam[3]; /* three potential parameters*/
107 long fudge; /* 2**fudgefactor */
108 long l_at_rad; /* finite attractor radius */
109 double f_at_rad; /* finite attractor radius */
110 int bitshift; /* fudgefactor */
111
112 int badconfig = 0; /* 'fractint.cfg' ok? */
113 int diskisactive; /* disk-video drivers flag */
114 int diskvideo; /* disk-video access flag */
115 int hasinverse = 0;
116 /* note that integer grid is set when integerfractal && !invert; */
117 /* otherwise the floating point grid is set; never both at once */
118 long far *lx0, far *ly0; /* x, y grid */
119 long far *lx1, far *ly1; /* adjustment for rotate */
120 /* note that lx1 & ly1 values can overflow into sign bit; since */
121 /* they're used only to add to lx0/ly0, 2s comp straightens it out */
122 double far *dx0, far *dy0; /* floating pt equivs */
123 double far *dx1, far *dy1;
124 int integerfractal; /* TRUE if fractal uses integer math */
125
126 /* usr_xxx is what the user wants, vs what we may be forced to do */
127 char usr_stdcalcmode;
128 int usr_periodicitycheck;
129 long usr_distest;
130 char usr_floatflag;
131
132 int viewwindow; /* 0 for full screen, 1 for window */
133 float viewreduction; /* window auto-sizing */
134 int viewcrop; /* nonzero to crop default coords */
135 float finalaspectratio; /* for view shape and rotation */
136 int viewxdots,viewydots; /* explicit view sizing */
137 int video_cutboth; /* nonzero to keep virtual aspect */
138 int zscroll; /* screen/zoombox 0 fixed, 1 relaxed */
139
140 /* HISTORY far *history = NULL; */
141 U16 history = 0;
142 int maxhistory = 10;
143
144 /* variables defined by the command line/files processor */
145 int comparegif=0; /* compare two gif files flag */
146 int timedsave=0; /* when doing a timed save */
147 int resave_flag=0; /* tells encoder not to incr filename */
148 int started_resaves=0; /* but incr on first resave */
149 int save_system; /* from and for save files */
150 int tabmode = 1; /* tab display enabled */
151
152 /* for historical reasons (before rotation): */
153 /* top left corner of screen is (xxmin,yymax) */
154 /* bottom left corner of screen is (xx3rd,yy3rd) */
155 /* bottom right corner of screen is (xxmax,yymin) */
156 double xxmin,xxmax,yymin,yymax,xx3rd,yy3rd; /* selected screen corners */
157 long xmin, xmax, ymin, ymax, x3rd, y3rd; /* integer equivs */
158 double sxmin,sxmax,symin,symax,sx3rd,sy3rd; /* displayed screen corners */
159 double plotmx1,plotmx2,plotmy1,plotmy2; /* real->screen multipliers */
160
161 int calc_status = -1; /* -1 no fractal */
162 /* 0 parms changed, recalc reqd */
163 /* 1 actively calculating */
164 /* 2 interrupted, resumable */
165 /* 3 interrupted, not resumable */
166 /* 4 completed */
167 long calctime;
168
169 int max_colors; /* maximum palette size */
170 int zoomoff; /* = 0 when zoom is disabled */
171 int savedac; /* save-the-Video DAC flag */
172 int browsing; /* browse mode flag */
173 char file_name_stack[16][MAX_NAME]; /* array of file names used while browsing */
174 int name_stack_ptr ;
175 double toosmall;
176 int minbox;
177 int no_sub_images;
178 int autobrowse,doublecaution;
179 char brwscheckparms,brwschecktype;
180 char browsemask[MAX_NAME];
181 int scale_map[12] = {1,2,3,4,5,6,7,8,9,10,11,12}; /*RB, array for mapping notes to a (user defined) scale */
182
183
184 #define RESTART 1
185 #define IMAGESTART 2
186 #define RESTORESTART 3
187 #define CONTINUE 4
188
check_samename(void)189 static void check_samename(void)
190 {
191 char drive[FILE_MAX_DRIVE];
192 char dir[FILE_MAX_DIR];
193 char fname[FILE_MAX_FNAME];
194 char ext[FILE_MAX_EXT];
195 char path[FILE_MAX_PATH];
196 splitpath(savename,drive,dir,fname,ext);
197 if(strcmp(fname,"fract001"))
198 {
199 makepath(path,drive,dir,fname,"gif");
200 if(access(path,0)==0)
201 exit(0);
202 }
203 }
204
205 /* Do nothing if math error */
my_floating_point_err(int sig)206 static void my_floating_point_err(int sig)
207 {
208 if(sig != 0)
209 overflow = 1;
210 }
211
212 #ifdef XFRACT
213 int
214 #else
215 void
216 #endif
main(int argc,char ** argv)217 main(int argc, char **argv)
218 {
219 int resumeflag;
220 int kbdchar; /* keyboard key-hit value */
221 int kbdmore; /* continuation variable */
222 char stacked=0; /* flag to indicate screen stacked */
223
224 /* this traps non-math library floating point errors */
225 signal( SIGFPE, my_floating_point_err );
226
227 initasmvars(); /* initialize ASM stuff */
228 InitMemory();
229 checkfreemem(0);
230 load_videotable(1); /* load fractint.cfg, no message yet if bad */
231 init_help();
232
233 restart: /* insert key re-starts here */
234 autobrowse = FALSE;
235 brwschecktype = TRUE;
236 brwscheckparms = TRUE;
237 doublecaution = TRUE;
238 no_sub_images = FALSE;
239 toosmall = 6;
240 minbox = 3;
241 strcpy(browsemask,"*.gif");
242 strcpy(browsename," ");
243 name_stack_ptr= -1; /* init loaded files stack */
244
245 evolving = FALSE;
246 paramrangex = 4;
247 opx = newopx = -2.0;
248 paramrangey = 3;
249 opy = newopy = -1.5;
250 odpx = odpy = 0;
251 gridsz = 9;
252 fiddlefactor = 1;
253 fiddle_reduction = 1.0;
254 this_gen_rseed = (unsigned int)clock_ticks();
255 srand(this_gen_rseed);
256 initgene(); /*initialise pointers to lots of fractint variables for the evolution engine*/
257 start_showorbit = 0;
258 showdot = -1; /* turn off showdot if entered with <g> command */
259 calc_status = -1; /* no active fractal image */
260
261 fract_dir1 = getenv("FRACTDIR");
262 if (fract_dir1==NULL) {
263 fract_dir1 = ".";
264 }
265 #ifdef SRCDIR
266 fract_dir2 = SRCDIR;
267 #else
268 fract_dir2 = ".";
269 #endif
270
271 cmdfiles(argc,argv); /* process the command-line */
272 #ifdef XFRACT
273 UnixInit();
274 #endif
275 dopause(0); /* pause for error msg if not batch */
276 init_msg(0,"",NULL,0); /* this causes getakey if init_msg called on runup */
277 checkfreemem(1);
278 if(debugflag==450 && initbatch==1) /* abort if savename already exists */
279 check_samename();
280 #ifdef XFRACT
281 initUnixWindow();
282 #endif
283 memcpy(olddacbox,dacbox,256*3); /* save in case colors= present */
284
285 if (debugflag == 8088) cpu = 86; /* for testing purposes */
286 if (debugflag == 2870 && fpu >= 287 ) {
287 fpu = 287; /* for testing purposes */
288 cpu = 286;
289 }
290 if (debugflag == 870 && fpu >= 87 ) {
291 fpu = 87; /* for testing purposes */
292 cpu = 86;
293 }
294 if (debugflag == 70) fpu = 0; /* for testing purposes */
295 if (getenv("NO87")) fpu = 0;
296
297 if (fpu >= 287 && debugflag != 72) /* Fast 287 math */
298 setup287code();
299 adapter_detect(); /* check what video is really present */
300 if (debugflag >= 9002 && debugflag <= 9100) /* for testing purposes */
301 if (video_type > (debugflag-9000)/2) /* adjust the video value */
302 video_type = (debugflag-9000)/2;
303
304 diskisactive = 0; /* disk-video is inactive */
305 diskvideo = 0; /* disk driver is not in use */
306 setvideotext(); /* switch to text mode */
307 savedac = 0; /* don't save the VGA DAC */
308
309 #ifndef XFRACT
310 if (debugflag == 10000) /* check for free memory */
311 showfreemem();
312
313 if (badconfig < 0) /* fractint.cfg bad, no msg yet */
314 bad_fractint_cfg_msg();
315 #endif
316
317 max_colors = 256; /* the Windows version is lower */
318 max_kbdcount=(cpu>=386) ? 80 : 30; /* check the keyboard this often */
319
320 if (showfile && initmode < 0) {
321 intro(); /* display the credits screen */
322 if (keypressed() == ESC) {
323 getakey();
324 /* JPD : do not exit automatically under credits screen ...
325 goodbye();
326 */
327 }
328 }
329
330 browsing = FALSE;
331
332 if (!functionpreloaded)
333 set_if_old_bif();
334 stacked = 0;
335 restorestart:
336 if (colorpreloaded)
337 memcpy(dacbox,olddacbox,256*3); /* restore in case colors= present */
338
339 lookatmouse = 0; /* ignore mouse */
340
341 while (showfile <= 0) { /* image is to be loaded */
342 char *hdg;
343 tabmode = 0;
344 if (!browsing ) /*RB*/
345 {
346 if (overlay3d) {
347 hdg = "Select File for 3D Overlay";
348 helpmode = HELP3DOVLY;
349 }
350 else if (display3d) {
351 hdg = "Select File for 3D Transform";
352 helpmode = HELP3D;
353 }
354 else {
355 hdg = "Select File to Restore";
356 helpmode = HELPSAVEREST;
357 }
358 if (showfile < 0 && getafilename(hdg,gifmask,readname) < 0) {
359 showfile = 1; /* cancelled */
360 initmode = -1;
361 break;
362 }
363
364 name_stack_ptr = 0; /* 'r' reads first filename for browsing */
365 strcpy(file_name_stack[name_stack_ptr],browsename);
366 }
367
368 evolving = viewwindow = 0;
369 showfile = 0;
370 helpmode = -1;
371 tabmode = 1;
372 if(stacked)
373 {
374 discardscreen();
375 setvideotext();
376 stacked = 0;
377 }
378 if (read_overlay() == 0) /* read hdr, get video mode */
379 break; /* got it, exit */
380 if (browsing) /* break out of infinite loop, but lose your mind */
381 showfile = 1;
382 else
383 showfile = -1; /* retry */
384 }
385
386 helpmode = HELPMENU; /* now use this help mode */
387 tabmode = 1;
388 lookatmouse = 0; /* ignore mouse */
389
390 if (((overlay3d && !initbatch) || stacked) && initmode < 0) { /* overlay command failed */
391 unstackscreen(); /* restore the graphics screen */
392 stacked = 0;
393 overlay3d = 0; /* forget overlays */
394 display3d = 0; /* forget 3D */
395 if (calc_status ==3)
396 calc_status = 0;
397 resumeflag = 1;
398 goto resumeloop; /* ooh, this is ugly */
399 }
400
401 savedac = 0; /* don't save the VGA DAC */
402 imagestart: /* calc/display a new image */
403 if(stacked)
404 {
405 discardscreen();
406 stacked = 0;
407 }
408 #ifdef XFRACT
409 usr_floatflag = 1;
410 #endif
411 got_status = -1; /* for tab_display */
412
413 if (showfile)
414 if (calc_status > 0) /* goto imagestart implies re-calc */
415 calc_status = 0;
416
417 if (initbatch == 0)
418 lookatmouse = -PAGE_UP; /* just mouse left button, == pgup */
419
420 cyclelimit = initcyclelimit; /* default cycle limit */
421
422 adapter = initmode; /* set the video adapter up */
423 initmode = -1; /* (once) */
424
425 while (adapter < 0) { /* cycle through instructions */
426 if (initbatch) { /* batch, nothing to do */
427 initbatch = 4; /* exit with error condition set */
428 goodbye();
429 }
430 kbdchar = main_menu(0);
431 if (kbdchar == INSERT) goto restart; /* restart pgm on Insert Key */
432 if (kbdchar == DELETE) /* select video mode list */
433 kbdchar = select_video_mode(-1);
434 if ((adapter = check_vidmode_key(0,kbdchar)) >= 0)
435 break; /* got a video mode now */
436 #ifndef XFRACT
437 if ('A' <= kbdchar && kbdchar <= 'Z')
438 kbdchar = tolower(kbdchar);
439 #endif
440 #ifndef XFRACT
441 if (kbdchar == 'd') { /* shell to DOS */
442 setclear();
443 printf("\n\nShelling to DOS - type 'exit' to return\n\n");
444 shell_to_dos();
445 goto imagestart;
446 }
447 #else
448 if (kbdchar == 'd') { /* redraw image in Xfractint */
449 initmode = adapter;
450 goto imagestart;
451 }
452 #endif
453
454 #ifndef XFRACT
455 if (kbdchar == '@' || kbdchar == '2') { /* execute commands */
456 #else
457 if (kbdchar == F2 || kbdchar == '@') { /* We mapped @ to F2 */
458 #endif
459 if ((get_commands() & 4) == 0)
460 goto imagestart;
461 kbdchar = '3'; /* 3d=y so fall thru '3' code */
462 }
463 #ifndef XFRACT
464 if (kbdchar == 'r' || kbdchar == '3' || kbdchar == '#') {
465 #else
466 if (kbdchar == 'r' || kbdchar == '3' || kbdchar == F3) {
467 #endif
468 display3d = 0;
469 if (kbdchar == '3' || kbdchar == '#' || kbdchar == F3)
470 display3d = 1;
471 if(colorpreloaded)
472 memcpy(olddacbox,dacbox,256*3); /* save in case colors= present */
473 setvideotext(); /* switch to text mode */
474 showfile = -1;
475 goto restorestart;
476 }
477 if (kbdchar == 't') { /* set fractal type */
478 julibrot = 0;
479 get_fracttype();
480 goto imagestart;
481 }
482 if (kbdchar == 'x') { /* generic toggle switch */
483 get_toggles();
484 goto imagestart;
485 }
486 if (kbdchar == 'y') { /* generic toggle switch */
487 get_toggles2();
488 goto imagestart;
489 }
490 if (kbdchar == 'z') { /* type specific parms */
491 get_fract_params(1);
492 goto imagestart;
493 }
494 if (kbdchar == 'v') { /* view parameters */
495 get_view_params();
496 goto imagestart;
497 }
498 if (kbdchar == 2) { /* ctrl B = browse parms*/
499 get_browse_params();
500 goto imagestart;
501 }
502 if (kbdchar == 6) { /* ctrl f = sound parms*/
503 get_sound_params();
504 goto imagestart;
505 }
506 if (kbdchar == 'f') { /* floating pt toggle */
507 if (usr_floatflag == 0)
508 usr_floatflag = 1;
509 else
510 usr_floatflag = 0;
511 goto imagestart;
512 }
513 if (kbdchar == 'i') { /* set 3d fractal parms */
514 get_fract3d_params(); /* get the parameters */
515 goto imagestart;
516 }
517 if (kbdchar == 'g') {
518 get_cmd_string(); /* get command string */
519 goto imagestart;
520 }
521 /* buzzer(2); */ /* unrecognized key */
522 }
523
524 zoomoff = 1; /* zooming is enabled */
525 helpmode = HELPMAIN; /* now use this help mode */
526 resumeflag = 0; /* allows taking goto inside big_while_loop() */
527 resumeloop:
528 param_history(0); /* save old history */
529 /* this switch processes gotos that are now inside function */
530 switch(big_while_loop(&kbdmore,&stacked,resumeflag))
531 {
532 case RESTART:
533 goto restart;
534 case IMAGESTART:
535 goto imagestart;
536 case RESTORESTART:
537 goto restorestart;
538 default:
539 break;
540 }
541 #ifdef XFRACT
542 return(0);
543 #endif
544 }
545
546 int check_key()
547 {
548 int key;
549 if((key = keypressed()) != 0) {
550 if (show_orbit)
551 scrub_orbit();
552 if(key != 'o' && key != 'O') {
553 fflush(stdout);
554 return(-1);
555 }
556 getakey();
557 if (dotmode != 11)
558 show_orbit = 1 - show_orbit;
559 }
560 return(0);
561 }
562
563 /* timer function:
564 timer(0,(*fractal)()) fractal engine
565 timer(1,NULL,int width) decoder
566 timer(2) encoder
567 */
568 #ifndef USE_VARARGS
569 int timer(int timertype,int(*subrtn)(),...)
570 #else
571 int timer(va_alist)
572 va_dcl
573 #endif
574 {
575 va_list arg_marker; /* variable arg list */
576 char *timestring;
577 time_t ltime;
578 FILE *fp = NULL;
579 int out=0;
580 int i;
581 int do_bench;
582
583 #ifndef USE_VARARGS
584 va_start(arg_marker,subrtn);
585 #else
586 int timertype;
587 int (*subrtn)();
588 va_start(arg_marker);
589 timertype = va_arg(arg_marker, int);
590 subrtn = (int (*)())va_arg(arg_marker, int *);
591 #endif
592
593 do_bench = timerflag; /* record time? */
594 if (timertype == 2) /* encoder, record time only if debug=200 */
595 do_bench = (debugflag == 200);
596 if(do_bench)
597 fp=dir_fopen(workdir,"bench","a");
598 timer_start = clock_ticks();
599 switch(timertype) {
600 case 0:
601 out = (*(int(*)(void))subrtn)();
602 break;
603 case 1:
604 i = va_arg(arg_marker,int);
605 out = (int)decoder((short)i); /* not indirect, safer with overlays */
606 break;
607 case 2:
608 out = encoder(); /* not indirect, safer with overlays */
609 break;
610 }
611 /* next assumes CLK_TCK is 10^n, n>=2 */
612 timer_interval = (clock_ticks() - timer_start) / (CLK_TCK/100);
613
614 if(do_bench) {
615 time(<ime);
616 timestring = ctime(<ime);
617 timestring[24] = 0; /*clobber newline in time string */
618 switch(timertype) {
619 case 1:
620 fprintf(fp,"decode ");
621 break;
622 case 2:
623 fprintf(fp,"encode ");
624 break;
625 }
626 fprintf(fp,"%s type=%s resolution = %dx%d maxiter=%ld",
627 timestring,
628 curfractalspecific->name,
629 xdots,
630 ydots,
631 maxit);
632 fprintf(fp," time= %ld.%02ld secs\n",timer_interval/100,timer_interval%100);
633 if(fp != NULL)
634 fclose(fp);
635 }
636 return(out);
637 }
638