File: common\jiim.c
1 /*
2 * JIIM.C
3 *
4 * Generates Inverse Julia in real time, lets move a cursor which determines
5 * the J-set.
6 *
7 * The J-set is generated in a fixed-size window, a third of the screen.
8 *
9 * The routines used to set/move the cursor and to save/restore the
10 * window were "borrowed" from editpal.c (TW - now we *use* the editpal code)
11 * (if you don't know how to write good code, look for someone who does)
12 *
13 * JJB [jbuhler@gidef.edu.ar]
14 * TIW Tim Wegner
15 * MS Michael Snyder
16 * KS Ken Shirriff
17 * Revision History:
18 *
19 * 7-28-92 JJB Initial release out of editpal.c
20 * 7-29-92 JJB Added SaveRect() & RestoreRect() - now the
21 * screen is restored after leaving.
22 * 7-30-92 JJB Now, if the cursor goes into the window, the
23 * window is moved to the other side of the screen.
24 * Worked from the first time!
25 * 10-09-92 TIW A major rewrite that merged cut routines duplicated
26 * in EDITPAL.C and added orbits feature.
27 * 11-02-92 KS Made cursor blink
28 * 11-18-92 MS Altered Inverse Julia to use MIIM method.
29 * 11-25-92 MS Modified MIIM support routines to better be
30 * shared with stand-alone inverse julia in
31 * LORENZ.C, and to use DISKVID for swap space.
32 * 05-05-93 TIW Boy this change file really got out of date.
33 * Added orbits capability, various commands, some
34 * of Dan Farmer's ideas like circles and lines
35 * connecting orbits points.
36 * 12-18-93 TIW Removed use of float only for orbits, fixed a
37 * helpmode bug.
38 *
39 */
40
41 #include <string.h>
42
43 #ifndef USE_VARARGS
44 #include <stdarg.h>
45 #else
46 #include <varargs.h> 47 #endif
48
49 #ifdef __TURBOC__
50 # include <mem.h> /* to get mem...() declarations */ 51 #endif
52
53 /* see Fractint.c for a description of the "include" hierarchy */
54 #include "port.h"
55 #include "prototyp.h"
56 #include "helpdefs.h"
57 #include "fractype.h"
58
59 #define FAR_RESERVE 8192L /* amount of far mem we will leave avail. */
60 #define MAXRECT 1024 /* largest width of SaveRect/RestoreRect */
61
62 #define newx(size) mem_alloc(size)
63 #define delete(block) block=NULL
64
65 int show_numbers =0; /* toggle for display of coords */
66 U16 memory_handle = 0;
67 FILE *file;
68 int windows = 0; /* windows management system */
69
70 int xc, yc; /* corners of the window */
71 int xd, yd; /* dots in the window */
72 double xcjul = BIG;
73 double ycjul = BIG;
74
75 void displays(int x, int y, int fg, int bg, char *str, int len)
76 {
77 int i;
78 for(i=0;i<len; i++)
79 displayc(x+i*8, y, fg, bg, str[i]);
80 }
81
82 /* circle routines from Dr. Dobbs June 1990 */
83 int xbase, ybase;
84 unsigned int xAspect, yAspect;
85
86 void SetAspect(double aspect)
87 {
88 xAspect = 0;
89 yAspect = 0;
90 aspect = fabs(aspect);
91 if (aspect != 1.0) {
92 if (aspect > 1.0)
93 yAspect = (unsigned int)(65536.0 / aspect);
94 else
95 xAspect = (unsigned int)(65536.0 * aspect);
96 }
97 }
98
99 void _fastcall c_putcolor(int x, int y, int color)
100 {
101 /* avoid writing outside window */
102 if ( x < xc || y < yc || x >= xc + xd || y >= yc + yd )
103 return ;
104 if(y >= sydots - show_numbers) /* avoid overwriting coords */
105 return;
106 if(windows == 2) /* avoid overwriting fractal */
107 if (0 <= x && x < xdots && 0 <= y && y < ydots)
108 return;
109 putcolor(x, y, color);
110 }
111
112
113 int c_getcolor(int x, int y)
114 {
115 /* avoid reading outside window */
116 if ( x < xc || y < yc || x >= xc + xd || y >= yc + yd )
117 return 1000;
118 if(y >= sydots - show_numbers) /* avoid overreading coords */
119 return 1000;
120 if(windows == 2) /* avoid overreading fractal */
121 if (0 <= x && x < xdots && 0 <= y && y < ydots)
122 return 1000;
123 return getcolor(x, y);
124 }
125
126 void circleplot(int x, int y, int color)
127 {
128 if (xAspect == 0)
129 if (yAspect == 0)
130 c_putcolor(x+xbase, y+ybase,color);
131 else
132 c_putcolor(x+xbase, (short)(ybase + (((long) y * (long) yAspect) >> 16)),color);
133 else
134 c_putcolor((int)(xbase + (((long) x * (long) xAspect) >> 16)), y+ybase, color);
135 }
136
137 void plot8(int x, int y, int color)
138 {
139 circleplot(x,y,color);
140 circleplot(-x,y,color);
141 circleplot(x,-y,color);
142 circleplot(-x,-y,color);
143 circleplot(y,x,color);
144 circleplot(-y,x,color);
145 circleplot(y,-x,color);
146 circleplot(-y,-x,color);
147 }
148
149 void circle(int radius, int color)
150 {
151 int x,y,sum;
152
153 x = 0;
154 y = radius << 1;
155 sum = 0;
156
157 while (x <= y)
158 {
159 if ( !(x & 1) ) /* plot if x is even */
160 plot8( x >> 1, (y+1) >> 1, color);
161 sum += (x << 1) + 1;
162 x++;
163 if (sum > 0)
164 {
165 sum -= (y << 1) - 1;
166 y--;
167 }
168 }
169 }
170
171
172 /*
173 * MIIM section:
174 *
175 * Global variables and service functions used for computing
176 * MIIM Julias will be grouped here (and shared by code in LORENZ.C)
177 *
178 */
179
180
181 long ListFront, ListBack, ListSize; /* head, tail, size of MIIM Queue */
182 long lsize, lmax; /* how many in queue (now, ever) */
183 int maxhits = 1;
184 int OKtoMIIM;
185 int SecretExperimentalMode;
186 float luckyx = 0, luckyy = 0;
187
188 static void fillrect(int x, int y, int width, int depth, int color)
189 {
190 /* fast version of fillrect */
191 if(hasinverse == 0)
192 return;
193 memset(dstack, color % colors, width);
194 while (depth-- > 0)
195 {
196 if(keypressed()) /* we could do this less often when in fast modes */
197 return;
198 putrow(x, y++, width, (char *)dstack);
199 }
200 }
201
202 /*
203 * Queue/Stack Section:
204 *
205 * Defines a buffer that can be used as a FIFO queue or LIFO stack.
206 */
207
208 int
209 QueueEmpty() /* True if NO points remain in queue */
210 {
211 return (ListFront == ListBack);
212 }
213
214 #if 0 /* not used */
220 #endif
221
222 int
223 QueueFullAlmost() /* True if room for ONE more point in queue */
224 {
225 return (((ListFront + 2) % ListSize) == ListBack);
226 }
227
228 void
229 ClearQueue()
230 {
231 ListFront = ListBack = lsize = lmax = 0;
232 }
233
234
235 /*
236 * Queue functions for MIIM julia:
237 * move to JIIM.C when done
238 */
239
240 int Init_Queue(unsigned long request)
241 {
242 if (dotmode == 11)
243 {
244 static FCODE nono[] = "Don't try this in disk video mode, kids...\n";
245 stopmsg(0, nono);
246 ListSize = 0;
247 return 0;
248 }
249
250 #if 0
254 #endif
255
256 for (ListSize = request; ListSize > 1024; ListSize /= 2)
257 switch (common_startdisk(ListSize * 8, 1, 256))
258 {
259 case 0: /* success */
260 ListFront = ListBack = 0;
261 lsize = lmax = 0;
262 return 1;
263 case -1:
264 continue; /* try smaller queue size */
265 case -2:
266 ListSize = 0; /* cancelled by user */
267 return 0;
268 }
269
270 /* failed to get memory for MIIM Queue */
271 ListSize = 0;
272 return 0;
273 }
274
275 void
276 Free_Queue()
277 {
278 enddisk();
279 ListFront = ListBack = ListSize = lsize = lmax = 0;
280 }
281
282 int
283 PushLong(long x, long y)
284 {
285 if (((ListFront + 1) % ListSize) != ListBack)
286 {
287 if (ToMemDisk(8*ListFront, sizeof(x), &x) &&
288 ToMemDisk(8*ListFront +sizeof(x), sizeof(y), &y))
289 {
290 ListFront = (ListFront + 1) % ListSize;
291 if (++lsize > lmax)
292 {
293 lmax = lsize;
294 luckyx = (float)x;
295 luckyy = (float)y;
296 }
297 return 1;
298 }
299 }
300 return 0; /* fail */
301 }
302
303 int
304 PushFloat(float x, float y)
305 {
306 if (((ListFront + 1) % ListSize) != ListBack)
307 {
308 if (ToMemDisk(8*ListFront, sizeof(x), &x) &&
309 ToMemDisk(8*ListFront +sizeof(x), sizeof(y), &y))
310 {
311 ListFront = (ListFront + 1) % ListSize;
312 if (++lsize > lmax)
313 {
314 lmax = lsize;
315 luckyx = x;
316 luckyy = y;
317 }
318 return 1;
319 }
320 }
321 return 0; /* fail */
322 }
323
324 _CMPLX
325 PopFloat()
326 {
327 _CMPLX pop;
328 float popx, popy;
329
330 if (!QueueEmpty())
331 {
332 ListFront--;
333 if (ListFront < 0)
334 ListFront = ListSize - 1;
335 if (FromMemDisk(8*ListFront, sizeof(popx), &popx) &&
336 FromMemDisk(8*ListFront +sizeof(popx), sizeof(popy), &popy))
337 {
338 pop.x = popx;
339 pop.y = popy;
340 --lsize;
341 }
342 return pop;
343 }
344 pop.x = 0;
345 pop.y = 0;
346 return pop;
347 }
348
349 LCMPLX
350 PopLong()
351 {
352 LCMPLX pop;
353
354 if (!QueueEmpty())
355 {
356 ListFront--;
357 if (ListFront < 0)
358 ListFront = ListSize - 1;
359 if (FromMemDisk(8*ListFront, sizeof(pop.x), &pop.x) &&
360 FromMemDisk(8*ListFront +sizeof(pop.x), sizeof(pop.y), &pop.y))
361 --lsize;
362 return pop;
363 }
364 pop.x = 0;
365 pop.y = 0;
366 return pop;
367 }
368
369 int
370 EnQueueFloat(float x, float y)
371 {
372 return PushFloat(x, y);
373 }
374
375 int
376 EnQueueLong(long x, long y)
377 {
378 return PushLong(x, y);
379 }
380
381 _CMPLX
382 DeQueueFloat()
383 {
384 _CMPLX out;
385 float outx, outy;
386
387 if (ListBack != ListFront)
388 {
389 if (FromMemDisk(8*ListBack, sizeof(outx), &outx) &&
390 FromMemDisk(8*ListBack +sizeof(outx), sizeof(outy), &outy))
391 {
392 ListBack = (ListBack + 1) % ListSize;
393 out.x = outx;
394 out.y = outy;
395 lsize--;
396 }
397 return out;
398 }
399 out.x = 0;
400 out.y = 0;
401 return out;
402 }
403
404 LCMPLX
405 DeQueueLong()
406 {
407 LCMPLX out;
408 out.x = 0;
409 out.y = 0;
410
411 if (ListBack != ListFront)
412 {
413 if (FromMemDisk(8*ListBack, sizeof(out.x), &out.x) &&
414 FromMemDisk(8*ListBack +sizeof(out.x), sizeof(out.y), &out.y))
415 {
416 ListBack = (ListBack + 1) % ListSize;
417 lsize--;
418 }
419 return out;
420 }
421 out.x = 0;
422 out.y = 0;
423 return out;
424 }
425
426
427
428 /*
429 * End MIIM section;
430 */
431
432 static void SaveRect(int x, int y, int width, int depth)
433 {
434 char buff[MAXRECT];
435 int yoff;
436 if(hasinverse == 0)
437 return;
438 /* first, do any de-allocationg */
439
440 if (memory_handle != 0)
441 MemoryRelease(memory_handle);
442
443 /* allocate space and store the rect */
444
445 memset(dstack, color_dark, width);
446 if ((memory_handle = MemoryAlloc( (U16)width, (long)depth, FARMEM)) != 0)
447 {
448 Cursor_Hide();
449 for (yoff=0; yoff<depth; yoff++)
450 {
451 getrow(x, y+yoff, width, buff);
452 putrow(x, y+yoff, width, (char *)dstack);
453 MoveToMemory((BYTE *)buff, (U16)width, 1L, (long)(yoff), memory_handle);
454 }
455 Cursor_Show();
456 }
457 }
458
459
460 static void RestoreRect(int x, int y, int width, int depth)
461 {
462 char buff[MAXRECT];
463 int yoff;
464 if(hasinverse == 0)
465 return;
466
467 Cursor_Hide();
468 for (yoff=0; yoff<depth; yoff++)
469 {
470 MoveFromMemory((BYTE *)buff, (U16)width, 1L, (long)(yoff), memory_handle);
471 putrow(x, y+yoff, width, buff);
472 }
473 Cursor_Show();
474 }
475
476 /*
477 * interface to FRACTINT
478 */
479
480 _CMPLX SaveC = {-3000.0, -3000.0};
481
482 void Jiim(int which) /* called by fractint */
483 {
484 struct affine cvt;
485 int exact = 0;
486 int oldhelpmode;
487 int count = 0; /* coloring julia */
488 static int mode = 0; /* point, circle, ... */
489 int oldlookatmouse = lookatmouse;
490 double cr, ci, r;
491 int xfactor, yfactor; /* aspect ratio */
492
493 int xoff, yoff; /* center of the window */
494 int x, y;
495 int still, kbdchar= -1;
496
497 long iter;
498 int color;
499 float zoom;
500 int oldsxoffs, oldsyoffs;
501 int savehasinverse;
502 int (*oldcalctype)(void);
503 int old_x, old_y;
504 double aspect;
505 static int randir = 0;
506 static int rancnt = 0;
507 int actively_computing = 1;
508 int first_time = 1;
509 int old_debugflag;
510
511 old_debugflag = debugflag;
512 /* must use standard fractal or be calcfroth */
513 if(fractalspecific[fractype].calctype != StandardFractal
514 && fractalspecific[fractype].calctype != calcfroth)
515 return;
516 oldhelpmode = helpmode;
517 if(which == JIIM)
518 helpmode = HELP_JIIM;
519 else
520 {
521 helpmode = HELP_ORBITS;
522 hasinverse = 1;
523
524 #if 0 /* I don't think this is needed any more */
531 #endif
532 }
533 oldsxoffs = sxoffs;
534 oldsyoffs = syoffs;
535 oldcalctype = calctype;
536 show_numbers = 0;
537 using_jiim = 1;
538 mem_init(strlocn, 10*1024);
539 line_buff = newx(max(sxdots,sydots));
540 aspect = ((double)xdots*3)/((double)ydots*4); /* assumes 4:3 */
541 actively_computing = 1;
542 SetAspect(aspect);
543 lookatmouse = 3;
544
545 /* this code moved from just below to avoid boxx/strlocn conflict */
546 if(which == ORBIT)
547 (*PER_IMAGE)();
548 else
549 color = color_bright;
550 /* end moved code */
551
552 Cursor_Construct();
553
554 /*
555 * MIIM code:
556 * Grab far memory for Queue/Stack before SaveRect gets it.
557 */
558 OKtoMIIM = 0;
559 if (which == JIIM && debugflag != 300)
560 OKtoMIIM = Init_Queue((long)8*1024); /* Queue Set-up Successful? */
561
562 maxhits = 1;
563 if (which == ORBIT)
564 plot = c_putcolor; /* for line with clipping */
565
566 /*
567 * end MIIM code.
568 */
569
570 if (!video_scroll) {
571 vesa_xres = sxdots;
572 vesa_yres = sydots;
573 }
574
575 if(sxoffs != 0 || syoffs != 0) /* we're in view windows */
576 {
577 savehasinverse = hasinverse;
578 hasinverse = 1;
579 SaveRect(0,0,xdots,ydots);
580 sxoffs = video_startx;
581 syoffs = video_starty;
582 RestoreRect(0,0,xdots,ydots);
583 hasinverse = savehasinverse;
584 }
585
586 if(xdots == vesa_xres || ydots == vesa_yres ||
587 vesa_xres-xdots < vesa_xres/3 ||
588 vesa_yres-ydots < vesa_yres/3 ||
589 xdots >= MAXRECT )
590 {
591 /* this mode puts orbit/julia in an overlapping window 1/3 the size of
592 the physical screen */
593 windows = 0; /* full screen or large view window */
594 xd = vesa_xres / 3;
595 yd = vesa_yres / 3;
596 xc = video_startx + xd * 2;
597 yc = video_starty + yd * 2;
598 xoff = video_startx + xd * 5 / 2;
599 yoff = video_starty + yd * 5 / 2;
600 }
601 else if(xdots > vesa_xres/3 && ydots > vesa_yres/3)
602 {
603 /* Julia/orbit and fractal don't overlap */
604 windows = 1;
605 xd = vesa_xres - xdots;
606 yd = vesa_yres - ydots;
607 xc = video_startx + xdots;
608 yc = video_starty + ydots;
609 xoff = xc + xd/2;
610 yoff = yc + yd/2;
611
612 }
613 else
614 {
615 /* Julia/orbit takes whole screen */
616 windows = 2;
617 xd = vesa_xres;
618 yd = vesa_yres;
619 xc = video_startx;
620 yc = video_starty;
621 xoff = video_startx + xd/2;
622 yoff = video_starty + yd/2;
623 }
624
625 xfactor = (int)(xd/5.33);
626 yfactor = (int)(-yd/4);
627
628 if(windows == 0)
629 SaveRect(xc,yc,xd,yd);
630 else if(windows == 2) /* leave the fractal */
631 {
632 fillrect(xdots, yc, xd-xdots, yd, color_dark);
633 fillrect(xc , ydots, xdots, yd-ydots, color_dark);
634 }
635 else /* blank whole window */
636 fillrect(xc, yc, xd, yd, color_dark);
637
638 setup_convert_to_screen(&cvt);
639
640 /* reuse last location if inside window */
641 col = (int)(cvt.a*SaveC.x + cvt.b*SaveC.y + cvt.e + .5);
642 row = (int)(cvt.c*SaveC.x + cvt.d*SaveC.y + cvt.f + .5);
643 if(col < 0 || col >= xdots ||
644 row < 0 || row >= ydots)
645 {
646 cr = (xxmax + xxmin) / 2.0;
647 ci = (yymax + yymin) / 2.0;
648 }
649 else
650 {
651 cr = SaveC.x;
652 ci = SaveC.y;
653 }
654
655 old_x = old_y = -1;
656
657 col = (int)(cvt.a*cr + cvt.b*ci + cvt.e + .5);
658 row = (int)(cvt.c*cr + cvt.d*ci + cvt.f + .5);
659
660 /* possible extraseg arrays have been trashed, so set up again */
661 if(integerfractal)
662 fill_lx_array();
663 else
664 fill_dx_array();
665
666 Cursor_SetPos(col, row);
667 Cursor_Show();
668 color = color_bright;
669
670 iter = 1;
671 still = 1;
672 zoom = 1;
673
674 #ifdef XFRACT
675 Cursor_StartMouseTracking(); 676 #endif
677
678 while (still)
679 {
680 int dcol, drow;
681 if (actively_computing) {
682 Cursor_CheckBlink();
683 } else {
684 Cursor_WaitKey();
685 }
686 if(keypressed() || first_time) /* prevent burning up UNIX CPU */
687 {
688 first_time = 0;
689 while(keypressed())
690 {
691 Cursor_WaitKey();
692 kbdchar = getakey();
693
694 dcol = drow = 0;
695 xcjul = BIG;
696 ycjul = BIG;
697 switch (kbdchar)
698 {
699 case 1143: /* ctrl - keypad 5 */
700 case 1076: /* keypad 5 */
701 break; /* do nothing */
702 case CTL_PAGE_UP:
703 dcol = 4;
704 drow = -4;
705 break;
706 case CTL_PAGE_DOWN:
707 dcol = 4;
708 drow = 4;
709 break;
710 case CTL_HOME:
711 dcol = -4;
712 drow = -4;
713 break;
714 case CTL_END:
715 dcol = -4;
716 drow = 4;
717 break;
718 case PAGE_UP:
719 dcol = 1;
720 drow = -1;
721 break;
722 case PAGE_DOWN:
723 dcol = 1;
724 drow = 1;
725 break;
726 case HOME:
727 dcol = -1;
728 drow = -1;
729 break;
730 case END:
731 dcol = -1;
732 drow = 1;
733 break;
734 case UP_ARROW:
735 drow = -1;
736 break;
737 case DOWN_ARROW:
738 drow = 1;
739 break;
740 case LEFT_ARROW:
741 dcol = -1;
742 break;
743 case RIGHT_ARROW:
744 dcol = 1;
745 break;
746 case UP_ARROW_2:
747 drow = -4;
748 break;
749 case DOWN_ARROW_2:
750 drow = 4;
751 break;
752 case LEFT_ARROW_2:
753 dcol = -4;
754 break;
755 case RIGHT_ARROW_2:
756 dcol = 4;
757 break;
758 case 'z':
759 case 'Z':
760 zoom = (float)1.0;
761 break;
762 case '<':
763 case ',':
764 zoom /= (float)1.15;
765 break;
766 case '>':
767 case '.':
768 zoom *= (float)1.15;
769 break;
770 case SPACE:
771 xcjul = cr;
772 ycjul = ci;
773 goto finish;
774 /* break; */
775 case 'c': /* circle toggle */
776 case 'C': /* circle toggle */
777 mode = mode ^ 1;
778 break;
779 case 'l':
780 case 'L':
781 mode = mode ^ 2;
782 break;
783 case 'n':
784 case 'N':
785 show_numbers = 8 - show_numbers;
786 if(windows == 0 && show_numbers == 0)
787 {
788 Cursor_Hide();
789 cleartempmsg();
790 Cursor_Show();
791 }
792 break;
793 case 'p':
794 case 'P':
795 get_a_number(&cr,&ci);
796 exact = 1;
797 col = (int)(cvt.a*cr + cvt.b*ci + cvt.e + .5);
798 row = (int)(cvt.c*cr + cvt.d*ci + cvt.f + .5);
799 dcol = drow = 0;
800 break;
801 case 'h': /* hide fractal toggle */
802 case 'H': /* hide fractal toggle */
803 if(windows == 2)
804 windows = 3;
805 else if(windows == 3 && xd == vesa_xres)
806 {
807 RestoreRect(video_startx, video_starty, xdots, ydots);
808 windows = 2;
809 }
810 break;
811 #ifdef XFRACT
814 #endif
815 case '0':
816 case '1':
817 case '2':
818 /* case '3': */ /* don't use '3', it's already meaningful */
819 case '4':
820 case '5':
821 case '6':
822 case '7':
823 case '8':
824 case '9':
825 if (which == JIIM)
826 {
827 SecretExperimentalMode = kbdchar - '0';
828 break;
829 }
830 default:
831 still = 0;
832 /* ismand = (short)(1 - ismand); */
833 } /* switch */
834 if(kbdchar == 's' || kbdchar == 'S')
835 goto finish;
836 if(dcol > 0 || drow > 0)
837 exact = 0;
838 col += dcol;
839 row += drow;
840 #ifdef XFRACT
847 #endif
848
849 /* keep cursor in logical screen */
850 if(col >= xdots) {
851 col = xdots -1; exact = 0;
852 }
853 if(row >= ydots) {
854 row = ydots -1; exact = 0;
855 }
856 if(col < 0) {
857 col = 0; exact = 0;
858 }
859 if(row < 0) {
860 row = 0; exact = 0;
861 }
862
863 Cursor_SetPos(col,row);
864 } /* end while (keypressed) */
865
866 if(exact == 0)
867 {
868 if(integerfractal)
869 {
870 cr = lxpixel();
871 ci = lypixel();
872 cr /= (1L<<bitshift);
873 ci /= (1L<<bitshift);
874 }
875 else
876 {
877 cr = dxpixel();
878 ci = dypixel();
879 }
880 }
881 actively_computing = 1;
882 if(show_numbers) /* write coordinates on screen */
883 {
884 char str[41];
885 sprintf(str,"%16.14f %16.14f %3d",cr,ci,getcolor(col,row));
886 if(windows == 0)
887 {
888 /* show temp msg will clear self if new msg is a
889 different length - pad to length 40*/
890 while((int)strlen(str) < 40)
891 strcat(str," ");
892 str[40] = 0;
893 Cursor_Hide();
894 actively_computing = 1;
895 showtempmsg(str);
896 Cursor_Show();
897 }
898 else
899 displays(5, vesa_yres-show_numbers, WHITE, BLACK, str,strlen(str));
900 }
901 iter = 1;
902 old.x = old.y = lold.x = lold.y = 0;
903 SaveC.x = init.x = cr;
904 SaveC.y = init.y = ci;
905 linit.x = (long)(init.x*fudge);
906 linit.y = (long)(init.y*fudge);
907
908 old_x = old_y = -1;
909 /*
910 * MIIM code:
911 * compute fixed points and use them as starting points of JIIM
912 */
913 if (which == JIIM && OKtoMIIM)
914 {
915 _CMPLX f1, f2, Sqrt; /* Fixed points of Julia */
916
917 Sqrt = ComplexSqrtFloat(1 - 4 * cr, -4 * ci);
918 f1.x = (1 + Sqrt.x) / 2;
919 f2.x = (1 - Sqrt.x) / 2;
920 f1.y = Sqrt.y / 2;
921 f2.y = -Sqrt.y / 2;
922
923 ClearQueue();
924 maxhits = 1;
925 EnQueueFloat((float)f1.x, (float)f1.y);
926 EnQueueFloat((float)f2.x, (float)f2.y);
927 }
928 /*
929 * End MIIM code.
930 */
931 if(which == ORBIT)
932 {
933 PER_PIXEL();
934 }
935 /* move window if bumped */
936 if(windows==0 && col>xc && col < xc+xd && row>yc && row < yc+yd)
937 {
938 RestoreRect(xc,yc,xd,yd);
939 if (xc == video_startx + xd*2)
940 xc = video_startx + 2;
941 else
942 xc = video_startx + xd*2;
943 xoff = xc + xd / 2;
944 SaveRect(xc,yc,xd,yd);
945 }
946 if(windows == 2)
947 {
948 fillrect(xdots, yc, xd-xdots, yd-show_numbers, color_dark);
949 fillrect(xc , ydots, xdots, yd-ydots-show_numbers, color_dark);
950 }
951 else
952 fillrect(xc, yc, xd, yd, color_dark);
953
954 } /* end if (keypressed) */
955
956 if(which == JIIM)
957 {
958 if(hasinverse == 0)
959 continue;
960 /*
961 * MIIM code:
962 * If we have MIIM queue allocated, then use MIIM method.
963 */
964 if (OKtoMIIM)
965 {
966 if (QueueEmpty())
967 {
968 if (maxhits < colors - 1 && maxhits < 5 &&
969 (luckyx != 0.0 || luckyy != 0.0))
970 {
971 int i;
972
973 lsize = lmax = 0;
974 old.x = new.x = luckyx;
975 old.y = new.y = luckyy;
976 luckyx = luckyy = (float)0.0;
977 for (i=0; i<199; i++)
978 {
979 old = ComplexSqrtFloat(old.x - cr, old.y - ci);
980 new = ComplexSqrtFloat(new.x - cr, new.y - ci);
981 EnQueueFloat( (float)new.x, (float)new.y);
982 EnQueueFloat((float)-old.x, (float)-old.y);
983 }
984 maxhits++;
985 }
986 else
987 continue; /* loop while (still) */
988 }
989
990 old = DeQueueFloat();
991
992 #if 0 /* try a different new method */
996 #endif
997 x = (int)(old.x * xfactor * zoom + xoff);
998 y = (int)(old.y * yfactor * zoom + yoff);
999 color = c_getcolor(x, y);
1000 if (color < maxhits)
1001 {
1002 c_putcolor(x, y, color + 1);
1003 new = ComplexSqrtFloat(old.x - cr, old.y - ci);
1004 EnQueueFloat( (float)new.x, (float)new.y);
1005 EnQueueFloat((float)-new.x, (float)-new.y);
1006 }
1007 }
1008 else
1009 {
1010 /*
1011 * end Msnyder code, commence if not MIIM code.
1012 */
1013 old.x -= cr;
1014 old.y -= ci;
1015 r = old.x*old.x + old.y*old.y;
1016 if(r > 10.0)
1017 {
1018 old.x = old.y = 0.0; /* avoids math error */
1019 iter = 1;
1020 r = 0;
1021 }
1022 iter++;
1023 color = ((count++)>>5)%colors; /* chg color every 32 pts */
1024 if(color==0)
1025 color = 1;
1026
1027 /* r = sqrt(old.x*old.x + old.y*old.y); calculated above */
1028 r = sqrt(r);
1029 new.x = sqrt(fabs((r + old.x)/2));
1030 if (old.y < 0)
1031 new.x = -new.x;
1032
1033 new.y = sqrt(fabs((r - old.x)/2));
1034
1035
1036 switch (SecretExperimentalMode) {
1037 case 0: /* unmodified random walk */
1038 default:
1039 if (rand() % 2)
1040 {
1041 new.x = -new.x;
1042 new.y = -new.y;
1043 }
1044 x = (int)(new.x * xfactor * zoom + xoff);
1045 y = (int)(new.y * yfactor * zoom + yoff);
1046 break;
1047 case 1: /* always go one direction */
1048 if (SaveC.y < 0)
1049 {
1050 new.x = -new.x;
1051 new.y = -new.y;
1052 }
1053 x = (int)(new.x * xfactor * zoom + xoff);
1054 y = (int)(new.y * yfactor * zoom + yoff);
1055 break;
1056 case 2: /* go one dir, draw the other */
1057 if (SaveC.y < 0)
1058 {
1059 new.x = -new.x;
1060 new.y = -new.y;
1061 }
1062 x = (int)(-new.x * xfactor * zoom + xoff);
1063 y = (int)(-new.y * yfactor * zoom + yoff);
1064 break;
1065 case 4: /* go negative if max color */
1066 x = (int)(new.x * xfactor * zoom + xoff);
1067 y = (int)(new.y * yfactor * zoom + yoff);
1068 if (c_getcolor(x, y) == colors - 1)
1069 {
1070 new.x = -new.x;
1071 new.y = -new.y;
1072 x = (int)(new.x * xfactor * zoom + xoff);
1073 y = (int)(new.y * yfactor * zoom + yoff);
1074 }
1075 break;
1076 case 5: /* go positive if max color */
1077 new.x = -new.x;
1078 new.y = -new.y;
1079 x = (int)(new.x * xfactor * zoom + xoff);
1080 y = (int)(new.y * yfactor * zoom + yoff);
1081 if (c_getcolor(x, y) == colors - 1)
1082 {
1083 x = (int)(new.x * xfactor * zoom + xoff);
1084 y = (int)(new.y * yfactor * zoom + yoff);
1085 }
1086 break;
1087 case 7:
1088 if (SaveC.y < 0)
1089 {
1090 new.x = -new.x;
1091 new.y = -new.y;
1092 }
1093 x = (int)(-new.x * xfactor * zoom + xoff);
1094 y = (int)(-new.y * yfactor * zoom + yoff);
1095 if(iter > 10)
1096 {
1097 if(mode == 0) /* pixels */
1098 c_putcolor(x, y, color);
1099 else if (mode & 1) /* circles */
1100 {
1101 xbase = x;
1102 ybase = y;
1103 circle((int)(zoom*(xd >> 1)/iter),color);
1104 }
1105 if ((mode & 2) && x > 0 && y > 0 && old_x > 0 && old_y > 0)
1106 {
1107 draw_line(x, y, old_x, old_y, color);
1108 }
1109 old_x = x;
1110 old_y = y;
1111 }
1112 x = (int)(new.x * xfactor * zoom + xoff);
1113 y = (int)(new.y * yfactor * zoom + yoff);
1114 break;
1115 case 8: /* go in long zig zags */
1116 if (rancnt >= 300)
1117 rancnt = -300;
1118 if (rancnt < 0)
1119 {
1120 new.x = -new.x;
1121 new.y = -new.y;
1122 }
1123 x = (int)(new.x * xfactor * zoom + xoff);
1124 y = (int)(new.y * yfactor * zoom + yoff);
1125 break;
1126 case 9: /* "random run" */
1127 switch (randir) {
1128 case 0: /* go random direction for a while */
1129 if (rand() % 2)
1130 {
1131 new.x = -new.x;
1132 new.y = -new.y;
1133 }
1134 if (++rancnt > 1024)
1135 {
1136 rancnt = 0;
1137 if (rand() % 2)
1138 randir = 1;
1139 else
1140 randir = -1;
1141 }
1142 break;
1143 case 1: /* now go negative dir for a while */
1144 new.x = -new.x;
1145 new.y = -new.y;
1146 /* fall through */
1147 case -1: /* now go positive dir for a while */
1148 if (++rancnt > 512)
1149 randir = rancnt = 0;
1150 break;
1151 }
1152 x = (int)(new.x * xfactor * zoom + xoff);
1153 y = (int)(new.y * yfactor * zoom + yoff);
1154 break;
1155 } /* end switch SecretMode (sorry about the indentation) */
1156 } /* end if not MIIM */
1157 }
1158 else /* orbits */
1159 {
1160 if(iter < maxit)
1161 {
1162 color = (int)iter%colors;
1163 if(integerfractal)
1164 {
1165 old.x = lold.x; old.x /= fudge;
1166 old.y = lold.y; old.y /= fudge;
1167 }
1168 x = (int)((old.x - init.x) * xfactor * 3 * zoom + xoff);
1169 y = (int)((old.y - init.y) * yfactor * 3 * zoom + yoff);
1170 if((*ORBITCALC)())
1171 iter = maxit;
1172 else
1173 iter++;
1174 }
1175 else
1176 {
1177 x = y = -1;
1178 actively_computing = 0;
1179 }
1180 }
1181 if(which == ORBIT || iter > 10)
1182 {
1183 if(mode == 0) /* pixels */
1184 c_putcolor(x, y, color);
1185 else if (mode & 1) /* circles */
1186 {
1187 xbase = x;
1188 ybase = y;
1189 circle((int)(zoom*(xd >> 1)/iter),color);
1190 }
1191 if ((mode & 2) && x > 0 && y > 0 && old_x > 0 && old_y > 0)
1192 {
1193 draw_line(x, y, old_x, old_y, color);
1194 }
1195 old_x = x;
1196 old_y = y;
1197 }
1198 old = new;
1199 lold = lnew;
1200 } /* end while(still) */
1201 finish:
1202
1203 /*
1204 * Msnyder code:
1205 * free MIIM queue
1206 */
1207
1208 Free_Queue();
1209 /*
1210 * end Msnyder code.
1211 */
1212
1213 if(kbdchar != 's'&& kbdchar != 'S')
1214 {
1215 Cursor_Hide();
1216 if(windows == 0)
1217 RestoreRect(xc,yc,xd,yd);
1218 else if(windows >= 2 )
1219 {
1220 if(windows == 2)
1221 {
1222 fillrect(xdots, yc, xd-xdots, yd, color_dark);
1223 fillrect(xc , ydots, xdots, yd-ydots, color_dark);
1224 }
1225 else
1226 fillrect(xc, yc, xd, yd, color_dark);
1227 if(windows == 3 && xd == vesa_xres) /* unhide */
1228 {
1229 RestoreRect(0, 0, xdots, ydots);
1230 windows = 2;
1231 }
1232 Cursor_Hide();
1233 savehasinverse = hasinverse;
1234 hasinverse = 1;
1235 SaveRect(0,0,xdots,ydots);
1236 sxoffs = oldsxoffs;
1237 syoffs = oldsyoffs;
1238 RestoreRect(0,0,xdots,ydots);
1239 hasinverse = savehasinverse;
1240 }
1241 }
1242 Cursor_Destroy();
1243 #ifdef XFRACT
1244 Cursor_EndMouseTracking(); 1245 #endif
1246 delete(line_buff);
1247
1248 if (memory_handle != 0) {
1249 MemoryRelease(memory_handle);
1250 memory_handle = 0;
1251 }
1252 #if 0
1258 #endif
1259
1260 lookatmouse = oldlookatmouse;
1261 using_jiim = 0;
1262 calctype = oldcalctype;
1263 debugflag = old_debugflag; /* yo Chuck! */
1264 helpmode = oldhelpmode;
1265 if(kbdchar == 's' || kbdchar == 'S')
1266 {
1267 viewwindow = viewxdots = viewydots = 0;
1268 viewreduction = (float)4.2;
1269 viewcrop = 1;
1270 finalaspectratio = screenaspect;
1271 xdots = sxdots;
1272 ydots = sydots;
1273 dxsize = xdots - 1;
1274 dysize = ydots - 1;
1275 sxoffs = 0;
1276 syoffs = 0;
1277 freetempmsg();
1278 }
1279 else
1280 cleartempmsg();
1281 if (file != NULL)
1282 {
1283 fclose(file);
1284 file = NULL;
1285 dir_remove(tempdir,scrnfile);
1286 }
1287 show_numbers = 0;
1288 ungetakey(kbdchar);
1289
1290 if (curfractalspecific->calctype == calcfroth)
1291 froth_cleanup();
1292 }
1293