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