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