File: common\fractint.c
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][13]; /* 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[13];
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
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 */
206 static void my_floating_point_err(int sig)
207 {
208 if(sig != 0)
209 overflow = 1;
210 }
211
212 #ifdef XFRACT
214 #else
215 void
216 #endif
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 #ifdef XFRACT
233 #endif
234 init_help();
235
236 restart: /* insert key re-starts here */
237 autobrowse = FALSE;
238 brwschecktype = TRUE;
239 brwscheckparms = TRUE;
240 doublecaution = TRUE;
241 no_sub_images = FALSE;
242 toosmall = 6;
243 minbox = 3;
244 strcpy(browsemask,"*.gif");
245 strcpy(browsename," ");
246 name_stack_ptr= -1; /* init loaded files stack */
247
248 evolving = FALSE;
249 paramrangex = 4;
250 opx = newopx = -2.0;
251 paramrangey = 3;
252 opy = newopy = -1.5;
253 odpx = odpy = 0;
254 gridsz = 9;
255 fiddlefactor = 1;
256 fiddle_reduction = 1.0;
257 this_gen_rseed = (unsigned int)clock_ticks();
258 srand(this_gen_rseed);
259 initgene(); /*initialise pointers to lots of fractint variables for the evolution engine*/
260 start_showorbit = 0;
261 showdot = -1; /* turn off showdot if entered with <g> command */
262 calc_status = -1; /* no active fractal image */
263
264 fract_dir1 = getenv("FRACTDIR");
265 if (fract_dir1==NULL) {
266 fract_dir1 = ".";
267 }
268 #ifdef SRCDIR
270 #else
271 fract_dir2 = ".";
272 #endif
273
274 cmdfiles(argc,argv); /* process the command-line */
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
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 goodbye();
325 }
326 }
327
328 browsing = FALSE;
329
330 if (!functionpreloaded)
331 set_if_old_bif();
332 stacked = 0;
333 restorestart:
334 if (colorpreloaded)
335 memcpy(dacbox,olddacbox,256*3); /* restore in case colors= present */
336
337 lookatmouse = 0; /* ignore mouse */
338
339 while (showfile <= 0) { /* image is to be loaded */
340 char *hdg;
341 tabmode = 0;
342 if (!browsing ) /*RB*/
343 {
344 if (overlay3d) {
345 hdg = "Select File for 3D Overlay";
346 helpmode = HELP3DOVLY;
347 }
348 else if (display3d) {
349 hdg = "Select File for 3D Transform";
350 helpmode = HELP3D;
351 }
352 else {
353 hdg = "Select File to Restore";
354 helpmode = HELPSAVEREST;
355 }
356 if (showfile < 0 && getafilename(hdg,gifmask,readname) < 0) {
357 showfile = 1; /* cancelled */
358 initmode = -1;
359 break;
360 }
361
362 name_stack_ptr = 0; /* 'r' reads first filename for browsing */
363 strcpy(file_name_stack[name_stack_ptr],browsename);
364 }
365
366 evolving = viewwindow = 0;
367 showfile = 0;
368 helpmode = -1;
369 tabmode = 1;
370 if(stacked)
371 {
372 discardscreen();
373 setvideotext();
374 stacked = 0;
375 }
376 if (read_overlay() == 0) /* read hdr, get video mode */
377 break; /* got it, exit */
378 if (browsing) /* break out of infinite loop, but lose your mind */
379 showfile = 1;
380 else
381 showfile = -1; /* retry */
382 }
383
384 helpmode = HELPMENU; /* now use this help mode */
385 tabmode = 1;
386 lookatmouse = 0; /* ignore mouse */
387
388 if (((overlay3d && !initbatch) || stacked) && initmode < 0) { /* overlay command failed */
389 unstackscreen(); /* restore the graphics screen */
390 stacked = 0;
391 overlay3d = 0; /* forget overlays */
392 display3d = 0; /* forget 3D */
393 if (calc_status ==3)
394 calc_status = 0;
395 resumeflag = 1;
396 goto resumeloop; /* ooh, this is ugly */
397 }
398
399 savedac = 0; /* don't save the VGA DAC */
400 imagestart: /* calc/display a new image */
401 if(stacked)
402 {
403 discardscreen();
404 stacked = 0;
405 }
406 #ifdef XFRACT
408 #endif
409 got_status = -1; /* for tab_display */
410
411 if (showfile)
412 if (calc_status > 0) /* goto imagestart implies re-calc */
413 calc_status = 0;
414
415 if (initbatch == 0)
416 lookatmouse = -PAGE_UP; /* just mouse left button, == pgup */
417
418 cyclelimit = initcyclelimit; /* default cycle limit */
419
420
421 adapter = initmode; /* set the video adapter up */
422 initmode = -1; /* (once) */
423
424 while (adapter < 0) { /* cycle through instructions */
425 if (initbatch) { /* batch, nothing to do */
426 initbatch = 4; /* exit with error condition set */
427 goodbye();
428 }
429 kbdchar = main_menu(0);
430 if (kbdchar == INSERT) goto restart; /* restart pgm on Insert Key */
431 if (kbdchar == DELETE) /* select video mode list */
432 kbdchar = select_video_mode(-1);
433 if ((adapter = check_vidmode_key(0,kbdchar)) >= 0)
434 break; /* got a video mode now */
435 #ifndef XFRACT
436 if ('A' <= kbdchar && kbdchar <= 'Z')
437 kbdchar = tolower(kbdchar);
438 #endif
439 if (kbdchar == 'd') { /* shell to DOS */
440 setclear();
441 #ifndef XFRACT
442 printf("\n\nShelling to DOS - type 'exit' to return\n\n");
443 #else
444 printf("\n\nShelling to Linux/Unix - type 'exit' to return\n\n"); 445 #endif
446 shell_to_dos();
447 goto imagestart;
448 }
449
450 #ifndef XFRACT
451 if (kbdchar == '@' || kbdchar == '2') { /* execute commands */
454 #endif
455 if ((get_commands() & 4) == 0)
456 goto imagestart;
457 kbdchar = '3'; /* 3d=y so fall thru '3' code */
458 }
459 #ifndef XFRACT
460 if (kbdchar == 'r' || kbdchar == '3' || kbdchar == '#') {
463 #endif
464 display3d = 0;
465 if (kbdchar == '3' || kbdchar == '#' || kbdchar == F3)
466 display3d = 1;
467 if(colorpreloaded)
468 memcpy(olddacbox,dacbox,256*3); /* save in case colors= present */
469 setvideotext(); /* switch to text mode */
470 showfile = -1;
471 goto restorestart;
472 }
473 if (kbdchar == 't') { /* set fractal type */
474 julibrot = 0;
475 get_fracttype();
476 goto imagestart;
477 }
478 if (kbdchar == 'x') { /* generic toggle switch */
479 get_toggles();
480 goto imagestart;
481 }
482 if (kbdchar == 'y') { /* generic toggle switch */
483 get_toggles2();
484 goto imagestart;
485 }
486 if (kbdchar == 'z') { /* type specific parms */
487 get_fract_params(1);
488 goto imagestart;
489 }
490 if (kbdchar == 'v') { /* view parameters */
491 get_view_params();
492 goto imagestart;
493 }
494 if (kbdchar == 2) { /* ctrl B = browse parms*/
495 get_browse_params();
496 goto imagestart;
497 }
498 if (kbdchar == 6) { /* ctrl f = sound parms*/
499 get_sound_params();
500 goto imagestart;
501 }
502 if (kbdchar == 'f') { /* floating pt toggle */
503 if (usr_floatflag == 0)
504 usr_floatflag = 1;
505 else
506 usr_floatflag = 0;
507 goto imagestart;
508 }
509 if (kbdchar == 'i') { /* set 3d fractal parms */
510 get_fract3d_params(); /* get the parameters */
511 goto imagestart;
512 }
513 if (kbdchar == 'g') {
514 get_cmd_string(); /* get command string */
515 goto imagestart;
516 }
517 /* buzzer(2); */ /* unrecognized key */
518 }
519
520 zoomoff = 1; /* zooming is enabled */
521 helpmode = HELPMAIN; /* now use this help mode */
522 resumeflag = 0; /* allows taking goto inside big_while_loop() */
523 resumeloop:
524 param_history(0); /* save old history */
525 /* this switch processes gotos that are now inside function */
526 switch(big_while_loop(&kbdmore,&stacked,resumeflag))
527 {
528 case RESTART:
529 goto restart;
530 case IMAGESTART:
531 goto imagestart;
532 case RESTORESTART:
533 goto restorestart;
534 default:
535 break;
536 }
537 #ifdef XFRACT
539 #endif
540 }
541
542 int check_key()
543 {
544 int key;
545 if((key = keypressed()) != 0) {
546 if (show_orbit)
547 scrub_orbit();
548 if(key != 'o' && key != 'O') {
549 fflush(stdout);
550 return(-1);
551 }
552 getakey();
553 if (dotmode != 11)
554 show_orbit = 1 - show_orbit;
555 }
556 return(0);
557 }
558
559 /* timer function:
560 timer(0,(*fractal)()) fractal engine
561 timer(1,NULL,int width) decoder
562 timer(2) encoder
563 */
564 #ifndef USE_VARARGS
565 int timer(int timertype,int(*subrtn)(),...)
569 #endif
570 {
571 va_list arg_marker; /* variable arg list */
572 char *timestring;
573 time_t ltime;
574 FILE *fp = NULL;
575 int out=0;
576 int i;
577 int do_bench;
578
579 #ifndef USE_VARARGS
580 va_start(arg_marker,subrtn);
587 #endif
588
589 do_bench = timerflag; /* record time? */
590 if (timertype == 2) /* encoder, record time only if debug=200 */
591 do_bench = (debugflag == 200);
592 if(do_bench)
593 fp=dir_fopen(workdir,"bench","a");
594 timer_start = clock_ticks();
595 switch(timertype) {
596 case 0:
597 out = (*(int(*)(void))subrtn)();
598 break;
599 case 1:
600 i = va_arg(arg_marker,int);
601 out = (int)decoder((short)i); /* not indirect, safer with overlays */
602 break;
603 case 2:
604 out = encoder(); /* not indirect, safer with overlays */
605 break;
606 }
607 /* next assumes CLK_TCK is 10^n, n>=2 */
608 timer_interval = (clock_ticks() - timer_start) / (CLK_TCK/100);
609
610 if(do_bench) {
611 time(<ime);
612 timestring = ctime(<ime);
613 timestring[24] = 0; /*clobber newline in time string */
614 switch(timertype) {
615 case 1:
616 fprintf(fp,"decode ");
617 break;
618 case 2:
619 fprintf(fp,"encode ");
620 break;
621 }
622 fprintf(fp,"%s type=%s resolution = %dx%d maxiter=%ld",
623 timestring,
624 curfractalspecific->name,
625 xdots,
626 ydots,
627 maxit);
628 fprintf(fp," time= %ld.%02ld secs\n",timer_interval/100,timer_interval%100);
629 if(fp != NULL)
630 fclose(fp);
631 }
632 return(out);
633 }
634