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