diff options
author | Bad Diode <bd@badd10de.dev> | 2021-06-02 17:26:08 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-06-02 17:26:08 +0200 |
commit | f6686f1e86927f038086023362251ebe78ce5ad6 (patch) | |
tree | d196fc1c32c55442a2ac75d4ce046b1c0e0d6d48 /src/renderer.c | |
download | stepper-f6686f1e86927f038086023362251ebe78ce5ad6.tar.gz stepper-f6686f1e86927f038086023362251ebe78ce5ad6.zip |
Init repo with basic BG framebuffer renderer
Diffstat (limited to 'src/renderer.c')
-rw-r--r-- | src/renderer.c | 86 |
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 | |||
13 | static 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 | |||
18 | IWRAM_CODE | ||
19 | void | ||
20 | draw_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 | |||
38 | IWRAM_CODE | ||
39 | void | ||
40 | flip_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 | |||
57 | void | ||
58 | renderer_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 | } | ||