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
213 int
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
232 UnixInit();
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
269 fract_dir2 = 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
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 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
407 usr_floatflag = 1;
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 */
452 #else 453 if (kbdchar == F2 || kbdchar == '@') { /* We mapped @ to F2 */
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 == '#') {
461 #else 462 if (kbdchar == 'r' || kbdchar == '3' || kbdchar == F3) {
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
538 return(0);
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)(),...)
566 #else 567 int timer(va_alist) 568 va_dcl
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);
581 #else 582 int timertype; 583 int (*subrtn)(); 584 va_start(arg_marker); 585 timertype = va_arg(arg_marker, int); 586 subrtn = (int (*)())va_arg(arg_marker, int *);
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(&ltime); 612 timestring = ctime(&ltime); 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