]> git.sur5r.net Git - cc65/blob - samples/mandelbrot.c
small space optimization -- 3 bytes reduced
[cc65] / samples / mandelbrot.c
1 /*****************************************************************************
2  * mandelbrot sample program for cc65.                                       *
3  *                                                                           *
4  * (w)2002 by groepaz/hitmen, TGI support by Stefan Haubenthal               *
5  *****************************************************************************/
6
7
8
9 #include <stdlib.h>
10 #include <time.h>
11 #include <conio.h>
12 #include <tgi.h>
13
14
15
16 /* Graphics definitions */
17 #define SCREEN_X        (tgi_getxres())
18 #define SCREEN_Y        (tgi_getyres())
19 #define MAXCOL          (tgi_getcolorcount())
20
21 #define maxiterations   32
22 #define fpshift         (10)
23 #define tofp(_x)        ((_x)<<fpshift)
24 #define fromfp(_x)      ((_x)>>fpshift)
25 #define fpabs(_x)       (abs(_x))
26
27 #define mulfp(_a,_b)    ((((signed long)_a)*(_b))>>fpshift)
28 #define divfp(_a,_b)    ((((signed long)_a)<<fpshift)/(_b))
29
30 /* Workaround missing clock stuff */
31 #if defined(__APPLE2__) || defined(__APPLE2ENH__)
32 #  define clock()       0
33 #  define CLK_TCK       1
34 #endif
35
36 /* Use static local variables for speed */
37 #pragma static-locals (1);
38
39
40
41 void mandelbrot (signed short x1, signed short y1, signed short x2,
42                  signed short y2)
43 {
44     register unsigned char count;
45     register signed short r, r1, i;
46     register signed short xs, ys, xx, yy;
47     register signed short x, y;
48
49     /* calc stepwidth */
50     xs = ((x2 - x1) / (SCREEN_X));
51     ys = ((y2 - y1) / (SCREEN_Y));
52
53     yy = y1;
54     for (y = 0; y < (SCREEN_Y); y++) {
55         yy += ys;
56         xx = x1;
57         for (x = 0; x < (SCREEN_X); x++) {
58             xx += xs;
59             /* do iterations */
60             r = 0;
61             i = 0;
62             for (count = 0; (count < maxiterations) &&
63                  (fpabs (r) < tofp (2)) && (fpabs (i) < tofp (2));
64                  ++count) {
65                 r1 = (mulfp (r, r) - mulfp (i, i)) + xx;
66                 /* i = (mulfp(mulfp(r,i),tofp(2)))+yy; */
67                 i = (((signed long) r * i) >> (fpshift - 1)) + yy;
68                 r = r1;
69             }
70             if (count == maxiterations) {
71                 tgi_setcolor (0);
72             } else {
73                 if (MAXCOL == 2)
74                     tgi_setcolor (1);
75                 else
76                     tgi_setcolor (count % MAXCOL);
77             }
78             /* set pixel */
79             tgi_setpixel (x, y);
80         }
81     }
82 }
83
84 int main (void)
85 {
86     clock_t t;
87     unsigned long sec;
88     unsigned sec10;
89     unsigned char err;
90
91     clrscr ();
92
93     /* Load the graphics driver */
94     cprintf ("initializing... mompls\r\n");
95     tgi_load_driver (tgi_stddrv);
96     err = tgi_geterror ();
97     if (err  != TGI_ERR_OK) {
98         cprintf ("Error #%d initializing graphics.\r\n%s\r\n",
99                  err, tgi_geterrormsg (err));
100         exit (EXIT_FAILURE);
101     };
102     cprintf ("ok.\n\r");
103
104     /* Initialize graphics */
105     tgi_init ();
106     tgi_clear ();
107
108     t = clock ();
109
110     /* calc mandelbrot set */
111     mandelbrot (tofp (-2), tofp (-2), tofp (2), tofp (2));
112
113     t = clock () - t;
114
115     /* Fetch the character from the keyboard buffer and discard it */
116     (void) cgetc ();
117
118     /* shut down gfx mode and return to textmode */
119     tgi_done ();
120
121     /* Calculate stats */
122     sec = (t * 10) / CLK_TCK;
123     sec10 = sec % 10;
124     sec /= 10;
125
126     /* Output stats */
127     cprintf ("time  : %lu.%us\n\r", sec, sec10);
128
129     /* Wait for a key, then end */
130     cputs ("Press any key when done...\n\r");
131     (void) cgetc ();
132
133     /* Done */
134     return EXIT_SUCCESS;
135
136 }