1 /* generalasm.c
2  * This file contains routines to replace general.asm.
3  *
4  * This file Copyright 1991 Ken Shirriff.  It may be used according to the
5  * fractint license conditions, blah blah blah.
6  */
7 
8 #include <string.h>
9 #ifndef NOBSTRING
10 #ifndef sun
11 /* If this gives you an error, read the README and modify the Makefile. */
12 #include <bstring.h>
13 #endif
14 #endif
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <signal.h>
18 #include <sys/types.h>
19 #include <sys/time.h>
20 
21 #include "port.h"
22 #include "prototyp.h"
23 int overflow = 0;
24 
25 int boxx[2304], boxy[1024];
26 int boxvalues[512];
27 char tstack[4096];
28 BYTE dacbox[256][3];
29 BYTE olddacbox[256][3];
30 
31 extern int tabmode;
32 
33 int DivideOverflow = 0;
34 int cpu=0;		/* cpu type: 86, 186, 286, or 386 */
35 int fpu=0;		/* fpu type: 0, 87, 287, 387 */
36 
37 SEGTYPE extraseg=0;		/* extra 64K segment (allocated by init) */
38 /* ********************** Mouse Support Variables ************************** */
39 
40 int lookatmouse=0;	/* see notes at mouseread routine */
41 long savebase=0;		/* base clock ticks */
42 long saveticks=0;	/* save after this many ticks */
43 int finishrow=0;	/* save when this row is finished */
44 
45 int inside_help = 0;
46 
47 extern int slides;	/* 1 for playback */
48 
toextra(tooffset,fromaddr,fromcount)49 unsigned int toextra(tooffset, fromaddr, fromcount)
50 unsigned int tooffset;
51 char *fromaddr;
52 int fromcount;
53 {
54     bcopy(fromaddr,(char *)(extraseg+tooffset),fromcount);
55     return tooffset;
56 }
57 
fromextra(fromoffset,toaddr,tocount)58 unsigned int fromextra(fromoffset, toaddr, tocount)
59 unsigned int fromoffset;
60 char *toaddr;
61 int tocount;
62 {
63     bcopy((char *)(extraseg+fromoffset),toaddr,tocount);
64     return fromoffset;
65 }
66 
67 unsigned int
cmpextra(cmpoffset,cmpaddr,cmpcount)68 cmpextra(cmpoffset,cmpaddr,cmpcount)
69 unsigned int cmpoffset;
70 char *cmpaddr;
71 int cmpcount;
72 {
73     return bcmp((char *)(extraseg+cmpoffset),cmpaddr,cmpcount);
74 }
75 
76 /*
77 ; ****************** Function initasmvars() *****************************
78 */
79 void
initasmvars(void)80 initasmvars(void)
81 {
82     if (cpu!=0) return;
83     overflow = 0;
84     extraseg = malloc(0x18000);
85 
86     /* set cpu type */
87     cpu = 1;
88 
89     /* set fpu type */
90    /* not needed, set fpu in sstools.ini */
91 }
92 
fpe_handler(int signum)93 void fpe_handler(int signum)
94 {
95     signal(SIGFPE, fpe_handler);
96     overflow = 1;
97 }
98 
99 /*
100 ;
101 ;       32-bit integer multiply routine with an 'n'-bit shift.
102 ;       Overflow condition returns 0x7fffh with overflow = 1;
103 ;
104 ;       long x, y, z, multiply();
105 ;       int n;
106 ;
107 ;       z = multiply(x,y,n)
108 ;
109 */
110 
111 /*
112  * 32 bit integer multiply with n bit shift.
113  * Note that we fake integer multiplication with floating point
114  * multiplication.
115  */
116 long
multiply(x,y,n)117 multiply(x, y, n)
118 long x,y;
119 int n;
120 {
121     register long l;
122     l = ((float)x)* ((float)y)/(float)(1<<n);
123     if (l==0x7fffffff) {
124 	overflow = 1;
125     }
126     return l;
127 }
128 
129 /*
130 ;
131 ;       32-bit integer divide routine with an 'n'-bit shift.
132 ;       Overflow condition returns 0x7fffh with overflow = 1;
133 ;
134 ;       z = divide(x,y,n);       z = x / y;
135 */
136 long
divide(x,y,n)137 divide(x,y,n)
138 long x,y;
139 int n;
140 {
141     return (long) ( ((float)x)/ ((float)y)*(float)(1<<n));
142 }
143 
144 /*
145 ; ****************** Function getakey() *****************************
146 ; **************** Function keypressed() ****************************
147 
148 ;       'getakey()' gets a key from either a "normal" or an enhanced
149 ;       keyboard.   Returns either the vanilla ASCII code for regular
150 ;       keys, or 1000+(the scan code) for special keys (like F1, etc)
151 ;       Use of this routine permits the Control-Up/Down arrow keys on
152 ;       enhanced keyboards.
153 ;
154 ;       The concept for this routine was "borrowed" from the MSKermit
155 ;       SCANCHEK utility
156 ;
157 ;       'keypressed()' returns a zero if no keypress is outstanding,
158 ;       and the value that 'getakey()' will return if one is.  Note
159 ;       that you must still call 'getakey()' to flush the character.
160 ;       As a sidebar function, calls 'help()' if appropriate, or
161 ;       'tab_display()' if appropriate.
162 ;       Think of 'keypressed()' as a super-'kbhit()'.
163 */
164 int keybuffer = 0;
165 
166 int getkeynowait(void);
167 int getkeyint(int);
168 
169 int
keypressed(void)170 keypressed(void) {
171     int ch;
172     ch = getkeynowait();
173     if (!ch) return 0;
174     keybuffer = ch;
175     if (ch==F1 && helpmode) {
176 	keybuffer = 0;
177 	inside_help = 1;
178 	help(0);
179 	inside_help = 0;
180 	return 0;
181     } else if (ch==TAB && tabmode) {
182 	keybuffer = 0;
183 	tab_display();
184 	return 0;
185     }
186     return ch;
187 }
188 
189 /* Wait for a key.
190  * This should be used instead of:
191  * while (!keypressed()) {}
192  * If timeout=1, waitkeypressed will time out after .5 sec.
193  */
194 int
waitkeypressed(timeout)195 waitkeypressed(timeout)
196 int timeout;
197 {
198     while (!keybuffer) {
199 	keybuffer = getkeyint(1);
200 	if (timeout) break;
201     }
202     return keypressed();
203 }
204 
205 /*
206  * This routine returns a key, ignoring F1
207  */
208 int
getakeynohelp(void)209 getakeynohelp(void) {
210     int ch;
211     while (1) {
212 	ch = getakey();
213 	if (ch != F1) break;
214     }
215     return ch;
216 }
217 /*
218  * This routine returns a keypress
219  */
220 int
getakey(void)221 getakey(void)
222 {
223     int ch;
224 
225     do {
226 	ch = getkeyint(1);
227     } while (ch==0);
228     return ch;
229 }
230 
231 /*
232  * This routine returns the current key, or 0.
233  */
234 int
getkeynowait(void)235 getkeynowait(void) {
236     return getkeyint(0);
237 }
238 
239 /*
240  * This is the low level key handling routine.
241  * If block is set, we want to block before returning, since we are waiting
242  * for a key press.
243  * We also have to handle the slide file, etc.
244  */
245 
246 int
getkeyint(block)247 getkeyint(block)
248 int block;
249 {
250     int ch;
251     int curkey;
252 
253     if (keybuffer) {
254 	ch = keybuffer;
255 	keybuffer = 0;
256 	return ch;
257     }
258     curkey = xgetkey(0);
259     if (slides==1 && curkey == ESC) {
260 	stopslideshow();
261 	return 0;
262     }
263 
264     if (curkey==0 && slides==1) {
265 	curkey = slideshw();
266     }
267 
268     if (curkey==0 && block) {
269 	curkey = xgetkey(1);
270 	if (slides==1 && curkey == ESC) {
271 	    stopslideshow();
272 	    return 0;
273 	}
274     }
275 
276     if (curkey && slides==2) {
277 	recordshw(curkey);
278     }
279 
280     return curkey;
281 }
282 
283 /*
284 ; ****************** Function buzzer(int buzzertype) *******************
285 ;
286 ;       Sound a tone based on the value of the parameter
287 ;
288 ;       0 = normal completion of task
289 ;       1 = interrupted task
290 ;       2 = error contition
291 
292 ;       "buzzer()" codes:  strings of two-word pairs
293 ;               (frequency in cycles/sec, delay in milliseconds)
294 ;               frequency == 0 means no sound
295 ;               delay     == 0 means end-of-tune
296 */
297 void
buzzer(buzzertype)298 buzzer(buzzertype)
299 int buzzertype;
300 {
301     if ((soundflag & 7) != 0) {
302         printf("\007");
303         fflush(stdout);
304     }
305     if (buzzertype==0) {
306         redrawscreen();
307     }
308 }
309 
310 /*
311 ; ***************** Function delay(int delaytime) ************************
312 ;
313 ;       performs a delay loop for 'delaytime' milliseconds
314 */
315 void
delay(delaytime)316 delay(delaytime)
317 int delaytime;
318 {
319     static struct timeval delay;
320     delay.tv_sec = delaytime/1000;
321     delay.tv_usec = (delaytime%1000)*1000;
322 #if defined( __SVR4) || defined(LINUX) || defined(__DragonFly__)
323     (void) select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &delay);
324 #else
325     (void) select(0, (int *) 0, (int *) 0, (int *) 0, &delay);
326 #endif
327 }
328 
329 /*
330 ; ************** Function tone(int frequency,int delaytime) **************
331 ;
332 ;       buzzes the speaker with this frequency for this amount of time
333 */
334 void
tone(frequency,delaytime)335 tone(frequency, delaytime)
336 int frequency, delaytime;
337 {
338 }
339 
340 /*
341 ; ************** Function snd(int hertz) and nosnd() **************
342 ;
343 ;       turn the speaker on with this frequency (snd) or off (nosnd)
344 ;
345 ; *****************************************************************
346 */
347 void
snd(hertz)348 snd(hertz)
349 int hertz;
350 {
351 }
352 
353 void
nosnd(void)354 nosnd(void)
355 {}
356 
357 /*
358 ; long readticker() returns current bios ticker value
359 */
360 long
readticker(void)361 readticker(void)
362 {
363     return clock_ticks();
364 }
365 
366 /*
367  * checkautosave() determines when auto save is needed.
368  * Returns 1 if yes
369  * Returns 0 if no
370  */
checkautosave(void)371 int checkautosave(void)
372 {
373 
374 long timervalue;
375 
376 if (saveticks != 0) /* timer running */
377    {
378    /* get current timer value */
379    timervalue = readticker() - savebase;
380    if (timervalue >= saveticks) /* time to check */
381       {
382 
383       /* time to save, check for end of row */
384       if (finishrow == -1) /* end of row */
385          {
386           if (calc_status == 1) /* still calculating, check row */
387             {
388              if (got_status == 0 || got_status == 1) /* 1 or 2 pass, or solid guessing */
389                 {
390                 finishrow = currow;
391                 }
392              }
393          else /* done calculating */
394              timedsave = 1; /* do the save */
395 
396          }
397       else /* not end of row */
398          if (finishrow != currow) /* start of next row */
399             timedsave = 1; /* do the save */
400 
401       } /* time to check */
402    } /* timer running */
403    if (timedsave == 1) {
404      keybuffer = 9999;
405      return(1);
406    }
407    return(0);
408 }
409 
410 /*
411 ; ************************* Far Segment RAM Support **************************
412 ;
413 ;
414 ;       farptr = (char far *)farmemalloc(long bytestoalloc);
415 ;       (void)farmemfree(farptr);
416 */
417 
418 VOIDPTR
farmemalloc(len)419 farmemalloc(len)
420 long len;
421 {
422     return (VOIDPTR )malloc((unsigned)len);
423 }
424 
425 void
farmemfree(addr)426 farmemfree(addr)
427 VOIDPTR addr;
428 {
429     free((char *)addr);
430 }
431 
erasesegment(segaddress,segvalue)432 void erasesegment(segaddress,segvalue)
433 int segaddress;
434 int segvalue;
435 {
436 }
437 
438 
439 int
farread(handle,buf,len)440 farread(handle, buf, len)
441 int handle;
442 VOIDPTR buf;
443 unsigned len;
444 {
445     return read(handle, buf, len);
446 }
447 
448 int
farwrite(handle,buf,len)449 farwrite(handle, buf, len)
450 int handle;
451 VOIDPTR buf;
452 unsigned len;
453 {
454     return write(handle,buf,len);
455 }
456 
457 
458 long
normalize(ptr)459 normalize(ptr)
460 char *ptr;
461 {
462     return (long) ptr;
463 }
464 
465 /*
466 ; *************** Far string/memory functions *********
467 */
468 int
far_strlen(a)469 far_strlen (a)
470 char *a;
471 {
472     return strlen(a);
473 }
474 
475 
476 void
far_strcpy(a,b)477 far_strcpy (a,b)
478 char *a,*b;
479 {
480     strcpy(a,b);
481 }
482 
483 int
far_strcmp(a,b)484 far_strcmp (a,b)
485 char *a, *b;
486 {
487     return strcmp(a,b);
488 }
489 
490 int
far_stricmp(a,b)491 far_stricmp(a,b)
492 char *a,*b;
493 {
494    return stricmp(a,b);
495 }
496 
497 int
far_strnicmp(a,b,n)498 far_strnicmp(a,b,n)
499 char *a,*b;
500 int n;
501 {
502     return strnicmp(a,b,n);
503 }
504 
505 void
far_strcat(a,b)506 far_strcat (a,b)
507 char *a,*b;
508 {
509     strcat(a,b);
510 }
511 
512 void
far_memset(a,c,len)513 far_memset ( a,c,len)
514 VOIDFARPTR a;
515 int c;
516 unsigned int len;
517 {
518     memset(a,c,len);
519 }
520 
521 void
far_memcpy(a,b,len)522 far_memcpy ( a,b,len)
523 VOIDFARPTR a,b;
524 int len;
525 {
526     memcpy(a,b,len);
527 }
528 
529 int
far_memcmp(a,b,len)530 far_memcmp (a,b,len)
531 VOIDFARPTR a,b;
532 int len;
533 {
534     return memcmp(a,b,len);
535 }
536 
537 int
far_memicmp(a,b,len)538 far_memicmp(a,b,len)
539 VOIDFARPTR a,b;
540 int len;
541 {
542     return memicmp(a,b,len);
543 }
544 
545 /* --------------------------------------------------------------------
546  * The following routines are used for encoding/decoding gif images.
547  * If we aren't on a PC, things are rough for decoding the fractal info
548  * structure in the GIF file.  These routines look after converting the
549  * MS_DOS format data into a form we can use.
550  * If dir==0, we convert to MSDOS form.  Otherwise we convert from MSDOS.
551  */
552 
553 static void getChar(), getInt(), getLong(), getFloat(), getDouble();
554 
555 void
decode_fractal_info(info,dir)556 decode_fractal_info(info,dir)
557     struct fractal_info *info;
558     int dir;
559 {
560     unsigned char *buf;
561     unsigned char *bufPtr;
562     int i;
563 
564     if (dir==1) {
565 	buf = (unsigned char *)malloc(FRACTAL_INFO_SIZE);
566 	bufPtr = buf;
567 	bcopy((char *)info,(char *)buf,FRACTAL_INFO_SIZE);
568     }  else {
569 	buf = (unsigned char *)malloc(sizeof(struct fractal_info));
570 	bufPtr = buf;
571 	bcopy((char *)info,(char *)buf,sizeof(struct fractal_info));
572     }
573 
574     if (dir==1) {
575 	strncpy(info->info_id,(char *)bufPtr,8);
576     } else {
577 	strncpy((char *)bufPtr,info->info_id,8);
578     }
579     bufPtr += 8;
580     getInt(&info->iterationsold,&bufPtr,dir);
581     getInt(&info->fractal_type,&bufPtr,dir);
582     getDouble(&info->xmin,&bufPtr,dir);
583     getDouble(&info->xmax,&bufPtr,dir);
584     getDouble(&info->ymin,&bufPtr,dir);
585     getDouble(&info->ymax,&bufPtr,dir);
586     getDouble(&info->creal,&bufPtr,dir);
587     getDouble(&info->cimag,&bufPtr,dir);
588     getInt(&info->videomodeax,&bufPtr,dir);
589     getInt(&info->videomodebx,&bufPtr,dir);
590     getInt(&info->videomodecx,&bufPtr,dir);
591     getInt(&info->videomodedx,&bufPtr,dir);
592     getInt(&info->dotmode,&bufPtr,dir);
593     getInt(&info->xdots,&bufPtr,dir);
594     getInt(&info->ydots,&bufPtr,dir);
595     getInt(&info->colors,&bufPtr,dir);
596     getInt(&info->version,&bufPtr,dir);
597     getFloat(&info->parm3,&bufPtr,dir);
598     getFloat(&info->parm4,&bufPtr,dir);
599     getFloat(&info->potential[0],&bufPtr,dir);
600     getFloat(&info->potential[1],&bufPtr,dir);
601     getFloat(&info->potential[2],&bufPtr,dir);
602     getInt(&info->rseed,&bufPtr,dir);
603     getInt(&info->rflag,&bufPtr,dir);
604     getInt(&info->biomorph,&bufPtr,dir);
605     getInt(&info->inside,&bufPtr,dir);
606     getInt(&info->logmap,&bufPtr,dir);
607     getFloat(&info->invert[0],&bufPtr,dir);
608     getFloat(&info->invert[1],&bufPtr,dir);
609     getFloat(&info->invert[2],&bufPtr,dir);
610     getInt(&info->decomp[0],&bufPtr,dir);
611     getInt(&info->decomp[1],&bufPtr,dir);
612     getInt(&info->symmetry,&bufPtr,dir);
613     for (i=0;i<16;i++) {
614 	getInt(&info->init3d[i],&bufPtr,dir);
615     }
616     getInt(&info->previewfactor,&bufPtr,dir);
617     getInt(&info->xtrans,&bufPtr,dir);
618     getInt(&info->ytrans,&bufPtr,dir);
619     getInt(&info->red_crop_left,&bufPtr,dir);
620     getInt(&info->red_crop_right,&bufPtr,dir);
621     getInt(&info->blue_crop_left,&bufPtr,dir);
622     getInt(&info->blue_crop_right,&bufPtr,dir);
623     getInt(&info->red_bright,&bufPtr,dir);
624     getInt(&info->blue_bright,&bufPtr,dir);
625     getInt(&info->xadjust,&bufPtr,dir);
626     getInt(&info->eyeseparation,&bufPtr,dir);
627     getInt(&info->glassestype,&bufPtr,dir);
628     getInt(&info->outside,&bufPtr,dir);
629     getDouble(&info->x3rd,&bufPtr,dir);
630     getDouble(&info->y3rd,&bufPtr,dir);
631     getChar(&info->stdcalcmode,&bufPtr,dir);
632     getChar(&info->useinitorbit,&bufPtr,dir);
633     getInt(&info->calc_status,&bufPtr,dir);
634     getLong(&info->tot_extend_len,&bufPtr,dir);
635     getInt(&info->distest,&bufPtr,dir);
636     getInt(&info->floatflag,&bufPtr,dir);
637     getInt(&info->bailoutold,&bufPtr,dir);
638     getLong(&info->calctime,&bufPtr,dir);
639     for (i=0;i<4;i++) {
640 	getChar(&info->trigndx[i],&bufPtr,dir);
641     }
642     getInt(&info->finattract,&bufPtr,dir);
643     getDouble(&info->initorbit[0],&bufPtr,dir);
644     getDouble(&info->initorbit[1],&bufPtr,dir);
645     getInt(&info->periodicity,&bufPtr,dir);
646     getInt(&info->pot16bit,&bufPtr,dir);
647     getFloat(&info->faspectratio,&bufPtr,dir);
648     getInt(&info->system,&bufPtr,dir);
649     getInt(&info->release,&bufPtr,dir);
650     getInt(&info->flag3d,&bufPtr,dir);
651     getInt(&info->transparent[0],&bufPtr,dir);
652     getInt(&info->transparent[1],&bufPtr,dir);
653     getInt(&info->ambient,&bufPtr,dir);
654     getInt(&info->haze,&bufPtr,dir);
655     getInt(&info->randomize,&bufPtr,dir);
656     getInt(&info->rotate_lo,&bufPtr,dir);
657     getInt(&info->rotate_hi,&bufPtr,dir);
658     getInt(&info->distestwidth,&bufPtr,dir);
659     getDouble(&info->dparm3,&bufPtr,dir);
660     getDouble(&info->dparm4,&bufPtr,dir);
661     getInt(&info->fillcolor,&bufPtr,dir);
662     getDouble(&info->mxmaxfp,&bufPtr,dir);
663     getDouble(&info->mxminfp,&bufPtr,dir);
664     getDouble(&info->mymaxfp,&bufPtr,dir);
665     getDouble(&info->myminfp,&bufPtr,dir);
666     getInt(&info->zdots,&bufPtr,dir);
667     getFloat(&info->originfp,&bufPtr,dir);
668     getFloat(&info->depthfp,&bufPtr,dir);
669     getFloat(&info->heightfp,&bufPtr,dir);
670     getFloat(&info->widthfp,&bufPtr,dir);
671     getFloat(&info->distfp,&bufPtr,dir);
672     getFloat(&info->eyesfp,&bufPtr,dir);
673     getInt(&info->orbittype,&bufPtr,dir);
674     getInt(&info->juli3Dmode,&bufPtr,dir);
675     getInt(&info->maxfn,&bufPtr,dir);
676     getInt(&info->inversejulia,&bufPtr,dir);
677     getDouble(&info->dparm5,&bufPtr,dir);
678     getDouble(&info->dparm6,&bufPtr,dir);
679     getDouble(&info->dparm7,&bufPtr,dir);
680     getDouble(&info->dparm8,&bufPtr,dir);
681     getDouble(&info->dparm9,&bufPtr,dir);
682     getDouble(&info->dparm10,&bufPtr,dir);
683     getLong(&info->bailout,&bufPtr,dir);
684     getInt(&info->bailoutest,&bufPtr,dir);
685     getLong(&info->iterations,&bufPtr,dir);
686     getInt(&info->bf_math,&bufPtr,dir);
687     getInt(&info->bflength,&bufPtr,dir);
688     getInt(&info->yadjust,&bufPtr,dir);
689     getInt(&info->old_demm_colors,&bufPtr,dir);
690     getLong(&info->logmap,&bufPtr,dir);
691     getLong(&info->distest,&bufPtr,dir);
692     getDouble(&info->dinvert[0],&bufPtr,dir);
693     getDouble(&info->dinvert[1],&bufPtr,dir);
694     getDouble(&info->dinvert[2],&bufPtr,dir);
695     getInt(&info->logcalc,&bufPtr,dir);
696     getInt(&info->stoppass,&bufPtr,dir);
697     getInt(&info->quick_calc,&bufPtr,dir);
698     getDouble(&info->closeprox,&bufPtr,dir);
699     getInt(&info->nobof,&bufPtr,dir);
700     getLong(&info->orbit_interval,&bufPtr,dir);
701     getInt(&info->orbit_delay,&bufPtr,dir);
702     getDouble(&info->math_tol[0],&bufPtr,dir);
703     getDouble(&info->math_tol[1],&bufPtr,dir);
704 
705     for (i=0;i<(sizeof(info->future)/sizeof(short));i++) {
706         getInt(&info->future[i],&bufPtr,dir);
707     }
708     if (bufPtr-buf != FRACTAL_INFO_SIZE) {
709 	printf("Warning: loadfile miscount on fractal_info structure.\n");
710 	printf("Components add up to %d bytes, but FRACTAL_INFO_SIZE = %d\n",
711 		bufPtr-buf, FRACTAL_INFO_SIZE);
712     }
713     if (dir==0) {
714 	bcopy((char *)buf,(char *)info,FRACTAL_INFO_SIZE);
715     }
716 
717     free(buf);
718 }
719 
720 /*
721  * This routine gets a char out of the buffer.
722  * It updates the buffer pointer accordingly.
723  */
getChar(dst,src,dir)724 static void getChar(dst,src,dir)
725     unsigned char *dst;
726     unsigned char **src;
727     int dir;
728 {
729     if (dir==1) {
730 	*dst = **src;
731     } else {
732 	**src = *dst;
733     }
734     (*src)++;
735 }
736 
737 /*
738  * This routine gets an int out of the buffer.
739  * It updates the buffer pointer accordingly.
740  */
getInt(dst,src,dir)741 static void getInt(dst,src,dir)
742     short *dst;
743     unsigned char **src;
744     int dir;
745 {
746     if (dir==1) {
747 	*dst = (*src)[0] + ((((char *)(*src))[1])<<8);
748     } else {
749 	(*src)[0] = (*dst)&0xff;
750 	(*src)[1] = ((*dst)&0xff00)>>8;
751     }
752     (*src) += 2; /* sizeof(int) in MS_DOS */
753 }
754 
755 /*
756  * This routine gets a long out of the buffer.
757  * It updates the buffer pointer accordingly.
758  */
getLong(dst,src,dir)759 static void getLong(dst,src,dir)
760     long *dst;
761     unsigned char **src;
762     int dir;
763 {
764     if (dir==1) {
765 	*dst = ((unsigned long)((*src)[0])) +
766 	    (((unsigned long)((*src)[1]))<<8) +
767 	    (((unsigned long)((*src)[2]))<<16) +
768 	    (((long)(((char *)(*src))[3]))<<24);
769     } else {
770 	(*src)[0] = (*dst)&0xff;
771 	(*src)[1] = ((*dst)&0xff00)>>8;
772 	(*src)[2] = ((*dst)&0xff0000)>>16;
773 #ifdef __SVR4
774 	(*src)[3] = (unsigned)((*dst)&0xff000000)>>24;
775 #else
776 	(*src)[3] = ((*dst)&0xff000000)>>24;
777 #endif
778     }
779     (*src) += 4; /* sizeof(long) in MS_DOS */
780 }
781 
782 #define P4 16.
783 #define P7 128.
784 #define P8 256.
785 #define P12 4096.
786 #define P15 32768.
787 #define P20 1048576.
788 #define P23 8388608.
789 #define P28 268435456.
790 #define P36 68719476736.
791 #define P44 17592186044416.
792 #define P52 4503599627370496.
793 
794 
795 /*
796  * This routine gets a double out of the buffer, or puts a double into the
797  * buffer;
798  * It updates the buffer pointer accordingly.
799  */
getDouble(dst,src,dir)800 static void getDouble(dst,src,dir)
801     double *dst;
802     unsigned char **src;
803     int dir;
804 {
805     int e;
806     double f;
807     int i;
808     if (dir==1) {
809 	for (i=0;i<8;i++) {
810 	    if ((*src)[i] != 0) break;
811 	}
812 	if (i==8) {
813 	    *dst = 0;
814 	} else {
815 #ifdef __SVR4
816 	    e = (((*src)[7]&0x7f)<<4) + ((int)((*src)[6]&0xf0)>>4) - 1023;
817 	    f = 1 + (int)((*src)[6]&0x0f)/P4 + (int)((*src)[5])/P12 +
818         (int)((*src)[4])/P20 + (int)((*src)[3])/P28 + (int)((*src)[2])/P36 +
819         (int)((*src)[1])/P44 + (int)((*src)[0])/P52;
820 #else
821       e = (((*src)[7]&0x7f)<<4) + (((*src)[6]&0xf0)>>4) - 1023;
822       f = 1 + ((*src)[6]&0x0f)/P4 + (*src)[5]/P12 + (*src)[4]/P20 +
823     (*src)[3]/P28 + (*src)[2]/P36 + (*src)[1]/P44 + (*src)[0]/P52;
824 #endif
825 	    f *= pow(2.,(double)e);
826 	    if ((*src)[7]&0x80) {
827 		f = -f;
828 	    }
829 	    *dst = f;
830 	}
831     } else {
832 	if (*dst==0) {
833 	    bzero((char *)(*src),8);
834 	} else {
835 	    int s=0;
836 	    f = *dst;
837 	    if (f<0) {
838 		s = 0x80;
839 		f = -f;
840 	    }
841 	    e = log(f)/log(2.);
842 	    f = f/pow(2.,(double)e) - 1;
843 	    if (f<0) {
844 		e--;
845 		f = (f+1)*2-1;
846 	    } else if (f>=1) {
847 		e++;
848 		f = (f+1)/2-1;
849 	    }
850 	    e += 1023;
851 	    (*src)[7] = s | ((e&0x7f0)>>4);
852 	    f *= P4;
853 	    (*src)[6] = ((e&0x0f)<<4) | (((int)f)&0x0f);
854 	    f = (f-(int)f)*P8;
855 	    (*src)[5] = (((int)f)&0xff);
856 	    f = (f-(int)f)*P8;
857 	    (*src)[4] = (((int)f)&0xff);
858 	    f = (f-(int)f)*P8;
859 	    (*src)[3] = (((int)f)&0xff);
860 	    f = (f-(int)f)*P8;
861 	    (*src)[2] = (((int)f)&0xff);
862 	    f = (f-(int)f)*P8;
863 	    (*src)[1] = (((int)f)&0xff);
864 	    f = (f-(int)f)*P8;
865 	    (*src)[0] = (((int)f)&0xff);
866 	}
867     }
868     *src += 8; /* sizeof(double) in MSDOS */
869 }
870 
871 /*
872  * This routine gets a float out of the buffer.
873  * It updates the buffer pointer accordingly.
874  */
getFloat(dst,src,dir)875 static void getFloat(dst,src,dir)
876     float *dst;
877     unsigned char **src;
878     int dir;
879 {
880     int e;
881     double f;
882     int i;
883     if (dir==1) {
884 	for (i=0;i<4;i++) {
885 	    if ((*src)[i] != 0) break;
886 	}
887 	if (i==4) {
888 	    *dst = 0;
889 	} else {
890 #ifdef __SVR4
891 	    e = ((((*src)[3]&0x7f)<<1) | ((int)((*src)[2]&0x80)>>7)) - 127;
892 	    f = 1 + (int)((*src)[2]&0x7f)/P7 + (int)((*src)[1])/P15 + (int)((*src)[0])/P23;
893 #else
894       e = ((((*src)[3]&0x7f)<<1) | (((*src)[2]&0x80)>>7)) - 127;
895       f = 1 + ((*src)[2]&0x7f)/P7 + (*src)[1]/P15 + (*src)[0]/P23;
896 #endif
897 	    f *= pow(2.,(double)e);
898 	    if ((*src)[3]&0x80) {
899 		f = -f;
900 	    }
901 	    *dst = f;
902 	}
903     } else {
904 	if (*dst==0) {
905 	    bzero((char *)(*src),4);
906 	} else {
907 	    int s=0;
908 	    f = *dst;
909 	    if (f<0) {
910 		s = 0x80;
911 		f = -f;
912 	    }
913 	    e = log(f)/log(2.);
914 	    f = f/pow(2.,(double)e) - 1;
915 	    if (f<0) {
916 		e--;
917 		f = (f+1)*2-1;
918 	    } else if (f>=1) {
919 		e++;
920 		f = (f+1)/2-1;
921 	    }
922 	    e += 127;
923 	    (*src)[3] = s | ((e&0xf7)>>1);
924 	    f *= P7;
925 	    (*src)[2] = ((e&0x01)<<7) | (((int)f)&0x7f);
926 	    f = (f-(int)f)*P8;
927 	    (*src)[1] = (((int)f)&0xff);
928 	    f = (f-(int)f)*P8;
929 	    (*src)[0] = (((int)f)&0xff);
930 	}
931     }
932     *src += 4; /* sizeof(float) in MSDOS */
933 }
934 
935 /*
936  * Fix up the ranges data.
937  */
938 void
fix_ranges(ranges,num,dir)939 fix_ranges(ranges,num,dir)
940     int *ranges, num;
941     int dir;
942 {
943     unsigned char *buf;
944     unsigned char *bufPtr;
945     int i;
946 
947     if (dir==1) {
948 	buf = (unsigned char *)malloc(num*2);
949 	bufPtr = buf;
950 	bcopy((char *)ranges, (char *)buf, num*2);
951     } else {
952 	buf = (unsigned char *)malloc(num*sizeof(int));
953 	bufPtr = buf;
954 	bcopy((char *)ranges, (char *)buf, num*sizeof(int));
955     }
956     for (i=0;i<num;i++) {
957 	getInt(&ranges[i],&bufPtr,dir);
958     }
959     free((char *)buf);
960 }
961 
962 void
decode_evolver_info(info,dir)963 decode_evolver_info(info,dir)
964     struct evolution_info *info;
965     int dir;
966 {
967     unsigned char *buf;
968     unsigned char *bufPtr;
969     int i;
970 
971     if (dir==1) {
972 	buf = (unsigned char *)malloc(EVOLVER_INFO_SIZE);
973 	bufPtr = buf;
974 	bcopy((char *)info,(char *)buf,EVOLVER_INFO_SIZE);
975     }  else {
976 	buf = (unsigned char *)malloc(sizeof(struct evolution_info));
977 	bufPtr = buf;
978 	bcopy((char *)info,(char *)buf,sizeof(struct evolution_info));
979     }
980 
981     getInt(&info->evolving,&bufPtr,dir);
982     getInt(&info->gridsz,&bufPtr,dir);
983     getInt(&info->this_gen_rseed,&bufPtr,dir);
984     getDouble(&info->fiddlefactor,&bufPtr,dir);
985     getDouble(&info->paramrangex,&bufPtr,dir);
986     getDouble(&info->paramrangey,&bufPtr,dir);
987     getDouble(&info->opx,&bufPtr,dir);
988     getDouble(&info->opy,&bufPtr,dir);
989     getInt(&info->odpx,&bufPtr,dir);
990     getInt(&info->odpy,&bufPtr,dir);
991     getInt(&info->px,&bufPtr,dir);
992     getInt(&info->py,&bufPtr,dir);
993     getInt(&info->sxoffs,&bufPtr,dir);
994     getInt(&info->syoffs,&bufPtr,dir);
995     getInt(&info->xdots,&bufPtr,dir);
996     getInt(&info->ydots,&bufPtr,dir);
997     for (i=0;i<NUMGENES;i++) {
998         getInt(&info->mutate[i],&bufPtr,dir);
999     }
1000     getInt(&info->ecount,&bufPtr,dir);
1001 
1002     for (i=0;i<(sizeof(info->future)/sizeof(short));i++) {
1003         getInt(&info->future[i],&bufPtr,dir);
1004     }
1005     if (bufPtr-buf != EVOLVER_INFO_SIZE) {
1006 	printf("Warning: loadfile miscount on evolution_info structure.\n");
1007 	printf("Components add up to %d bytes, but EVOLVER_INFO_SIZE = %d\n",
1008 		bufPtr-buf, EVOLVER_INFO_SIZE);
1009     }
1010     if (dir==0) {
1011 	bcopy((char *)buf,(char *)info,EVOLVER_INFO_SIZE);
1012     }
1013 
1014     free(buf);
1015 }
1016 
1017 void
decode_orbits_info(info,dir)1018 decode_orbits_info(info,dir)
1019     struct orbits_info *info;
1020     int dir;
1021 {
1022     unsigned char *buf;
1023     unsigned char *bufPtr;
1024     int i;
1025 
1026     if (dir==1) {
1027 	buf = (unsigned char *)malloc(ORBITS_INFO_SIZE);
1028 	bufPtr = buf;
1029 	bcopy((char *)info,(char *)buf,ORBITS_INFO_SIZE);
1030     }  else {
1031 	buf = (unsigned char *)malloc(sizeof(struct orbits_info));
1032 	bufPtr = buf;
1033 	bcopy((char *)info,(char *)buf,sizeof(struct orbits_info));
1034     }
1035 
1036     getDouble(&info->oxmin,&bufPtr,dir);
1037     getDouble(&info->oxmax,&bufPtr,dir);
1038     getDouble(&info->oymin,&bufPtr,dir);
1039     getDouble(&info->oymax,&bufPtr,dir);
1040     getDouble(&info->ox3rd,&bufPtr,dir);
1041     getDouble(&info->oy3rd,&bufPtr,dir);
1042     getInt(&info->keep_scrn_coords,&bufPtr,dir);
1043     getChar(&info->drawmode,&bufPtr,dir);
1044     getChar(&info->dummy,&bufPtr,dir);
1045 
1046     for (i=0;i<(sizeof(info->future)/sizeof(short));i++) {
1047         getInt(&info->future[i],&bufPtr,dir);
1048     }
1049     if (bufPtr-buf != ORBITS_INFO_SIZE) {
1050 	printf("Warning: loadfile miscount on orbits_info structure.\n");
1051 	printf("Components add up to %d bytes, but ORBITS_INFO_SIZE = %d\n",
1052 		bufPtr-buf, ORBITS_INFO_SIZE);
1053     }
1054     if (dir==0) {
1055 	bcopy((char *)buf,(char *)info,ORBITS_INFO_SIZE);
1056     }
1057 
1058     free(buf);
1059 }
1060 
1061