home *** CD-ROM | disk | FTP | other *** search
/ Fractal Creations (Second Edition) / FRACTALS_2E.iso / frasrc.exe / FRACTINT.C < prev    next >
C/C++ Source or Header  |  1993-08-21  |  56KB  |  1,757 lines

  1. /*
  2.     FRACTINT - The Ultimate Fractal Generator
  3.             Main Routine
  4. */
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <time.h>
  10. #ifndef XFRACT
  11. #include <dos.h>
  12. #include <stdarg.h>
  13. #else
  14. #include <varargs.h>
  15. #endif
  16. #include <ctype.h>
  17. #include "prototyp.h"
  18. /* routines in this module    */
  19.  
  20. static void cmp_line_cleanup();
  21. static void move_zoombox(int);
  22. static int call_line3d(BYTE *pixels, int linelen);
  23. void clear_zoombox();
  24. static void note_zoom();
  25. static void restore_zoom();
  26. static void setup287code();
  27.  
  28. #ifndef XFRACT
  29. extern    int timer(int timertype,int(*subrtn)(),...);
  30. #else
  31. extern  int timer();
  32. #endif
  33.  
  34. #define PUTTHEMHERE 1        /* stuff common external arrays here */
  35.  
  36. #include "fractint.h"
  37. #include "mpmath.h"
  38. #include "fractype.h"
  39. #include "helpdefs.h"
  40.  
  41. long timer_start,timer_interval;    /* timer(...) start & total */
  42. extern int  timerflag;
  43.  
  44. int    adapter;        /* Video Adapter chosen from list in ...h */
  45.  
  46. extern double xcjul, ycjul;
  47. extern int soundflag;
  48. extern int julibrot;
  49.  
  50. extern char gifmask[];
  51. extern int TPlusErr;
  52.  
  53. extern int save_release, bailout;
  54. extern int Transparent3D, far NewTPFractal, tpdepth;
  55. extern int AntiAliasing, Shadowing;
  56. extern int pot16bit;        /* save 16 bit values for continuous potential */
  57. extern int disk16bit;        /* disk video up & running with 16 bit values */
  58. extern int video_type;        /* coded value indicating video adapter type */
  59. extern int usr_biomorph;
  60. extern int escape_exit;
  61. extern int forcesymmetry;
  62. extern float  screenaspect;
  63. extern    char    readname[];    /* name of fractal input file */
  64. extern    int    showfile;    /* zero if display of file is pending */
  65. #define MAXHISTORY    10    /* save this many historical rcds */
  66. struct historystruct {        /* history structure */
  67.     int fractype;        /* fractal type */
  68.     double param[MAXPARAMS];/* parameters   */
  69.     double xxmin;        /* top left    */
  70.     double yymax;        /* top left    */
  71.     double xxmax;        /* bottom right */
  72.     double yymin;        /* bottom right */
  73.     double xx3rd;        /* bottom left    */
  74.     double yy3rd;        /* bottom left    */
  75.     } far *history;
  76.  
  77. char *fract_dir1="", *fract_dir2="";
  78.  
  79. #ifdef __TURBOC__
  80.  
  81. /* yes, I *know* it's supposed to be compatible with Microsoft C,
  82.    but some of the routines need to know if the "C" code
  83.    has been compiled with Turbo-C.  This flag is a 1 if FRACTINT.C
  84.    (and presumably the other routines as well) has been compiled
  85.    with Turbo-C. */
  86. int compiled_by_turboc = 1;
  87.  
  88. /* set size to be used for overlays, a bit bigger than largest (help) */
  89. unsigned _ovrbuffer = 54 * 64; /* that's 54k for overlays, counted in paragraphs */
  90.  
  91. #else
  92.  
  93. int compiled_by_turboc = 0;
  94.  
  95. #endif
  96.  
  97. extern char savename[];     /* save files using this name */
  98. extern char preview;        /* 3D preview mode flag */
  99. extern char temp1[];        /* temporary strings        */
  100. extern int  debugflag;        /* internal use only - you didn't see this */
  101. /*
  102.    the following variables are out here only so
  103.    that the calcfract() and assembler routines can get at them easily
  104. */
  105.     int    active_system = 0;    /* 0 for DOS, WINFRAC for Windows */
  106.     int    dotmode;        /* video access method        */
  107.     int    textsafe2;        /* textsafe override from videotable */
  108.     int    oktoprint;        /* 0 if printf() won't work */
  109.     int    sxdots,sydots;        /* # of dots on the physical screen    */
  110.     int    sxoffs,syoffs;        /* physical top left of logical screen */
  111.     int    xdots, ydots;        /* # of dots on the logical screen     */
  112.     double    dxsize, dysize;     /* xdots-1, ydots-1        */
  113.     int    colors;         /* maximum colors available */
  114.     int    maxit;            /* try this many iterations */
  115.     int    boxcount;        /* 0 if no zoom-box yet     */
  116.     int    zrotate;        /* zoombox rotation        */
  117.     double    zbx,zby;        /* topleft of zoombox        */
  118.     double    zwidth,zdepth,zskew;    /* zoombox size & shape     */
  119.  
  120.     int    fractype;        /* if == 0, use Mandelbrot  */
  121.     char    stdcalcmode;        /* '1', '2', 'g', 'b'       */
  122.     long    creal, cimag;        /* real, imag'ry parts of C */
  123.     long    delx, dely;        /* screen pixel increments  */
  124.     long    delx2, dely2;        /* screen pixel increments  */
  125.     double    delxx, delyy;        /* screen pixel increments  */
  126.     double    delxx2, delyy2;     /* screen pixel increments  */
  127.     long    delmin;         /* for calcfrac/calcmand    */
  128.     double    ddelmin;        /* same as a double        */
  129.     double    param[MAXPARAMS];    /* parameters               */
  130.     double    potparam[3];        /* three potential parameters*/
  131.     long    fudge;            /* 2**fudgefactor        */
  132.     long    l_at_rad;        /* finite attractor radius  */
  133.     double    f_at_rad;        /* finite attractor radius  */
  134.     int    bitshift;        /* fudgefactor            */
  135.  
  136.     int    badconfig = 0;        /* 'fractint.cfg' ok?       */
  137.     int    diskisactive;        /* disk-video drivers flag  */
  138.     int    diskvideo;        /* disk-video access flag   */
  139.     int hasinverse = 0;
  140.     /* note that integer grid is set when integerfractal && !invert;    */
  141.     /* otherwise the floating point grid is set; never both at once     */
  142.     long    far *lx0, far *ly0;    /* x, y grid            */
  143.     long    far *lx1, far *ly1;    /* adjustment for rotate    */
  144.     /* note that lx1 & ly1 values can overflow into sign bit; since     */
  145.     /* they're used only to add to lx0/ly0, 2s comp straightens it out  */
  146.     double far *dx0, far *dy0;    /* floating pt equivs */
  147.     double far *dx1, far *dy1;
  148.     int    integerfractal;     /* TRUE if fractal uses integer math */
  149.  
  150.     /* usr_xxx is what the user wants, vs what we may be forced to do */
  151.     char    usr_stdcalcmode;
  152.     int    usr_periodicitycheck;
  153.     int    usr_distest;
  154.     char    usr_floatflag;
  155.  
  156.     int    viewwindow;        /* 0 for full screen, 1 for window */
  157.     float    viewreduction;        /* window auto-sizing */
  158.     int    viewcrop;        /* nonzero to crop default coords */
  159.     float    finalaspectratio;    /* for view shape and rotation */
  160.     int    viewxdots,viewydots;    /* explicit view sizing */
  161. extern    int    inside;         /* inside color: 1=blue     */
  162. extern    int    outside;        /* outside color, if set    */
  163. extern    int    cyclelimit;        /* color-rotator upper limit */
  164. extern    int    display3d;        /* 3D display flag: 0 = OFF */
  165. extern    int    overlay3d;        /* 3D overlay flag: 0 = OFF */
  166. extern    int    boxcolor;        /* zoom box color */
  167. extern    int    color_bright;        /* set by find_special_colors */
  168.  
  169. #ifndef XFRACT
  170. extern BYTE dacbox[256][3];    /* Video-DAC (filled in by SETVIDEO) */
  171. extern BYTE olddacbox[256][3]; /* backup copy of the Video-DAC */
  172. #else
  173. BYTE dacbox[256][3];   /* Video-DAC (filled in by SETVIDEO) */
  174. BYTE olddacbox[256][3]; /* backup copy of the Video-DAC */
  175. #endif
  176. extern struct videoinfo far videotable[];
  177. extern BYTE far *mapdacbox;    /* default dacbox when map= specified */
  178. extern int    daclearn, daccount;    /* used by the color-cyclers */
  179. extern SEGTYPE    extraseg;        /* used by Save-to-DISK routines */
  180. extern int    cpu;            /* cpu type            */
  181. extern int    fpu;            /* fpu type            */
  182. extern int    iit;            /* iit fpu?            */
  183. extern int    lookatmouse;        /* used to select mouse mode    */
  184. extern int    (*outln)(BYTE *, int);    /* called in decoder */
  185.        void    (*outln_cleanup)();
  186. extern int    filetype;        /* GIF or other */
  187.  
  188. /* variables defined by the command line/files processor */
  189. extern    double    inversion[];
  190. extern    int    invert;     /* non-zero if inversion active */
  191. extern    int    initbatch;    /* 1 if batch run (no kbd)  */
  192.                  /* 2 batch, no save */
  193.                  /* 3 user interrupt, errorlevel 2 */
  194.                  /* 4 program error errorlevel 1, save */
  195.                  /* 5 program error errorlevel 1, don't save */
  196.                 /* -1 complete first, then set to 1 */
  197.  
  198. extern    int    initmode;        /* initial video mode        */
  199. extern    int    goodmode;        /* video.asm sets nonzero if mode ok */
  200. extern    int    initcyclelimit;     /* initial cycle limit        */
  201. extern    int    LogFlag;        /* non-zero if logarithmic palettes */
  202. extern    int    reallyega;        /* == 0 if it's really an EGA */
  203.  
  204. extern char showbox;        /* flag to show box and vector in preview */
  205. extern unsigned initsavetime;    /* timed save interval */
  206.  
  207. int    comparegif=0;            /* compare two gif files flag */
  208. int    timedsave=0;            /* when doing a timed save */
  209. extern long saveticks, savebase;    /* timed save vars for general.asm */
  210. extern int  finishrow;            /* for general.asm timed save */
  211. int    resave_flag=0;            /* tells encoder not to incr filename */
  212. int    started_resaves=0;        /* but incr on first resave */
  213. int    save_system;            /* from and for save files */
  214. int    tabmode = 1;            /* tab display enabled */
  215. extern    int got_status;
  216. extern    int loaded3d;
  217. extern    int colorstate,colorpreloaded;    /* comments in cmdfiles */
  218. extern int functionpreloaded; /* set in cmdfiles for old bifs JCO 7/5/92 */
  219.  
  220. extern int  show_orbit;
  221.  
  222. #ifdef XFRACT
  223. extern int XZoomWaiting;
  224. #endif
  225.  
  226. /* for historical reasons (before rotation):         */
  227. /*    top    left  corner of screen is (xxmin,yymax) */
  228. /*    bottom left  corner of screen is (xx3rd,yy3rd) */
  229. /*    bottom right corner of screen is (xxmax,yymin) */
  230. double    xxmin,xxmax,yymin,yymax,xx3rd,yy3rd; /* selected screen corners  */
  231. long    xmin, xmax, ymin, ymax, x3rd, y3rd;  /* integer equivs         */
  232. double    sxmin,sxmax,symin,symax,sx3rd,sy3rd; /* displayed screen corners */
  233. double    plotmx1,plotmx2,plotmy1,plotmy2;     /* real->screen multipliers */
  234.  
  235. int calc_status; /* -1 no fractal            */
  236.          /*  0 parms changed, recalc reqd   */
  237.          /*  1 actively calculating        */
  238.          /*  2 interrupted, resumable        */
  239.          /*  3 interrupted, not resumable   */
  240.          /*  4 completed            */
  241. long calctime;
  242.  
  243. int max_colors;                /* maximum palette size */
  244. extern int max_kbdcount;        /* governs keyboard-check speed */
  245.  
  246. int       zoomoff;            /* = 0 when zoom is disabled    */
  247. extern int nxtscreenflag; /* for cellular next screen generation */
  248.  
  249. static int far fromtext_flag = 0;    /* = 1 if we're in graphics mode */
  250. int       savedac;            /* save-the-Video DAC flag    */
  251.  
  252. void main(int argc, char **argv)
  253. {
  254.    double  jxxmin, jxxmax, jyymin, jyymax; /* "Julia mode" entry point */
  255.    double  jxx3rd, jyy3rd;
  256.    int       frommandel;            /* if julia entered from mandel */
  257.    int       axmode, bxmode, cxmode, dxmode; /* video mode (BIOS ##)    */
  258.    int       historyptr;            /* pointer into history tbl    */
  259.    int       historyflag;         /* are we backing off in history? */
  260.    int       kbdchar;            /* keyboard key-hit value    */
  261.    int       kbdmore;            /* continuation variable    */
  262.    int       i, k;            /* temporary loop counters    */
  263.    double  ftemp;            /* fp temp            */
  264.    char stacked=0;            /* flag to indicate screen stacked */
  265.  
  266.    initasmvars();            /* initialize ASM stuff */
  267.  
  268.    if (extraseg == 0        /* oops.  not enough memory */
  269.      || (history = (struct historystruct far * ) farmemalloc((unsigned long)
  270.               (MAXHISTORY * sizeof(*history)))) == NULL
  271.      || (ly0 = (long far *) farmemalloc(4096L)) == NULL) {
  272.       buzzer(2);
  273.       printf(" I'm sorry, but you don't have enough free memory \n");
  274.       printf(" to run this program.\n\n");
  275.       exit(1);
  276.       }
  277.    farmemfree((BYTE far *)ly0); /* was just to check for min space */
  278.  
  279.    dx0 = MK_FP(extraseg,0);
  280.    dy1 = (dx1 = (dy0 = dx0 + MAXPIXELS) + MAXPIXELS) + MAXPIXELS;
  281.    lx0 = (long far *) dx0;
  282.    ly1 = (lx1 = (ly0 = lx0 + MAXPIXELS) + MAXPIXELS) + MAXPIXELS;
  283.  
  284.    historyptr = 0;            /* initialize history ptr */
  285.    historyflag = 0;
  286.    history[historyptr].fractype = -1;
  287.  
  288.    load_videotable(1); /* load fractint.cfg, no message yet if bad */
  289. #ifdef XFRACT
  290.    UnixInit();
  291. #endif
  292.    init_help();
  293.  
  294. restart:                /* insert key re-starts here */
  295.  
  296.    cmdfiles(argc,argv);         /* process the command-line */
  297.    if(debugflag==450 && strcmp(savename,"fract001") != 0)
  298.    {
  299.       char name[80];
  300.       strcpy(name,savename);
  301.       strcat(name,".gif");
  302.       if(access(name,0)==0)
  303.          exit(0);
  304.    }   
  305. #ifdef XFRACT
  306.    initUnixWindow();
  307. #endif
  308.  
  309.    memcpy(olddacbox,dacbox,256*3);    /* save in case colors= present */
  310.  
  311.    if (debugflag == 8088)         cpu =    86; /* for testing purposes */
  312.    if (debugflag == 2870 && fpu >= 287 ) fpu = 287; /* for testing purposes */
  313.    if (debugflag ==  870 && fpu >=  87 ) fpu =    87; /* for testing purposes */
  314.    if (debugflag ==   70)         fpu =     0; /* for testing purposes */
  315.    if (getenv("NO87")) fpu = 0;
  316.    fract_dir1 = getenv("FRACTDIR");
  317.    if (fract_dir1==NULL) {
  318.        fract_dir1 = ".";
  319.    }
  320. #ifdef SRCDIR
  321.    fract_dir2 = SRCDIR;
  322. #else
  323.    fract_dir2 = ".";
  324. #endif
  325.    if (fpu == 0)       iit = 0;
  326.    if (fpu >= 287 && debugflag != 72)    /* Fast 287 math */
  327.       setup287code();
  328.  
  329.    /* IIT math coprocessor chip logic */
  330.    if(iit == 0 && fpu)
  331.       if(IITCoPro())
  332.          iit = 3;  /* detect iit chip */
  333.    if(iit < 0) iit = 0;  /* user wants chip turned off */
  334.    if(iit>0)
  335.    {
  336.       if(F4x4Check())
  337.          iit = 2;    /* semaphore TSR is installed */
  338.       else if(iit == 3)
  339.          iit = 0;    /* we detetct chip but no tsr - don't use */
  340.       /* else user forced iit == 1 */
  341.    }
  342.  
  343.    adapter_detect();            /* check what video is really present */
  344.    if (debugflag >= 9002 && debugflag <= 9100) /* for testing purposes */
  345.       if (video_type > (debugflag-9000)/2)     /* adjust the video value */
  346.      video_type = (debugflag-9000)/2;
  347.  
  348.    diskisactive = 0;            /* disk-video is inactive */
  349.    diskvideo = 0;            /* disk driver is not in use */
  350.    setvideotext();            /* switch to text mode */
  351.    calc_status = -1;            /* no active fractal image */
  352.    savedac = 0;             /* don't save the VGA DAC */
  353.  
  354.    if (debugflag == 10000)        /* check for free memory */
  355.       showfreemem();
  356.  
  357. #ifndef XFRACT
  358.    if (badconfig < 0)            /* fractint.cfg bad, no msg yet */
  359.       bad_fractint_cfg_msg();
  360. #endif
  361.  
  362.    max_colors = 256;                    /* the Windows version is lower */
  363.    max_kbdcount=(cpu==386) ? 80 : 30;   /* check the keyboard this often */
  364.  
  365.    if (showfile && initmode < 0) {
  366.       intro();                /* display the credits screen */
  367.       if (keypressed() == ESC) {
  368.      getakey();
  369.      goodbye();
  370.      }
  371.       }
  372.  
  373.    if (colorpreloaded)
  374.       memcpy(dacbox,olddacbox,256*3);    /* restore in case colors= present */
  375.    if (!functionpreloaded)
  376.       set_if_old_bif();
  377.    stacked = 0;
  378. restorestart:
  379.  
  380.    lookatmouse = 0;            /* ignore mouse */
  381.  
  382.    while (showfile <= 0) {        /* image is to be loaded */
  383.       char *hdg;
  384.       tabmode = 0;
  385.       if (overlay3d) {
  386.      hdg = "Select File for 3D Overlay";
  387.      helpmode = HELP3DOVLY;
  388.      }
  389.       else if (display3d) {
  390.      hdg = "Select File for 3D Transform";
  391.      helpmode = HELP3D;
  392.      }
  393.       else {
  394.      hdg = "Select File to Restore";
  395.      helpmode = HELPSAVEREST;
  396.      }
  397.       if (showfile < 0 && getafilename(hdg,gifmask,readname) < 0) {
  398.      showfile = 1;             /* cancelled */
  399.      initmode = -1;
  400.      break;
  401.      }
  402.       showfile = 0;
  403.       helpmode = -1;
  404.       tabmode = 1;
  405.       if(stacked)
  406.       {
  407.          discardscreen();
  408.          setvideotext();
  409.          stacked = 0;
  410.       }
  411.       if (read_overlay() == 0)         /* read hdr, get video mode */
  412.      break;              /* got it, exit */
  413.       showfile = -1;             /* retry */
  414.       }
  415.  
  416.    helpmode = HELPMENU;         /* now use this help mode */
  417.    tabmode = 1;
  418.    lookatmouse = 0;            /* ignore mouse */
  419.  
  420.    if ((overlay3d || stacked) && initmode < 0) {    /* overlay command failed */
  421.       unstackscreen();            /* restore the graphics screen */
  422.       stacked = 0;
  423.       overlay3d = 0;            /* forget overlays */
  424.       display3d = 0;            /* forget 3D */
  425.       if (calc_status > 0 && calc_status !=2)
  426.      calc_status = 0;
  427.       goto resumeloop;            /* ooh, this is ugly */
  428.       }
  429.  
  430.    savedac = 0;             /* don't save the VGA DAC */
  431. imagestart:                /* calc/display a new image */
  432.    if(stacked)
  433.    {
  434.       discardscreen();
  435.       stacked = 0;
  436.    }
  437. #ifdef XFRACT
  438.    usr_floatflag = 1;
  439. #endif
  440.    got_status = -1;            /* for tab_display */
  441.  
  442.    if (showfile)
  443.       if (calc_status > 0)        /* goto imagestart implies re-calc */
  444.      calc_status = 0;
  445.  
  446.    if (initbatch == 0)
  447.       lookatmouse = -PAGE_UP;        /* just mouse left button, == pgup */
  448.  
  449.    cyclelimit = initcyclelimit;     /* default cycle limit     */
  450.  
  451.    frommandel = 0;
  452.  
  453.    adapter = initmode;            /* set the video adapter up */
  454.    initmode = -1;            /* (once)            */
  455.  
  456.    while (adapter < 0) {        /* cycle through instructions */
  457.       if (initbatch) {                /* batch, nothing to do */
  458.          initbatch = 4;            /* exit with error condition set */
  459.          goodbye();
  460.       }
  461.       kbdchar = main_menu(0);
  462.       if (kbdchar == INSERT) goto restart;    /* restart pgm on Insert Key */
  463.       if (kbdchar == DELETE)            /* select video mode list */
  464.      kbdchar = select_video_mode(-1);
  465.       if ((adapter = check_vidmode_key(0,kbdchar)) >= 0)
  466.      break;                 /* got a video mode now */
  467. #ifndef XFRACT
  468.       if ('A' <= kbdchar && kbdchar <= 'Z')
  469.      kbdchar = tolower(kbdchar);
  470. #endif
  471.       if (kbdchar == 'd') {                     /* shell to DOS */
  472.      setclear();
  473.      printf("\n\nShelling to DOS - type 'exit' to return\n\n");
  474.      shell_to_dos();
  475.      goto imagestart;
  476.      }
  477. #ifndef XFRACT
  478.       if (kbdchar == '@') {                     /* execute commands */
  479. #else
  480.       if (kbdchar == F2 || kbdchar == '@') {     /* We mapped @ to F2 */
  481. #endif
  482.      if ((get_commands() & 4) == 0)
  483.         goto imagestart;
  484.      kbdchar = '3';                         /* 3d=y so fall thru '3' code */
  485.      }
  486. #ifndef XFRACT
  487.       if (kbdchar == 'r' || kbdchar == '3' || kbdchar == '#') {
  488. #else
  489.       if (kbdchar == 'r' || kbdchar == '3' || kbdchar == F3) {
  490. #endif
  491.      display3d = 0;
  492.      if (kbdchar == '3' || kbdchar == '#' || kbdchar == F3)
  493.         display3d = 1;
  494.      setvideotext(); /* switch to text mode */
  495.      showfile = -1;
  496.      goto restorestart;
  497.      }
  498.       if (kbdchar == 't') {                     /* set fractal type */
  499.          julibrot = 0;
  500.      get_fracttype();
  501.      goto imagestart;
  502.      }
  503.       if (kbdchar == 'x') {                     /* generic toggle switch */
  504.      get_toggles();
  505.      goto imagestart;
  506.      }
  507.       if (kbdchar == 'y') {                     /* generic toggle switch */
  508.      get_toggles2();
  509.      goto imagestart;
  510.      }
  511.       if (kbdchar == 'z') {                     /* type specific parms */
  512.      get_fract_params(1);
  513.      goto imagestart;
  514.      }
  515.       if (kbdchar == 'v') {                     /* view parameters */
  516.      get_view_params();
  517.      goto imagestart;
  518.      }
  519.       if (kbdchar == 'f') {                     /* floating pt toggle */
  520.      if (usr_floatflag == 0)
  521.         usr_floatflag = 1;
  522.      else
  523.         usr_floatflag = 0;
  524.      goto imagestart;
  525.      }
  526.       if (kbdchar == 'i') {                     /* set 3d fractal parms */
  527.      get_fract3d_params(); /* get the parameters */
  528.      goto imagestart;
  529.      }
  530.       if (kbdchar == 'g') {
  531.      get_cmd_string(); /* get command string */
  532.      goto imagestart;
  533.          }
  534.       /* buzzer(2); */                /* unrecognized key */
  535.       }
  536.  
  537.    zoomoff = 1;         /* zooming is enabled */
  538.    helpmode = HELPMAIN;     /* now use this help mode */
  539.  
  540.    while (1) {            /* eternal loop */
  541.  
  542.       if (calc_status != 2 || showfile == 0) {
  543. #ifdef XFRACT
  544.          if (resizeWindow()) {
  545.          calc_status = -1;
  546.      }
  547. #endif
  548.      far_memcpy((char far *)&videoentry,(char far *)&videotable[adapter],
  549.             sizeof(videoentry));
  550.      axmode  = videoentry.videomodeax; /* video mode (BIOS call)   */
  551.      bxmode  = videoentry.videomodebx; /* video mode (BIOS call)   */
  552.      cxmode  = videoentry.videomodecx; /* video mode (BIOS call)   */
  553.      dxmode  = videoentry.videomodedx; /* video mode (BIOS call)   */
  554.      dotmode = videoentry.dotmode;       /* assembler dot read/write */
  555.      xdots     = videoentry.xdots;       /* # dots across the screen */
  556.      ydots     = videoentry.ydots;       /* # dots down the screen   */
  557.      colors  = videoentry.colors;       /* # colors available */
  558.      textsafe2 = dotmode / 100;
  559.      dotmode  %= 100;
  560.      sxdots  = xdots;
  561.      sydots  = ydots;
  562.      sxoffs = syoffs = 0;
  563.  
  564.      diskvideo = 0;         /* set diskvideo flag */
  565.      if (dotmode == 11)        /* default assumption is disk */
  566.         diskvideo = 2;
  567.  
  568.      memcpy(olddacbox,dacbox,256*3); /* save the DAC */
  569.      diskisactive = 1;        /* flag for disk-video routines */
  570.  
  571.      if (overlay3d) {
  572.         unstackscreen();        /* restore old graphics image */
  573.         overlay3d = 0;
  574.         }
  575.  
  576.      else {
  577.         setvideomode(axmode,bxmode,cxmode,dxmode); /* switch video modes */
  578.         if (goodmode == 0) {
  579.            static char far msg[] = {"That video mode is not available with your adapter."};
  580.            static char far TPlusStr[] = "This video mode requires 'noninterlaced=yes'";
  581.  
  582.            if(TPlusErr) {
  583.           stopmsg(0, TPlusStr);
  584.           TPlusErr = 0;
  585.           }
  586.            else
  587.           stopmsg(0,msg);
  588.            initmode = -1;
  589.            setvideotext(); /* switch to text mode */
  590.            goto restorestart;
  591.            }
  592.  
  593.         if(Transparent3D && curfractalspecific->orbitcalc == Formula) {
  594.            char far *ErrMsg;
  595.            if((ErrMsg = TrueColorAutoDetect()) != ((char far*)0)) {
  596.           stopmsg(0, ErrMsg);
  597.           Transparent3D = 0;
  598.           }
  599.            else {
  600.           tpdepth = 0;
  601.           NewTPFractal = 1;
  602.           }
  603.            }
  604.         else if(AntiAliasing) {
  605.            if(dotmode != 11) {
  606.           static char far DiskVidError[] =
  607.             "Anti-aliasing resolution too high, try a lower value or lower\n\
  608. screen resolution.";
  609.           /* Ensure the absolute resolution is < MAXPIXELS */
  610.           if(AntiAliasing >= 8 ||
  611.              ((long)xdots << AntiAliasing) > MAXPIXELS)
  612.              goto AntiAliasError;
  613.           if(!colors)
  614.              TrueColorAutoDetect();
  615.           if(SetupShadowVideo() != 0) {
  616. AntiAliasError:
  617.              stopmsg(0, DiskVidError);
  618.              initmode = -1;
  619.              setvideotext(); /* switch to text mode */
  620.              goto restorestart;
  621.              }
  622.           }
  623.            }
  624.         }
  625.  
  626.      diskisactive = 0;        /* flag for disk-video routines */
  627.      if (savedac || colorpreloaded) {
  628.         memcpy(dacbox,olddacbox,256*3); /* restore the DAC */
  629.         spindac(0,1);
  630.         colorpreloaded = 0;
  631.         }
  632.      else { /* reset DAC to defaults, which setvideomode has done for us */
  633.         if (mapdacbox) { /* but there's a map=, so load that */
  634.            far_memcpy((char far *)dacbox,mapdacbox,768);
  635.            spindac(0,1);
  636.            }
  637.         else if ((dotmode == 11 && colors == 256) || !colors) {
  638.            /* disk video, setvideomode via bios didn't get it right, so: */
  639. #ifndef XFRACT
  640.            ValidateLuts("default"); /* read the default palette file */
  641. #endif
  642.            }
  643.         colorstate = 0;
  644.         }
  645.      if (viewwindow) {
  646.         ftemp = finalaspectratio
  647.             * (double)sydots / (double)sxdots / screenaspect;
  648.         if ((xdots = viewxdots)) { /* xdots specified */
  649.            if ((ydots = viewydots) == 0) /* calc ydots? */
  650.           ydots = (double)xdots * ftemp + 0.5;
  651.            }
  652.         else
  653.            if (finalaspectratio <= screenaspect) {
  654.           xdots = (double)sxdots / viewreduction + 0.5;
  655.           ydots = (double)xdots * ftemp + 0.5;
  656.           }
  657.            else {
  658.           ydots = (double)sydots / viewreduction + 0.5;
  659.           xdots = (double)ydots / ftemp + 0.5;
  660.           }
  661.         if (xdots > sxdots || ydots > sydots) {
  662.            static char far msg[] = {"View window too large; using full screen."};
  663.            stopmsg(0,msg);
  664.            xdots = sxdots;
  665.            ydots = sydots;
  666.            }
  667.         else if (xdots <= sxdots/20 || ydots <= sydots/20) { /* so ssg works */
  668.            static char far msg[] = {"View window too small; using full screen."};
  669.            stopmsg(0,msg);
  670.            xdots = sxdots;
  671.            ydots = sydots;
  672.            }
  673.         sxoffs = (sxdots - xdots) / 2;
  674.         syoffs = (sydots - ydots) / 3;
  675.         }
  676.      dxsize = xdots - 1;        /* convert just once now */
  677.      dysize = ydots - 1;
  678.      }
  679.       if(savedac == 0)
  680.         savedac = 2;            /* assume we save next time (except jb) */
  681.       else
  682.       savedac = 1;            /* assume we save next time */
  683.       if (initbatch == 0)
  684.      lookatmouse = -PAGE_UP;    /* mouse left button == pgup */
  685.  
  686.       if(showfile == 0) {        /* loading an image */
  687.      outln_cleanup = NULL;        /* outln routine can set this */
  688.      if (display3d)         /* set up 3D decoding */
  689.         outln = call_line3d;
  690.      else if(filetype >= 1)     /* old .tga format input file */
  691.         outln = outlin16;
  692.      else if(comparegif)        /* debug 50 */
  693.         outln = cmp_line;
  694.      else if(pot16bit) {        /* .pot format input file */
  695.         if (pot_startdisk() < 0)
  696.         {                /* pot file failed?  */
  697.            extern int potflag;
  698.  
  699.            showfile = 1;
  700.            potflag  = 0;
  701.            pot16bit = 0;
  702.            initmode = -1;
  703.            calc_status = 2;        /* "resume" without 16-bit */
  704.            setvideotext();
  705.            get_fracttype();
  706.            goto imagestart;
  707.         }
  708.         outln = pot_line;
  709.      }
  710.      else                /* regular gif/fra input file */
  711.             if(soundflag > 0)
  712.                outln = sound_line;      /* sound decoding */
  713.             else
  714.                outln = out_line;        /* regular decoding */
  715.      if(filetype == 0)
  716.      {
  717.         if(iit == 2 && usr_floatflag != 0)
  718.            if(F4x4Lock()==0)
  719.               iit = -1;  /* semaphore not free - no iit */
  720.         if(debugflag==2224)
  721.          {
  722.             char buf[80];
  723.             sprintf(buf,"iit=%d floatflag=%d",iit,usr_floatflag);
  724.             stopmsg(4,(char far *)buf);
  725.          }
  726.  
  727.         i = funny_glasses_call(gifview);
  728.         if(iit == 2)
  729.            F4x4Free();      /* unlock semaphore */
  730.         else if(iit == -1)
  731.            iit = 2;         /* semaphore operating */
  732.      }
  733.      else
  734.         i = funny_glasses_call(tgaview);
  735.      if(outln_cleanup)        /* cleanup routine defined? */
  736.         (*outln_cleanup)();
  737.      if(i == 0)
  738.         buzzer(0);
  739.      else {
  740.         calc_status = -1;
  741.         if (keypressed()) {
  742.            buzzer(1);
  743.            while (keypressed()) getakey();
  744.            texttempmsg("*** load incomplete ***");
  745.            }
  746.         }
  747.      }
  748.  
  749.       zoomoff = 1;            /* zooming is enabled */
  750.       if (dotmode == 11 || (curfractalspecific->flags&NOZOOM) != 0)
  751.      zoomoff = 0;            /* for these cases disable zooming */
  752.  
  753.       calcfracinit();
  754. #ifdef XFRACT
  755.       schedulealarm(1);
  756. #endif
  757.  
  758.       sxmin = xxmin; /* save 3 corners for zoom.c ref points */
  759.       sxmax = xxmax;
  760.       sx3rd = xx3rd;
  761.       symin = yymin;
  762.       symax = yymax;
  763.       sy3rd = yy3rd;
  764.  
  765.       if (history[0].fractype == -1)    /* initialize the history file */
  766.      for (i = 0; i < MAXHISTORY; i++) {
  767.         int j;
  768.         history[i].xxmax = xxmax;
  769.         history[i].xxmin = xxmin;
  770.         history[i].yymax = yymax;
  771.         history[i].yymin = yymin;
  772.         history[i].xx3rd = xx3rd;
  773.         history[i].yy3rd = yy3rd;
  774.         for(j=0;j<MAXPARAMS;j++)
  775.            history[i].param[j] = param[j];
  776.         history[i].fractype = fractype;
  777.         }
  778.  
  779.       if ( history[historyptr].xxmax != xxmax  || /* save any (new) zoom data */
  780.        history[historyptr].xxmin != xxmin  ||
  781.        history[historyptr].yymax != yymax  ||
  782.        history[historyptr].yymin != yymin  ||
  783.        history[historyptr].xx3rd != xx3rd  ||
  784.        history[historyptr].yy3rd != yy3rd  ||
  785.        history[historyptr].param[0] != param[0] ||
  786.        history[historyptr].param[1] != param[1] ||
  787.        history[historyptr].param[2] != param[2] ||
  788.        history[historyptr].param[3] != param[3] ||
  789.        history[historyptr].param[4] != param[4] ||
  790.        history[historyptr].param[5] != param[5] ||
  791.        history[historyptr].param[6] != param[6] ||
  792.        history[historyptr].param[7] != param[7] ||
  793.        history[historyptr].param[8] != param[8] ||
  794.        history[historyptr].param[9] != param[9] ||
  795.        history[historyptr].fractype != fractype) {
  796.            int j;
  797.      if (historyflag == 0) /* if we're not backing off for <\> */
  798.         if (++historyptr == MAXHISTORY) historyptr = 0;
  799.      history[historyptr].xxmax = xxmax;
  800.      history[historyptr].xxmin = xxmin;
  801.      history[historyptr].yymax = yymax;
  802.      history[historyptr].yymin = yymin;
  803.      history[historyptr].xx3rd = xx3rd;
  804.      history[historyptr].yy3rd = yy3rd;
  805.          for(j=0;j<MAXPARAMS;j++)
  806.             history[historyptr].param[j] = param[j];
  807.      history[historyptr].fractype = fractype;
  808.      }
  809.       historyflag = 0;
  810.  
  811.       if (display3d || showfile) {    /* paranoia: these vars don't get set */
  812.      save_system  = active_system;    /*   unless really doing some work,   */
  813.      }                /*   so simple <r> + <s> keeps number */
  814.  
  815.       if(showfile == 0) {        /* image has been loaded */
  816.      showfile = 1;
  817.      if (initbatch == 1 && calc_status == 2)
  818.         initbatch = -1; /* flag to finish calc before save */
  819.      if (loaded3d)        /* 'r' of image created with '3' */
  820.         display3d = 1;  /* so set flag for 'b' command */
  821.      }
  822.       else {                /* draw an image */
  823.      diskisactive = 1;        /* flag for disk-video routines */
  824.      if (initsavetime != 0        /* autosave and resumable? */
  825.        && (curfractalspecific->flags&NORESUME) == 0) {
  826.         savebase = readticker(); /* calc's start time */
  827.         saveticks = (long)initsavetime * 1092; /* bios ticks/minute */
  828.         if ((saveticks & 65535L) == 0)
  829.            ++saveticks; /* make low word nonzero */
  830.         finishrow = -1;
  831.         }
  832.  
  833.      if(Transparent3D && curfractalspecific->orbitcalc == Formula)
  834.         i = Transp3DFnct();
  835.      else {
  836.         i = calcfract();    /* draw the fractal using "C" */
  837.         if(AntiAliasing && i == 0)
  838.            AntiAliasPass();
  839.         }
  840.      if (i == 0)
  841.         buzzer(0); /* finished!! */
  842.  
  843.      saveticks = 0;         /* turn off autosave timer */
  844.      if (dotmode == 11 && i == 0) /* disk-video */
  845.         dvid_status(0,"Image has been completed");
  846.      diskisactive = 0;        /* flag for disk-video routines */
  847.      }
  848.  
  849. #ifndef XFRACT
  850.       boxcount = 0;            /* no zoom box yet  */
  851.       zwidth = 0;
  852. #else
  853.       if (!XZoomWaiting) {
  854.       boxcount = 0;            /* no zoom box yet  */
  855.       zwidth = 0;
  856.       }
  857. #endif
  858.  
  859.       if (fractype == PLASMA && cpu > 88) {
  860.      cyclelimit = 256;        /* plasma clouds need quick spins */
  861.      daccount = 256;
  862.      daclearn = 1;
  863.      }
  864.  
  865. resumeloop:                /* return here on failed overlays */
  866.  
  867.       kbdmore = 1;
  868.       while (kbdmore == 1) {        /* loop through command keys */
  869.  
  870.      if (timedsave != 0) {
  871.         if (timedsave == 1) {    /* woke up for timed save */
  872.            getakey();     /* eat the dummy char */
  873.            kbdchar = 's'; /* do the save */
  874.            resave_flag = 1;
  875.            timedsave = 2;
  876.            }
  877.         else {            /* save done, resume */
  878.            timedsave = 0;
  879.            resave_flag = 2;
  880.            kbdchar = ENTER;
  881.            }
  882.         }
  883.      else if (initbatch == 0) {    /* not batch mode */
  884.         lookatmouse = (zwidth == 0) ? -PAGE_UP : 3;
  885.         if (calc_status == 2 && zwidth == 0 && !keypressed()) {
  886.            kbdchar = ENTER;        /* no visible reason to stop, continue */
  887.         } else {            /* wait for a real keystroke */
  888. #ifndef XFRACT
  889.                while (!keypressed()) { }  /* enables help */
  890. #else
  891.                waitkeypressed(0);
  892. #endif
  893.            kbdchar = getakey();
  894.            if (kbdchar == ESC || kbdchar == 'm' || kbdchar == 'M') {
  895.                   if (kbdchar == ESC && escape_exit != 0)
  896.                       /* don't ask, just get out */
  897.                       goodbye();
  898.           stackscreen();
  899. #ifndef XFRACT
  900.           kbdchar = main_menu(1);
  901. #else
  902.                   if (XZoomWaiting) {
  903.               kbdchar = ENTER;
  904.           } else {
  905.               kbdchar = main_menu(1);
  906.               if (XZoomWaiting) {
  907.               kbdchar = ENTER;
  908.               }
  909.           }
  910. #endif
  911.           if (kbdchar == '\\'
  912.             || check_vidmode_key(0,kbdchar) >= 0)
  913.              discardscreen();
  914.           else if (kbdchar == 'x' || kbdchar == 'y' ||
  915.                    kbdchar == 'z' || kbdchar == 'g' ) 
  916.              fromtext_flag = 1;
  917.           else
  918.              unstackscreen();
  919.           }
  920.            }
  921.         }
  922.      else {             /* batch mode, fake next keystroke */
  923.         if (initbatch == -1) {    /* finish calc */
  924.            kbdchar = ENTER;
  925.            initbatch = 1;
  926.            }
  927.         else if (initbatch == 1 || initbatch == 4 ) {    /* save-to-disk */
  928. /*
  929.            while(keypressed())
  930.          getakey();
  931. */
  932.            if (debugflag == 50)
  933.           kbdchar = 'r';
  934.            else
  935.           kbdchar = 's';
  936.            if(initbatch == 1) initbatch = 2;
  937.            if(initbatch == 4) initbatch = 5;
  938.            }
  939.         else {
  940.            if(calc_status != 4) initbatch = 3; /* bailout with error */
  941.            goodbye();        /* done, exit */
  942.            }
  943.         }
  944.  
  945. #ifndef XFRACT
  946.          if ('A' <= kbdchar && kbdchar <= 'Z')
  947.             kbdchar = tolower(kbdchar);
  948. #endif
  949.      switch (kbdchar) {
  950.         int x,y,v;
  951.         case 't':                   /* new fractal type             */
  952.            julibrot = 0;
  953.            clear_zoombox();
  954.            stackscreen();
  955.            if ((i = get_fracttype()) >= 0) {
  956.           discardscreen();
  957.           savedac = 0;
  958.           if (i == 0) {
  959.              initmode = adapter;
  960.              frommandel = 0;
  961.              }
  962.           else
  963.              if (initmode < 0)    /* it is supposed to be... */
  964.             setvideotext(); /* reset to text mode       */
  965.           goto imagestart;
  966.           }
  967.            unstackscreen();
  968.            break;
  969.         case 24:                    /* Ctl-X, Ctl-Y, CTL-Z do flipping */
  970.         case 25:
  971.         case 26:
  972.            flip_image(kbdchar);
  973.            break;
  974.         case 'x':                   /* invoke options screen        */
  975.         case 'y':
  976.         case 'z':                   /* type specific parms */
  977.         case 'g':
  978.            if (fromtext_flag == 1)
  979.                fromtext_flag = 0;
  980.            else
  981.                stackscreen();
  982.            if (kbdchar == 'x')
  983.           i = get_toggles();
  984.            else if (kbdchar == 'y')
  985.           i = get_toggles2();
  986.            else if (kbdchar =='z')
  987.           i = get_fract_params(1);
  988.                else
  989.                   i = get_cmd_string();
  990.            if (i > 0) {        /* time to redraw? */
  991.           discardscreen();
  992.           kbdmore = calc_status = 0;
  993.           }
  994.            else
  995.           unstackscreen();
  996.            break;
  997. #ifndef XFRACT
  998.         case '@':                   /* execute commands */
  999. #else
  1000.         case F2:                   /* execute commands */
  1001. #endif
  1002.            stackscreen();
  1003.            i = get_commands();
  1004.            if (initmode != -1) {    /* video= was specified */
  1005.           adapter = initmode;
  1006.           initmode = -1;
  1007.           i |= 1;
  1008.           savedac = 0;
  1009.           }
  1010.            else if (colorpreloaded) { /* colors= was specified */
  1011.           spindac(0,1);
  1012.           colorpreloaded = 0;
  1013.           }
  1014.            else if ((i & 8))    /* reset was specified */
  1015.           savedac = 0;
  1016.            if ((i & 4)) {        /* 3d = was specified */
  1017.           kbdchar = '3';
  1018.           unstackscreen();
  1019.           goto do_3d_transform; /* pretend '3' was keyed */
  1020.           }
  1021.            if ((i & 1)) {        /* fractal parameter changed */
  1022.           discardscreen();
  1023.           if(!functionpreloaded)
  1024.             set_if_old_bif(); /* old bifs need function set, JCO 7/5/92 */
  1025.           if(fractype==MANDELTRIG && usr_floatflag==1
  1026.              && save_release < 1800 && bailout == 0)
  1027.             bailout = 2500;
  1028.           if(fractype==LAMBDATRIG && usr_floatflag==1
  1029.              && save_release < 1800 && bailout == 0)
  1030.             bailout = 2500;
  1031.           kbdmore = calc_status = 0;
  1032.           }
  1033.            else
  1034.           unstackscreen();
  1035.            break;
  1036.         case 'v':                   /* invoke options screen        */
  1037.            i = get_view_params();    /* get the parameters */
  1038.            if (i > 0)        /* time to redraw? */
  1039.           kbdmore = calc_status = 0;
  1040.            break;
  1041.         case 'f':                   /* floating pt toggle           */
  1042.            if (usr_floatflag == 0)
  1043.           usr_floatflag = 1;
  1044.            else
  1045.           usr_floatflag = 0;
  1046.            initmode = adapter;
  1047.            goto imagestart;
  1048.         case 'i':                   /* 3d fractal parms */
  1049.            if (get_fract3d_params() >= 0) /* get the parameters */
  1050.           calc_status = kbdmore = 0;  /* time to redraw */
  1051.            break;
  1052.         case 'a':                  /* starfield parms               */
  1053.            clear_zoombox();
  1054.            if (get_starfield_params() >= 0) {
  1055.               if (starfield() >= 0)
  1056.              calc_status = 0;
  1057.           continue;
  1058.           }
  1059.            break;
  1060.         case 15:   /* ctrl-o */
  1061.         case 'o':
  1062.             /* must use standard fractal and have a float variant */
  1063.             if(fractalspecific[fractype].calctype == StandardFractal &&
  1064.                (fractalspecific[fractype].isinteger == 0 ||
  1065.                 fractalspecific[fractype].tofloat != NOFRACTAL))
  1066.             {
  1067.                clear_zoombox();
  1068.                Jiim(ORBIT);
  1069.             }
  1070.             break;
  1071.         case SPACE:               /* spacebar, toggle mand/julia    */
  1072.         if (fractype == CELLULAR) {
  1073.             if(nxtscreenflag)
  1074.               nxtscreenflag = 0; /* toggle flag to stop generation */
  1075.             else
  1076.               nxtscreenflag = 1; /* toggle flag to generate next screen */
  1077.             calc_status = 2;
  1078.             kbdmore = 0;
  1079.         }
  1080.         else {
  1081.            if (curfractalspecific->tojulia != NOFRACTAL
  1082.          && param[0] == 0.0 && param[1] == 0.0) {
  1083.           /* switch to corresponding Julia set */
  1084.          if(1)
  1085.          {
  1086.              int key;
  1087.               if(fractype==MANDEL || fractype==MANDELFP)
  1088.                  hasinverse=1;
  1089.               else
  1090.                  hasinverse=0;
  1091.              clear_zoombox();
  1092.              Jiim(JIIM);
  1093.              key = getakey(); /* flush keyboard buffer */
  1094.              if(key != SPACE)
  1095.              {
  1096.                 ungetakey(key);
  1097.                 break;
  1098.              }
  1099.           }
  1100.           fractype = curfractalspecific->tojulia;
  1101.           curfractalspecific = &fractalspecific[fractype];
  1102.           if(xcjul == BIG || ycjul == BIG)
  1103.           {
  1104.                 param[0] = (xxmax + xxmin) / 2;
  1105.              param[1] = (yymax + yymin) / 2;
  1106.           }
  1107.           else
  1108.           {
  1109.                 param[0] = xcjul;
  1110.              param[1] = ycjul;
  1111.              xcjul = ycjul = BIG;
  1112.           }
  1113.           jxxmin = sxmin; jxxmax = sxmax;
  1114.           jyymax = symax; jyymin = symin;
  1115.           jxx3rd = sx3rd; jyy3rd = sy3rd;
  1116.           frommandel = 1 ;
  1117.           xxmin = curfractalspecific->xmin;
  1118.           xxmax = curfractalspecific->xmax;
  1119.           yymin = curfractalspecific->ymin;
  1120.           yymax = curfractalspecific->ymax;
  1121.           xx3rd = xxmin;
  1122.           yy3rd = yymin;
  1123.           if (usr_distest == 0 && usr_biomorph != -1 && bitshift != 29) {
  1124.              xxmin *= 3.0;
  1125.              xxmax *= 3.0;
  1126.              yymin *= 3.0;
  1127.              yymax *= 3.0;
  1128.              xx3rd *= 3.0;
  1129.              yy3rd *= 3.0;
  1130.              }
  1131.           zoomoff = 1;
  1132.           calc_status = 0;
  1133.           kbdmore = 0;
  1134.           }
  1135.            else if (curfractalspecific->tomandel != NOFRACTAL) {
  1136.           /* switch to corresponding Mandel set */
  1137.           fractype = curfractalspecific->tomandel;
  1138.           curfractalspecific = &fractalspecific[fractype];
  1139.           if (frommandel) {
  1140.              xxmin = jxxmin;  xxmax = jxxmax;
  1141.              yymin = jyymin;  yymax = jyymax;
  1142.              xx3rd = jxx3rd;  yy3rd = jyy3rd;
  1143.              }
  1144.           else {
  1145.              double ccreal,ccimag;
  1146.              ccreal = (curfractalspecific->xmax - curfractalspecific->xmin) / 2;
  1147.              ccimag = (curfractalspecific->ymax - curfractalspecific->ymin) / 2;
  1148.              xxmin = xx3rd = param[0] - ccreal;
  1149.              xxmax = param[0] + ccreal;
  1150.              yymin = yy3rd = param[1] - ccimag;
  1151.              yymax = param[1] + ccimag;
  1152.              }
  1153.           param[0] = 0;
  1154.           param[1] = 0;
  1155.           zoomoff = 1;
  1156.           calc_status = 0;
  1157.           kbdmore = 0;
  1158.           }
  1159.            else
  1160.           buzzer(2); /* can't switch */
  1161.            } /* end of else for if == cellular */
  1162.            break;
  1163.         case 'j':                 /* inverse julia toggle */
  1164.            /* if the inverse types proliferate, something more elegant will
  1165.               be needed */
  1166.            if(fractype==JULIA || fractype==JULIAFP || fractype==INVERSEJULIA)
  1167.            {
  1168.               static int oldtype = -1;
  1169.               if(fractype==JULIA || fractype==JULIAFP)
  1170.               {
  1171.                  oldtype=fractype;
  1172.                  fractype=INVERSEJULIA;
  1173.               }
  1174.               else if(fractype==INVERSEJULIA)
  1175.               {
  1176.                  if(oldtype != -1)
  1177.                     fractype=oldtype;
  1178.                  else
  1179.                     fractype=JULIA;
  1180.               }
  1181.              curfractalspecific = &fractalspecific[fractype];
  1182.              zoomoff = 1;
  1183.              calc_status = 0;
  1184.              kbdmore = 0;
  1185.           }
  1186. #if 0
  1187.           else if(fractype==MANDEL || fractype==MANDELFP)
  1188.           {
  1189.             clear_zoombox();
  1190.             Jiim(JIIM);
  1191.             }
  1192. #endif
  1193.           else
  1194.           buzzer(2);
  1195.            break;
  1196.         case '\\':                 /* return to prev image    */
  1197.            if (--historyptr < 0)
  1198.           historyptr = MAXHISTORY-1;
  1199.            xxmax  = history[historyptr].xxmax;
  1200.            xxmin  = history[historyptr].xxmin;
  1201.            yymax  = history[historyptr].yymax;
  1202.            yymin  = history[historyptr].yymin;
  1203.            xx3rd  = history[historyptr].xx3rd;
  1204.            yy3rd  = history[historyptr].yy3rd;
  1205.            {
  1206.               int j;
  1207.               for(j=0;j<MAXPARAMS;j++)
  1208.                     param[j] = history[historyptr].param[j];
  1209.                }
  1210.            fractype = history[historyptr].fractype;
  1211.            curfractalspecific = &fractalspecific[fractype];
  1212.            zoomoff = 1;
  1213.            initmode = adapter;
  1214.            if (curfractalspecific->isinteger != 0 &&
  1215.            curfractalspecific->tofloat != NOFRACTAL)
  1216.           usr_floatflag = 0;
  1217.            if (curfractalspecific->isinteger == 0 &&
  1218.            curfractalspecific->tofloat != NOFRACTAL)
  1219.           usr_floatflag = 1;
  1220.            historyflag = 1; /* avoid re-store parms due to rounding errs */
  1221.            goto imagestart;
  1222.         case 'd':                   /* shell to MS-DOS              */
  1223.            stackscreen();
  1224. #ifndef XFRACT
  1225.            if (axmode == 0 || axmode > 7) {
  1226. static char far dosmsg[]={"\
  1227. Note:  Your graphics image is still squirreled away in your video\n\
  1228. adapter's memory.  Switching video modes will clobber part of that\n\
  1229. image.  Sorry - it's the best we could do."};
  1230.           putstring(0,0,7,dosmsg);
  1231.           movecursor(6,0);
  1232.           }
  1233. #endif
  1234.            shell_to_dos();
  1235.            unstackscreen();
  1236. /*           calc_status = 0; */
  1237.            break;
  1238.         case 'c':                   /* switch to color cycling      */
  1239.         case '+':                   /* rotate palette               */
  1240.         case '-':                   /* rotate palette               */
  1241.            clear_zoombox();
  1242.            memcpy(olddacbox,dacbox,256*3);
  1243.            rotate((kbdchar == 'c') ? 0 : ((kbdchar == '+') ? 1 : -1));
  1244.            if (memcmp(olddacbox,dacbox,256*3))
  1245.           colorstate = 1;
  1246.            continue;
  1247.         case 'e':                   /* switch to color editing      */
  1248.            clear_zoombox();
  1249.            if (dacbox[0][0] != 255 && !reallyega && colors >= 16
  1250.          && dotmode != 11) {
  1251.           int oldhelpmode;
  1252.           oldhelpmode = helpmode;
  1253.           memcpy(olddacbox,dacbox,256*3);
  1254.           helpmode = HELPXHAIR;
  1255.           EditPalette();
  1256.           helpmode = oldhelpmode;
  1257.           if (memcmp(olddacbox,dacbox,256*3))
  1258.              colorstate = 1;
  1259.           }
  1260.            continue;
  1261.         case 's':                   /* save-to-disk                 */
  1262.            diskisactive = 1;    /* flag for disk-video routines */
  1263.            note_zoom();
  1264.            savetodisk(savename);
  1265.            restore_zoom();
  1266.            diskisactive = 0;    /* flag for disk-video routines */
  1267.            continue;
  1268.         case '#':                   /* 3D overlay                   */
  1269. #ifdef XFRACT
  1270.         case F3:                   /* 3D overlay                   */
  1271. #endif
  1272.            clear_zoombox();
  1273.            overlay3d = 1;
  1274.         case '3':                   /* restore-from (3d)            */
  1275. do_3d_transform:
  1276.            if(overlay3d)    
  1277.               display3d = 2;    /* for <b> command         */
  1278.            else   
  1279.            display3d = 1;
  1280.         case 'r':                   /* restore-from                 */
  1281.            comparegif = 0;
  1282.            frommandel = 0;
  1283.            if(kbdchar == 'r')  {
  1284.           if(debugflag == 50) {
  1285.              comparegif = overlay3d = 1;
  1286.              if (initbatch == 2) {
  1287.             stackscreen(); /* save graphics image */
  1288.             strcpy(readname,savename);
  1289.             showfile = 0;
  1290.             goto restorestart;
  1291.             }
  1292.              }
  1293.           else
  1294.              comparegif = overlay3d = 0;
  1295.           display3d = 0;
  1296.           }
  1297.            stackscreen(); /* save graphics image */
  1298.         if (overlay3d)
  1299.               stacked = 0;
  1300.             else
  1301.               stacked = 1;
  1302.            if (resave_flag) {
  1303.           updatesavename(savename); /* do the pending increment */
  1304.           resave_flag = started_resaves = 0;
  1305.           }
  1306.            showfile = -1;
  1307.            goto restorestart;
  1308.         case 'b':                   /* make batch file              */
  1309.            make_batch_file();
  1310.            break;
  1311.         case 'p':                   /* print current image          */
  1312.            note_zoom();
  1313.            Print_Screen();
  1314.            restore_zoom();
  1315.            if (!keypressed())
  1316.           buzzer(0);
  1317.            else {
  1318.           buzzer(1);
  1319.           getakey();
  1320.           }
  1321.            continue;
  1322.             case ENTER:                 /* Enter                        */
  1323.             case ENTER_2:               /* Numeric-Keypad Enter         */
  1324. #ifdef XFRACT
  1325.                XZoomWaiting = 0;
  1326. #endif
  1327.            if (zwidth != 0.0) {    /* do a zoom */
  1328.           init_pan_or_recalc(0);
  1329.           kbdmore = 0;
  1330.           }
  1331.            if (calc_status != 4)    /* don't restart if image complete */
  1332.           kbdmore = 0;
  1333.            break;
  1334.             case CTL_ENTER:             /* control-Enter                */
  1335.             case CTL_ENTER_2:           /* Control-Keypad Enter         */
  1336.            init_pan_or_recalc(1);
  1337.            kbdmore = 0;
  1338.            zoomout(); /* calc corners for zooming out */
  1339.            break;
  1340.             case INSERT:                /* insert                       */
  1341.            setvideotext(); /* force text mode */
  1342.            goto restart;
  1343.             case LEFT_ARROW:            /* cursor left                  */
  1344.             case RIGHT_ARROW:           /* cursor right                 */
  1345.             case UP_ARROW:              /* cursor up                    */
  1346.             case DOWN_ARROW:            /* cursor down                  */
  1347.             case LEFT_ARROW_2:          /* Ctrl-cursor left             */
  1348.             case RIGHT_ARROW_2:         /* Ctrl-cursor right            */
  1349.             case UP_ARROW_2:            /* Ctrl-cursor up               */
  1350.             case DOWN_ARROW_2:          /* Ctrl-cursor down             */
  1351.            move_zoombox(kbdchar);
  1352.            break;
  1353.             case CTL_HOME:              /* Ctrl-home                    */
  1354.            if (boxcount && (curfractalspecific->flags&NOROTATE) == 0) {
  1355.                   i = key_count(CTL_HOME);
  1356.           if ((zskew -= 0.02*i) < -0.48)
  1357.              zskew = -0.48;
  1358.           }
  1359.            break;
  1360.             case CTL_END:               /* Ctrl-end                     */
  1361.                if (boxcount && (curfractalspecific->flags&NOROTATE) == 0) {
  1362.                   i = key_count(CTL_END);
  1363.           if ((zskew += 0.02*i) > 0.48)
  1364.              zskew = 0.48;
  1365.           }
  1366.            break;
  1367.             case CTL_PAGE_UP:           /* Ctrl-pgup                    */
  1368.                if (boxcount)
  1369.                   chgboxi(0,-2*key_count(CTL_PAGE_UP));
  1370.                break;
  1371.             case CTL_PAGE_DOWN:         /* Ctrl-pgdn                    */
  1372.                if (boxcount)
  1373.                   chgboxi(0,2*key_count(CTL_PAGE_DOWN));
  1374.                break;
  1375.             case PAGE_UP:               /* page up                      */
  1376.            if (zoomoff == 1)
  1377.           if (zwidth == 0) { /* start zoombox */
  1378.              zwidth = zdepth = 1;
  1379.              zrotate = zskew = 0;
  1380.              zbx = zby = 0;
  1381.              find_special_colors();
  1382.              boxcolor = color_bright;
  1383.              }
  1384.           else
  1385.                      resizebox(0-key_count(PAGE_UP));
  1386.                break;
  1387.             case PAGE_DOWN:             /* page down                    */
  1388.            if (boxcount) {
  1389.           if (zwidth >= .999 && zdepth >= 0.999) /* end zoombox */
  1390.              zwidth = 0;
  1391.           else
  1392.                      resizebox(key_count(PAGE_DOWN));
  1393.                   }
  1394.                break;
  1395.             case CTL_MINUS:             /* Ctrl-kpad-                  */
  1396.                if (boxcount && (curfractalspecific->flags&NOROTATE) == 0)
  1397.                   zrotate += key_count(CTL_MINUS);
  1398.                break;
  1399.             case CTL_PLUS:              /* Ctrl-kpad+               */
  1400.                if (boxcount && (curfractalspecific->flags&NOROTATE) == 0)
  1401.                   zrotate -= key_count(CTL_PLUS);
  1402.                break;
  1403.             case CTL_INSERT:            /* Ctrl-ins                 */
  1404.                boxcolor += key_count(CTL_INSERT);
  1405.                break;
  1406.             case CTL_DEL:               /* Ctrl-del                 */
  1407.                boxcolor -= key_count(CTL_DEL);
  1408.            break;
  1409.         case DELETE:        /* select video mode from list */
  1410.            stackscreen();
  1411.            kbdchar = select_video_mode(adapter);
  1412.            if (check_vidmode_key(0,kbdchar) >= 0) /* picked a new mode? */
  1413.           discardscreen();
  1414.            else
  1415.           unstackscreen();
  1416.            /* fall through */
  1417.         default:            /* other (maybe a valid Fn key) */
  1418.            if ((k = check_vidmode_key(0,kbdchar)) >= 0) {
  1419.           adapter = k;
  1420. /*          if (videotable[adapter].dotmode != 11       Took out so that */
  1421. /*            || videotable[adapter].colors != colors)  DAC is not reset */
  1422. /*             savedac = 0;                    when changing video modes */
  1423.           calc_status = 0;
  1424.           kbdmore = 0;
  1425.           continue;
  1426.           }
  1427.            break;
  1428.  
  1429.         } /* end of the big switch */
  1430.  
  1431.      if (zoomoff == 1 && kbdmore == 1) /* draw/clear a zoom box? */
  1432.         drawbox(1);
  1433. #ifdef XFRACT
  1434.      if (resizeWindow()) {
  1435.          calc_status = -1;
  1436.      }
  1437. #endif
  1438.      }
  1439.       }
  1440.  
  1441. }
  1442.  
  1443. /* read keystrokes while = specified key, return 1+count;    */
  1444. /* used to catch up when moving zoombox is slower than keyboard */
  1445. int key_count(int keynum)
  1446. {  int ctr;
  1447.    ctr = 1;
  1448.    while (keypressed() == keynum) {
  1449.       getakey();
  1450.       ++ctr;
  1451.       }
  1452.    return ctr;
  1453. }
  1454.  
  1455. /* do all pending movement at once for smooth mouse diagonal moves */
  1456. static void move_zoombox(int keynum)
  1457. {  int vertical, horizontal, getmore;
  1458.    if (boxcount == 0)
  1459.       return;
  1460.    vertical = horizontal = 0;
  1461.    getmore = 1;
  1462.    while (getmore) {
  1463.       switch (keynum) {
  1464.          case LEFT_ARROW:               /* cursor left */
  1465.             --horizontal;
  1466.             break;
  1467.          case RIGHT_ARROW:              /* cursor right */
  1468.             ++horizontal;
  1469.             break;
  1470.          case UP_ARROW:                 /* cursor up */
  1471.             --vertical;
  1472.             break;
  1473.          case DOWN_ARROW:               /* cursor down */
  1474.             ++vertical;
  1475.             break;
  1476.          case LEFT_ARROW_2:             /* Ctrl-cursor left */
  1477.             horizontal -= 5;
  1478.             break;
  1479.          case RIGHT_ARROW_2:             /* Ctrl-cursor right */
  1480.             horizontal += 5;
  1481.             break;
  1482.          case UP_ARROW_2:               /* Ctrl-cursor up */
  1483.             vertical -= 5;
  1484.             break;
  1485.          case DOWN_ARROW_2:             /* Ctrl-cursor down */
  1486.         vertical += 5;
  1487.         break;
  1488.      default:
  1489.         getmore = 0;
  1490.      }
  1491.       if (getmore) {
  1492.      if (getmore == 2)        /* eat last key used */
  1493.         getakey();
  1494.      getmore = 2;
  1495.      keynum = keypressed();     /* next pending key */
  1496.      }
  1497.       }
  1498.    if (horizontal!=0)
  1499.       moveboxf((double)horizontal/dxsize,0.0);
  1500.    if (vertical!=0)
  1501.       moveboxf(0.0,(double)vertical/dysize);
  1502. }
  1503.  
  1504. /* displays differences between current image file and new image */
  1505. static FILE *cmp_fp;
  1506. static errcount;
  1507. int cmp_line(BYTE *pixels, int linelen)
  1508. {
  1509.    extern int rowcount;
  1510.    int row,col;
  1511.    int oldcolor;
  1512.    if((row = rowcount++) == 0) {
  1513.       errcount = 0;
  1514.       cmp_fp = fopen("cmperr",(initbatch)?"a":"w");
  1515.       outln_cleanup = cmp_line_cleanup;
  1516.       }
  1517.    if(pot16bit) { /* 16 bit info, ignore odd numbered rows */
  1518.       if((row & 1) != 0) return(0);
  1519.       row >>= 1;
  1520.       }
  1521.    for(col=0;col<linelen;col++) {
  1522.       oldcolor=getcolor(col,row);
  1523.       if(oldcolor==pixels[col])
  1524.      putcolor(col,row,0);
  1525.       else {
  1526.      if(oldcolor==0)
  1527.         putcolor(col,row,1);
  1528.      ++errcount;
  1529.      if(initbatch == 0)
  1530.         fprintf(cmp_fp,"#%5d col %3d row %3d old %3d new %3d\n",
  1531.            errcount,col,row,oldcolor,pixels[col]);
  1532.      }
  1533.       }
  1534.    return(0);
  1535. }
  1536.  
  1537. static void cmp_line_cleanup()
  1538. {
  1539.    char *timestring;
  1540.    time_t ltime;
  1541.    if(initbatch) {
  1542.       time(<ime);
  1543.       timestring = ctime(<ime);
  1544.       timestring[24] = 0; /*clobber newline in time string */
  1545.       fprintf(cmp_fp,"%s compare to %s has %5d errs\n",
  1546.              timestring,readname,errcount);
  1547.       }
  1548.    fclose(cmp_fp);
  1549. }
  1550.  
  1551. int pot_line(BYTE *pixels, int linelen)
  1552. {
  1553.    extern int rowcount;
  1554.    int row,col,saverowcount;
  1555.    if (rowcount == 0)
  1556.       if (pot_startdisk() < 0)
  1557.      return -1;
  1558.    saverowcount = rowcount;
  1559.    row = (rowcount >>= 1);
  1560.    if ((saverowcount & 1) != 0) /* odd line */
  1561.       row += ydots;
  1562.    else             /* even line */
  1563.       if (dotmode != 11) /* display the line too */
  1564.      out_line(pixels,linelen);
  1565.    for (col = 0; col < xdots; ++col)
  1566.       writedisk(col+sxoffs,row+syoffs,*(pixels+col));
  1567.    rowcount = saverowcount + 1;
  1568.    return(0);
  1569. }
  1570.  
  1571. static int call_line3d(BYTE *pixels, int linelen)
  1572. {
  1573.    /* this routine exists because line3d might be in an overlay */
  1574.    return(line3d(pixels,linelen));
  1575. }
  1576.  
  1577.  
  1578. void clear_zoombox()
  1579. {
  1580.    zwidth = 0;
  1581.    drawbox(0);
  1582.    reset_zoom_corners();
  1583. }
  1584.  
  1585. void reset_zoom_corners()
  1586. {
  1587.    xxmin = sxmin;
  1588.    xxmax = sxmax;
  1589.    xx3rd = sx3rd;
  1590.    yymax = symax;
  1591.    yymin = symin;
  1592.    yy3rd = sy3rd;
  1593. }
  1594.  
  1595. static char far *savezoom;
  1596. extern int boxcount;
  1597. extern char boxx[],boxy[];
  1598. extern char boxvalues[];
  1599.  
  1600. static void note_zoom()
  1601. {
  1602.    if (boxcount) { /* save zoombox stuff in far mem before encode (mem reused) */
  1603.       if ((savezoom = farmemalloc((long)(5*boxcount))) == NULL)
  1604.      clear_zoombox(); /* not enuf mem so clear the box */
  1605.       else {
  1606.      reset_zoom_corners(); /* reset these to overall image, not box */
  1607.      far_memcpy(savezoom,boxx,boxcount*2);
  1608.      far_memcpy(savezoom+boxcount*2,boxy,boxcount*2);
  1609.      far_memcpy(savezoom+boxcount*4,boxvalues,boxcount);
  1610.      }
  1611.       }
  1612. }
  1613.  
  1614. static void restore_zoom()
  1615. {
  1616.    if (boxcount) { /* restore zoombox arrays */
  1617.       far_memcpy(boxx,savezoom,boxcount*2);
  1618.       far_memcpy(boxy,savezoom+boxcount*2,boxcount*2);
  1619.       far_memcpy(boxvalues,savezoom+boxcount*4,boxcount);
  1620.       farmemfree(savezoom);
  1621.       drawbox(1); /* get the xxmin etc variables recalc'd by redisplaying */
  1622.       }
  1623. }
  1624.  
  1625.  
  1626. /*
  1627.    Function setup287code is called by main() when a 287
  1628.    or better fpu is detected.
  1629. */
  1630. #define ORBPTR(x) fractalspecific[x].orbitcalc
  1631. static void setup287code()
  1632. {
  1633.    ORBPTR(MANDELFP)      = ORBPTR(JULIAFP)     = FJuliafpFractal;
  1634.    ORBPTR(BARNSLEYM1FP)   = ORBPTR(BARNSLEYJ1FP) = FBarnsley1FPFractal;
  1635.    ORBPTR(BARNSLEYM2FP)   = ORBPTR(BARNSLEYJ2FP) = FBarnsley2FPFractal;
  1636.    ORBPTR(MANOWARFP)      = ORBPTR(MANOWARJFP)     = FManOWarfpFractal;
  1637.    ORBPTR(MANDELLAMBDAFP) = ORBPTR(LAMBDAFP)     = FLambdaFPFractal;
  1638. }
  1639.  
  1640. int sound_line(pixels, linelen)
  1641. BYTE *pixels;
  1642. int linelen;
  1643. {
  1644.    extern int rowcount;
  1645.    extern int basehertz;
  1646.    extern int xdots;
  1647.    extern int colors;
  1648.    extern int orbit_delay;
  1649.    int i;
  1650.    for(i=0;i<linelen;i++)
  1651.    {
  1652.       putcolor(i,rowcount,pixels[i]);
  1653.       if(orbit_delay > 0)
  1654.          sleepms(orbit_delay);
  1655.       snd((int)(pixels[i]*3000/colors+basehertz));
  1656.       if(keypressed())
  1657.       {
  1658.         nosnd();
  1659.         return(-1);
  1660.       }
  1661.    }
  1662.    nosnd();
  1663.    rowcount++;
  1664.    return(0);
  1665. }
  1666.  
  1667. int check_key()
  1668. {
  1669.    int key;
  1670.    if((key = keypressed()) != 0) {
  1671.       if(key != 'o' && key != 'O') {
  1672.      fflush(stdout);
  1673.      return(-1);
  1674.       }
  1675.       getakey();
  1676.       if (dotmode != 11)
  1677.      show_orbit = 1 - show_orbit;
  1678.    }
  1679.    return(0);
  1680. }
  1681.  
  1682. /* timer function:
  1683.      timer(0,(*fractal)())        fractal engine
  1684.      timer(1,NULL,int width)        decoder
  1685.      timer(2)                encoder
  1686.   */
  1687. #ifndef XFRACT
  1688. int timer(int timertype,int(*subrtn)(),...)
  1689. #else
  1690. int timer(va_alist)
  1691. va_dcl
  1692. #endif
  1693. {
  1694.    va_list arg_marker;    /* variable arg list */
  1695.    char *timestring;
  1696.    time_t ltime;
  1697.    FILE *fp;
  1698.    int out;
  1699.    int i;
  1700.    int do_bench;
  1701.  
  1702. #ifndef XFRACT
  1703.    va_start(arg_marker,subrtn);
  1704. #else
  1705.    int timertype;
  1706.    int (*subrtn)();
  1707.    va_start(arg_marker);
  1708.    timertype = va_arg(arg_marker, int);
  1709.    subrtn = ( int (*)()) va_arg(arg_marker, int *);
  1710. #endif
  1711.  
  1712.    do_bench = timerflag; /* record time? */
  1713.    if (timertype == 2)     /* encoder, record time only if debug=200 */
  1714.       do_bench = (debugflag == 200);
  1715.    if(do_bench)
  1716.       fp=fopen("bench","a");
  1717.    timer_start = clock_ticks();
  1718.    switch(timertype) {
  1719.       case 0:
  1720.      out = (*subrtn)();
  1721.      break;
  1722.       case 1:
  1723.      i = va_arg(arg_marker,int);
  1724.      out = decoder(i);         /* not indirect, safer with overlays */
  1725.      break;
  1726.       case 2:
  1727.      out = encoder();         /* not indirect, safer with overlays */
  1728.      break;
  1729.       }
  1730.    /* next assumes CLK_TCK is 10^n, n>=2 */
  1731.    timer_interval = (clock_ticks() - timer_start) / (CLK_TCK/100);
  1732.  
  1733.    if(do_bench) {
  1734.       time(<ime);
  1735.       timestring = ctime(<ime);
  1736.       timestring[24] = 0; /*clobber newline in time string */
  1737.       switch(timertype) {
  1738.      case 1:
  1739.         fprintf(fp,"decode ");
  1740.         break;
  1741.      case 2:
  1742.         fprintf(fp,"encode ");
  1743.         break;
  1744.      }
  1745.       fprintf(fp,"%s type=%s resolution = %dx%d maxiter=%d",
  1746.       timestring,
  1747.       curfractalspecific->name,
  1748.       xdots,
  1749.       ydots,
  1750.       maxit);
  1751.       fprintf(fp," time= %ld.%02ld secs\n",timer_interval/100,timer_interval%100);
  1752.       if(fp != NULL)
  1753.      fclose(fp);
  1754.       }
  1755.    return(out);
  1756. }
  1757.