diff options
author | Bad Diode <bd@badd10de.dev> | 2021-04-27 12:36:28 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-04-27 12:36:28 +0200 |
commit | af05a2979f97d00eab36261374af1eaf2ac3c833 (patch) | |
tree | 726757223f51ca3130e95d5e52a49dc3200958a5 /src | |
parent | a0efde919bedfbb427d2e2c5ae34e06489930b0c (diff) | |
download | gba-experiments-af05a2979f97d00eab36261374af1eaf2ac3c833.tar.gz gba-experiments-af05a2979f97d00eab36261374af1eaf2ac3c833.zip |
Add DMA control macros and small memory copy test
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 69 | ||||
-rw-r--r-- | src/main.c | 96 | ||||
-rw-r--r-- | src/sprites.h | 1 | ||||
-rw-r--r-- | src/text.h | 9 |
4 files changed, 101 insertions, 74 deletions
diff --git a/src/common.h b/src/common.h index 669fb6e..e3405be 100644 --- a/src/common.h +++ b/src/common.h | |||
@@ -305,6 +305,7 @@ unpack_1bb(u8 hex) { | |||
305 | } | 305 | } |
306 | 306 | ||
307 | // Unpack N tiles packed at 1bpp. | 307 | // Unpack N tiles packed at 1bpp. |
308 | static inline void | ||
308 | unpack_tiles(u32 *src, u32 *dst, size_t n_tiles) { | 309 | unpack_tiles(u32 *src, u32 *dst, size_t n_tiles) { |
309 | u32 *target_src = src + n_tiles * 2; | 310 | u32 *target_src = src + n_tiles * 2; |
310 | while (src != target_src) { | 311 | while (src != target_src) { |
@@ -316,4 +317,72 @@ unpack_tiles(u32 *src, u32 *dst, size_t n_tiles) { | |||
316 | } | 317 | } |
317 | } | 318 | } |
318 | 319 | ||
320 | // | ||
321 | // Direct Memory Access (DMA) | ||
322 | // | ||
323 | |||
324 | |||
325 | // Source, destination, and control registers. | ||
326 | #define DMA_SRC(N) *((vu32*) 0x040000B0 + (N) * 12) | ||
327 | #define DMA_DST(N) *((vu32*) 0x040000B4 + (N) * 12) | ||
328 | #define DMA_CTRL(N) *((vu32*) 0x040000B8 + (N) * 12) | ||
329 | |||
330 | // DMA control bits. | ||
331 | #define DMA_DST_INC (0 << 0x15) | ||
332 | #define DMA_DST_DEC (1 << 0x15) | ||
333 | #define DMA_DST_FIXED (2 << 0x15) | ||
334 | #define DMA_DST_RELOAD (3 << 0x15) | ||
335 | #define DMA_SRC_INC (0 << 0x17) | ||
336 | #define DMA_SRC_DEC (1 << 0x17) | ||
337 | #define DMA_SRC_FIXED (2 << 0x17) | ||
338 | #define DMA_REPEAT (1 << 0x19) | ||
339 | #define DMA_CHUNK_16 (0 << 0x1A) | ||
340 | #define DMA_CHUNK_32 (1 << 0x1A) | ||
341 | #define DMA_NOW (0 << 0x1C) | ||
342 | #define DMA_VBLANK (1 << 0x1C) | ||
343 | #define DMA_HBLANK (2 << 0x1C) | ||
344 | #define DMA_REFRESH (3 << 0x1C) | ||
345 | #define DMA_IRQ (1 << 0x1E) | ||
346 | #define DMA_ENABLE (1 << 0x1F) | ||
347 | |||
348 | // Custom struct for cleaner DMA transfer functions. | ||
349 | typedef struct DmaStr { | ||
350 | const void *src; | ||
351 | void *dst; | ||
352 | u32 ctrl; | ||
353 | } DmaStr; | ||
354 | |||
355 | #define DMA_TRANSFER ((volatile DmaStr*) 0x040000B0) | ||
356 | |||
357 | // Transfer `count` number of chunks from src to dst using a DMA channel. Note | ||
358 | // that chunks are not bytes, but instead configured based on bits set by | ||
359 | // DMA_CTRL. | ||
360 | inline void | ||
361 | dma_transfer_copy(void *dst, const void *src, u32 count, int channel, u32 options) { | ||
362 | DMA_TRANSFER[channel].ctrl = 0; | ||
363 | DMA_TRANSFER[channel].src = src; | ||
364 | DMA_TRANSFER[channel].dst = dst; | ||
365 | DMA_TRANSFER[channel].ctrl = count | options; | ||
366 | } | ||
367 | |||
368 | inline void | ||
369 | dma_transfer_fill(void *dst, volatile u32 src, u32 count, int channel, u32 options) { | ||
370 | DMA_TRANSFER[channel].ctrl = 0; | ||
371 | DMA_TRANSFER[channel].src = (const void *)&src; | ||
372 | DMA_TRANSFER[channel].dst = dst; | ||
373 | DMA_TRANSFER[channel].ctrl = count | options | DMA_SRC_FIXED; | ||
374 | } | ||
375 | |||
376 | // Copy N number of bytes using a DMA channel. | ||
377 | inline void | ||
378 | dma_copy(void *dst, const void *src, u32 size, int channel) { | ||
379 | dma_transfer_copy(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); | ||
380 | } | ||
381 | |||
382 | // Fill the dst location with the word set at src. | ||
383 | inline void | ||
384 | dma_fill(void *dst, const void *src, u32 size, int channel) { | ||
385 | dma_transfer_fill(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); | ||
386 | } | ||
387 | |||
319 | #endif // GBAEXP_COMMON_H | 388 | #endif // GBAEXP_COMMON_H |
@@ -22,83 +22,43 @@ int main(void) { | |||
22 | init_sprite_pal(0, COLOR_WHITE); | 22 | init_sprite_pal(0, COLOR_WHITE); |
23 | init_sprites(0); | 23 | init_sprites(0); |
24 | init_button_sprites(); | 24 | init_button_sprites(); |
25 | Color colors[16] = { | ||
26 | COLOR_BLUE, | ||
27 | COLOR_BLUE, | ||
28 | COLOR_BLUE, | ||
29 | COLOR_BLUE, | ||
30 | COLOR_BLUE, | ||
31 | COLOR_BLUE, | ||
32 | COLOR_BLUE, | ||
33 | COLOR_BLUE, | ||
34 | COLOR_BLUE, | ||
35 | COLOR_BLUE, | ||
36 | COLOR_BLUE, | ||
37 | COLOR_BLUE, | ||
38 | COLOR_BLUE, | ||
39 | COLOR_BLUE, | ||
40 | COLOR_BLUE, | ||
41 | COLOR_BLUE, | ||
42 | }; | ||
43 | // These should be equivalent here, but remember that the dma_copy and | ||
44 | // dma_fill functions will always work on U32 chunks. | ||
45 | // | ||
46 | // memcpy(&PAL_BUFFER_SPRITES[0], colors, 16 * sizeof(Color)); | ||
47 | // dma_copy(&PAL_BUFFER_SPRITES[0], colors, 16 * sizeof(Color), 3); | ||
48 | |||
49 | u32 color = COLOR_RED | COLOR_RED << 16; | ||
50 | dma_fill(&PAL_BUFFER_SPRITES[0], color, 16 * sizeof(Color), 3); | ||
25 | 51 | ||
26 | // Initialize text engine. | 52 | // Initialize text engine. |
27 | txt_init(0, COLOR_RED, 0); | 53 | // txt_init(0, COLOR_RED, 0); |
28 | txt_position(0, 6); | 54 | // txt_printf("TEST"); |
29 | txt_printf("Strings: %s\n", "Hello World"); | ||
30 | txt_printf("Signed ints: %d\n", -100000); | ||
31 | txt_printf("Unsigned ints: %u\n", 1234567); | ||
32 | txt_printf("Hex values: 0x%x\n", 1024); | ||
33 | 55 | ||
34 | int frame_counter = 0; | 56 | int frame_counter = 0; |
35 | int x = 0; | ||
36 | int y = 0; | ||
37 | while(true) { | 57 | while(true) { |
38 | wait_vsync(); | 58 | wait_vsync(); |
39 | poll_keys(); | 59 | poll_keys(); |
40 | 60 | ||
41 | txt_position(0, 0); | ||
42 | txt_printf("Frame counter: %d\n", frame_counter); | ||
43 | |||
44 | if (key_hold(KEY_DOWN)) { | ||
45 | y += 3; | ||
46 | } | ||
47 | if (key_hold(KEY_UP)) { | ||
48 | y -= 3; | ||
49 | } | ||
50 | if (key_hold(KEY_LEFT)) { | ||
51 | x -= 3; | ||
52 | } | ||
53 | if (key_hold(KEY_RIGHT)) { | ||
54 | x += 3; | ||
55 | } | ||
56 | |||
57 | if (key_pressed(KEY_A)) { | ||
58 | txt_clear_line(); | ||
59 | txt_printf("Pressed key: A"); | ||
60 | } | ||
61 | if (key_pressed(KEY_B)) { | ||
62 | txt_clear_line(); | ||
63 | txt_printf("Pressed key: B"); | ||
64 | } | ||
65 | if (key_pressed(KEY_L)) { | ||
66 | txt_clear_line(); | ||
67 | txt_printf("Pressed key: L"); | ||
68 | } | ||
69 | if (key_pressed(KEY_R)) { | ||
70 | txt_clear_line(); | ||
71 | txt_printf("Pressed key: R"); | ||
72 | } | ||
73 | if (key_pressed(KEY_START)) { | ||
74 | txt_clear_line(); | ||
75 | txt_printf("Pressed key: Start"); | ||
76 | } | ||
77 | if (key_pressed(KEY_SELECT)) { | ||
78 | txt_clear_line(); | ||
79 | txt_printf("Pressed key: Select"); | ||
80 | } | ||
81 | if (key_pressed(KEY_UP)) { | ||
82 | txt_clear_line(); | ||
83 | txt_printf("Pressed key: Up"); | ||
84 | } | ||
85 | if (key_pressed(KEY_DOWN)) { | ||
86 | txt_clear_line(); | ||
87 | txt_printf("Pressed key: Down"); | ||
88 | } | ||
89 | if (key_pressed(KEY_LEFT)) { | ||
90 | txt_clear_line(); | ||
91 | txt_printf("Pressed key: Left"); | ||
92 | } | ||
93 | if (key_pressed(KEY_RIGHT)) { | ||
94 | txt_clear_line(); | ||
95 | txt_printf("Pressed key: Right"); | ||
96 | } | ||
97 | |||
98 | frame_counter++; | 61 | frame_counter++; |
99 | // BG_H_SCROLL_0 = x; | ||
100 | // BG_V_SCROLL_0 = y; | ||
101 | |||
102 | update_button_sprites(); | 62 | update_button_sprites(); |
103 | }; | 63 | }; |
104 | 64 | ||
diff --git a/src/sprites.h b/src/sprites.h index 88ca787..0b55f0d 100644 --- a/src/sprites.h +++ b/src/sprites.h | |||
@@ -73,7 +73,6 @@ init_sprite_pal(size_t starting_index, Color col) { | |||
73 | for (size_t i = 0; i < 16; ++i) { | 73 | for (size_t i = 0; i < 16; ++i) { |
74 | PAL_BUFFER_SPRITES[i + starting_index] = col; | 74 | PAL_BUFFER_SPRITES[i + starting_index] = col; |
75 | } | 75 | } |
76 | |||
77 | } | 76 | } |
78 | 77 | ||
79 | #endif // GBAEXP_SPRITES_H | 78 | #endif // GBAEXP_SPRITES_H |
@@ -2,6 +2,7 @@ | |||
2 | #define GBAEXP_TILES_H | 2 | #define GBAEXP_TILES_H |
3 | 3 | ||
4 | #include <stdarg.h> | 4 | #include <stdarg.h> |
5 | #include <stdio.h> | ||
5 | 6 | ||
6 | #include "common.h" | 7 | #include "common.h" |
7 | #include "bd-font.c" | 8 | #include "bd-font.c" |
@@ -75,11 +76,9 @@ txt_printf(char *msg, ...) { | |||
75 | va_list arg_list; | 76 | va_list arg_list; |
76 | va_start(arg_list, msg); | 77 | va_start(arg_list, msg); |
77 | char c; | 78 | char c; |
78 | char prev_c; | ||
79 | while ((c = *msg++) != '\0') { | 79 | while ((c = *msg++) != '\0') { |
80 | if (c != '%') { | 80 | if (c != '%') { |
81 | txt_putc(c); | 81 | txt_putc(c); |
82 | prev_c = c; | ||
83 | continue; | 82 | continue; |
84 | } | 83 | } |
85 | c = *msg++; | 84 | c = *msg++; |
@@ -88,19 +87,19 @@ txt_printf(char *msg, ...) { | |||
88 | txt_puts(va_arg(arg_list, char *)); | 87 | txt_puts(va_arg(arg_list, char *)); |
89 | } break; | 88 | } break; |
90 | case 'd': { | 89 | case 'd': { |
91 | char buf[32] = {0}; | 90 | char buf[12] = {0}; |
92 | int x = va_arg(arg_list, int); | 91 | int x = va_arg(arg_list, int); |
93 | sprintf(buf, "%d", x); | 92 | sprintf(buf, "%d", x); |
94 | txt_puts(buf); | 93 | txt_puts(buf); |
95 | } break; | 94 | } break; |
96 | case 'u': { | 95 | case 'u': { |
97 | char buf[32] = {0}; | 96 | char buf[12] = {0}; |
98 | unsigned int x = va_arg(arg_list, unsigned int); | 97 | unsigned int x = va_arg(arg_list, unsigned int); |
99 | sprintf(buf, "%u", x); | 98 | sprintf(buf, "%u", x); |
100 | txt_puts(buf); | 99 | txt_puts(buf); |
101 | } break; | 100 | } break; |
102 | case 'x': { | 101 | case 'x': { |
103 | char buf[32] = {0}; | 102 | char buf[12] = {0}; |
104 | unsigned int x = va_arg(arg_list, unsigned int); | 103 | unsigned int x = va_arg(arg_list, unsigned int); |
105 | sprintf(buf, "%x", x); | 104 | sprintf(buf, "%x", x); |
106 | txt_puts(buf); | 105 | txt_puts(buf); |