a17550b9752c27588036e182009b15e538473807
[dosdemo] / src / fract.c
1 #include <string.h>
2 #include <limits.h>
3 #include "demo.h"
4 #include "screen.h"
5 #include "gfxutil.h"
6
7 struct vec2x {
8         long x, y;
9 };
10
11 static int init(void);
12 static void destroy(void);
13 static void draw(void);
14 static int julia(long x, long y, long cx, long cy, int max_iter);
15
16 static struct screen scr = {
17         "fract",
18         init,
19         destroy,
20         0, 0,
21         draw
22 };
23
24 /*static long aspect_24x8 = (long)(1.3333333 * 256.0);*/
25 static long xscale_24x8 = (long)(1.3333333 * 1.2 * 256.0);
26 static long yscale_24x8 = (long)(1.2 * 256.0);
27 static int cx, cy;
28 static int max_iter = 50;
29
30 #define WALK_SIZE       20
31
32 struct screen *fract_screen(void)
33 {
34         return &scr;
35 }
36
37 static int init(void)
38 {
39         return 0;
40 }
41
42 static void destroy(void)
43 {
44 }
45
46 #define PACK_RGB16(r, g, b) \
47         (((((r) >> 3) & 0x1f) << 11) | ((((g) >> 2) & 0x3f) << 5) | (((b) >> 3) & 0x1f))
48
49 static void draw(void)
50 {
51         int i, j;
52         unsigned short *pixels = vmem_back;
53
54         cx = mouse_x;
55         cy = mouse_y;
56
57         for(i=0; i<fb_height; i++) {
58                 for(j=0; j<fb_width; j++) {
59                         unsigned char pidx = julia(j, i, cx, cy, max_iter) & 0xff;
60                         *pixels++ = (pidx >> 3) | ((pidx >> 2) << 5) | ((pidx >> 3) << 11);
61                 }
62         }
63
64         pixels = vmem_back;
65         pixels[mouse_y * fb_width + mouse_x] = 0xffe;
66         swap_buffers(vmem_back);
67 }
68
69 static long normalize_coord(long x, long range)
70 {
71         /* 2 * x / range - 1*/
72         return (x << 17) / range - 65536;
73 }
74
75 static int julia(long x, long y, long cx, long cy, int max_iter)
76 {
77         int i;
78
79         /* convert to fixed point roughly [-1, 1] */
80         x = (normalize_coord(x, fb_width) >> 8) * xscale_24x8;
81         y = (normalize_coord(y, fb_height) >> 8) * yscale_24x8;
82         cx = (normalize_coord(cx, fb_width) >> 8) * xscale_24x8;
83         cy = (normalize_coord(cy, fb_height) >> 8) * yscale_24x8;
84
85         for(i=0; i<max_iter; i++) {
86                 /* z_n = z_{n-1}**2 + c */
87                 long px = x >> 8;
88                 long py = y >> 8;
89
90                 if(px * px + py * py > (4 << 16)) {
91                         break;
92                 }
93                 x = px * px - py * py + cx;
94                 y = (px * py << 1) + cy;
95         }
96
97         return i < max_iter ? (256 * i / max_iter) : 0;
98 }