summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-04-27 12:36:28 +0200
committerBad Diode <bd@badd10de.dev>2021-04-27 12:36:28 +0200
commitaf05a2979f97d00eab36261374af1eaf2ac3c833 (patch)
tree726757223f51ca3130e95d5e52a49dc3200958a5
parenta0efde919bedfbb427d2e2c5ae34e06489930b0c (diff)
downloadgba-experiments-af05a2979f97d00eab36261374af1eaf2ac3c833.tar.gz
gba-experiments-af05a2979f97d00eab36261374af1eaf2ac3c833.zip
Add DMA control macros and small memory copy test
-rw-r--r--src/common.h69
-rw-r--r--src/main.c96
-rw-r--r--src/sprites.h1
-rw-r--r--src/text.h9
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.
308static inline void
308unpack_tiles(u32 *src, u32 *dst, size_t n_tiles) { 309unpack_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.
349typedef 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.
360inline void
361dma_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
368inline void
369dma_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.
377inline void
378dma_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.
383inline void
384dma_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
diff --git a/src/main.c b/src/main.c
index 3bd5865..efd460f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
diff --git a/src/text.h b/src/text.h
index e38c220..c852fc2 100644
--- a/src/text.h
+++ b/src/text.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);