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