home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / dos / fraktale / frasr192.exe / ENCODER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-21  |  26.7 KB  |  815 lines

  1. /*
  2.     encoder.c - GIF Encoder and associated routines
  3. */
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #ifndef XFRACT
  9. #include <io.h>
  10. #endif
  11. #include "fractint.h"
  12. #include "fractype.h"
  13. #include "prototyp.h"
  14.  
  15. /* MCP 10-27-91 */
  16. #ifdef WINFRACT
  17.    extern int OperCancelled;
  18.    void OpenStatusBox(void);
  19.    void UpdateStatusBox(unsigned long Partial, unsigned long Total);
  20.    void CloseStatusBox(void);
  21. #endif
  22.  
  23. static int inittable(void);
  24. static int _fastcall shftwrite(BYTE *color,int numcolors);
  25. static int _fastcall raster(unsigned int);
  26. static int  _fastcall extend_blk_len(int datalen);
  27. static int _fastcall put_extend_blk(int block_id,int block_len,char far *block_data);
  28. static int  _fastcall store_item_name(char *);
  29. static void _fastcall setup_save_info(struct fractal_info far *save_info);
  30.  
  31. #ifdef XFRACT
  32. int decode_fractal_info();
  33. #endif
  34.  
  35. /*
  36.             Save-To-Disk Routines (GIF)
  37.  
  38. GIF and 'Graphics Interchange Format' are trademarks (tm) of Compuserve
  39. Incorporated, an H&R Block Company.
  40.  
  41.  
  42. The following routines perform the GIF encoding when the 's' key is pressed.
  43. The routines refer to several variables that are declared elsewhere
  44. [colors, xdots, ydots, and 'dacbox'], and rely on external routines to
  45. actually read and write screen pixels [getcolor(x,y) and putcolor(x,y,color)].
  46. (Writing pixels is just stuffed in here as a sort of visual status report,
  47. and has nothing to do with any GIF function.)    They also rely on the
  48. existence of an externally-defined 64K dataspace and they use the routines
  49. 'toextra()' and 'cmpextra()' to deal with that dataspace (in the same manner
  50. as 'memcpy()' and 'memcmp()' would).   Otherwise, they perform a generic
  51. GIF-encoder function.
  52.  
  53. Note that these routines use small string- and hash-tables, and "flush"
  54. the GIF entries whenever the hash-table gets two-thirds full or the string
  55. table gets full.   They also use the GIF encoding technique of limiting the
  56. encoded string length to a specific size, "adding" a string to the hash table
  57. at that point even if a matching string exists ("adding" is in quotes, because
  58. if a matching string exists we can increment the code counter but safely throw
  59. the duplicate string away, saving both string space and a hash table entry).
  60.  
  61.    This results in relatively good speed and small data space, but at the
  62. expense of compression efficiency (filesize).    These trade-offs could be
  63. adjusted by modifying the #DEFINEd variables below.
  64.  
  65. Note that the 'strlocn' and 'teststring' routines are declared
  66. to be external just so that they can be defined (and the space re-used)
  67. elsewhere.  The actual declarations are in the assembler code.
  68.  
  69. */
  70.  
  71. #define MAXTEST   100        /* maximum single string length */
  72. #define MAXSTRING 64000L     /* total space reserved for strings */
  73.                 /* maximum number of strings available */
  74. #define MAXENTRY  5003        /* (a prime number is best for hashing) */
  75.  
  76. #ifdef XFRACT
  77. unsigned int strlocn[10240];
  78. BYTE teststring[MAXTEST];
  79. BYTE block[266];   /* GIF-encoded blocks go here */
  80. #endif
  81.  
  82. static int numsaves = 0;    /* For adjusting 'save-to-disk' filenames */
  83.  
  84. static FILE *out;
  85. static int last_colorbar;
  86. static int save16bit;
  87. static int outcolor1s, outcolor2s;
  88.  
  89. static int lentest, lastentry, numentries, numrealentries;
  90. static unsigned int nextentry;
  91. static int clearcode, endcode;
  92. static unsigned int hashcode;
  93.  
  94. static BYTE blockcount;
  95. static int startbits, codebits, bytecount, bitcount;
  96.  
  97. static BYTE paletteBW[] = {            /* B&W palette */
  98.       0,  0,  0, 63, 63, 63,
  99.     };
  100. static BYTE paletteCGA[] = {            /* 4-color (CGA) palette  */
  101.       0,  0,  0, 21, 63, 63, 63, 21, 63, 63, 63, 63,
  102.     };
  103. static BYTE paletteEGA[] = {            /* 16-color (EGA/CGA) pal */
  104.       0,  0,  0,  0,  0, 42,  0, 42,  0,  0, 42, 42,
  105.      42,  0,  0, 42,  0, 42, 42, 21,  0, 42, 42, 42,
  106.      21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
  107.      63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
  108.     };
  109.  
  110. int savetodisk(char *filename)    /* save-to-disk routine */
  111.    {
  112.    char tmpmsg[41]; /* before openfile in case of overrun */
  113.    char openfile[80], openfiletype[10];
  114.    char tmpfile[80];
  115.     char *period;
  116.    int newfile;
  117.    int i, j, outcolor1, outcolor2, interrupted;
  118. restart:
  119.  
  120.    save16bit = disk16bit;
  121.    if (gif87a_flag) /* not storing non-standard fractal info */
  122.       save16bit = 0;
  123.  
  124.    strcpy(openfile,filename);        /* decode and open the filename */
  125.    strcpy(openfiletype,DEFAULTFRACTALTYPE);/* determine the file extension */
  126.    if (save16bit)
  127.       strcpy(openfiletype,".pot");
  128. #if 0
  129.    /* this logic fails if directory name hhas period */      
  130.    for (i = 0; i < (int)strlen(openfile); i++)
  131.       if (openfile[i] == '.') {
  132.          strcpy(openfiletype,&openfile[i]);
  133.          openfile[i] = 0;
  134.          }
  135. #endif
  136.    if((period = has_ext(openfile)) != NULL)
  137.    {
  138.       strcpy(openfiletype,period);
  139.       *period = 0;
  140.    }   
  141.    if (resave_flag != 1)
  142.       updatesavename(filename); /* for next time */
  143.  
  144.    strcat(openfile,openfiletype);
  145.  
  146.    strcpy(tmpfile,openfile);
  147.    if (access(openfile,0) != 0) /* file doesn't exist */
  148.       newfile = 1;
  149.    else { /* file already exists */
  150.       if (overwrite == 0) {
  151.          if (resave_flag == 0)
  152.             goto restart;
  153.          if (started_resaves == 0) { /* first save of a savetime set */
  154.             updatesavename(filename);
  155.             goto restart;
  156.             }
  157.          }
  158.       if (access(openfile,2) != 0) {
  159.          sprintf(tmpmsg,s_cantwrite,openfile);
  160.          stopmsg(0,tmpmsg);
  161.          return -1;
  162.          }
  163.       newfile = 0;
  164.       i = strlen(tmpfile);
  165.       while (--i >= 0 && tmpfile[i] != SLASHC)
  166.          tmpfile[i] = 0;
  167.       strcat(tmpfile,"fractint.tmp");
  168.       }
  169.  
  170.    started_resaves = (resave_flag == 1) ? 1 : 0;
  171.    if (resave_flag == 2) /* final save of savetime set? */
  172.       resave_flag = 0;
  173.  
  174.    if ((out=fopen(tmpfile,"wb")) == NULL) {
  175.       sprintf(tmpmsg,s_cantcreate,tmpfile);
  176.       stopmsg(0,tmpmsg);
  177.       return -1;
  178.       }
  179.  
  180.    if (dotmode == 11) {            /* disk-video */
  181.       char buf[60];
  182.       sprintf(buf,"Saving %s",openfile);
  183.       dvid_status(1,buf);
  184.       }
  185. #ifdef XFRACT
  186.       else {
  187.       putstring(3,0,0,"Saving to:");
  188.       putstring(4,0,0,openfile);
  189.       putstring(5,0,0,"               ");
  190.       }
  191. #endif
  192.  
  193.    busy = 1;
  194.  
  195.    if (debugflag != 200)
  196.       interrupted = encoder();
  197.    else
  198.       interrupted = timer(2,NULL);    /* invoke encoder() via timer */
  199.  
  200.    busy = 0;
  201.  
  202.    fclose(out);
  203.  
  204.    if (interrupted) {
  205.       char buf[200];
  206.       sprintf(buf,"Save of %s interrupted.\nCancel to ",openfile);
  207.       if (newfile)
  208.          strcat(buf,"delete the file,\ncontinue to keep the partial image.");
  209.       else
  210.          strcat(buf,"retain the original file,\ncontinue to replace original with new partial image.");
  211.       interrupted = 1;
  212.       if (stopmsg(2,buf) < 0) {
  213.          interrupted = -1;
  214.          unlink(tmpfile);
  215.          }
  216.       }
  217.  
  218.    if (newfile == 0 && interrupted >= 0) { /* replace the real file */
  219.       unlink(openfile);        /* success assumed since we checked */
  220.       rename(tmpfile,openfile);    /* earlier with access            */
  221.       }
  222.  
  223.    if (dotmode != 11) {            /* supress this on disk-video */
  224.       if (active_system == 0) {        /* no bars in Windows version */
  225.          outcolor1 = outcolor1s;
  226.          outcolor2 = outcolor2s;
  227.          for (j = 0; j <= last_colorbar; j++) {
  228.             if ((j & 4) == 0) {
  229.                if (++outcolor1 >= colors) outcolor1 = 0;
  230.                if (++outcolor2 >= colors) outcolor2 = 0;
  231.                }
  232.             for (i = 0; 250*i < xdots; i++) { /* clear vert status bars */
  233.                putcolor(i,j,getcolor(i,j)^outcolor1);
  234.                putcolor(xdots-1-i,j,getcolor(xdots-1-i,j)^outcolor2);
  235.                }
  236.             }
  237.          }
  238. #ifdef XFRACT
  239.          putstring(5,0,0,"Saving done\n");
  240. #endif
  241.       }
  242.    else                    /* disk-video */
  243.       dvid_status(1,"");
  244.  
  245.    if (interrupted) {
  246.       static FCODE msg[] = {" *interrupted* save "};
  247.       texttempmsg(msg);
  248.       if (initbatch >= 1) initbatch = 3; /* if batch mode, set error level */
  249.       return -1;
  250.       }
  251.    if (timedsave == 0) {
  252.       buzzer(0);
  253.       if (initbatch == 0) {
  254.          extract_filename(tmpfile,openfile);
  255.          sprintf(tmpmsg," File saved as %s ",tmpfile);
  256.          texttempmsg(tmpmsg);
  257.          }
  258.       }
  259.    if(initsavetime < 0)
  260.       goodbye();
  261.    return 0;
  262.    }
  263.  
  264.  
  265. int encoder()
  266. {
  267. int i, ydot, xdot, color, outcolor1, outcolor2;
  268. int width;
  269. int rownum, rowlimit;
  270. unsigned int hashentry;
  271. BYTE bitsperpixel, x;
  272. int entrynum;
  273. struct fractal_info save_info;
  274. unsigned int maxstring;
  275.  
  276. ydot = 0;
  277. /* arbitrary math uses top of extraseg - steal from encoder if necessary */
  278. if(bf_save_len) 
  279. {
  280.    maxstring = (unsigned int)(0x10000l-(bf_save_len+2)*22);
  281.    maxstring = min((unsigned int)MAXSTRING,maxstring);
  282. }    
  283. else
  284.    maxstring = MAXSTRING;
  285.  
  286. if(initbatch)            /* flush any impending keystrokes */
  287.    while(keypressed())
  288.       getakey();
  289.  
  290. setup_save_info(&save_info);
  291.  
  292. #ifndef XFRACT
  293. bitsperpixel = 0;            /* calculate bits / pixel */
  294. for (i = colors; i >= 2; i /= 2 )
  295.     bitsperpixel++;
  296.  
  297. startbits = bitsperpixel+1;        /* start coding with this many bits */
  298. if (colors == 2)
  299.     startbits++;            /* B&W Klooge */
  300. #else
  301.     if (colors==2) {
  302.         bitsperpixel = 1;
  303.         startbits = 3;
  304.     } else {
  305.         bitsperpixel = 8;
  306.         startbits = 9;
  307.     }
  308. #endif
  309.  
  310. clearcode = 1 << (startbits - 1);    /* set clear and end codes */
  311. endcode = clearcode+1;
  312.  
  313. outcolor1 = 0;                /* use these colors to show progress */
  314. outcolor2 = 1;                /* (this has nothing to do with GIF) */
  315. if (colors > 2) {
  316.     outcolor1 = 2;
  317.     outcolor2 = 3;
  318.     }
  319. if (((++numsaves) & 1) == 0) {            /* reverse the colors on alt saves */
  320.     i = outcolor1;
  321.     outcolor1 = outcolor2;
  322.     outcolor2 = i;
  323.     }
  324. outcolor1s = outcolor1;
  325. outcolor2s = outcolor2;
  326.  
  327. if (gif87a_flag == 1) {
  328.     if (fwrite("GIF87a",6,1,out) != 1) goto oops;  /* old GIF Signature */
  329. } else {
  330.     if (fwrite("GIF89a",6,1,out) != 1) goto oops;  /* new GIF Signature */
  331. }
  332.  
  333. width = xdots;
  334. rowlimit = ydots;
  335. if (save16bit) {
  336.     /* pot16bit info is stored as:
  337.        file:    double width rows, right side of row is low 8 bits
  338.        diskvid: ydots rows of colors followed by ydots rows of low 8 bits
  339.        decoder: returns (row of color info then row of low 8 bits) * ydots
  340.        */
  341.     rowlimit <<= 1;
  342.     width <<= 1;
  343.     }
  344. if (write2(&width,2,1,out) != 1) goto oops;  /* screen descriptor */
  345. if (write2(&ydots,2,1,out) != 1) goto oops;
  346. x = (BYTE)(128 + ((6-1)<<4) + (bitsperpixel-1)); /* color resolution == 6 bits worth */
  347. if (write1(&x,1,1,out) != 1) goto oops;
  348. if (fputc(0,out) != 0) goto oops;    /* background color */
  349. i = 0;
  350. /** PB, changed to always store pixel aspect ratio, some utilities
  351.     have been reported to like it **/
  352. /**
  353. if ( finalaspectratio < screenaspect-0.01
  354.   || finalaspectratio > screenaspect+0.01) {
  355.  **/
  356. if (viewwindow                    /* less than full screen?  */
  357.   && (viewxdots == 0 || viewydots == 0))    /* and we picked the dots? */
  358.    i = (int)(((double)sydots / (double)sxdots) * 64.0/screenaspect - 14.5);
  359. else /* must risk loss of precision if numbers low */
  360.    i = (int)((((double)ydots / (double)xdots) / finalaspectratio) * 64 - 14.5);
  361. if (i < 1)   i = 1;
  362. if (i > 255) i = 255;
  363. if (gif87a_flag) i = 0;    /* for some decoders which can't handle aspect */
  364. if (fputc(i,out) != i) goto oops;    /* pixel aspect ratio */
  365.  
  366. #ifndef XFRACT
  367. if (colors == 256) {            /* write out the 256-color palette */
  368.     if (gotrealdac) {         /* got a DAC - must be a VGA */
  369.         if (!shftwrite((BYTE *)dacbox,colors)) goto oops;
  370. #else
  371. if (colors > 2) {
  372.         if (gotrealdac) {               /* got a DAC - must be a VGA */
  373.                 if (!shftwrite((BYTE *)dacbox,256)) goto oops;
  374. #endif
  375.      } else {            /* uh oh - better fake it */
  376.         for (i = 0; i < 256; i += 16)
  377.             if (!shftwrite(paletteEGA,16)) goto oops;
  378.         }
  379.     }
  380. if (colors == 2) {            /* write out the B&W palette */
  381.     if (!shftwrite(paletteBW,colors)) goto oops;
  382.     }
  383. #ifndef XFRACT
  384. if (colors == 4) {            /* write out the CGA palette */
  385.     if (!shftwrite(paletteCGA,colors))goto oops;
  386.     }
  387. if (colors == 16) {            /* Either EGA or VGA */
  388.     if (gotrealdac) {
  389.         if (!shftwrite((BYTE *)dacbox,colors))goto oops;
  390.         }
  391.      else    {            /* no DAC - must be an EGA */
  392.         if (!shftwrite(paletteEGA,colors))goto oops;
  393.         }
  394.     }
  395. #endif
  396.  
  397. if (fwrite(",",1,1,out) != 1) goto oops;  /* Image Descriptor */
  398. i = 0;
  399. if (write2(&i,2,1,out) != 1) goto oops;
  400. if (write2(&i,2,1,out) != 1) goto oops;
  401. if (write2(&width,2,1,out) != 1) goto oops;
  402. if (write2(&ydots,2,1,out) != 1) goto oops;
  403. if (write1(&i,1,1,out) != 1) goto oops;
  404.  
  405. bitsperpixel = (BYTE)(startbits - 1);        /* raster data starts here */
  406. if (write1(&bitsperpixel,1,1,out) != 1) goto oops;
  407.  
  408. codebits = startbits;            /* start encoding */
  409.  
  410. if (!raster(9999)) goto oops;        /* initialize the raster routine */
  411.  
  412. if (!inittable()) goto oops;        /* initialize the LZW tables */
  413.  
  414. for ( rownum = 0; rownum < ydots; rownum++
  415. #ifdef WINFRACT
  416.       , UpdateStatusBox(rownum, ydots)
  417. #endif
  418. ) {  /* scan through the dots */
  419.     for (ydot = rownum; ydot < rowlimit; ydot += ydots) {
  420.     for (xdot = 0; xdot < xdots; xdot++) {
  421.         if (save16bit == 0 || ydot < ydots)
  422.             color = getcolor(xdot,ydot);
  423.         else
  424.             color = readdisk(xdot+sxoffs,ydot+syoffs);
  425.         teststring[0] = (BYTE)++lentest;
  426.         teststring[lentest] = (BYTE)color;
  427.         if (lentest == 1) {        /* root entry? */
  428.             lastentry = color;
  429.             continue;
  430.             }
  431.         if (lentest == 2)        /* init   the hash code */
  432.             hashcode = 301 * (teststring[1]+1);
  433.         hashcode *= (color + lentest);    /* update the hash code */
  434.         hashentry = ++hashcode % MAXENTRY;
  435.         for( i = 0; i < MAXENTRY; i++) {
  436.             if (++hashentry >= MAXENTRY) hashentry = 0;
  437.             if (cmpextra(strlocn[hashentry]+sizeof(int),
  438.                 (char *)teststring,lentest+1) == 0)
  439.                     break;
  440.             if (strlocn[hashentry] == 0) i = MAXENTRY;
  441.             }
  442.         /* found an entry and string length isn't too bad */
  443.         if (strlocn[hashentry] != 0 && lentest < MAXTEST-1-sizeof(int)) {
  444.             fromextra(strlocn[hashentry],(char *)&entrynum,sizeof(int));
  445.             lastentry = entrynum;
  446.             continue;
  447.             }
  448.         if (!raster(lastentry)) goto oops;    /* write entry */
  449.         numentries++;        /* act like you added one, anyway */
  450.         if (strlocn[hashentry] == 0) {    /* add new string, if any */
  451.             entrynum = numentries+endcode;
  452.             strlocn[hashentry] = nextentry;
  453.             toextra(nextentry, (char *)&entrynum,sizeof(int));
  454.             toextra(nextentry+sizeof(int),
  455.                 (char *)teststring,lentest+1);
  456.             nextentry += lentest+1+sizeof(int);
  457.             numrealentries++;
  458.             }
  459.         teststring[0] = 1;        /* reset current entry */
  460.         teststring[1] = (BYTE)color;
  461.         lentest = 1;
  462.         lastentry = color;
  463.  
  464.         if ((numentries+endcode) == (1<<codebits))
  465.             codebits++;         /* use longer encoding */
  466.  
  467.         if ( numentries + endcode > 4093 ||    /* out of room? */
  468.             numrealentries > (MAXENTRY*2)/3 ||
  469.             nextentry > maxstring-MAXTEST-1-2*sizeof(int)) {
  470.             if (!raster(lastentry)) goto oops;    /* flush & restart */
  471.             if (!inittable()) goto oops;
  472.             }
  473.         }
  474.     if (dotmode != 11            /* supress this on disk-video */
  475.         && active_system == 0        /* and in Windows version     */
  476.         && ydot == rownum) {
  477.         if ((ydot & 4) == 0) {
  478.             if (++outcolor1 >= colors) outcolor1 = 0;
  479.             if (++outcolor2 >= colors) outcolor2 = 0;
  480.             }
  481.         for (i = 0; 250*i < xdots; i++) {    /* display vert status bars */
  482.                             /*   (this is NOT GIF-related)    */
  483.             /* PB Changed following code to xor color, so that
  484.                image can be restored at end and resumed
  485.                putcolor(      i,ydot,outcolor1);
  486.                putcolor(xdots-1-i,ydot,outcolor2);
  487.             */
  488.             putcolor(i,ydot,getcolor(i,ydot)^outcolor1);
  489.             putcolor(xdots-1-i,ydot,getcolor(xdots-1-i,ydot)^outcolor2);
  490.             }
  491.         last_colorbar = ydot;
  492.         }
  493. #ifdef WINFRACT
  494.         keypressed();
  495.         if (OperCancelled)
  496. #else
  497.         if (keypressed())                     /* keyboard hit - bail out */
  498. #endif
  499.         ydot = rownum = 9999;
  500.     }
  501.     }
  502.  
  503. if (!raster(lastentry)) goto oops;    /* tidy up - dump the last code */
  504.  
  505. if (!raster(endcode)) goto oops;    /* finish the map */
  506.  
  507. if (fputc(0,out) != 0) goto oops;    /* raster data ends here */
  508.  
  509. if (gif87a_flag == 0) { /* store non-standard fractal info */
  510.     /* loadfile.c has notes about extension block structure */
  511.     if (ydot >= 9999)
  512.         save_info.calc_status = 0; /* partial save is not resumable */
  513.     save_info.tot_extend_len = 0;
  514.     if (resume_info != NULL && save_info.calc_status == 2) {
  515.         /* resume info block, 002 */
  516.         save_info.tot_extend_len += extend_blk_len(resume_len);
  517.         if (!put_extend_blk(2,resume_len,resume_info))goto oops;
  518.         }
  519.     if (save_info.fractal_type == FORMULA || save_info.fractal_type == FFORMULA)
  520.         save_info.tot_extend_len += store_item_name(FormName);
  521.     if (save_info.fractal_type == LSYSTEM)
  522.         save_info.tot_extend_len += store_item_name(LName);
  523.     if (save_info.fractal_type == IFS || save_info.fractal_type == IFS3D)
  524.         save_info.tot_extend_len += store_item_name(IFSName);
  525.     if (display3d <= 0 && rangeslen) {
  526.         /* ranges block, 004 */
  527.         save_info.tot_extend_len += extend_blk_len(rangeslen*2);
  528. #ifdef XFRACT
  529.         fix_ranges(ranges,rangeslen,0);
  530.         put_extend_blk(4,rangeslen*2,(char far *)ranges);
  531.         fix_ranges(ranges,rangeslen,0);
  532. #else
  533.         if (!put_extend_blk(4,rangeslen*2,(char far *)ranges))
  534.             goto oops;
  535. #endif
  536.         }
  537.     /* Extended parameters block 005 */
  538.         if(bf_math)
  539.     {
  540.        save_info.tot_extend_len += extend_blk_len(22*(bflength+2));
  541.        /* note: this assumes variables allocated in order starting with
  542.           bfxmin in init_bf2() in BIGNUM.C */
  543.        if (!put_extend_blk(5,22*(bflength+2),(char far *)bfxmin)) 
  544.           goto oops;
  545.         }
  546.  
  547.     /* main and last block, 001 */
  548.     save_info.tot_extend_len += extend_blk_len(FRACTAL_INFO_SIZE);
  549. #ifdef XFRACT
  550.         decode_fractal_info(&save_info,0);
  551. #endif
  552.     if (!put_extend_blk(1,FRACTAL_INFO_SIZE,(char far *)&save_info)) {
  553.         goto oops;
  554.     }
  555.     }
  556.  
  557. if (fwrite(";",1,1,out) != 1) goto oops;          /* GIF Terminator */
  558.  
  559. return ((ydot < 9999) ? 0 : 1);
  560.  
  561. oops:
  562.     {
  563.     fflush(out);
  564.     stopmsg(0,"Error Writing to disk (Disk full?)");
  565.     return 1;
  566.     }
  567. }
  568.  
  569. static int _fastcall shftwrite(BYTE *color,int numcolors)
  570. /* shift IBM colors to GIF */
  571. {
  572. BYTE thiscolor;
  573. int i,j;
  574. for (i = 0; i < numcolors; i++)
  575.     for (j = 0; j < 3; j++) {
  576.         thiscolor = color[3*i+j];
  577.         thiscolor = (BYTE)(thiscolor << 2);
  578.         thiscolor = (BYTE)(thiscolor + (BYTE)(thiscolor >> 6));
  579.         if (fputc(thiscolor,out) != (int)thiscolor) return(0);
  580.         }
  581. return(1);
  582. }
  583.  
  584. static int inittable()         /* routine to init tables */
  585. {
  586. int i;
  587.  
  588. if (!raster(clearcode)) return(0);    /* signal that table is initialized */
  589.  
  590. numentries = 0;             /* initialize the table */
  591. numrealentries = 0;
  592. nextentry = 1;
  593. lentest = 0;
  594. codebits = startbits;
  595.  
  596. toextra(0,"\0",1);                      /* clear the hash entries */
  597. for (i = 0; i < MAXENTRY; i++)
  598.     strlocn[i] = 0;
  599.  
  600. return(1);
  601. }
  602.  
  603. static int _fastcall raster(unsigned int code)    /* routine to block and output codes */
  604. {
  605. unsigned int icode, i, j;
  606.  
  607. if (code == 9999) {            /* special start-up signal */
  608.     bytecount = 0;
  609.     bitcount = 0;
  610.     for (i = 0; i < 266; i++)
  611.         block[i] = 0;
  612.     return(1);
  613.     }
  614.  
  615. icode = code << bitcount;        /* update the bit string */
  616. block[bytecount  ] |= (icode & 255);
  617. block[bytecount+1] |= ((icode>>8) & 255);
  618. icode = (code>>8) << bitcount;
  619. block[bytecount+2] |= ((icode>>8) & 255);
  620. bitcount += codebits;
  621. while (bitcount >= 8) {         /* locate next starting point */
  622.     bitcount -= 8;
  623.     bytecount++;
  624.     }
  625.  
  626. if (bytecount > 250 || code == (unsigned int)endcode) {    /* time to write a block */
  627.     if (code == (unsigned int)endcode)
  628.         while (bitcount > 0) {        /* if EOF, find the real end */
  629.             bitcount -= 8;
  630.             bytecount++;
  631.             }
  632.     i = bytecount;
  633.     blockcount = (BYTE)i;
  634.         if (write1(&blockcount,1,1,out) != 1) return(0); /* write the block */
  635.     if (fwrite(block,i,1,out) != 1) return(0);
  636.     bytecount = 0;                /* now re-start the block */
  637.     for (j = 0; j < 5; j++)         /* (may have leftover bits) */
  638.         block[j] = block[j+i];
  639.     for (j = 5; j < 266; j++)
  640.         block[j] = 0;
  641.     }
  642. return(1);
  643. }
  644.  
  645.  
  646. static int _fastcall extend_blk_len(int datalen)
  647. {
  648.    return(datalen + (datalen+254)/255 + 15);
  649.    /*       data   +    1.per.block   + 14 for id + 1 for null at end  */
  650. }
  651.  
  652. static int _fastcall put_extend_blk(int block_id,int block_len,char far *block_data)
  653. {
  654.    int i,j;
  655.    char header[15];
  656.    strcpy(header,"!\377\013fractint");
  657.    sprintf(&header[11],"%03u",block_id);
  658.    if (fwrite(header,14,1,out) != 1) return(0);
  659.    i = (block_len + 254) / 255;
  660.    while (--i >= 0) {
  661.       block_len -= (j = min(block_len,255));
  662.       if (fputc(j,out) != j) return(0);
  663.       while (--j >= 0)
  664.      fputc(*(block_data++),out);
  665.       }
  666.    if (fputc(0,out) != 0) return(0);
  667.    return(1);
  668. }
  669.  
  670. static int _fastcall store_item_name(char *nameptr)
  671. {
  672.    char tmpname[40];
  673.    strcpy(tmpname,nameptr);
  674.    /* formula/lsys/ifs info block, 003 */
  675.    put_extend_blk(3,40,tmpname);
  676.    return(extend_blk_len(40));
  677. }
  678.  
  679. static void _fastcall setup_save_info(struct fractal_info far *save_info)
  680. {
  681.    int i;
  682.    if(fractype != FORMULA && fractype != FFORMULA)
  683.       maxfn = 0;     
  684.    /* set save parameters in save structure */
  685.    far_strcpy(save_info->info_id, INFO_ID);
  686.    save_info->version          = 10; /* file version, independant of system */
  687.  
  688.    if(maxit <= 32767)
  689.      save_info->iterationsold      = (short)maxit;
  690.    else
  691.      save_info->iterationsold      = 32767;
  692.  
  693.    save_info->fractal_type    = (short)fractype;
  694.    save_info->xmin          = xxmin;
  695.    save_info->xmax          = xxmax;
  696.    save_info->ymin          = yymin;
  697.    save_info->ymax          = yymax;
  698.    save_info->creal          = param[0];
  699.    save_info->cimag          = param[1];
  700.    save_info->videomodeax     = (short)videoentry.videomodeax;
  701.    save_info->videomodebx     = (short)videoentry.videomodebx;
  702.    save_info->videomodecx     = (short)videoentry.videomodecx;
  703.    save_info->videomodedx     = (short)videoentry.videomodedx;
  704.    save_info->dotmode          = (short)(videoentry.dotmode % 100);
  705.    save_info->xdots          = (short)videoentry.xdots;
  706.    save_info->ydots          = (short)videoentry.ydots;
  707.    save_info->colors          = (short)videoentry.colors;
  708.    save_info->parm3          = 0; /* pre version==7 fields */
  709.    save_info->parm4          = 0;
  710.    save_info->dparm3          = param[2];
  711.    save_info->dparm4          = param[3];
  712.    save_info->dparm5          = param[4];
  713.    save_info->dparm6          = param[5];
  714.    save_info->dparm7          = param[6];
  715.    save_info->dparm8          = param[7];
  716.    save_info->dparm9          = param[8];
  717.    save_info->dparm10         = param[9];
  718.    save_info->fillcolor          = (short)fillcolor;
  719.    save_info->potential[0]    = (float)potparam[0];
  720.    save_info->potential[1]    = (float)potparam[1];
  721.    save_info->potential[2]    = (float)potparam[2];
  722.    save_info->rflag          = (short)rflag;
  723.    save_info->rseed          = (short)rseed;
  724.    save_info->inside          = (short)inside;
  725.    save_info->logmap          = (short)LogFlag;
  726.    save_info->invert[0]       = (float)inversion[0];
  727.    save_info->invert[1]       = (float)inversion[1];
  728.    save_info->invert[2]       = (float)inversion[2];
  729.    save_info->decomp[0]       = (short)decomp[0];
  730.    save_info->biomorph          = (short)usr_biomorph;
  731.    save_info->symmetry          = (short)forcesymmetry;
  732.    for (i = 0; i < 16; i++)
  733.       save_info->init3d[i] = (short)init3d[i];
  734.    save_info->previewfactor   = (short)previewfactor;
  735.    save_info->xtrans          = (short)xtrans;
  736.    save_info->ytrans          = (short)ytrans;
  737.    save_info->red_crop_left   = (short)red_crop_left;
  738.    save_info->red_crop_right  = (short)red_crop_right;
  739.    save_info->blue_crop_left  = (short)blue_crop_left;
  740.    save_info->blue_crop_right = (short)blue_crop_right;
  741.    save_info->red_bright      = (short)red_bright;
  742.    save_info->blue_bright     = (short)blue_bright;
  743.    save_info->xadjust          = (short)xadjust;
  744.    save_info->yadjust          = (short)yadjust;
  745.    save_info->eyeseparation   = (short)eyeseparation;
  746.    save_info->glassestype     = (short)glassestype;
  747.    save_info->outside          = (short)outside;
  748.    save_info->x3rd          = xx3rd;
  749.    save_info->y3rd          = yy3rd;
  750.    save_info->calc_status     = (short)calc_status;
  751.    save_info->stdcalcmode     = (char)((three_pass&&stdcalcmode=='3')?127:stdcalcmode);
  752.    save_info->distest          = (short)distest;
  753.    save_info->floatflag       = floatflag;
  754.  
  755.    if (bailout >= 4 && bailout <= 32000)
  756.      save_info->bailoutold      = (short)bailout;
  757.    else
  758.      save_info->bailoutold      = 0;
  759.  
  760.    save_info->calctime          = calctime;
  761.    save_info->trigndx[0]      = trigndx[0];
  762.    save_info->trigndx[1]      = trigndx[1];
  763.    save_info->trigndx[2]      = trigndx[2];
  764.    save_info->trigndx[3]      = trigndx[3];
  765.    save_info->finattract      = (short)finattract;
  766.    save_info->initorbit[0]    = initorbit.x;
  767.    save_info->initorbit[1]    = initorbit.y;
  768.    save_info->useinitorbit    = useinitorbit;
  769.    save_info->periodicity     = (short)periodicitycheck;
  770.    save_info->pot16bit          = (short)disk16bit;
  771.    save_info->faspectratio    = finalaspectratio;
  772.    save_info->system          = (short)save_system;
  773.  
  774. /* the following should match code in MISCOVL.C */
  775.    if (fractype == LYAPUNOV ||
  776.        fractype == FROTH || fractype == FROTHFP ||
  777.        fix_bof() || fix_period_bof() || use_old_distest || decomp[0] == 2)
  778.      save_info->release          = (short)min(save_release,release);
  779.    else
  780.      save_info->release          = (short)release;
  781.  
  782.    save_info->flag3d          = (short)display3d;
  783.    save_info->ambient          = (short)Ambient;
  784.    save_info->randomize       = (short)RANDOMIZE;
  785.    save_info->haze          = (short)haze;
  786.    save_info->transparent[0]  = (short)transparent[0];
  787.    save_info->transparent[1]  = (short)transparent[1];
  788.    save_info->rotate_lo       = (short)rotate_lo;
  789.    save_info->rotate_hi       = (short)rotate_hi;
  790.    save_info->distestwidth    = (short)distestwidth;
  791.    save_info->mxmaxfp         = mxmaxfp;
  792.    save_info->mxminfp         = mxminfp;
  793.    save_info->mymaxfp         = mymaxfp;
  794.    save_info->myminfp         = myminfp;
  795.    save_info->zdots           = (short)zdots;
  796.    save_info->originfp        = originfp;
  797.    save_info->depthfp         = depthfp;    
  798.    save_info->heightfp        = heightfp;
  799.    save_info->widthfp         = widthfp;    
  800.    save_info->distfp          = distfp;    
  801.    save_info->eyesfp          = eyesfp;    
  802.    save_info->orbittype       = (short)neworbittype;
  803.    save_info->juli3Dmode      = (short)juli3Dmode;
  804.    save_info->maxfn           = maxfn;
  805.    save_info->inversejulia    = (short)((major_method << 8) + minor_method); /* MVS */
  806.    save_info->bailout         = bailout;
  807.    save_info->bailoutest      = (short)bailoutest;
  808.    save_info->iterations      = maxit;
  809.    save_info->bflength        = (short)bnlength;
  810.    save_info->bf_math         = (short)bf_math;
  811.    save_info->old_demm_colors = (short)old_demm_colors;
  812.    for (i = 0; i < sizeof(save_info->future)/sizeof(short); i++)
  813.       save_info->future[i] = 0;
  814. }
  815.