Monorepo for Aesthetic.Computer
aesthetic.computer
1#include <gb/gb.h>
2#include <stdio.h>
3#include <gbdk/console.h>
4#include <string.h>
5
6// Sine table: 256 entries, values from -64 to +64
7const int8_t sine_table[256] = {
8 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45,
9 48, 51, 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 80, 82, 85, 87,
10 89, 91, 94, 96, 98, 100, 102, 103, 105, 107, 108, 110, 112, 113, 114, 116,
11 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 126, 126, 127, 127, 127, 127,
12 127, 127, 127, 127, 127, 126, 126, 125, 124, 124, 123, 122, 121, 120, 119, 118,
13 117, 116, 114, 113, 112, 110, 108, 107, 105, 103, 102, 100, 98, 96, 94, 91,
14 89, 87, 85, 82, 80, 78, 75, 73, 70, 67, 65, 62, 59, 57, 54, 51,
15 48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3,
16 0, -3, -6, -9, -12, -15, -18, -21, -24, -27, -30, -33, -36, -39, -42, -45,
17 -48, -51, -54, -57, -59, -62, -65, -67, -70, -73, -75, -78, -80, -82, -85, -87,
18 -89, -91, -94, -96, -98, -100, -102, -103, -105, -107, -108, -110, -112, -113, -114, -116,
19 -117, -118, -119, -120, -121, -122, -123, -124, -124, -125, -126, -126, -127, -127, -127, -127,
20 -127, -127, -127, -127, -127, -126, -126, -125, -124, -124, -123, -122, -121, -120, -119, -118,
21 -117, -116, -114, -113, -112, -110, -108, -107, -105, -103, -102, -100, -98, -96, -94, -91,
22 -89, -87, -85, -82, -80, -78, -75, -73, -70, -67, -65, -62, -59, -57, -54, -51,
23 -48, -45, -42, -39, -36, -33, -30, -27, -24, -21, -18, -15, -12, -9, -6, -3
24};
25
26int8_t sin_lookup(uint8_t angle) {
27 return sine_table[angle];
28}
29
30int8_t cos_lookup(uint8_t angle) {
31 return sine_table[(angle + 64) & 0xFF];
32}
33
34// Buffer for tile data manipulation
35uint8_t tile_buffer[16];
36uint8_t next_tile_id = 128; // Start at 128 to avoid printf's font tiles (0-127)
37
38// Plot a pixel in the background by modifying tile data
39void plot_pixel(uint8_t x, uint8_t y) {
40 uint8_t tile_x, tile_y;
41 uint8_t pixel_x, pixel_y;
42 uint8_t tile_num;
43 uint8_t row_offset;
44 uint8_t bit_mask;
45
46 // Convert screen coordinates to tile coordinates
47 tile_x = x / 8;
48 tile_y = y / 8;
49
50 // Get pixel position within the tile (0-7)
51 pixel_x = x % 8;
52 pixel_y = y % 8;
53
54 // Get the tile number from the background map
55 get_bkg_tiles(tile_x, tile_y, 1, 1, &tile_num);
56
57 // If tile is 0 (empty), allocate a new tile
58 if(tile_num == 0) {
59 // Make sure we don't run out of tiles (max 256)
60 if(next_tile_id >= 255) return;
61
62 tile_num = next_tile_id;
63 next_tile_id++;
64 set_bkg_tiles(tile_x, tile_y, 1, 1, &tile_num);
65
66 // Clear the tile buffer
67 memset(tile_buffer, 0, 16);
68 } else {
69 // Read existing tile data
70 get_bkg_data(tile_num, 1, tile_buffer);
71 }
72
73 // Set the pixel in the tile data
74 // Each row is 2 bytes (low bit plane, high bit plane)
75 row_offset = pixel_y * 2;
76 bit_mask = 0x80 >> pixel_x; // Bit 7 is leftmost pixel
77
78 // Set both bit planes to make pixel black (color 3)
79 tile_buffer[row_offset] |= bit_mask; // Low bit plane
80 tile_buffer[row_offset + 1] |= bit_mask; // High bit plane
81
82 // Write the modified tile back to VRAM
83 set_bkg_data(tile_num, 1, tile_buffer);
84}
85
86void main(void) {
87 uint16_t angle = 0; // Angle in degrees: 0-359
88 int16_t turtle_x_fixed = 80 << 8;
89 int16_t turtle_y_fixed = 72 << 8;
90 int16_t dx, dy;
91 uint16_t step = 0;
92 uint8_t delay_counter = 0;
93 uint8_t pixel_x, pixel_y;
94 int16_t radius_fixed = 25 << 8; // 25 pixel radius
95
96 // Display must be off to initialize
97 DISPLAY_OFF;
98
99 // Initialize background (all tiles start at 0 = blank)
100 uint8_t i, j;
101 uint8_t blank = 0;
102 for(i = 0; i < 18; i++) {
103 for(j = 0; j < 20; j++) {
104 set_bkg_tiles(j, i, 1, 1, &blank);
105 }
106 }
107
108 SHOW_BKG;
109 DISPLAY_ON;
110
111 // Print status in top-left (uses tiles 0-127 for font)
112 gotoxy(0, 0);
113 printf("TURTLE CIRCLE");
114
115 // Move turtle to starting position (right side of circle at 0°)
116 turtle_x_fixed += radius_fixed;
117
118 while(1) {
119 wait_vbl_done();
120
121 delay_counter++;
122 if(delay_counter >= 2) {
123 delay_counter = 0;
124
125 if(step < 360) {
126 // Use polar coordinates: calculate position directly from angle
127 // x = center_x + radius * cos(angle)
128 // y = center_y + radius * sin(angle)
129
130 // Convert angle (0-36000 hundredths) to lookup table (0-255)
131 angle_byte = (uint8_t)((angle_degrees * 256UL) / 36000UL);
132
133 // Get cos/sin from lookup table (values are -127 to +127)
134 int16_t cos_val = cos_lookup(angle_byte);
135 int16_t sin_val = sin_lookup(angle_byte);
136
137 // Calculate position: center + (radius * cos/sin) / 127
138 // radius_fixed is already in 8.8 format (25 << 8)
139 // cos/sin are scaled to 127, so multiply then divide by 127
140 int16_t x_offset = (radius_fixed * cos_val) / 127;
141 int16_t y_offset = (radius_fixed * sin_val) / 127;
142
143 // turtle positions start at center (80, 72) in 8.8 fixed point
144 int16_t x_pos = (80 << 8) + x_offset;
145 int16_t y_pos = (72 << 8) + y_offset;
146
147 // Convert to screen pixels
148 int16_t x_int = x_pos >> 8;
149 int16_t y_int = y_pos >> 8;
150
151 // Only plot if on screen
152 if(x_int >= 0 && x_int < 160 && y_int >= 0 && y_int < 144) {
153 pixel_x = (uint8_t)x_int;
154 pixel_y = (uint8_t)y_int;
155 plot_pixel(pixel_x, pixel_y);
156 }
157
158 // Turn: increment angle by 1 degree
159 angle_degrees += 100;
160 if(angle_degrees >= 36000) angle_degrees -= 36000;
161
162 step++;
163
164 // Update step counter and angle debug more frequently
165 if(step % 5 == 0) {
166 gotoxy(0, 1);
167 printf("S:%d A:%d.%02d ", step, angle_degrees/100, angle_degrees%100);
168 gotoxy(0, 2);
169 printf("X:%d Y:%d ", x_int, y_int);
170 }
171 }
172 }
173 }
174}