summaryrefslogtreecommitdiffstats
path: root/src/text.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/text.h')
-rw-r--r--src/text.h142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/text.h b/src/text.h
new file mode 100644
index 0000000..e38c220
--- /dev/null
+++ b/src/text.h
@@ -0,0 +1,142 @@
1#ifndef GBAEXP_TILES_H
2#define GBAEXP_TILES_H
3
4#include <stdarg.h>
5
6#include "common.h"
7#include "bd-font.c"
8
9typedef struct TextEngine {
10 // Currently working on tiled backgrounds only. The X and Y positions
11 // correspond to the tile X and Y starting from the top left of the screen.
12 // For a 240x160 screen, we have 30x20 tiles available.
13 size_t cursor_x;
14 size_t cursor_y;
15 // Pointer to the screenblock being used for writing to the screen.
16 u16 *screenblock;
17} TextEngine;
18
19static TextEngine text_engine = {0};
20
21void
22txt_putc(char c) {
23 if (c == '\0') {
24 return;
25 }
26 if (c == '\n') {
27 text_engine.cursor_x = 0;
28 text_engine.cursor_y++;
29 } else {
30 text_engine.screenblock[text_engine.cursor_x + 32 * text_engine.cursor_y] = c;
31 text_engine.cursor_x++;
32 if (text_engine.cursor_x >= 30) {
33 text_engine.cursor_x = 0;
34 text_engine.cursor_y++;
35 }
36 }
37 if (text_engine.cursor_y >= 20) {
38 text_engine.cursor_y = 0;
39 }
40}
41
42static inline void
43txt_puts(char *msg) {
44 while (*msg) {
45 txt_putc(*msg++);
46 }
47}
48
49void
50txt_init(size_t bg, Color clr, size_t cb_idx) {
51 // The screenblock for the tile map should start after the tile memory
52 // (MEM_VRAM + 0x2000 for 256 characters). Since each screenblock is
53 // composed of 1024 screenblock entries of u16 (2 bytes), we need an
54 // screenblock index offset of 8192 / (1024 * 2) = 4 screen blocks.
55 size_t sb_idx = cb_idx * 8 + 4;
56
57 // Set the background parameters for the text layer.
58 BG_CTRL(bg) = BG_CHARBLOCK(cb_idx) | BG_SCREENBLOCK(sb_idx) | BG_PRIORITY(3);
59
60 // Load font data in video memory. Each character is unpacked into a tile of
61 // 8 32bit values (4bpp), meaning that for the full ASCII set of 256
62 // characters, we need 8192 bytes of VRAM (8 * 4 * 256).
63 unpack_tiles(&bd_font, &CHARBLOCK_MEM[cb_idx], 256);
64
65 // Load palette color.
66 PAL_BUFFER_BG[1] = clr;
67
68 // Update text_engine variables.
69 text_engine.screenblock = SCREENBLOCK_MEM[sb_idx];
70}
71
72// Print text to the screen with formatting.
73void
74txt_printf(char *msg, ...) {
75 va_list arg_list;
76 va_start(arg_list, msg);
77 char c;
78 char prev_c;
79 while ((c = *msg++) != '\0') {
80 if (c != '%') {
81 txt_putc(c);
82 prev_c = c;
83 continue;
84 }
85 c = *msg++;
86 switch (c) {
87 case 's': {
88 txt_puts(va_arg(arg_list, char *));
89 } break;
90 case 'd': {
91 char buf[32] = {0};
92 int x = va_arg(arg_list, int);
93 sprintf(buf, "%d", x);
94 txt_puts(buf);
95 } break;
96 case 'u': {
97 char buf[32] = {0};
98 unsigned int x = va_arg(arg_list, unsigned int);
99 sprintf(buf, "%u", x);
100 txt_puts(buf);
101 } break;
102 case 'x': {
103 char buf[32] = {0};
104 unsigned int x = va_arg(arg_list, unsigned int);
105 sprintf(buf, "%x", x);
106 txt_puts(buf);
107 } break;
108 default: {
109 txt_putc('%');
110 txt_putc(c);
111 } break;
112 }
113 }
114}
115
116void
117txt_clear_line(void) {
118 for (size_t i = 0; i < 30; ++i) {
119 text_engine.screenblock[i + 32 * text_engine.cursor_y] = ' ';
120 }
121 text_engine.cursor_x = 0;
122}
123
124void
125txt_clear_screen(void) {
126 for (size_t j = 0; j < 20; ++j) {
127 for (size_t i = 0; i < 30; ++i) {
128 text_engine.screenblock[i + 32 * j] = ' ';
129 }
130 }
131 text_engine.cursor_x = 0;
132 text_engine.cursor_y = 0;
133}
134
135void
136txt_position(size_t tile_x, size_t tile_y) {
137 text_engine.cursor_x = tile_x;
138 text_engine.cursor_y = tile_y;
139}
140
141#endif // GBAEXP_TILES_H
142