home *** CD-ROM | disk | FTP | other *** search
/ Fractal Creations (Second Edition) / FRACTALS_2E.iso / frasrc.exe / LSYS.C < prev    next >
C/C++ Source or Header  |  1993-02-18  |  22KB  |  896 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #ifdef __TURBOC__
  6. #include <alloc.h>
  7. #elif !defined(__386BSD__)
  8. #include <malloc.h>
  9. #endif
  10. #include "fractint.h"
  11. #include "prototyp.h"
  12.  
  13. #define size    ssize
  14. /* Needed for use of asm -- helps decide which pointer to function
  15.  * to put into the struct lsys_cmds.
  16.  */
  17. extern int cpu;
  18. extern int fpu;
  19. extern int debugflag;
  20. extern int xdots,ydots;
  21. extern int colors;
  22. extern char LFileName[];
  23. extern char LName[];
  24. extern double param[];
  25. extern int overflow;
  26. extern float  screenaspect;
  27.  
  28. struct lsys_cmd {
  29.   char ch;
  30.   void (*f)(long n);
  31.   long n;
  32. };
  33.  
  34. static double      _fastcall getnumber(char far **);
  35. static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_cmd far **,int);
  36. static int      _fastcall findscale(struct lsys_cmd far *, struct lsys_cmd far **, int);
  37. static struct lsys_cmd far * _fastcall drawLSys(struct lsys_cmd far *, struct lsys_cmd far **, int);
  38. static int      _fastcall readLSystemFile(char *);
  39. static void      _fastcall free_rules_mem(void);
  40. static int      _fastcall save_rule(char *,char far **);
  41. static struct lsys_cmd far *SizeTransform(char far *s);
  42. static struct lsys_cmd far *DrawTransform(char far *s);
  43. static void free_lcmds();
  44.  
  45. static long aspect; /* aspect ratio of each pixel, ysize/xsize */
  46.  
  47. /* Some notes to Adrian from PB, made when I integrated with v15:
  48.      printfs changed to work with new user interface
  49.      bug at end of readLSystemFile, the line which said rulind=0 fixed
  50.        to say *rulind=0
  51.      the calloc was not worthwhile, it was just for a 54 byte area, cheaper
  52.        to keep it as a static;    but there was a static 201 char buffer I
  53.        changed to not be static
  54.      use of strdup was a nono, caused problems running out of space cause
  55.        the memory allocated each time was never freed; I've changed to
  56.        use far memory and to free when done
  57.    */
  58.  
  59. long sins[50];
  60. long coss[50];
  61. /* dmaxangle is maxangle - 1. */
  62. char maxangle,dmaxangle,curcolor;
  63. long size;
  64. unsigned long realangle;
  65. long xpos,ypos;
  66. char counter,angle,reverse,stackoflow;
  67. long lsys_Xmin, lsys_Xmax, lsys_Ymin, lsys_Ymax;
  68.  
  69. /* Macro to take an FP number and turn it into a
  70.  * 16/16-bit fixed-point number.
  71.  */
  72. #define FIXEDMUL    524288L
  73. #define FIXEDPT(x)    ((long) (FIXEDMUL * (x)))
  74.  
  75. /* The number by which to multiply sines, cosines and other
  76.  * values with magnitudes less than or equal to 1.
  77.  * sins and coss are a 3/29 bit fixed-point scheme (so the
  78.  * range is +/- 2, with good accuracy.    The range is to
  79.  * avoid overflowing when the aspect ratio is taken into
  80.  * account.
  81.  */
  82. #define FIXEDLT1    536870912.0
  83.  
  84. /* Multiply by this number to convert an unsigned 32-bit long
  85.  * to an angle from 0-2PI.
  86.  */
  87. #define ANGLE2DOUBLE    (2*PI / 4294967296.)
  88.  
  89. static int ispow2(long n)
  90. {
  91.   return (n == (n & -n));
  92. }
  93.  
  94.  
  95. #ifdef XFRACT
  96. static void lsys_doplus(long n)
  97. {
  98.   if (reverse) {
  99.     if (++angle == maxangle)
  100.       angle = 0;
  101.   }
  102.   else {
  103.     if (angle)
  104.       angle--;
  105.     else
  106.       angle = dmaxangle;
  107.   }
  108. }
  109. #endif
  110.  
  111.  
  112. #ifdef XFRACT
  113. /* This is the same as lsys_doplus, except maxangle is a power of 2. */
  114. static void lsys_doplus_pow2(long n)
  115. {
  116.   if (reverse) {
  117.     angle++;
  118.     angle &= dmaxangle;
  119.   }
  120.   else {
  121.     angle--;
  122.     angle &= dmaxangle;
  123.   }
  124. }
  125. #endif
  126.  
  127.  
  128. #ifdef XFRACT
  129. static void lsys_dominus(long n)
  130. {
  131.   if (reverse) {
  132.     if (angle)
  133.       angle--;
  134.     else
  135.       angle = dmaxangle;
  136.   }
  137.   else {
  138.     if (++angle == maxangle)
  139.       angle = 0;
  140.   }
  141. }
  142. #endif
  143.  
  144.  
  145. #ifdef XFRACT
  146. static void lsys_dominus_pow2(long n)
  147. {
  148.   if (reverse) {
  149.     angle--;
  150.     angle &= dmaxangle;
  151.   }
  152.   else {
  153.     angle++;
  154.     angle &= dmaxangle;
  155.   }
  156. }
  157. #endif
  158.  
  159. static void lsys_doslash(long n)
  160. {
  161.   if (reverse)
  162.     realangle -= n;
  163.   else
  164.     realangle += n;
  165. }
  166. #ifdef XFRACT
  167. #define lsys_doslash_386 lsys_doslash
  168. #endif
  169.  
  170. static void lsys_dobslash(long n)
  171. {
  172.   if (reverse)
  173.     realangle += n;
  174.   else
  175.     realangle -= n;
  176. }
  177.  
  178. #ifdef XFRACT
  179. #define lsys_dobslash_386 lsys_dobslash
  180. #endif
  181.  
  182. static void lsys_doat(long n)
  183. {
  184.   size = multiply(size, n, 19);
  185. }
  186.  
  187. #ifdef XFRACT
  188. #define lsys_doat_386 lsys_doat
  189. #endif
  190.  
  191. static void lsys_dopipe(long n)
  192. {
  193.   angle += maxangle / 2;
  194.   angle %= maxangle;
  195. }
  196.  
  197.  
  198. #ifdef XFRACT
  199. static void lsys_dopipe_pow2(long n)
  200. {
  201.   angle += maxangle >> 1;
  202.   angle &= dmaxangle;
  203. }
  204. #endif
  205.  
  206.  
  207. #ifdef XFRACT
  208. static void lsys_dobang(long n)
  209. {
  210.   reverse = ! reverse;
  211. }
  212. #endif
  213.  
  214. static void lsys_dosizedm(long n)
  215. {
  216.   double angle = (double) realangle * ANGLE2DOUBLE;
  217.   double s, c;
  218.   long fixedsin, fixedcos;
  219.   FPUsincos(&angle, &s, &c);
  220.   fixedsin = (long) (s * FIXEDLT1);
  221.   fixedcos = (long) (c * FIXEDLT1);
  222.  
  223.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  224.   ypos += multiply(size, fixedsin, 29);
  225.  
  226. /* xpos+=size*aspect*cos(realangle*PI/180);  */
  227. /* ypos+=size*sin(realangle*PI/180);         */
  228.   if (xpos>lsys_Xmax) lsys_Xmax=xpos;
  229.   if (ypos>lsys_Ymax) lsys_Ymax=ypos;
  230.   if (xpos<lsys_Xmin) lsys_Xmin=xpos;
  231.   if (ypos<lsys_Ymin) lsys_Ymin=ypos;
  232. }
  233.  
  234. static void lsys_dosizegf(long n)
  235. {
  236.   xpos += multiply(size, (long) coss[angle], 29);
  237.   ypos += multiply(size, (long) sins[angle], 29);
  238. /* xpos+=size*coss[angle];                   */
  239. /* ypos+=size*sins[angle];                   */
  240.   if (xpos>lsys_Xmax) lsys_Xmax=xpos;
  241.   if (ypos>lsys_Ymax) lsys_Ymax=ypos;
  242.   if (xpos<lsys_Xmin) lsys_Xmin=xpos;
  243.   if (ypos<lsys_Ymin) lsys_Ymin=ypos;
  244. }
  245.  
  246. #ifdef XFRACT
  247. #define lsys_dosizegf_386 lsys_dosizegf
  248. #endif
  249.  
  250. static void lsys_dodrawd(long n)
  251. {
  252.   double angle = (double) realangle * ANGLE2DOUBLE;
  253.   double s, c;
  254.   long fixedsin, fixedcos;
  255.   int lastx, lasty;
  256.   FPUsincos(&angle, &s, &c);
  257.   fixedsin = (long) (s * FIXEDLT1);
  258.   fixedcos = (long) (c * FIXEDLT1);
  259.  
  260.   lastx=(int) (xpos >> 19);
  261.   lasty=(int) (ypos >> 19);
  262.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  263.   ypos += multiply(size, fixedsin, 29);
  264. /* xpos+=size*aspect*cos(realangle*PI/180);   */
  265. /* ypos+=size*sin(realangle*PI/180);          */
  266.   draw_line(lastx,lasty,(int)(xpos >> 19),(int)(ypos>>19),curcolor);
  267. }
  268.  
  269. static void lsys_dodrawm(long n)
  270. {
  271.   double angle = (double) realangle * ANGLE2DOUBLE;
  272.   double s, c;
  273.   long fixedsin, fixedcos;
  274.   FPUsincos(&angle, &s, &c);
  275.   fixedsin = (long) (s * FIXEDLT1);
  276.   fixedcos = (long) (c * FIXEDLT1);
  277.  
  278. /* xpos+=size*aspect*cos(realangle*PI/180);   */
  279. /* ypos+=size*sin(realangle*PI/180);          */
  280.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  281.   ypos += multiply(size, fixedsin, 29);
  282. }
  283.  
  284. static void lsys_dodrawg(long n)
  285. {
  286.   xpos += multiply(size, (long) coss[angle], 29);
  287.   ypos += multiply(size, (long) sins[angle], 29);
  288. /* xpos+=size*coss[angle];                    */
  289. /* ypos+=size*sins[angle];                    */
  290. }
  291.  
  292. #ifdef XFRACT
  293. #define  lsys_dodrawg_386 lsys_dodrawg
  294. #endif
  295.  
  296. static void lsys_dodrawf(long n)
  297. {
  298.   int lastx = (int) (xpos >> 19);
  299.   int lasty = (int) (ypos >> 19);
  300.   xpos += multiply(size, (long) coss[angle], 29);
  301.   ypos += multiply(size, (long) sins[angle], 29);
  302. /* xpos+=size*coss[angle];                    */
  303. /* ypos+=size*sins[angle];                    */
  304.   draw_line(lastx,lasty,(int)(xpos>>19),(int)(ypos>>19),curcolor);
  305. }
  306.  
  307. static void lsys_dodrawc(long n)
  308. {
  309.   curcolor = ((int) n) % colors;
  310. }
  311.  
  312. static void lsys_dodrawgt(long n)
  313. {
  314.   curcolor -= n;
  315.   if ((curcolor &= colors-1) == 0)
  316.     curcolor = colors-1;
  317. }
  318.  
  319. static void lsys_dodrawlt(long n)
  320. {
  321.   curcolor += n;
  322.   if ((curcolor &= colors-1) == 0)
  323.     curcolor = 1;
  324. }
  325.  
  326. static double _fastcall getnumber(char far **str)
  327. {
  328.    char numstr[30];
  329.    float ret;
  330.    int i,root,inverse;
  331.  
  332.    root=0;
  333.    inverse=0;
  334.    strcpy(numstr,"");
  335.    (*str)++;
  336.    switch (**str)
  337.    {
  338.    case 'q':
  339.       root=1;
  340.       (*str)++;
  341.       break;
  342.    case 'i':
  343.       inverse=1;
  344.       (*str)++;
  345.       break;
  346.    }
  347.    switch (**str)
  348.    {
  349.    case 'q':
  350.       root=1;
  351.       (*str)++;
  352.       break;
  353.    case 'i':
  354.       inverse=1;
  355.       (*str)++;
  356.       break;
  357.    }
  358.    i=0;
  359.    while (**str<='9' && **str>='0' || **str=='.')
  360.    {
  361.       numstr[i++]= **str;
  362.       (*str)++;
  363.    }
  364.    (*str)--;
  365.    numstr[i]=0;
  366.    ret=atof(numstr);
  367.    if (root)
  368.      ret=sqrt(ret);
  369.    if (inverse)
  370.      ret = 1/ret;
  371.    return ret;
  372. }
  373.  
  374. static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *command, struct lsys_cmd far **rules, int depth)
  375. {
  376.    struct lsys_cmd far **rulind;
  377.    int tran;
  378.  
  379. if (overflow)     /* integer math routines overflowed */
  380.     return NULL;
  381.  
  382. #ifndef __TURBOC__
  383.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  384.       stackoflow = 1;
  385.       return NULL;
  386.       }
  387. #endif
  388.  
  389.    while (command->ch && command->ch !=']') {
  390.       if (! (counter++)) {
  391.      /* let user know we're not dead */
  392.      if (thinking(1,"L-System thinking (higher orders take longer)")) {
  393.         counter--;
  394.         return NULL;
  395.      }
  396.       }
  397.       tran=0;
  398.       if (depth) {
  399.      for(rulind=rules;*rulind;rulind++)
  400.         if ((*rulind)->ch==command->ch) {
  401.            tran=1;
  402.            if (findsize((*rulind)+1,rules,depth-1) == NULL)
  403.           return(NULL);
  404.         }
  405.       }
  406.       if (!depth || !tran) {
  407.     if (command->f)
  408.       (*command->f)(command->n);
  409.     else if (command->ch == '[') {
  410.       char saveang,saverev;
  411.       long savesize,savex,savey;
  412.       unsigned long saverang;
  413.  
  414.       saveang=angle;
  415.       saverev=reverse;
  416.       savesize=size;
  417.       saverang=realangle;
  418.       savex=xpos;
  419.       savey=ypos;
  420.       if ((command=findsize(command+1,rules,depth)) == NULL)
  421.          return(NULL);
  422.       angle=saveang;
  423.       reverse=saverev;
  424.       size=savesize;
  425.       realangle=saverang;
  426.       xpos=savex;
  427.       ypos=savey;
  428.     }
  429.       }
  430.       command++;
  431.    }
  432.    return command;
  433. }
  434.  
  435. static int _fastcall findscale(struct lsys_cmd far *command, struct lsys_cmd far **rules, int depth)
  436. {
  437.    float horiz,vert;
  438.    double xmin, xmax, ymin, ymax;
  439.    double locsize;
  440.    double locaspect;
  441.    int i;
  442.    struct lsys_cmd far *fsret;
  443.    locaspect=screenaspect*xdots/ydots;
  444.    aspect = FIXEDPT(locaspect);
  445.    for(i=0;i<maxangle;i++) {
  446.       sins[i]=(long) ((sin(2*i*PI/maxangle)) * FIXEDLT1);
  447.       coss[i]=(long) ((locaspect * cos(2*i*PI/maxangle)) * FIXEDLT1);
  448.    }
  449.    xpos=ypos=lsys_Xmin=lsys_Xmax=lsys_Ymax=lsys_Ymin=angle=reverse=realangle=counter=0;
  450.    size=FIXEDPT(1);
  451.    fsret = findsize(command,rules,depth);
  452.    thinking(0, NULL); /* erase thinking message if any */
  453.    xmin = (double) lsys_Xmin / FIXEDMUL;
  454.    xmax = (double) lsys_Xmax / FIXEDMUL;
  455.    ymin = (double) lsys_Ymin / FIXEDMUL;
  456.    ymax = (double) lsys_Ymax / FIXEDMUL;
  457.    locsize = (double) size / FIXEDMUL;
  458.    if (fsret == NULL)
  459.       return 0;
  460.    if (xmax == xmin)
  461.       horiz = 1E37;
  462.    else
  463.       horiz = (xdots-10)/(xmax-xmin);
  464.    if (ymax == ymin)
  465.       vert = 1E37;
  466.    else
  467.       vert = (ydots-6) /(ymax-ymin);
  468.    locsize = (vert<horiz) ? vert : horiz;
  469.  
  470.    if (horiz == 1E37)
  471.       xpos = FIXEDPT(xdots/2);
  472.    else
  473.       xpos = FIXEDPT(-xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2);
  474.    if (vert == 1E37)
  475.       ypos = FIXEDPT(ydots/2);
  476.    else
  477.       ypos = FIXEDPT(-ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2);
  478.    size = FIXEDPT(locsize);
  479.    return 1;
  480. }
  481.  
  482. static struct lsys_cmd far * _fastcall drawLSys(struct lsys_cmd far *command,struct lsys_cmd far **rules,int depth)
  483. {
  484.    struct lsys_cmd far **rulind;
  485.    int tran;
  486.  
  487. if (overflow)     /* integer math routines overflowed */
  488.     return NULL;
  489.  
  490. #ifndef __TURBOC__
  491.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  492.       stackoflow = 1;
  493.       return NULL;
  494.       }
  495. #endif
  496.  
  497.    while (command->ch && command->ch !=']') {
  498.       if (!(counter++)) {
  499.      if (check_key()) {
  500.         counter--;
  501.         return NULL;
  502.      }
  503.       }
  504.       tran=0;
  505.       if (depth) {
  506.      for(rulind=rules;*rulind;rulind++)
  507.         if ((*rulind)->ch == command->ch) {
  508.            tran=1;
  509.            if (drawLSys((*rulind)+1,rules,depth-1) == NULL)
  510.           return NULL;
  511.         }
  512.       }
  513.       if (!depth||!tran) {
  514.     if (command->f)
  515.       (*command->f)(command->n);
  516.     else if (command->ch == '[') {
  517.       char saveang,saverev,savecolor;
  518.       long savesize,savex,savey;
  519.       unsigned long saverang;
  520.  
  521.       saveang=angle;
  522.       saverev=reverse;
  523.       savesize=size;
  524.       saverang=realangle;
  525.       savex=xpos;
  526.       savey=ypos;
  527.       savecolor=curcolor;
  528.       if ((command=drawLSys(command+1,rules,depth)) == NULL)
  529.          return(NULL);
  530.       angle=saveang;
  531.       reverse=saverev;
  532.       size=savesize;
  533.       realangle=saverang;
  534.       xpos=savex;
  535.       ypos=savey;
  536.       curcolor=savecolor;
  537.     }
  538.       }
  539.       command++;
  540.    }
  541.    return command;
  542. }
  543.  
  544. #define MAXRULES 27 /* this limits rules to 25 */
  545. static char far *ruleptrs[MAXRULES];
  546. static struct lsys_cmd far *rules2[MAXRULES];
  547.  
  548. static int _fastcall readLSystemFile(char *str)
  549. {
  550.    int c;
  551.    char far **rulind;
  552.    int err=0;
  553.    int linenum,check=0;
  554.    char inline[161],fixed[161],*word;
  555.    FILE *infile;
  556.    char msgbuf[481]; /* enough for 6 full lines */
  557.  
  558.    if (find_file_item(LFileName,str,&infile) < 0)
  559.       return -1;
  560.    while ((c = fgetc(infile)) != '{')
  561.       if (c == EOF) return -1;
  562.  
  563.    maxangle=0;
  564.    for(linenum=0;linenum<MAXRULES;++linenum) ruleptrs[linenum]=NULL;
  565.    rulind= &ruleptrs[1];
  566.    msgbuf[0]=linenum=0;
  567.  
  568.    while(fgets(inline,160,infile))  /* Max line length 160 chars */
  569.    {
  570.       linenum++;
  571.       if ((word = strchr(inline,';'))) /* strip comment */
  572.      *word = 0;
  573.       strlwr(inline);
  574.  
  575.       if (strspn(inline," \t\n") < strlen(inline)) /* not a blank line */
  576.       {
  577.      word=strtok(inline," =\t\n");
  578.      if (!strcmp(word,"axiom"))
  579.      {
  580.         save_rule(strtok(NULL," \t\n"),&ruleptrs[0]);
  581.         check=1;
  582.      }
  583.      else if (!strcmp(word,"angle"))
  584.      {
  585.         maxangle=atoi(strtok(NULL," \t\n"));
  586.         dmaxangle = maxangle - 1;
  587.         check=1;
  588.      }
  589.      else if (!strcmp(word,"}"))
  590.         break;
  591.      else if (strlen(word)==1)
  592.      {
  593.         char *tok;
  594.         tok = strtok(NULL, " \t\n");
  595.         strcpy(fixed, word);
  596.         if (tok != NULL) {     /* Some strcat's die if they cat with NULL */
  597.         strcat(fixed, tok);
  598.         }
  599.         save_rule(fixed, rulind++);
  600.         check=1;
  601.      }
  602.      else
  603.         if (err<6)
  604.         {
  605.            sprintf(&msgbuf[strlen(msgbuf)],
  606.                "Syntax error line %d: %s\n",linenum,word);
  607.            ++err;
  608.         }
  609.      if (check)
  610.      {
  611.         check=0;
  612.         if(word=strtok(NULL," \t\n"))
  613.            if (err<6)
  614.            {
  615.           sprintf(&msgbuf[strlen(msgbuf)],
  616.              "Extra text after command line %d: %s\n",linenum,word);
  617.           ++err;
  618.            }
  619.      }
  620.       }
  621.    }
  622.    fclose(infile);
  623.    if (!ruleptrs[0] && err<6)
  624.    {
  625.       strcat(msgbuf,"Error:  no axiom\n");
  626.       ++err;
  627.    }
  628.    if ((maxangle<3||maxangle>50) && err<6)
  629.    {
  630.       strcat(msgbuf,"Error:  illegal or missing angle\n");
  631.       ++err;
  632.    }
  633.    if (err)
  634.    {
  635.       msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */
  636.       stopmsg(0,msgbuf);
  637.       return -1;
  638.    }
  639.    *rulind=NULL;
  640.    return 0;
  641. }
  642.  
  643. static char loaded=0;
  644.  
  645. int Lsystem()
  646. {
  647.    int order;
  648.    char far **rulesc;
  649.    struct lsys_cmd far **sc;
  650.  
  651.    if ( (!loaded) && LLoad())
  652.      return -1;
  653.  
  654.    overflow = 0;        /* reset integer math overflow flag */
  655.  
  656.    order=param[0];
  657.    if (order<=0)
  658.      order=0;
  659.    stackoflow = 0;
  660.  
  661.    sc = rules2;
  662.    for (rulesc = ruleptrs; *rulesc; rulesc++)
  663.      *sc++ = SizeTransform(*rulesc);
  664.    *sc = NULL;
  665.  
  666.    if (findscale(rules2[0], &rules2[1], order)) {
  667.       realangle = angle = reverse = 0;
  668.  
  669.       free_lcmds();
  670.       sc = rules2;
  671.       for (rulesc = ruleptrs; *rulesc; rulesc++)
  672.     *sc++ = DrawTransform(*rulesc);
  673.       *sc = NULL;
  674.  
  675.       /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
  676.       if ((curcolor=15) > colors) curcolor=colors-1;
  677.       drawLSys(rules2[0], &rules2[1], order);
  678.    }
  679.    if (stackoflow)
  680.    {
  681.       static char far msg[]={"insufficient memory, try a lower order"};
  682.       stopmsg(0,msg);
  683.    }
  684.    if (overflow) {
  685.       static char far msg[]={"Integer math routines failed, try a lower order"};
  686.       stopmsg(0,msg);
  687.       }
  688.    free_rules_mem();
  689.    free_lcmds();
  690.    loaded=0;
  691.    return 0;
  692. }
  693.  
  694. int LLoad()
  695. {
  696.    char i;
  697.    if (readLSystemFile(LName)) { /* error occurred */
  698.       free_rules_mem();
  699.       loaded=0;
  700.       return -1;
  701.    }
  702.    for(i=0;i<maxangle;i++) {
  703.       sins[i]=(long) ((sin(2*i*PI/maxangle)) * FIXEDLT1);
  704.       coss[i]=(long) (((double) aspect / (double) FIXEDMUL * cos(2*i*PI/maxangle)) * FIXEDLT1);
  705.    }
  706.    loaded=1;
  707.    return 0;
  708. }
  709.  
  710. static void _fastcall free_rules_mem()
  711. {
  712.    int i;
  713.    for(i=0;i<MAXRULES;++i)
  714.       if(ruleptrs[i]) farmemfree(ruleptrs[i]);
  715. }
  716.  
  717. static int _fastcall save_rule(char *rule,char far **saveptr)
  718. {
  719.    int i;
  720.    char far *tmpfar;
  721.    i=strlen(rule)+1;
  722.    if((tmpfar=farmemalloc((long)i))==NULL) {
  723.        stackoflow = 1;
  724.        return -1;
  725.        }
  726.    *saveptr=tmpfar;
  727.    while(--i>=0) *(tmpfar++)= *(rule++);
  728.    return 0;
  729. }
  730.  
  731. static struct lsys_cmd far *SizeTransform(char far *s)
  732. {
  733.   struct lsys_cmd far *ret;
  734.   struct lsys_cmd far *doub;
  735.   int maxval = 10;
  736.   int n = 0;
  737.   void (*f)(long);
  738.   long num;
  739.  
  740.   void (*plus)(long) = (ispow2(maxangle)) ? lsys_doplus_pow2 : lsys_doplus;
  741.   void (*minus)(long) = (ispow2(maxangle)) ? lsys_dominus_pow2 : lsys_dominus;
  742.   void (*pipe)(long) = (ispow2(maxangle)) ? lsys_dopipe_pow2 : lsys_dopipe;
  743.  
  744.   void (*slash)(long) =  (cpu == 386) ? lsys_doslash_386 : lsys_doslash;
  745.   void (*bslash)(long) = (cpu == 386) ? lsys_dobslash_386 : lsys_dobslash;
  746.   void (*at)(long) =     (cpu == 386) ? lsys_doat_386 : lsys_doat;
  747.   void (*dogf)(long) =   (cpu == 386) ? lsys_dosizegf_386 : lsys_dosizegf;
  748.  
  749.   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
  750.   if (ret == NULL) {
  751.        stackoflow = 1;
  752.        return NULL;
  753.        }
  754.   while (*s) {
  755.     f = NULL;
  756.     num = 0;
  757.     ret[n].ch = *s;
  758.     switch (*s) {
  759.       case '+': f = plus;            break;
  760.       case '-': f = minus;           break;
  761.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  762.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  763.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  764.       case '|': f = pipe;            break;
  765.       case '!': f = lsys_dobang;     break;
  766.       case 'd':
  767.       case 'm': f = lsys_dosizedm;   break;
  768.       case 'g':
  769.       case 'f': f = dogf;       break;
  770.       case '[': num = 1;        break;
  771.       case ']': num = 2;        break;
  772.       default:
  773.     num = 3;
  774.     break;
  775.     }
  776.     ret[n].f = f;
  777.     ret[n].n = num;
  778.     if (++n == maxval) {
  779.       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
  780.       if (doub == NULL) {
  781.          farmemfree(ret);
  782.          stackoflow = 1;
  783.          return NULL;
  784.          }
  785.       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
  786.       farmemfree(ret);
  787.       ret = doub;
  788.       maxval <<= 1;
  789.     }
  790.     s++;
  791.   }
  792.   ret[n].ch = 0;
  793.   ret[n].f = NULL;
  794.   ret[n].n = 0;
  795.   n++;
  796.  
  797.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  798.   if (doub == NULL) {
  799.        farmemfree(ret);
  800.        stackoflow = 1;
  801.        return NULL;
  802.        }
  803.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  804.   farmemfree(ret);
  805.   return doub;
  806. }
  807.  
  808. static struct lsys_cmd far *DrawTransform(char far *s)
  809. {
  810.   struct lsys_cmd far *ret;
  811.   struct lsys_cmd far *doub;
  812.   int maxval = 10;
  813.   int n = 0;
  814.   void (*f)(long);
  815.   long num;
  816.  
  817.   void (*plus)(long) = (ispow2(maxangle)) ? lsys_doplus_pow2 : lsys_doplus;
  818.   void (*minus)(long) = (ispow2(maxangle)) ? lsys_dominus_pow2 : lsys_dominus;
  819.   void (*pipe)(long) = (ispow2(maxangle)) ? lsys_dopipe_pow2 : lsys_dopipe;
  820.  
  821.   void (*slash)(long) =  (cpu == 386) ? lsys_doslash_386 : lsys_doslash;
  822.   void (*bslash)(long) = (cpu == 386) ? lsys_dobslash_386 : lsys_dobslash;
  823.   void (*at)(long) =     (cpu == 386) ? lsys_doat_386 : lsys_doat;
  824.   void (*drawg)(long) =  (cpu == 386) ? lsys_dodrawg_386 : lsys_dodrawg;
  825.  
  826.   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
  827.   if (ret == NULL) {
  828.        stackoflow = 1;
  829.        return NULL;
  830.        }
  831.   while (*s) {
  832.     f = NULL;
  833.     num = 0;
  834.     ret[n].ch = *s;
  835.     switch (*s) {
  836.       case '+': f = plus;            break;
  837.       case '-': f = minus;           break;
  838.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  839.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  840.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  841.       case '|': f = pipe;            break;
  842.       case '!': f = lsys_dobang;     break;
  843.       case 'd': f = lsys_dodrawd;    break;
  844.       case 'm': f = lsys_dodrawm;    break;
  845.       case 'g': f = drawg;           break;
  846.       case 'f': f = lsys_dodrawf;    break;
  847.       case 'c': f = lsys_dodrawc;    num = getnumber(&s);    break;
  848.       case '<': f = lsys_dodrawlt;   num = getnumber(&s);    break;
  849.       case '>': f = lsys_dodrawgt;   num = getnumber(&s);    break;
  850.       case '[': num = 1;        break;
  851.       case ']': num = 2;        break;
  852.       default:
  853.     num = 3;
  854.     break;
  855.     }
  856.     ret[n].f = f;
  857.     ret[n].n = num;
  858.     if (++n == maxval) {
  859.       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
  860.       if (doub == NULL) {
  861.            farmemfree(ret);
  862.            stackoflow = 1;
  863.            return NULL;
  864.            }
  865.       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
  866.       farmemfree(ret);
  867.       ret = doub;
  868.       maxval <<= 1;
  869.     }
  870.     s++;
  871.   }
  872.   ret[n].ch = 0;
  873.   ret[n].f = NULL;
  874.   ret[n].n = 0;
  875.   n++;
  876.  
  877.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  878.   if (doub == NULL) {
  879.        farmemfree(ret);
  880.        stackoflow = 1;
  881.        return NULL;
  882.        }
  883.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  884.   farmemfree(ret);
  885.   return doub;
  886. }
  887.  
  888. static void free_lcmds()
  889. {
  890.   struct lsys_cmd far **sc = rules2;
  891.  
  892.   while (*sc)
  893.     farmemfree(*sc++);
  894. }
  895.  
  896.