gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-lib/examples/gb/rand/src/rand.c
1 /***************************************************************************
2 * *
3 * Module : rand.c *
4 * *
5 * Purpose : A test for the rand() function, for the GBDK *
6 * *
7 * Version : 1, Januari 6 1998 *
8 * *
9 * Author : Luc Van den Borre ( Homepage : NOC.BASE.ORG ) *
10 * *
11 **************************************************************************/
12
13 #include <gb/gb.h>
14 #include <rand.h>
15 #include <gb/drawing.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdint.h>
19
20 #define RANGE_SIZE (160u / 4u)
21 #define HALF_RANGE_SIZE (RANGE_SIZE / 2u)
22
23 UBYTE accu[RANGE_SIZE];
24 UBYTE accua[RANGE_SIZE];
25 UBYTE accut[RANGE_SIZE];
26 UBYTE accub[RANGE_SIZE];
27
28 // Fast alternative to modulo for arbitrary 8 bit range sizes
29 // (range sizes that are exact powers of 2 can use faster bit shift or mask reductions)
30 //
31 // see: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
32 //
33 // Max value for RANGE is 256
34 #define RAND_RANGE_8BIT(randval, range) (uint8_t)(((randval & 0xFFu) * range) >> 8)
35
36 void main(void)
37 {
38 uint16_t seed;
39
40 memset(accu, 0, sizeof(accu));
41 memset(accua, 0, sizeof(accua));
42 memset(accut, 0, sizeof(accut));
43 memset(accut, 0, sizeof(accub));
44
45 /* We use the DIV register to get a random initial seed */
46 puts("Getting seed");
47 puts("Push any key (1)");
48 waitpad(0xFF);
49 waitpadup();
50 seed = DIV_REG;
51 puts("Push any key (2)");
52 waitpad(0xFF);
53 waitpadup();
54 seed |= (UWORD)DIV_REG << 8;
55
56 // initarand() calls initrand()
57 initarand(seed);
58
59 // Draw some divider lines
60 line(RANGE_SIZE * 1, 0, RANGE_SIZE * 1, 143);
61 line(RANGE_SIZE * 2, 0, RANGE_SIZE * 2, 143);
62 line(RANGE_SIZE * 3, 0, RANGE_SIZE * 3, 143);
63
64 while (1) {
65
66 // Generate standard random values in the range of 0 .. RANGE_SIZE - 1
67 // and accumulate the values into buckets, then plot the bucket sizes
68
69 // Using rand()
70 uint8_t r = RAND_RANGE_8BIT(rand(), RANGE_SIZE);
71
72 // Using arand()
73 uint8_t ra = RAND_RANGE_8BIT(arand(), RANGE_SIZE);
74
75 // Create a triangle distribution using (rand - rand)
76 uint8_t rt1 = RAND_RANGE_8BIT(rand(), HALF_RANGE_SIZE);
77 uint8_t rt2 = RAND_RANGE_8BIT(rand(), HALF_RANGE_SIZE);
78 uint8_t rt = HALF_RANGE_SIZE + (rt1 - rt2);
79
80 // Create a bell-curve-ish distribution using (rand - rand) + (rand - rand)
81 uint8_t rb1 = RAND_RANGE_8BIT(rand(), HALF_RANGE_SIZE / 2);
82 uint8_t rb2 = RAND_RANGE_8BIT(rand(), HALF_RANGE_SIZE / 2);
83 uint8_t rb3 = RAND_RANGE_8BIT(rand(), HALF_RANGE_SIZE / 2);
84 uint8_t rb4 = RAND_RANGE_8BIT(rand(), HALF_RANGE_SIZE / 2);
85 uint8_t rb = HALF_RANGE_SIZE + (rb1 - rb2) + (rb3 - rb4);
86
87
88 // Plot the updated rand value buckets
89 //
90 // rand | arand | rand with triangle distribution | bell-curve-ish
91
92 uint8_t r_bucket_height = ++accu[r];
93 if (r_bucket_height > 144) break;
94 plot(r + (RANGE_SIZE * 0), 144-r_bucket_height, LTGREY, SOLID);
95
96 uint8_t ra_bucket_height = ++accua[ra];
97 if (ra_bucket_height > 144) break;
98 plot(ra + (RANGE_SIZE * 1), 144 - ra_bucket_height, DKGREY, SOLID);
99
100 uint8_t rt_bucket_height = ++accut[rt];
101 if (rt_bucket_height > 144) break;
102 plot(rt + (RANGE_SIZE * 2), 144 - rt_bucket_height, BLACK, SOLID);
103
104 uint8_t rb_bucket_height = ++accub[rb];
105 if (rb_bucket_height > 144) break;
106 plot(rb + (RANGE_SIZE * 3), 144 - rb_bucket_height, BLACK, SOLID);
107 }
108 }
109
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.