File: common\lsys.c
1
2 #include <string.h>
3 #ifdef __TURBOC__
5 #else
6 #include <malloc.h>
7 #endif
8
9 /* see Fractint.c for a description of the "include" hierarchy */
10 #include "port.h"
11 #include "prototyp.h"
12 #include "lsys.h"
13
14 struct lsys_cmd {
15 void (*f)(struct lsys_turtlestatei *);
16 long n;
17 char ch;
18 };
19
20 static int _fastcall readLSystemFile(char *);
21 static void _fastcall free_rules_mem(void);
22 static int _fastcall rule_present(char symbol);
23 static int _fastcall save_rule(char *,char far **);
24 static int _fastcall append_rule(char *rule, int index);
25 static void free_lcmds(void);
26 static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_turtlestatei *, struct lsys_cmd far **,int);
27 static struct lsys_cmd far * drawLSysI(struct lsys_cmd far *command,struct lsys_turtlestatei *ts, struct lsys_cmd far **rules,int depth);
28 static int lsysi_findscale(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth);
29 static struct lsys_cmd far *LSysISizeTransform(char far *s, struct lsys_turtlestatei *ts);
30 static struct lsys_cmd far *LSysIDrawTransform(char far *s, struct lsys_turtlestatei *ts);
31 static void _fastcall lsysi_dosincos(void);
32
33 static void lsysi_doslash(struct lsys_turtlestatei *cmd);
34 static void lsysi_dobslash(struct lsys_turtlestatei *cmd);
35 static void lsysi_doat(struct lsys_turtlestatei *cmd);
36 static void lsysi_dopipe(struct lsys_turtlestatei *cmd);
37 static void lsysi_dosizedm(struct lsys_turtlestatei *cmd);
38 static void lsysi_dosizegf(struct lsys_turtlestatei *cmd);
39 static void lsysi_dodrawd(struct lsys_turtlestatei *cmd);
40 static void lsysi_dodrawm(struct lsys_turtlestatei *cmd);
41 static void lsysi_dodrawg(struct lsys_turtlestatei *cmd);
42 static void lsysi_dodrawf(struct lsys_turtlestatei *cmd);
43 static void lsysi_dodrawc(struct lsys_turtlestatei *cmd);
44 static void lsysi_dodrawgt(struct lsys_turtlestatei *cmd);
45 static void lsysi_dodrawlt(struct lsys_turtlestatei *cmd);
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 #define sins ((long *)(boxy))
60 #define coss (((long *)(boxy)+50)) /* 50 after the start of sins */
61 static char far *ruleptrs[MAXRULES];
62 static struct lsys_cmd far *rules2[MAXRULES];
63 char maxangle;
64 static char loaded=0;
65
66
67 int _fastcall ispow2(int n)
68 {
69 return (n == (n & -n));
70 }
71
72 LDBL _fastcall getnumber(char far **str)
73 {
74 char numstr[30];
75 LDBL ret;
76 int i,root,inverse;
77
78 root=0;
79 inverse=0;
80 strcpy(numstr,"");
81 (*str)++;
82 switch (**str)
83 {
84 case 'q':
85 root=1;
86 (*str)++;
87 break;
88 case 'i':
89 inverse=1;
90 (*str)++;
91 break;
92 }
93 switch (**str)
94 {
95 case 'q':
96 root=1;
97 (*str)++;
98 break;
99 case 'i':
100 inverse=1;
101 (*str)++;
102 break;
103 }
104 i=0;
105 while ((**str<='9' && **str>='0') || **str=='.')
106 {
107 numstr[i++]= **str;
108 (*str)++;
109 }
110 (*str)--;
111 numstr[i]=0;
112 ret=atof(numstr);
113 if (ret <= 0.0) /* this is a sanity check, JCO 8/31/94 */
114 return 0;
115 if (root)
116 ret=sqrtl(ret);
117 if (inverse)
118 ret = 1.0/ret;
119 return ret;
120 }
121
122 static int _fastcall readLSystemFile(char *str)
123 {
124 int c;
125 char far **rulind;
126 int err=0;
127 int linenum,check=0;
128 char inline1[MAX_LSYS_LINE_LEN+1],fixed[MAX_LSYS_LINE_LEN+1],*word;
129 FILE *infile;
130 char msgbuf[481]; /* enough for 6 full lines */
131
132 if (find_file_item(LFileName,str,&infile, 2) < 0)
133 return -1;
134 while ((c = fgetc(infile)) != '{')
135 if (c == EOF) return -1;
136 maxangle=0;
137 for(linenum=0;linenum<MAXRULES;++linenum) ruleptrs[linenum]=NULL;
138 rulind= &ruleptrs[1];
139 msgbuf[0]=(char)(linenum=0);
140
141 while(file_gets(inline1,MAX_LSYS_LINE_LEN,infile) > -1) /* Max line length chars */
142 {
143 static FCODE out_of_mem[] = {"Error: out of memory\n"};
144 linenum++;
145 if ((word = strchr(inline1,';')) != NULL) /* strip comment */
146 *word = 0;
147 strlwr(inline1);
148
149 if ((int)strspn(inline1," \t\n") < (int)strlen(inline1)) /* not a blank line */
150 {
151 word=strtok(inline1," =\t\n");
152 if (!strcmp(word,"axiom"))
153 {
154 if (save_rule(strtok(NULL," \t\n"),&ruleptrs[0])) {
155 far_strcat(msgbuf,out_of_mem);
156 ++err;
157 break;
158 }
159 check=1;
160 }
161 else if (!strcmp(word,"angle"))
162 {
163 maxangle=(char)atoi(strtok(NULL," \t\n"));
164 check=1;
165 }
166 else if (!strcmp(word,"}"))
167 break;
168 else if (!word[1])
169 {
170 char *temp;
171 int index, memerr = 0;
172
173 if (strchr("+-/\\@|!c<>][", *word))
174 {
175 sprintf(&msgbuf[strlen(msgbuf)],
176 "Syntax error line %d: Redefined reserved symbol %s\n",linenum,word);
177 ++err;
178 break;
179 }
180 temp = strtok(NULL," =\t\n");
181 index = rule_present(*word);
182
183 if (!index)
184 {
185 strcpy(fixed,word);
186 if (temp)
187 strcat(fixed,temp);
188 memerr = save_rule(fixed,rulind++);
189 }
190 else if (temp)
191 {
192 strcpy(fixed,temp);
193 memerr = append_rule(fixed,index);
194 }
195 if (memerr) {
196 far_strcat(msgbuf, out_of_mem);
197 ++err;
198 break;
199 }
200 check=1;
201 }
202 else
203 if (err<6)
204 {
205 sprintf(&msgbuf[strlen(msgbuf)],
206 "Syntax error line %d: %s\n",linenum,word);
207 ++err;
208 }
209 if (check)
210 {
211 check=0;
212 if((word=strtok(NULL," \t\n"))!=NULL)
213 if (err<6)
214 {
215 sprintf(&msgbuf[strlen(msgbuf)],
216 "Extra text after command line %d: %s\n",linenum,word);
217 ++err;
218 }
219 }
220 }
221 }
222 fclose(infile);
223 if (!ruleptrs[0] && err<6)
224 {
225 static FCODE no_axiom[] = {"Error: no axiom\n"};
226 far_strcat(msgbuf,no_axiom);
227 ++err;
228 }
229 if ((maxangle<3||maxangle>50) && err<6)
230 {
231 static FCODE missing_angle[] = {"Error: illegal or missing angle\n"};
232 far_strcat(msgbuf,missing_angle);
233 ++err;
234 }
235 if (err)
236 {
237 msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */
238 stopmsg(0,msgbuf);
239 return -1;
240 }
241 *rulind=NULL;
242 return 0;
243 }
244
245 int Lsystem(void)
246 {
247 int order;
248 char far **rulesc;
249 struct lsys_cmd far **sc;
250 int stackoflow = 0;
251
252 if ( (!loaded) && LLoad())
253 return -1;
254
255 overflow = 0; /* reset integer math overflow flag */
256
257 order=(int)param[0];
258 if (order<=0)
259 order=0;
260 if (usr_floatflag)
261 overflow = 1;
262 else {
263 struct lsys_turtlestatei ts;
264
265 ts.stackoflow = 0;
266 ts.maxangle = maxangle;
267 ts.dmaxangle = (char)(maxangle - 1);
268
269 sc = rules2;
270 for (rulesc = ruleptrs; *rulesc; rulesc++)
271 *sc++ = LSysISizeTransform(*rulesc, &ts);
272 *sc = NULL;
273
274 lsysi_dosincos();
275 if (lsysi_findscale(rules2[0], &ts, &rules2[1], order)) {
276 ts.realangle = ts.angle = ts.reverse = 0;
277
278 free_lcmds();
279 sc = rules2;
280 for (rulesc = ruleptrs; *rulesc; rulesc++)
281 *sc++ = LSysIDrawTransform(*rulesc, &ts);
282 *sc = NULL;
283
284 /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
285 if ((ts.curcolor=15) > colors)
286 ts.curcolor=(char)(colors-1);
287 drawLSysI(rules2[0], &ts, &rules2[1], order);
288 }
289 stackoflow = ts.stackoflow;
290 }
291
292 if (stackoflow) {
293 static FCODE msg[]={"insufficient memory, try a lower order"};
294 stopmsg(0,msg);
295 }
296 else if (overflow) {
297 struct lsys_turtlestatef ts;
298
299 overflow = 0;
300
301 ts.stackoflow = 0;
302 ts.maxangle = maxangle;
303 ts.dmaxangle = (char)(maxangle - 1);
304
305 sc = rules2;
306 for (rulesc = ruleptrs; *rulesc; rulesc++)
307 *sc++ = LSysFSizeTransform(*rulesc, &ts);
308 *sc = NULL;
309
310 lsysf_dosincos();
311 if (lsysf_findscale(rules2[0], &ts, &rules2[1], order)) {
312 ts.realangle = ts.angle = ts.reverse = 0;
313
314 free_lcmds();
315 sc = rules2;
316 for (rulesc = ruleptrs; *rulesc; rulesc++)
317 *sc++ = LSysFDrawTransform(*rulesc, &ts);
318 *sc = NULL;
319
320 /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
321 if ((ts.curcolor=15) > colors)
322 ts.curcolor=(char)(colors-1);
323 lsys_prepfpu(&ts);
324 drawLSysF(rules2[0], &ts, &rules2[1], order);
325 lsys_donefpu(&ts);
326 }
327 overflow = 0;
328 }
329 free_rules_mem();
330 free_lcmds();
331 loaded=0;
332 return 0;
333 }
334
335 int LLoad(void)
336 {
337 if (readLSystemFile(LName)) { /* error occurred */
338 free_rules_mem();
339 loaded=0;
340 return -1;
341 }
342 loaded=1;
343 return 0;
344 }
345
346 static void _fastcall free_rules_mem(void)
347 {
348 int i;
349 for(i=0;i<MAXRULES;++i)
350 if(ruleptrs[i]) farmemfree(ruleptrs[i]);
351 }
352
353 static int _fastcall rule_present(char symbol)
354 {
355 int i;
356
357 for (i = 1; i < MAXRULES && ruleptrs[i] && *ruleptrs[i] != symbol ; i++)
358 ;
359 return (i < MAXRULES && ruleptrs[i]) ? i : 0;
360 }
361
362 static int _fastcall save_rule(char *rule,char far **saveptr)
363 {
364 int i;
365 char far *tmpfar;
366 i=strlen(rule)+1;
367 if((tmpfar=(char far *)farmemalloc((long)i))==NULL) {
368 return -1;
369 }
370 *saveptr=tmpfar;
371 while(--i>=0) *(tmpfar++)= *(rule++);
372 return 0;
373 }
374
375 static int _fastcall append_rule(char *rule, int index)
376 {
377 char far *dst, far *old, far *sav;
378 int i, j;
379
380 old = sav = ruleptrs[index];
381 for (i = 0; *(old++); i++)
382 ;
383 j = strlen(rule) + 1;
384 if ((dst = (char far *)farmemalloc((long)(i + j))) == NULL)
385 return -1;
386
387 old = sav;
388 ruleptrs[index] = dst;
389 while (i-- > 0) *(dst++) = *(old++);
390 while (j-- > 0) *(dst++) = *(rule++);
391 farmemfree(sav);
392 return 0;
393 }
394
395 static void free_lcmds(void)
396 {
397 struct lsys_cmd far **sc = rules2;
398
399 while (*sc)
400 farmemfree(*sc++);
401 }
402
403 #ifdef XFRACT
411 #endif
412
413 /* integer specific routines */
414
415 #ifdef XFRACT
429 #else
430 extern void lsysi_doplus(struct lsys_turtlestatei *cmd);
431 #endif
432
433 #ifdef XFRACT
434 /* This is the same as lsys_doplus, except maxangle is a power of 2. */
435 static void lsysi_doplus_pow2(struct lsys_turtlestatei *cmd)
436 {
437 if (cmd->reverse) {
438 cmd->angle++;
439 cmd->angle &= cmd->dmaxangle;
440 }
441 else {
442 cmd->angle--;
443 cmd->angle &= cmd->dmaxangle;
444 }
445 } 446 #else
447 extern void lsysi_doplus_pow2(struct lsys_turtlestatei *cmd);
448 #endif
449
450 #ifdef XFRACT
464 #else
465 extern void lsysi_dominus(struct lsys_turtlestatei *cmd);
466 #endif
467
468 #ifdef XFRACT
480 #else
481 extern void lsysi_dominus_pow2(struct lsys_turtlestatei *cmd);
482 #endif
483
484 static void lsysi_doslash(struct lsys_turtlestatei *cmd)
485 {
486 if (cmd->reverse)
487 cmd->realangle -= cmd->num;
488 else
489 cmd->realangle += cmd->num;
490 }
491
492 #ifndef XFRACT
493 extern void lsysi_doslash_386(struct lsys_turtlestatei *cmd);
494 #endif
495
496 static void lsysi_dobslash(struct lsys_turtlestatei *cmd)
497 {
498 if (cmd->reverse)
499 cmd->realangle += cmd->num;
500 else
501 cmd->realangle -= cmd->num;
502 }
503
504 #ifndef XFRACT
505 extern void lsysi_dobslash_386(struct lsys_turtlestatei *cmd);
506 #endif
507
508 static void lsysi_doat(struct lsys_turtlestatei *cmd)
509 {
510 cmd->size = multiply(cmd->size, cmd->num, 19);
511 }
512
513 static void lsysi_dopipe(struct lsys_turtlestatei *cmd)
514 {
515 cmd->angle = (char)(cmd->angle + (char)(cmd->maxangle / 2));
516 cmd->angle %= cmd->maxangle;
517 }
518
519 #ifdef XFRACT
525 #else
526 extern void lsysi_dopipe_pow2(struct lsys_turtlestatei *cmd);
527 #endif
528
529 #ifdef XFRACT
534 #else
535 extern void lsysi_dobang(struct lsys_turtlestatei *cmd);
536 #endif
537
538 static void lsysi_dosizedm(struct lsys_turtlestatei *cmd)
539 {
540 double angle = (double) cmd->realangle * ANGLE2DOUBLE;
541 double s, c;
542 long fixedsin, fixedcos;
543
544 FPUsincos(&angle, &s, &c);
545 fixedsin = (long) (s * FIXEDLT1);
546 fixedcos = (long) (c * FIXEDLT1);
547
548 cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
549 cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
550
551 /* xpos+=size*aspect*cos(realangle*PI/180); */
552 /* ypos+=size*sin(realangle*PI/180); */
553 if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
554 if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
555 if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
556 if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
557 }
558
559 static void lsysi_dosizegf(struct lsys_turtlestatei *cmd)
560 {
561 cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[(int)cmd->angle], 29));
562 cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[(int)cmd->angle], 29));
563 /* xpos+=size*coss[angle]; */
564 /* ypos+=size*sins[angle]; */
565 if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
566 if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
567 if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
568 if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
569 }
570
571 static void lsysi_dodrawd(struct lsys_turtlestatei *cmd)
572 {
573 double angle = (double) cmd->realangle * ANGLE2DOUBLE;
574 double s, c;
575 long fixedsin, fixedcos;
576 int lastx, lasty;
577
578 FPUsincos(&angle, &s, &c);
579 fixedsin = (long) (s * FIXEDLT1);
580 fixedcos = (long) (c * FIXEDLT1);
581
582 lastx=(int) (cmd->xpos >> 19);
583 lasty=(int) (cmd->ypos >> 19);
584 cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
585 cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
586 /* xpos+=size*aspect*cos(realangle*PI/180); */
587 /* ypos+=size*sin(realangle*PI/180); */
588 draw_line(lastx,lasty,(int)(cmd->xpos >> 19),(int)(cmd->ypos >> 19),cmd->curcolor);
589 }
590
591 static void lsysi_dodrawm(struct lsys_turtlestatei *cmd)
592 {
593 double angle = (double) cmd->realangle * ANGLE2DOUBLE;
594 double s, c;
595 long fixedsin, fixedcos;
596
597 FPUsincos(&angle, &s, &c);
598 fixedsin = (long) (s * FIXEDLT1);
599 fixedcos = (long) (c * FIXEDLT1);
600
601 /* xpos+=size*aspect*cos(realangle*PI/180); */
602 /* ypos+=size*sin(realangle*PI/180); */
603 cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
604 cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
605 }
606
607 static void lsysi_dodrawg(struct lsys_turtlestatei *cmd)
608 {
609 cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[(int)cmd->angle], 29));
610 cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[(int)cmd->angle], 29));
611 /* xpos+=size*coss[angle]; */
612 /* ypos+=size*sins[angle]; */
613 }
614
615 static void lsysi_dodrawf(struct lsys_turtlestatei *cmd)
616 {
617 int lastx = (int) (cmd->xpos >> 19);
618 int lasty = (int) (cmd->ypos >> 19);
619 cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[(int)cmd->angle], 29));
620 cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[(int)cmd->angle], 29));
621 /* xpos+=size*coss[angle]; */
622 /* ypos+=size*sins[angle]; */
623 draw_line(lastx,lasty,(int)(cmd->xpos >> 19),(int)(cmd->ypos >> 19),cmd->curcolor);
624 }
625
626 static void lsysi_dodrawc(struct lsys_turtlestatei *cmd)
627 {
628 cmd->curcolor = (char)(((int) cmd->num) % colors);
629 }
630
631 static void lsysi_dodrawgt(struct lsys_turtlestatei *cmd)
632 {
633 cmd->curcolor = (char)(cmd->curcolor - (char)cmd->num);
634 if ((cmd->curcolor %= colors) == 0)
635 cmd->curcolor = (char)(colors-1);
636 }
637
638 static void lsysi_dodrawlt(struct lsys_turtlestatei *cmd)
639 {
640 cmd->curcolor = (char)(cmd->curcolor + (char)cmd->num);
641 if ((cmd->curcolor %= colors) == 0)
642 cmd->curcolor = 1;
643 }
644
645 static struct lsys_cmd far * _fastcall
646 findsize(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth)
647 {
648 struct lsys_cmd far **rulind;
649 int tran;
650
651 if (overflow) /* integer math routines overflowed */
652 return NULL;
653
654 if (stackavail() < 400) { /* leave some margin for calling subrtns */
655 ts->stackoflow = 1;
656 return NULL;
657 }
658
659 while (command->ch && command->ch !=']') {
660 static FCODE thinking_msg[] =
661 {"L-System thinking (higher orders take longer)"};
662 if (! (ts->counter++)) {
663 /* let user know we're not dead */
664 if (thinking(1,thinking_msg)) {
665 ts->counter--;
666 return NULL;
667 }
668 }
669 tran=0;
670 if (depth) {
671 for(rulind=rules;*rulind;rulind++)
672 if ((*rulind)->ch==command->ch) {
673 tran=1;
674 if (findsize((*rulind)+1,ts,rules,depth-1) == NULL)
675 return(NULL);
676 }
677 }
678 if (!depth || !tran) {
679 if (command->f) {
680 ts->num = command->n;
681 (*command->f)(ts);
682 }
683 else if (command->ch == '[') {
684 char saveang,saverev;
685 long savesize,savex,savey;
686 unsigned long saverang;
687
688 saveang=ts->angle;
689 saverev=ts->reverse;
690 savesize=ts->size;
691 saverang=ts->realangle;
692 savex=ts->xpos;
693 savey=ts->ypos;
694 if ((command=findsize(command+1,ts,rules,depth)) == NULL)
695 return(NULL);
696 ts->angle=saveang;
697 ts->reverse=saverev;
698 ts->size=savesize;
699 ts->realangle=saverang;
700 ts->xpos=savex;
701 ts->ypos=savey;
702 }
703 }
704 command++;
705 }
706 return command;
707 }
708
709 static int
710 lsysi_findscale(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth)
711 {
712 float horiz,vert;
713 double xmin, xmax, ymin, ymax;
714 double locsize;
715 double locaspect;
716 struct lsys_cmd far *fsret;
717
718 locaspect=screenaspect*xdots/ydots;
719 ts->aspect = FIXEDPT(locaspect);
720 ts->xpos =
721 ts->ypos =
722 ts->xmin =
723 ts->xmax =
724 ts->ymax =
725 ts->ymin =
726 ts->realangle =
727 ts->angle =
728 ts->reverse =
729 ts->counter = 0;
730 ts->size=FIXEDPT(1L);
731 fsret = findsize(command,ts,rules,depth);
732 thinking(0, NULL); /* erase thinking message if any */
733 xmin = (double) ts->xmin / FIXEDMUL;
734 xmax = (double) ts->xmax / FIXEDMUL;
735 ymin = (double) ts->ymin / FIXEDMUL;
736 ymax = (double) ts->ymax / FIXEDMUL;
737 if (fsret == NULL)
738 return 0;
739 if (xmax == xmin)
740 horiz = (float)1E37;
741 else
742 horiz = (float)((xdots-10)/(xmax-xmin));
743 if (ymax == ymin)
744 vert = (float)1E37;
745 else
746 vert = (float)((ydots-6) /(ymax-ymin));
747 locsize = (vert<horiz) ? vert : horiz;
748
749 if (horiz == 1E37)
750 ts->xpos = FIXEDPT(xdots/2);
751 else
752 /* ts->xpos = FIXEDPT(-xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2); */
753 ts->xpos = FIXEDPT((xdots-locsize*(xmax+xmin))/2);
754 if (vert == 1E37)
755 ts->ypos = FIXEDPT(ydots/2);
756 else
757 /* ts->ypos = FIXEDPT(-ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2); */
758 ts->ypos = FIXEDPT((ydots-locsize*(ymax+ymin))/2);
759 ts->size = FIXEDPT(locsize);
760
761 return 1;
762 }
763
764 static struct lsys_cmd far *
765 drawLSysI(struct lsys_cmd far *command,struct lsys_turtlestatei *ts, struct lsys_cmd far **rules,int depth)
766 {
767 struct lsys_cmd far **rulind;
768 int tran;
769
770 if (overflow) /* integer math routines overflowed */
771 return NULL;
772
773 if (stackavail() < 400) { /* leave some margin for calling subrtns */
774 ts->stackoflow = 1;
775 return NULL;
776 }
777
778
779 while (command->ch && command->ch !=']') {
780 if (!(ts->counter++)) {
781 if (keypressed()) {
782 ts->counter--;
783 return NULL;
784 }
785 }
786 tran=0;
787 if (depth) {
788 for(rulind=rules;*rulind;rulind++)
789 if ((*rulind)->ch == command->ch) {
790 tran=1;
791 if (drawLSysI((*rulind)+1,ts,rules,depth-1) == NULL)
792 return NULL;
793 }
794 }
795 if (!depth||!tran) {
796 if (command->f) {
797 ts->num = command->n;
798 (*command->f)(ts);
799 }
800 else if (command->ch == '[') {
801 char saveang,saverev,savecolor;
802 long savesize,savex,savey;
803 unsigned long saverang;
804
805 saveang=ts->angle;
806 saverev=ts->reverse;
807 savesize=ts->size;
808 saverang=ts->realangle;
809 savex=ts->xpos;
810 savey=ts->ypos;
811 savecolor=ts->curcolor;
812 if ((command=drawLSysI(command+1,ts,rules,depth)) == NULL)
813 return(NULL);
814 ts->angle=saveang;
815 ts->reverse=saverev;
816 ts->size=savesize;
817 ts->realangle=saverang;
818 ts->xpos=savex;
819 ts->ypos=savey;
820 ts->curcolor=savecolor;
821 }
822 }
823 command++;
824 }
825 return command;
826 }
827
828 static struct lsys_cmd far *
829 LSysISizeTransform(char far *s, struct lsys_turtlestatei *ts)
830 {
831 struct lsys_cmd far *ret;
832 struct lsys_cmd far *doub;
833 int maxval = 10;
834 int n = 0;
835 void (*f)();
836 long num;
837
838 void (*plus)() = (ispow2(ts->maxangle)) ? lsysi_doplus_pow2 : lsysi_doplus;
839 void (*minus)() = (ispow2(ts->maxangle)) ? lsysi_dominus_pow2 : lsysi_dominus;
840 void (*pipe)() = (ispow2(ts->maxangle)) ? lsysi_dopipe_pow2 : lsysi_dopipe;
841
842 void (*slash)() = (cpu >= 386) ? lsysi_doslash_386 : lsysi_doslash;
843 void (*bslash)() = (cpu >= 386) ? lsysi_dobslash_386 : lsysi_dobslash;
844 void (*at)() = (cpu >= 386) ? lsysi_doat_386 : lsysi_doat;
845 void (*dogf)() = (cpu >= 386) ? lsysi_dosizegf_386 : lsysi_dosizegf;
846
847 ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
848 if (ret == NULL) {
849 ts->stackoflow = 1;
850 return NULL;
851 }
852 while (*s) {
853 f = NULL;
854 num = 0;
855 ret[n].ch = *s;
856 switch (*s) {
857 case '+': f = plus; break;
858 case '-': f = minus; break;
859 case '/': f = slash; num = (long) (getnumber(&s) * 11930465L); break;
860 case '\\': f = bslash; num = (long) (getnumber(&s) * 11930465L); break;
861 case '@': f = at; num = FIXEDPT(getnumber(&s)); break;
862 case '|': f = pipe; break;
863 case '!': f = lsysi_dobang; break;
864 case 'd':
865 case 'm': f = lsysi_dosizedm; break;
866 case 'g':
867 case 'f': f = dogf; break;
868 case '[': num = 1; break;
869 case ']': num = 2; break;
870 default:
871 num = 3;
872 break;
873 }
874 #ifdef XFRACT
876 #else
877 ret[n].f = (void (*)(struct lsys_turtlestatei *))f;
878 #endif
879 ret[n].n = num;
880 if (++n == maxval) {
881 doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
882 if (doub == NULL) {
883 farmemfree(ret);
884 ts->stackoflow = 1;
885 return NULL;
886 }
887 far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
888 farmemfree(ret);
889 ret = doub;
890 maxval <<= 1;
891 }
892 s++;
893 }
894 ret[n].ch = 0;
895 ret[n].f = NULL;
896 ret[n].n = 0;
897 n++;
898
899 doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
900 if (doub == NULL) {
901 farmemfree(ret);
902 ts->stackoflow = 1;
903 return NULL;
904 }
905 far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
906 farmemfree(ret);
907 return doub;
908 }
909
910 static struct lsys_cmd far *
911 LSysIDrawTransform(char far *s, struct lsys_turtlestatei *ts)
912 {
913 struct lsys_cmd far *ret;
914 struct lsys_cmd far *doub;
915 int maxval = 10;
916 int n = 0;
917 void (*f)();
918 long num;
919
920 void (*plus)() = (ispow2(ts->maxangle)) ? lsysi_doplus_pow2 : lsysi_doplus;
921 void (*minus)() = (ispow2(ts->maxangle)) ? lsysi_dominus_pow2 : lsysi_dominus;
922 void (*pipe)() = (ispow2(ts->maxangle)) ? lsysi_dopipe_pow2 : lsysi_dopipe;
923
924 void (*slash)() = (cpu >= 386) ? lsysi_doslash_386 : lsysi_doslash;
925 void (*bslash)() = (cpu >= 386) ? lsysi_dobslash_386 : lsysi_dobslash;
926 void (*at)() = (cpu >= 386) ? lsysi_doat_386 : lsysi_doat;
927 void (*drawg)() = (cpu >= 386) ? lsysi_dodrawg_386 : lsysi_dodrawg;
928
929 ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
930 if (ret == NULL) {
931 ts->stackoflow = 1;
932 return NULL;
933 }
934 while (*s) {
935 f = NULL;
936 num = 0;
937 ret[n].ch = *s;
938 switch (*s) {
939 case '+': f = plus; break;
940 case '-': f = minus; break;
941 case '/': f = slash; num = (long) (getnumber(&s) * 11930465L); break;
942 case '\\': f = bslash; num = (long) (getnumber(&s) * 11930465L); break;
943 case '@': f = at; num = FIXEDPT(getnumber(&s)); break;
944 case '|': f = pipe; break;
945 case '!': f = lsysi_dobang; break;
946 case 'd': f = lsysi_dodrawd; break;
947 case 'm': f = lsysi_dodrawm; break;
948 case 'g': f = drawg; break;
949 case 'f': f = lsysi_dodrawf; break;
950 case 'c': f = lsysi_dodrawc; num = (long) getnumber(&s); break;
951 case '<': f = lsysi_dodrawlt; num = (long) getnumber(&s); break;
952 case '>': f = lsysi_dodrawgt; num = (long) getnumber(&s); break;
953 case '[': num = 1; break;
954 case ']': num = 2; break;
955 default:
956 num = 3;
957 break;
958 }
959 #ifdef XFRACT
961 #else
962 ret[n].f = (void (*)(struct lsys_turtlestatei *))f;
963 #endif
964 ret[n].n = num;
965 if (++n == maxval) {
966 doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
967 if (doub == NULL) {
968 farmemfree(ret);
969 ts->stackoflow = 1;
970 return NULL;
971 }
972 far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
973 farmemfree(ret);
974 ret = doub;
975 maxval <<= 1;
976 }
977 s++;
978 }
979 ret[n].ch = 0;
980 ret[n].f = NULL;
981 ret[n].n = 0;
982 n++;
983
984 doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
985 if (doub == NULL) {
986 farmemfree(ret);
987 ts->stackoflow = 1;
988 return NULL;
989 }
990 far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
991 farmemfree(ret);
992 return doub;
993 }
994
995 static void _fastcall lsysi_dosincos(void)
996 {
997 double locaspect;
998 double TWOPI = 2.0 * PI;
999 double twopimax;
1000 double twopimaxi;
1001 double s, c;
1002 int i;
1003
1004 locaspect=screenaspect*xdots/ydots;
1005 twopimax = TWOPI / maxangle;
1006 for(i=0;i<maxangle;i++) {
1007 twopimaxi = i * twopimax;
1008 FPUsincos(&twopimaxi, &s, &c);
1009 sins[i] = (long) (s * FIXEDLT1);
1010 coss[i] = (long) ((locaspect * c) * FIXEDLT1);
1011 }
1012 }
1013