aboutsummaryrefslogtreecommitdiffstats
path: root/src/renderer.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-06-02 17:26:08 +0200
committerBad Diode <bd@badd10de.dev>2021-06-02 17:26:08 +0200
commitf6686f1e86927f038086023362251ebe78ce5ad6 (patch)
treed196fc1c32c55442a2ac75d4ce046b1c0e0d6d48 /src/renderer.c
downloadstepper-f6686f1e86927f038086023362251ebe78ce5ad6.tar.gz
stepper-f6686f1e86927f038086023362251ebe78ce5ad6.zip
Init repo with basic BG framebuffer renderer
Diffstat (limited to 'src/renderer.c')
-rw-r--r--src/renderer.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/renderer.c b/src/renderer.c
new file mode 100644
index 0000000..9fe55b2
--- /dev/null
+++ b/src/renderer.c
@@ -0,0 +1,86 @@
1// TODO: For now we pack front/backbuffers together but this make it so that we
2// can only use 2 backgrounds. Instead we can move the backbuffer to the end of
3// the VRAM. This will give us 3 backgrounds but eats into the available memory
4// for sprites but should be fine for non sprite intensive applications.
5#define FRONTBUFFER ((u32*)(MEM_VRAM))
6#define BACKBUFFER ((u32*)(MEM_VRAM + KB(96) - KB(20)))
7
8// Adjust both of these if the location of the map changes. Each screnblock
9// requires 2K.
10#define FRONTBUFFER_TILEMAP ((u16*)(MEM_VRAM + KB(20)))
11#define FRONTBUFFER_SCREENBLOCK 10
12
13static u32 dirty_tiles[21] = {0};
14
15// TODO: Allow disable bound checking at compile time.
16#define BOUNDCHECK_SCREEN() if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return;
17
18IWRAM_CODE
19void
20draw_pixel(u16 x, u16 y, u8 color) {
21 BOUNDCHECK_SCREEN();
22
23 // Find row position for the given x/y coordinates.
24 size_t tile_x = x / 8;
25 size_t tile_y = y / 8;
26 size_t start_col = x % 8;
27 size_t start_row = y % 8;
28 size_t pos = start_row + (tile_x + tile_y * 32) * 8;
29
30 // Update backbuffer.
31 size_t shift = start_col * sizeof(u32);
32 BACKBUFFER[pos] = (BACKBUFFER[pos] & ~(0xF << shift)) | color << shift;
33
34 // Mark tile as dirty.
35 dirty_tiles[tile_y] |= 1 << tile_x;
36}
37
38IWRAM_CODE
39void
40flip_buffer(void) {
41 // Copy dirty tiles from the backbuffer to the frontbuffer.
42 Tile *dst = FRONTBUFFER;
43 Tile *src = BACKBUFFER;
44 for (size_t j = 0; j < 20; ++j) {
45 if (dirty_tiles[j] == 0) {
46 continue;
47 }
48 for (size_t i = 0, k = 1; i < 30; ++i, k <<= 1) {
49 if (dirty_tiles[j] & k) {
50 dst[i + j * 32] = src[i + j * 32];
51 }
52 }
53 dirty_tiles[j] = 0;
54 }
55}
56
57void
58renderer_init(void) {
59 // Initialize display mode and bg palette.
60 DISP_CTRL = DISP_MODE_0 | DISP_BG_0 | DISP_OBJ;
61
62 // Initialize backgrounds.
63 BG_CTRL(0) = BG_CHARBLOCK(0) | BG_SCREENBLOCK(FRONTBUFFER_SCREENBLOCK);
64
65 // TODO: Initialize other backgrounds if needed.
66
67 // Use DMA to clear front and back buffers.
68 dma_fill(FRONTBUFFER, 0, KB(20), 3);
69 dma_fill(BACKBUFFER, 0, KB(20), 3);
70
71 // Initialize default palette.
72 PAL_BUFFER_BG[0] = COLOR_BLACK;
73 PAL_BUFFER_BG[1] = COLOR_WHITE;
74 PAL_BUFFER_BG[2] = COLOR_RED;
75 PAL_BUFFER_BG[3] = COLOR_BLUE;
76 PAL_BUFFER_BG[4] = COLOR_CYAN;
77 PAL_BUFFER_BG[5] = COLOR_GREY;
78
79 // Initialize background memory map.
80 for (size_t i = 0; i < 32 * 20; ++i) {
81 FRONTBUFFER_TILEMAP[i] = i;
82 }
83
84// // Load font data into VRAM.
85// unpack_tiles(&bd_font, FONT_DATA, 256);
86}