home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / WINDOWS / PROGRAM / WINSRC20.ZIP / ENCODER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-03  |  22.3 KB  |  705 lines

  1. /*
  2.     encoder.c - GIF Encoder and associated routines
  3.     This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
  4. */
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "fractint.h"
  10. #include "fractype.h"
  11.  
  12. /* routines in this module    */
  13.  
  14. void encoder_overlay(void);
  15. int  savetodisk(char *);
  16. int  encoder();
  17.  
  18. static void setup_save_info(struct fractal_info *);
  19. static void inittable(void);
  20. static void shftwrite();
  21. static void raster(unsigned int);
  22. static int  extend_blk_len(int datalen);
  23. static void put_extend_blk(int block_id,int block_len,char far *block_data);
  24.  
  25. extern int initbatch;
  26. extern char far *resume_info;        /* pointer to resume info if allocated */
  27. extern int  resume_len;         /* length of resume info */
  28. extern char FormName[40];        /* formula name */
  29. extern int  active_system;        /* 0=dos, 1=windows */
  30.  
  31. extern    int    sxdots,sydots;        /* # of dots on the physical screen    */
  32. extern    int    sxoffs,syoffs;        /* physical top left of logical screen */
  33. extern    int    xdots, ydots;        /* # of dots on the logical screen     */
  34. extern    int    viewwindow;        /* 0 for full screen, 1 for window */
  35. extern    float    finalaspectratio;    /* for view shape and rotation */
  36. extern    int    viewxdots,viewydots;    /* explicit view sizing */
  37. extern    int    colors;         /* maximum colors available */
  38. extern    int    dotmode;        /* so we can detect disk-video */
  39. extern    int    warn;            /* warnings on/off */
  40. extern    int    resave_flag;        /* resaving after a timed save */
  41. extern    int    timedsave;        /* if doing an auto save */
  42. extern    int    disk16bit;        /* 16 bit continuous potential */
  43.  
  44. extern unsigned char dacbox[256][3];    /* Video-DAC (filled in by SETVIDEO) */
  45. extern int    daclearn, daccount;    /* used by the color-cyclers */
  46. extern int    reallyega;        /* "reall-an-EGA" flag */
  47. extern int    extraseg;        /* used by Save-to-GIF routines */
  48. extern int    debugflag;
  49.  
  50. extern int    gif87a_flag;        /* if 1, supress GIF extension blocks */
  51.  
  52. extern int    calc_status;
  53. extern long   calctime;
  54. extern char   stdcalcmode;
  55. extern int    fractype;
  56. extern double xxmin,xxmax;
  57. extern double yymin,yymax;
  58. extern double xx3rd,yy3rd;
  59. extern double param[4];
  60. extern int    maxit;            /* try this many iterations */
  61. extern int    inside;            /* inside color: 1=blue     */
  62. extern int    outside;            /* outside color, if set    */
  63. extern int    finattract;        /* finite attractor option  */
  64. extern int    forcesymmetry;
  65. extern int    LogFlag;            /* non-zero if logarithmic palettes */
  66. extern int    rflag, rseed;
  67. extern int    periodicitycheck;
  68. extern char   useinitorbit;
  69. extern struct complex initorbit;
  70. extern int    pot16bit;
  71. extern float  finalaspectratio;
  72. extern double potparam[3];        /* three potential parameters*/
  73. extern double inversion[];
  74. extern int    decomp[];
  75. extern int    distest;            /* non-zero if distance estimator   */
  76. extern int    init3d[20];        /* '3d=nn/nn/nn/...' values */
  77. extern char   floatflag;        /* floating-point fractals? */
  78. extern int    biomorph;
  79. extern int    bailout;            /* user input bailout value */
  80. extern int    previewfactor;
  81. extern int    xtrans;
  82. extern int    ytrans;
  83. extern int    red_crop_left;
  84. extern int    red_crop_right;
  85. extern int    blue_crop_left;
  86. extern int    blue_crop_right;
  87. extern int    red_bright;
  88. extern int    blue_bright;
  89. extern int    xadjust;
  90. extern int    eyeseparation;
  91. extern int    glassestype;
  92. extern int    save_system;
  93. extern int    save_release;
  94.  
  95. extern int    timer(int timertype,int(*subrtn)(),...);
  96.  
  97. /*
  98.             Save-To-Disk Routines (GIF)
  99.  
  100. GIF and 'Graphics Interchange Format' are trademarks (tm) of Compuserve
  101. Incorporated, an H&R Block Company.
  102.  
  103.  
  104. The following routines perform the GIF encoding when the 's' key is pressed.
  105. The routines refer to several variables that are declared elsewhere
  106. [colors, xdots, ydots, and 'dacbox'], and rely on external routines to
  107. actually read and write screen pixels [getcolor(x,y) and putcolor(x,y,color)].
  108. (Writing pixels is just stuffed in here as a sort of visual status report,
  109. and has nothing to do with any GIF function.)    They also rely on the
  110. existence of an externally-defined 64K dataspace and they use the routines
  111. 'toextra()' and 'cmpextra()' to deal with that dataspace (in the same manner
  112. as 'memcpy()' and 'memcmp()' would).   Otherwise, they perform a generic
  113. GIF-encoder function.
  114.  
  115. Note that these routines use small string- and hash-tables, and "flush"
  116. the GIF entries whenever the hash-table gets two-thirds full or the string
  117. table gets full.   They also use the GIF encoding technique of limiting the
  118. encoded string length to a specific size, "adding" a string to the hash table
  119. at that point even if a matching string exists ("adding" is in quotes, because
  120. if a matching string exists we can increment the code counter but safely throw
  121. the duplicate string away, saving both string space and a hash table entry).
  122.  
  123.    This results in relatively good speed and small data space, but at the
  124. expense of compression efficiency (filesize).    These trade-offs could be
  125. adjusted by modifying the #DEFINEd variables below.
  126.  
  127. Note that the 'strlocn' and 'teststring' routines are declared
  128. to be external just so that they can be defined (and the space re-used)
  129. elsewhere.  The actual declarations are in the assembler code.
  130.  
  131. */
  132.  
  133. #define MAXTEST   100        /* maximum single string length */
  134. #define MAXSTRING 64000     /* total space reserved for strings */
  135.                 /* maximum number of strings available */
  136. #define MAXENTRY  5003        /* (a prime number is best for hashing) */
  137.  
  138. extern unsigned int strlocn[MAXENTRY];
  139. extern unsigned char teststring[MAXTEST];
  140. extern unsigned char block[266];   /* GIF-encoded blocks go here */
  141.  
  142. static int numsaves = 0;    /* For adjusting 'save-to-disk' filenames */
  143.  
  144. static FILE *out;
  145. static int last_colorbar;
  146. static int save16bit;
  147. static int outcolor1s, outcolor2s;
  148.  
  149. static int lentest, lastentry, numentries, numrealentries;
  150. static unsigned int nextentry;
  151. static int clearcode, endcode;
  152. static unsigned int hashcode;
  153.  
  154. static unsigned char blockcount;
  155. static int startbits, codebits, bytecount, bitcount;
  156.  
  157. static char paletteBW[] = {            /* B&W palette */
  158.       0,  0,  0, 63, 63, 63,
  159.     };
  160. static char paletteCGA[] = {            /* 4-color (CGA) palette  */
  161.       0,  0,  0, 21, 63, 63, 63, 21, 63, 63, 63, 63,
  162.     };
  163. static char paletteEGA[] = {            /* 16-color (EGA/CGA) pal */
  164.       0,  0,  0,  0,  0, 42,  0, 42,  0,  0, 42, 42,
  165.      42,  0,  0, 42,  0, 42, 42, 21,  0, 42, 42, 42,
  166.      21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
  167.      63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
  168.     };
  169. int paletteVGA[] = {            /* VGA palette - to DAC registers */
  170.     0, 1, 2, 3, 4, 5,20, 7,56,57,58,59,60,61,62,63,
  171.     };
  172.  
  173. void encoder_overlay() { }    /* for restore_active_ovly */
  174.  
  175. int savetodisk(filename)    /* save-to-disk routine */
  176. char *filename;
  177. {
  178. char tmpmsg[41]; /* before openfile in case of overrun */
  179. char openfile[80], openfiletype[10];
  180. char tmpfile[80];
  181. int newfile;
  182. int i, j, outcolor1, outcolor2, interrupted;
  183.  
  184. ENTER_OVLY(OVLY_ENCODER);
  185.  
  186. if (extraseg == 0) {            /* not enough memory for this */
  187.     buzzer(2);
  188.     EXIT_OVLY;
  189.     return -1;
  190.     }
  191. restart:
  192.  
  193. save16bit = disk16bit;
  194. if (gif87a_flag) /* not storing non-standard fractal info */
  195.     save16bit = 0;
  196.  
  197. strcpy(openfile,filename);        /* decode and open the filename */
  198. strcpy(openfiletype,DEFAULTFRACTALTYPE);/* determine the file extension */
  199. if (save16bit)
  200.     strcpy(openfiletype,".pot");
  201. for (i = 0; i < strlen(openfile); i++)
  202.     if (openfile[i] == '.') {
  203.         strcpy(openfiletype,&openfile[i]);
  204.         openfile[i] = 0;
  205.         }
  206. if (resave_flag == 0)
  207.     updatesavename(filename); /* for next time */
  208.  
  209. strcat(openfile,openfiletype);
  210.  
  211. strcpy(tmpfile,openfile);
  212. if (access(openfile,0) != 0) /* file doesn't exist */
  213.     newfile = 1;
  214. else { /* file already exists */
  215.     if (warn && resave_flag == 0)
  216.         goto restart;
  217.     if (access(openfile,2) != 0) {
  218.         buzzer(2);
  219.         sprintf(tmpmsg," ?? Can't write %s ",openfile);
  220.         texttempmsg(tmpmsg);
  221.         EXIT_OVLY;
  222.         return -1;
  223.         }
  224.     newfile = 0;
  225.     i = strlen(tmpfile);
  226.     while (--i >= 0 && tmpfile[i] != '\\')
  227.         tmpfile[i] = 0;
  228.     strcat(tmpfile,"fractint.tmp");
  229.     }
  230. if ((out=fopen(tmpfile,"wb")) == NULL) {
  231.     buzzer(2);
  232.     sprintf(tmpmsg," ?? Couldn't create %s ",tmpfile);
  233.     texttempmsg(tmpmsg);
  234.     EXIT_OVLY;
  235.     return -1;
  236.     }
  237.  
  238. if (dotmode == 11) {            /* disk-video */
  239.     movecursor(2,0);
  240.     printf("...saving...");
  241.     }
  242.  
  243. if (debugflag != 200)
  244.     interrupted = encoder();
  245. else
  246.     interrupted = timer(2,NULL);    /* invoke encoder() via timer */
  247.  
  248. fclose(out);
  249.  
  250. if (newfile == 0) { /* now we're safely done, replace the real file */
  251.     if (unlink(openfile) != 0) {
  252.         buzzer(2);
  253.         sprintf(tmpmsg," ?? Can't replace %s ",openfile);
  254.         texttempmsg(tmpmsg);
  255.         EXIT_OVLY;
  256.         return -1;
  257.         }
  258.     if (rename(tmpfile,openfile) != 0) {
  259.         buzzer(2);
  260.         sprintf(tmpmsg," ?? Can't rename %s ",tmpfile);
  261.         texttempmsg(tmpmsg);
  262.         EXIT_OVLY;
  263.         return -1;
  264.         }
  265.     }
  266.  
  267. if (dotmode != 11) {            /* supress this on disk-video */
  268.     if (active_system == 0) {        /* no bars in Windows version */
  269.     outcolor1 = outcolor1s;
  270.     outcolor2 = outcolor2s;
  271.     for (j = 0; j <= last_colorbar; j++) {
  272.         if ((j & 4) == 0) {
  273.             if (++outcolor1 >= colors) outcolor1 = 0;
  274.             if (++outcolor2 >= colors) outcolor2 = 0;
  275.             }
  276.         for (i = 0; 250*i < xdots; i++) { /* clear vert status bars */
  277.             putcolor(i,j,getcolor(i,j)^outcolor1);
  278.             putcolor(xdots-1-i,j,getcolor(xdots-1-i,j)^outcolor2);
  279.             }
  280.         }
  281.     }
  282.     }
  283. else {                    /* disk-video */
  284.     movecursor(2,0);
  285.     printf("            ");
  286.     }
  287. if (interrupted) {
  288.     buzzer(1);
  289.     getakey();            /* read the (interrupt) key-press */
  290.     sprintf(tmpmsg," *INTERRUPTED* File %s ", openfile);
  291.     texttempmsg(tmpmsg);
  292.     EXIT_OVLY;
  293.     return -1;
  294.     }
  295. if (timedsave == 0) {
  296.     buzzer(0);
  297.     if (initbatch == 0) {
  298.         sprintf(tmpmsg," File saved as %s ",openfile);
  299.         texttempmsg(tmpmsg);
  300.         }
  301.     }
  302. EXIT_OVLY;
  303. return 0;
  304. }
  305.  
  306.  
  307. int encoder()
  308. {
  309. int i, j, ydot, xdot, color, outcolor1, outcolor2;
  310. int width;
  311. int rownum, rowlimit;
  312. unsigned int hashentry;
  313. unsigned char bitsperpixel, x;
  314. int entrynum;
  315. struct fractal_info save_info;
  316.  
  317. setup_save_info(&save_info);
  318.  
  319. bitsperpixel = 0;            /* calculate bits / pixel */
  320. for (i = colors; i >= 2; i /= 2 )
  321.     bitsperpixel++;
  322.  
  323. startbits = bitsperpixel+1;        /* start coding with this many bits */
  324. if (colors == 2)
  325.     startbits++;            /* B&W Klooge */
  326.  
  327. clearcode = 1 << (startbits - 1);    /* set clear and end codes */
  328. endcode = clearcode+1;
  329.  
  330. outcolor1 = 0;                /* use these colors to show progress */
  331. outcolor2 = 1;                /* (this has nothing to do with GIF) */
  332. if (colors > 2) {
  333.     outcolor1 = 2;
  334.     outcolor2 = 3;
  335.     }
  336. if (((++numsaves) & 1) == 0) {            /* reverse the colors on alt saves */
  337.     i = outcolor1;
  338.     outcolor1 = outcolor2;
  339.     outcolor2 = i;
  340.     }
  341. outcolor1s = outcolor1;
  342. outcolor2s = outcolor2;
  343.  
  344. if (gif87a_flag == 1)
  345.     fwrite("GIF87a",1,6,out);              /* old GIF Signature */
  346. else
  347.     fwrite("GIF89a",1,6,out);              /* new GIF Signature */
  348.  
  349. width = xdots;
  350. rowlimit = ydots;
  351. if (save16bit) {
  352.     /* pot16bit info is stored as:
  353.        file:    double width rows, right side of row is low 8 bits
  354.        diskvid: ydots rows of colors followed by ydots rows of low 8 bits
  355.        decoder: returns (row of color info then row of low 8 bits) * ydots
  356.        */
  357.     rowlimit <<= 1;
  358.     width <<= 1;
  359.     }
  360. fwrite(&width,2,1,out);         /* screen descriptor */
  361. fwrite(&ydots,2,1,out);
  362. x = 128 + ((6-1)<<4) + (bitsperpixel-1); /* color resolution == 6 bits worth */
  363. fwrite(&x,1,1,out);
  364. fputc(0,out);                /* background color */
  365. i = 0;
  366. if ( finalaspectratio < SCREENASPECT-0.01
  367.   || finalaspectratio > SCREENASPECT+0.01) { /* store non-standard aspect ratio */
  368.    if (viewwindow                   /* less than full screen?  */
  369.      && (viewxdots == 0 || viewydots == 0))    /* and we picked the dots? */
  370.       i = ((double)sydots / (double)sxdots) * 64.0/SCREENASPECT - 14.5;
  371.    else /* must risk loss of precision if numbers low */
  372.       i = (((double)ydots / (double)xdots) / finalaspectratio) * 64 - 14.5;
  373.    if (i < 1)    i = 1;
  374.    if (i > 255) i = 255;
  375.    }
  376. fputc(i,out);                /* pixel aspect ratio */
  377.  
  378. if (colors == 256) {            /* write out the 256-color palette */
  379.     if (dacbox[0][0] != 255)    /* got a DAC - must be a VGA */
  380.         shftwrite(dacbox,colors);
  381.     else                /* uh oh - better fake it */
  382.         for (i = 0; i < 256; i += 16)
  383.             shftwrite(paletteEGA,16);
  384.     }
  385. if (colors == 2)            /* write out the B&W palette */
  386.     shftwrite(paletteBW,colors);
  387. if (colors == 4)            /* write out the CGA palette */
  388.     shftwrite(paletteCGA,colors);
  389. if (colors == 16)            /* Either EGA or VGA */
  390.     if (dacbox[0][0] != 255) {    /* got a  DAC - must be a VGA */
  391.         if (reallyega)        /* well, maybe really an EGA */
  392.             shftwrite(dacbox,colors);
  393.         else
  394.             for (i = 0; i < colors; i++)
  395.                 shftwrite(dacbox[paletteVGA[i]],1);
  396.         }
  397.         else            /* no DAC - must be an EGA */
  398.             shftwrite(paletteEGA,colors);
  399.  
  400. fwrite(",",1,1,out);                    /* Image Descriptor */
  401. i = 0;
  402. fwrite(&i,2,1,out);
  403. fwrite(&i,2,1,out);
  404. fwrite(&width,2,1,out);
  405. fwrite(&ydots,2,1,out);
  406. fwrite(&i,1,1,out);
  407.  
  408. bitsperpixel = startbits - 1;        /* raster data starts here */
  409. fwrite(&bitsperpixel,1,1,out);
  410.  
  411. codebits = startbits;            /* start encoding */
  412.  
  413. raster(9999);                /* initialize the raster routine */
  414.  
  415. inittable();                /* initialize the LZW tables */
  416.  
  417. for (rownum = 0; rownum < ydots; rownum++) {  /* scan through the dots */
  418.     for (ydot = rownum; ydot < rowlimit; ydot += ydots) {
  419.     for (xdot = 0; xdot < xdots; xdot++) {
  420.         if (save16bit == 0 || ydot < ydots)
  421.             color = getcolor(xdot,ydot);
  422.         else
  423.             color = readdisk(xdot+sxoffs,ydot+syoffs);
  424.         teststring[0] = ++lentest;
  425.         teststring[lentest] = color;
  426.         if (lentest == 1) {        /* root entry? */
  427.             lastentry = color;
  428.             continue;
  429.             }
  430.         if (lentest == 2)        /* init   the hash code */
  431.             hashcode = 301 * (teststring[1]+1);
  432.         hashcode *= (color + lentest);    /* update the hash code */
  433.         hashentry = ++hashcode % MAXENTRY;
  434.         for( i = 0; i < MAXENTRY; i++) {
  435.             if (++hashentry >= MAXENTRY) hashentry = 0;
  436.             if (cmpextra(strlocn[hashentry]+2,
  437.                 teststring,lentest+1) == 0)
  438.                     break;
  439.             if (strlocn[hashentry] == 0) i = MAXENTRY;
  440.             }
  441.         /* found an entry and string length isn't too bad */
  442.         if (strlocn[hashentry] != 0 && lentest < MAXTEST-3) {
  443.             fromextra(strlocn[hashentry],&entrynum,2);
  444.             lastentry = entrynum;
  445.             continue;
  446.             }
  447.         raster(lastentry);            /* write entry */
  448.         numentries++;        /* act like you added one, anyway */
  449.         if (strlocn[hashentry] == 0) {    /* add new string, if any */
  450.             entrynum = numentries+endcode;
  451.             strlocn[hashentry] = nextentry;
  452.             toextra(nextentry, &entrynum,2);
  453.             toextra(nextentry+2,
  454.                 teststring,lentest+1);
  455.             nextentry += lentest+3;
  456.             numrealentries++;
  457.             }
  458.         teststring[0] = 1;        /* reset current entry */
  459.         teststring[1] = color;
  460.         lentest = 1;
  461.         lastentry = color;
  462.  
  463.         if ((numentries+endcode) == (1<<codebits))
  464.             codebits++;         /* use longer encoding */
  465.  
  466.         if ( numentries + endcode > 4093 ||    /* out of room? */
  467.             numrealentries > (MAXENTRY*2)/3 ||
  468.             nextentry > MAXSTRING-MAXTEST-5) {
  469.             raster(lastentry);        /* flush & restart */
  470.             inittable();
  471.             }
  472.         }
  473.     if (dotmode != 11            /* supress this on disk-video */
  474.         && active_system == 0        /* and in Windows version     */
  475.         && ydot == rownum) {
  476.         if ((ydot & 4) == 0) {
  477.             if (++outcolor1 >= colors) outcolor1 = 0;
  478.             if (++outcolor2 >= colors) outcolor2 = 0;
  479.             }
  480.         for (i = 0; 250*i < xdots; i++) {    /* display vert status bars */
  481.                             /*   (this is NOT GIF-related)    */
  482.             /* PB Changed following code to xor color, so that
  483.                image can be restored at end and resumed
  484.                putcolor(      i,ydot,outcolor1);
  485.                putcolor(xdots-1-i,ydot,outcolor2);
  486.             */
  487.             putcolor(i,ydot,getcolor(i,ydot)^outcolor1);
  488.             putcolor(xdots-1-i,ydot,getcolor(xdots-1-i,ydot)^outcolor2);
  489.             }
  490.         last_colorbar = ydot;
  491.         }
  492.     if (kbhit())                /* keyboard hit - bail out */
  493.         ydot = rownum = 9999;
  494.     }
  495.     }
  496.  
  497. raster(lastentry);            /* tidy up - dump the last code */
  498.  
  499. raster(endcode);            /* finish the map */
  500.  
  501. fputc(0,out);                /* raster data ends here */
  502.  
  503. if (gif87a_flag == 0) { /* store non-standard fractal info */
  504.     /* loadfile.c has notes about extension block structure */
  505.     if (ydot >= 9999)
  506.         save_info.calc_status = 0; /* partial save is not resumable */
  507.     save_info.tot_extend_len = 0;
  508.     if (resume_info != NULL && save_info.calc_status == 2) {
  509.         /* resume info block, 002 */
  510.         save_info.tot_extend_len += extend_blk_len(resume_len);
  511.         put_extend_blk(2,resume_len,resume_info);
  512.         }
  513.     if (save_info.fractal_type == FORMULA || save_info.fractal_type == FFORMULA) {
  514.         /* formula info block, 003 */
  515.         save_info.tot_extend_len += extend_blk_len(40);
  516.         put_extend_blk(3,40,FormName);
  517.         }
  518.     /* main and last block, 001 */
  519.     save_info.tot_extend_len += extend_blk_len(sizeof(save_info));
  520.     put_extend_blk(1,sizeof(save_info),(char far *)&save_info);
  521.     }
  522.  
  523. fwrite(";",1,1,out);                    /* GIF Terminator */
  524. return ((ydot < 9999) ? 0 : 1);
  525. }
  526.  
  527. static void shftwrite(color,numcolors)    /* shift IBM colors to GIF format */
  528. unsigned char color[];
  529. int numcolors;
  530. {
  531. unsigned char thiscolor;
  532. int i,j;
  533. for (i = 0; i < numcolors; i++)
  534.     for (j = 0; j < 3; j++) {
  535.         thiscolor = color[3*i+j];
  536.         thiscolor = thiscolor << 2;
  537.         thiscolor += (thiscolor >> 6);
  538.         /*    fwrite(&thiscolor,1,1,out); */
  539.         fputc(thiscolor,out);
  540.         }
  541. }
  542.  
  543. static void inittable()         /* routine to init tables */
  544. {
  545. int i;
  546.  
  547. raster(clearcode);            /* signal that table is initialized */
  548.  
  549. numentries = 0;             /* initialize the table */
  550. numrealentries = 0;
  551. nextentry = 1;
  552. lentest = 0;
  553. codebits = startbits;
  554.  
  555. toextra(0,"\0",1);                      /* clear the hash entries */
  556. for (i = 0; i < MAXENTRY; i++)
  557.     strlocn[i] = 0;
  558.  
  559. }
  560.  
  561. static void raster(code)        /* routine to block and output codes */
  562. unsigned int code;
  563. {
  564. unsigned int icode, i, j;
  565.  
  566. if (code == 9999) {            /* special start-up signal */
  567.     bytecount = 0;
  568.     bitcount = 0;
  569.     for (i = 0; i < 266; i++)
  570.         block[i] = 0;
  571.     return;
  572.     }
  573.  
  574. icode = code << bitcount;        /* update the bit string */
  575. block[bytecount  ] |= (icode & 255);
  576. block[bytecount+1] |= ((icode>>8) & 255);
  577. icode = (code>>8) << bitcount;
  578. block[bytecount+2] |= ((icode>>8) & 255);
  579. bitcount += codebits;
  580. while (bitcount >= 8) {         /* locate next starting point */
  581.     bitcount -= 8;
  582.     bytecount++;
  583.     }
  584.  
  585. if (bytecount > 250 || code == endcode) {    /* time to write a block */
  586.     if (code == endcode)
  587.         while (bitcount > 0) {        /* if EOF, find the real end */
  588.             bitcount -= 8;
  589.             bytecount++;
  590.             }
  591.     i = bytecount;
  592.     blockcount = i;
  593.     fwrite(&blockcount,1,1,out);        /* write the block */
  594.     fwrite(block,i,1,out);
  595.     bytecount = 0;                /* now re-start the block */
  596.     for (j = 0; j < 5; j++)         /* (may have leftover bits) */
  597.         block[j] = block[j+i];
  598.     for (j = 5; j < 266; j++)
  599.         block[j] = 0;
  600.     }
  601. }
  602.  
  603.  
  604. static int extend_blk_len(int datalen)
  605. {
  606.    return(datalen + (datalen+254)/255 + 15);
  607.    /*       data   +    1.per.block   + 14 for id + 1 for null at end  */
  608. }
  609.  
  610. static void put_extend_blk(int block_id,int block_len,char far *block_data)
  611. {
  612.    int i,j;
  613.    char header[15];
  614.    strcpy(header,"!\377\013fractint");
  615.    sprintf(&header[11],"%03u",block_id);
  616.    fwrite(header,14,1,out);
  617.    i = (block_len + 254) / 255;
  618.    while (--i >= 0) {
  619.       block_len -= (j = min(block_len,255));
  620.       fputc(j,out);
  621.       while (--j >= 0)
  622.      fputc(*(block_data++),out);
  623.       }
  624.    fputc(0,out);
  625. }
  626.  
  627. static void setup_save_info(struct fractal_info *save_info)
  628. {
  629.    int i;
  630.    /* set save parameters in save structure */
  631.    strcpy(save_info->info_id, INFO_ID);
  632.    save_info->version          = 5; /* file version, independant of system */
  633.    save_info->iterations      = maxit;
  634.    save_info->fractal_type    = fractype;
  635.    save_info->xmin          = xxmin;
  636.    save_info->xmax          = xxmax;
  637.    save_info->ymin          = yymin;
  638.    save_info->ymax          = yymax;
  639.    save_info->creal          = param[0];
  640.    save_info->cimag          = param[1];
  641.    save_info->videomodeax     = videoentry.videomodeax;
  642.    save_info->videomodebx     = videoentry.videomodebx;
  643.    save_info->videomodecx     = videoentry.videomodecx;
  644.    save_info->videomodedx     = videoentry.videomodedx;
  645.    save_info->dotmode          = videoentry.dotmode;
  646.    save_info->xdots          = videoentry.xdots;
  647.    save_info->ydots          = videoentry.ydots;
  648.    save_info->colors          = videoentry.colors;
  649.    save_info->parm3          = param[2];
  650.    save_info->parm4          = param[3];
  651.    save_info->potential[0]    = potparam[0];
  652.    save_info->potential[1]    = potparam[1];
  653.    save_info->potential[2]    = potparam[2];
  654.    save_info->rflag          = rflag;
  655.    save_info->rseed          = rseed;
  656.    save_info->inside          = inside;
  657.    save_info->logmap          = LogFlag;
  658.    save_info->invert[0]       = inversion[0];
  659.    save_info->invert[1]       = inversion[1];
  660.    save_info->invert[2]       = inversion[2];
  661.    save_info->decomp[0]       = decomp[0];
  662.    save_info->decomp[1]       = decomp[1];
  663.    save_info->biomorph          = biomorph;
  664.    save_info->symmetry          = forcesymmetry;
  665.    for (i = 0; i < 16; i++)
  666.       save_info->init3d[i] = init3d[i];
  667.    save_info->previewfactor   = previewfactor;
  668.    save_info->xtrans          = xtrans;
  669.    save_info->ytrans          = ytrans;
  670.    save_info->red_crop_left   = red_crop_left;
  671.    save_info->red_crop_right  = red_crop_right;
  672.    save_info->blue_crop_left  = blue_crop_left;
  673.    save_info->blue_crop_right = blue_crop_right;
  674.    save_info->red_bright      = red_bright;
  675.    save_info->blue_bright     = blue_bright;
  676.    save_info->xadjust          = xadjust;
  677.    save_info->eyeseparation   = eyeseparation;
  678.    save_info->glassestype     = glassestype;
  679.    save_info->outside          = outside;
  680.    save_info->x3rd          = xx3rd;
  681.    save_info->y3rd          = yy3rd;
  682.    save_info->calc_status     = calc_status;
  683.    save_info->stdcalcmode     = stdcalcmode;
  684.    save_info->distest          = distest;
  685.    save_info->floatflag       = floatflag;
  686.    save_info->bailout          = bailout;
  687.    save_info->calctime          = calctime;
  688.    save_info->trigndx[0]      = trigndx[0];
  689.    save_info->trigndx[1]      = trigndx[1];
  690.    save_info->trigndx[2]      = trigndx[2];
  691.    save_info->trigndx[3]      = trigndx[3];
  692.    save_info->finattract      = finattract;
  693.    save_info->initorbit[0]    = initorbit.x;
  694.    save_info->initorbit[1]    = initorbit.y;
  695.    save_info->useinitorbit    = useinitorbit;
  696.    save_info->periodicity     = periodicitycheck;
  697.    save_info->pot16bit          = disk16bit;
  698.    save_info->faspectratio    = finalaspectratio;
  699.    save_info->system          = save_system;
  700.    save_info->release          = save_release;
  701.    for (i = 0; i < sizeof(save_info->future)/sizeof(int); i++)
  702.       save_info->future[i] = 0;
  703. }
  704.  
  705.